diff --git a/app/src/main/java/se/ajpanton/statusbartweak/runtime/features/battery/BatteryBarController.java b/app/src/main/java/se/ajpanton/statusbartweak/runtime/features/battery/BatteryBarController.java index 9fa0094..ba941a8 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/runtime/features/battery/BatteryBarController.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/runtime/features/battery/BatteryBarController.java @@ -566,6 +566,15 @@ final class BatteryBarController { if (isKeyguardRoot(root)) { return BatteryBarGeometry.Scenario.LOCKSCREEN; } + SceneKey scene = runtimeContext.getModeStateRepository().getActiveScene(); + if (isPhoneRoot(root) + && scene != null + && scene.isLockscreen() + && isKeyguardLocked(root.getContext()) + && !isStatusBarSurfaceHidden(root) + && !isFullscreenSystemBarState()) { + return BatteryBarGeometry.Scenario.LOCKSCREEN; + } boolean fullscreen = isPhoneRoot(root) && (isUnlockedScene() || isLockedPhoneFullscreenRoot(root)) && (isStatusBarSurfaceHidden(root) || isFullscreenSystemBarState()); @@ -623,10 +632,14 @@ final class BatteryBarController { return scene == null || !scene.isUnlocked(); } if (isPhoneRoot(root)) { - if (isLockedPhoneStatusBarRoot(root)) { - return isLockedPhoneFullscreenRoot(root); + if (scene == null || scene.isUnlocked()) { + return true; } - return scene == null || scene.isUnlocked() || isLockedPhoneFullscreenRoot(root); + if (isLockedPhoneStatusBarRoot(root)) { + return isLockedPhoneFullscreenRoot(root) + || (!isStatusBarSurfaceHidden(root) && !isFullscreenSystemBarState()); + } + return false; } return true; } diff --git a/app/src/main/java/se/ajpanton/statusbartweak/runtime/layout/DarkIconDispatcherGuard.java b/app/src/main/java/se/ajpanton/statusbartweak/runtime/layout/DarkIconDispatcherGuard.java index dba4c52..98d1184 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/runtime/layout/DarkIconDispatcherGuard.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/runtime/layout/DarkIconDispatcherGuard.java @@ -17,6 +17,7 @@ import se.ajpanton.statusbartweak.runtime.render.StatusBarTintTarget; final class DarkIconDispatcherGuard { private final RuntimeContext runtimeContext; private final BooleanSupplier lockscreenSceneSupplier; + private final BooleanSupplier lockscreenDarkIconsSupplier; private final Runnable refreshAllRoots; private final Set dispatchers = Collections.newSetFromMap(new WeakHashMap<>()); @@ -25,10 +26,12 @@ final class DarkIconDispatcherGuard { DarkIconDispatcherGuard( RuntimeContext runtimeContext, BooleanSupplier lockscreenSceneSupplier, + BooleanSupplier lockscreenDarkIconsSupplier, Runnable refreshAllRoots ) { this.runtimeContext = runtimeContext; this.lockscreenSceneSupplier = lockscreenSceneSupplier; + this.lockscreenDarkIconsSupplier = lockscreenDarkIconsSupplier; this.refreshAllRoots = refreshAllRoots; } @@ -48,7 +51,7 @@ final class DarkIconDispatcherGuard { chain -> { Object dispatcher = chain.getThisObject(); track(dispatcher); - if (isLockscreenScene()) { + if (isLockscreenScene() && !shouldUseDarkLockscreenIcons()) { forceLightState(dispatcher); } Object result = chain.proceed(); @@ -63,7 +66,11 @@ final class DarkIconDispatcherGuard { return; } for (Object dispatcher : new ArrayList<>(dispatchers)) { - forceLightState(dispatcher); + if (shouldUseDarkLockscreenIcons()) { + restoreState(dispatcher, forcedStates.remove(dispatcher)); + } else { + forceLightState(dispatcher); + } ReflectionSupport.invokeMethod(dispatcher, "applyIconTint"); } } @@ -85,6 +92,10 @@ final class DarkIconDispatcherGuard { return lockscreenSceneSupplier.getAsBoolean(); } + private boolean shouldUseDarkLockscreenIcons() { + return lockscreenDarkIconsSupplier.getAsBoolean(); + } + private void track(Object dispatcher) { if (dispatcher != null) { dispatchers.add(dispatcher); @@ -92,6 +103,10 @@ final class DarkIconDispatcherGuard { } private void updateTintTarget(Object dispatcher) { + if (isLockscreenScene() && shouldUseDarkLockscreenIcons()) { + StatusBarTintTarget.setDarkIcons(true); + return; + } Object intensity = ReflectionSupport.getFieldValue(dispatcher, "mDarkIntensity"); if (intensity instanceof Number number) { StatusBarTintTarget.setDarkIcons(number.floatValue() > 0.5f); diff --git a/app/src/main/java/se/ajpanton/statusbartweak/runtime/layout/StockLayoutCanvasController.java b/app/src/main/java/se/ajpanton/statusbartweak/runtime/layout/StockLayoutCanvasController.java index 6e7d57a..1538dc5 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/runtime/layout/StockLayoutCanvasController.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/runtime/layout/StockLayoutCanvasController.java @@ -80,6 +80,7 @@ final class StockLayoutCanvasController { "mEntries", "entries" }; + private static final int APPEARANCE_LIGHT_STATUS_BARS = 8; private static final Set TARGET_ID_NAMES = Set.of( "clock", "left_clock_container", @@ -198,6 +199,7 @@ final class StockLayoutCanvasController { private int notificationDrawerCloseGeneration; private boolean notificationDrawerClosePending; private int aodVisualAlphaGeneration; + private int systemBarAppearance; private int systemBarRequestedVisibleTypes = WindowInsets.Type.statusBars(); private boolean statusBarTransientShown; @@ -207,6 +209,7 @@ final class StockLayoutCanvasController { darkIconDispatcherGuard = new DarkIconDispatcherGuard( runtimeContext, this::isLockscreenScene, + this::shouldUseDarkLockscreenStatusbarTint, this::scheduleUnlockedAppearanceRefreshForAllRoots); lockscreenCardsNotificationStripRenderer = new LockscreenCardsNotificationStripRenderer(); @@ -247,25 +250,35 @@ final class StockLayoutCanvasController { "onSystemBarAttributesChanged", chain -> { Object result = chain.proceed(); - updateSystemBarRequestedVisibleTypes(chain.getArgs()); + updateSystemBarAttributes(chain.getArgs()); return result; }); } - private void updateSystemBarRequestedVisibleTypes(List args) { - if (args == null || args.size() <= 5) { + private void updateSystemBarAttributes(List args) { + if (args == null || args.size() < 2) { return; } Integer displayId = asInteger(args.get(0)); - Integer requestedVisibleTypes = asInteger(args.get(5)); - if (displayId == null || displayId != 0 || requestedVisibleTypes == null) { + Integer appearance = asInteger(args.get(1)); + Integer requestedVisibleTypes = args.size() > 5 ? asInteger(args.get(5)) : null; + if (displayId == null || displayId != 0 || appearance == null) { return; } - if (systemBarRequestedVisibleTypes == requestedVisibleTypes) { - return; + boolean appearanceChanged = systemBarAppearance != appearance; + systemBarAppearance = appearance; + if (requestedVisibleTypes != null + && systemBarRequestedVisibleTypes != requestedVisibleTypes) { + systemBarRequestedVisibleTypes = requestedVisibleTypes; + if (statusBarsRequestedVisible()) { + releaseSuppressedHiddenStatusBarRoots(); + privacyOverlayHiddenStatusBarRoots.clear(); + } } - systemBarRequestedVisibleTypes = requestedVisibleTypes; - if (statusBarsRequestedVisible()) { + if (appearanceChanged) { + darkIconDispatcherGuard.forceLightStateForAll(); + requestUnlockedLayoutRefreshForAllRoots(); + } else if (statusBarsRequestedVisible()) { releaseSuppressedHiddenStatusBarRoots(); privacyOverlayHiddenStatusBarRoots.clear(); } @@ -1807,8 +1820,17 @@ final class StockLayoutCanvasController { return; } dirtyUnlockedLayoutRoots.add(root); - root.requestLayout(); - root.invalidate(); + Runnable refresh = () -> { + if (root.isAttachedToWindow()) { + root.requestLayout(); + root.invalidate(); + } + }; + if (isViewThread(root)) { + refresh.run(); + } else if (root.getHandler() != null) { + root.getHandler().post(refresh); + } } private View rootForShadeTarget(Object target) { @@ -2157,6 +2179,15 @@ final class StockLayoutCanvasController { return scene != null && scene.isLockscreen(); } + private boolean statusBarTintTargetEnabledForScene(SceneKey scene) { + return scene != null && (scene.isUnlocked() || shouldUseDarkLockscreenStatusbarTint()); + } + + private boolean shouldUseDarkLockscreenStatusbarTint() { + return isLockscreenScene() + && (systemBarAppearance & APPEARANCE_LIGHT_STATUS_BARS) != 0; + } + private void scheduleUnlockedAppearanceRefreshForRoot(View root) { scheduleUnlockedAppearanceRefreshForRoot(root, false); } @@ -2282,7 +2313,8 @@ final class StockLayoutCanvasController { if (unlockedIconRenderController.refreshUnlockedClockText( root, unlockedHosts.clockHost, - activeScene)) { + activeScene, + statusBarTintTargetEnabledForScene(activeScene))) { bringUnlockedHostsAndDebugOverlayToFront(root); } } @@ -2491,6 +2523,7 @@ final class StockLayoutCanvasController { unlockedHosts.statusHost, unlockedHosts.notificationHost, activeScene, + statusBarTintTargetEnabledForScene(activeScene), rootDirty, lockedCarrierTextSource()); boolean shouldShowUnlockedHosts = unlockedScene @@ -3493,8 +3526,13 @@ final class StockLayoutCanvasController { boolean shelfSurface = isCardsNotificationIconSurface(view); boolean shelfBackgroundSurface = isCardsNotificationShelfBackgroundSurface(view); boolean shadeIconOnlySurface = "keyguard_icononly_container_view".equals(idName); + boolean clockSurface = "clock".equals(idName) + || "left_clock_container".equals(idName) + || viewClassName.contains("QSClockIndicatorView") + || viewClassName.contains("statusbar.policy.Clock"); if (!("system_icons".equals(idName) || carrierSurface + || clockSurface || "system_icon_area".equals(idName) || "statusIcons".equals(idName) || "battery".equals(idName) @@ -4916,7 +4954,8 @@ final class StockLayoutCanvasController { lockscreenCardsNotificationRenderGenerationByRoot.remove(root); return; } - if (runtimeContext.getModeStateRepository().isSystemUiShadeLocked()) { + if (runtimeContext.getModeStateRepository().isSystemUiShadeLocked() + || hasVisibleLockscreenShadeHeader(root)) { removeLockscreenCardsNotificationHost(root); lockscreenCardsNotificationRenderGenerationByRoot.remove(root); return; @@ -4956,6 +4995,27 @@ final class StockLayoutCanvasController { } } + private boolean hasVisibleLockscreenShadeHeader(View root) { + if (root == null || !isNotificationShadeWindowRoot(root)) { + return false; + } + final boolean[] found = {false}; + walkTree(root, view -> { + if (found[0] || !(view instanceof TextView textView)) { + return; + } + if (!textView.isShown() || textView.getAlpha() <= 0f) { + return; + } + String idName = ViewIdNames.idName(textView); + String className = textView.getClass().getName(); + if ("header_clock".equals(idName) || className.contains("QSClockHeaderView")) { + found[0] = true; + } + }); + return found[0]; + } + private void renderAodCardsNotificationStripIfNeeded( View root, SbtSettings settings, diff --git a/app/src/main/java/se/ajpanton/statusbartweak/runtime/render/SnapshotModels.java b/app/src/main/java/se/ajpanton/statusbartweak/runtime/render/SnapshotModels.java index 25f248f..39a59e1 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/runtime/render/SnapshotModels.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/runtime/render/SnapshotModels.java @@ -484,4 +484,13 @@ final class LayoutPlan { notificationPlacements, carrierPlacement); } + + LayoutPlan withCarrierPlacement(ClockPlacement placement) { + return new LayoutPlan( + clockPlacement, + chipPlacements, + statusPlacements, + notificationPlacements, + placement); + } } diff --git a/app/src/main/java/se/ajpanton/statusbartweak/runtime/render/UnlockedIconSnapshotRenderController.java b/app/src/main/java/se/ajpanton/statusbartweak/runtime/render/UnlockedIconSnapshotRenderController.java index aeb176f..8075433 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/runtime/render/UnlockedIconSnapshotRenderController.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/runtime/render/UnlockedIconSnapshotRenderController.java @@ -65,6 +65,7 @@ public final class UnlockedIconSnapshotRenderController { ViewGroup statusHost, ViewGroup notificationHost, SceneKey scene, + boolean statusBarTintTargetEnabled, boolean forceStockRefresh, TextView externalCarrierView ) { @@ -80,7 +81,7 @@ public final class UnlockedIconSnapshotRenderController { return new RenderResult(true, true, true); } SbtSettings settings = RuntimeSettingsCache.get(root.getContext()); - setStatusBarTintTargetEnabled(scene.isUnlocked()); + setStatusBarTintTargetEnabled(statusBarTintTargetEnabled); layoutHostToRoot(root, clockHost); layoutHostToRoot(root, carrierHost); layoutHostToRoot(root, chipHost); @@ -235,6 +236,7 @@ public final class UnlockedIconSnapshotRenderController { lastClockSourceGeometryByRoot.put(root, currentClockSourceGeometry); layoutPlan = withCurrentDotColors(layoutPlan, collectedIcons); layoutPlan = withCurrentClockAppearance(root, layoutPlan, collectedIcons, settings); + layoutPlan = withCurrentCarrierAppearance(layoutPlan); lastLayoutPlanByRoot.put(root, layoutPlan); if (clockEnabledForScene(settings, scene) && layoutPlan.clockPlacement != null) { clockRenderer.render(clockHost, layoutPlan.clockPlacement); @@ -347,7 +349,8 @@ public final class UnlockedIconSnapshotRenderController { public boolean refreshUnlockedClockText( View root, ViewGroup clockHost, - SceneKey scene + SceneKey scene, + boolean statusBarTintTargetEnabled ) { if (root == null || clockHost == null @@ -361,7 +364,7 @@ public final class UnlockedIconSnapshotRenderController { return false; } SbtSettings settings = RuntimeSettingsCache.get(root.getContext()); - setStatusBarTintTargetEnabled(scene.isUnlocked()); + setStatusBarTintTargetEnabled(statusBarTintTargetEnabled); if (!clockEnabledForScene(settings, scene)) { return false; } @@ -595,6 +598,24 @@ public final class UnlockedIconSnapshotRenderController { return plan.withClockPlacement(updatedClock); } + private LayoutPlan withCurrentCarrierAppearance(LayoutPlan plan) { + int targetColor = statusBarTintTargetColor(); + if (plan == null + || plan.carrierPlacement == null + || !hasAlpha(targetColor) + || plan.carrierPlacement.textColorOverride == targetColor) { + return plan; + } + ClockPlacement previous = plan.carrierPlacement; + return plan.withCarrierPlacement(new ClockPlacement( + previous.source, + previous.contentDescription, + previous.rows, + previous.bounds, + targetColor, + previous.textSizePx)); + } + private int clockReferenceColor(ClockPlacement placement, CollectedIcons icons) { int targetColor = statusBarTintTargetColor(); if (hasAlpha(targetColor)) {