Fix call chip rendering and placement stability
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package se.ajpanton.statusbartweak.runtime;
|
||||
|
||||
public final class RuntimeMutationGuard {
|
||||
private static final ThreadLocal<Integer> SNAPSHOT_RENDER_DEPTH =
|
||||
ThreadLocal.withInitial(() -> 0);
|
||||
|
||||
private RuntimeMutationGuard() {
|
||||
}
|
||||
|
||||
public static void enterSnapshotRenderMutation() {
|
||||
SNAPSHOT_RENDER_DEPTH.set(SNAPSHOT_RENDER_DEPTH.get() + 1);
|
||||
}
|
||||
|
||||
public static void exitSnapshotRenderMutation() {
|
||||
int depth = SNAPSHOT_RENDER_DEPTH.get() - 1;
|
||||
if (depth <= 0) {
|
||||
SNAPSHOT_RENDER_DEPTH.remove();
|
||||
} else {
|
||||
SNAPSHOT_RENDER_DEPTH.set(depth);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSnapshotRenderMutation() {
|
||||
Integer depth = SNAPSHOT_RENDER_DEPTH.get();
|
||||
return depth != null && depth > 0;
|
||||
}
|
||||
}
|
||||
+6
@@ -34,6 +34,7 @@ import java.util.WeakHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import se.ajpanton.statusbartweak.runtime.NotificationKeyReflection;
|
||||
import se.ajpanton.statusbartweak.runtime.RuntimeMutationGuard;
|
||||
import se.ajpanton.statusbartweak.runtime.ViewIdNames;
|
||||
import se.ajpanton.statusbartweak.runtime.features.RuntimeContext;
|
||||
import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport;
|
||||
@@ -1491,6 +1492,9 @@ final class StockLayoutCanvasController {
|
||||
}
|
||||
|
||||
private void markStatusChipLifecycleDirtyIfNeeded(View view, View fallbackRoot) {
|
||||
if (RuntimeMutationGuard.isSnapshotRenderMutation()) {
|
||||
return;
|
||||
}
|
||||
if (view == null || !isStatusChipCandidate(view)) {
|
||||
View root = view != null ? unlockedStatusBarRootFor(view) : fallbackRoot;
|
||||
if (deferDrawerStatusChipRefresh(root)) {
|
||||
@@ -2989,6 +2993,7 @@ final class StockLayoutCanvasController {
|
||||
private boolean isTrackedStatusChipWriteTarget(View view) {
|
||||
if (view == null
|
||||
|| ownHiddenViewAlphaWriteDepth > 0
|
||||
|| RuntimeMutationGuard.isSnapshotRenderMutation()
|
||||
|| !trackedStatusChipSources.contains(view)
|
||||
|| !hiddenViewStates.containsKey(view)
|
||||
|| !view.isAttachedToWindow()
|
||||
@@ -3008,6 +3013,7 @@ final class StockLayoutCanvasController {
|
||||
private boolean isStatusChipShellWriteTarget(View view) {
|
||||
if (view == null
|
||||
|| ownHiddenViewAlphaWriteDepth > 0
|
||||
|| RuntimeMutationGuard.isSnapshotRenderMutation()
|
||||
|| !view.isAttachedToWindow()
|
||||
|| !isLayoutEnabled(view.getContext())
|
||||
|| !isStatusChipShell(view)) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.util.Objects;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import se.ajpanton.statusbartweak.runtime.NotificationKeyReflection;
|
||||
import se.ajpanton.statusbartweak.runtime.RuntimeMutationGuard;
|
||||
import se.ajpanton.statusbartweak.runtime.ViewIdNames;
|
||||
import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport;
|
||||
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds;
|
||||
@@ -748,6 +749,8 @@ final class SnapshotRenderer {
|
||||
bitmap.getHeight())) {
|
||||
return;
|
||||
}
|
||||
RuntimeMutationGuard.enterSnapshotRenderMutation();
|
||||
try {
|
||||
sourceView.setVisibility(View.VISIBLE);
|
||||
sourceView.setAlpha(1f);
|
||||
if (source.mode() == SnapshotMode.STATUS_CHIP) {
|
||||
@@ -756,8 +759,16 @@ final class SnapshotRenderer {
|
||||
sourceView.draw(canvas);
|
||||
}
|
||||
} finally {
|
||||
RuntimeMutationGuard.exitSnapshotRenderMutation();
|
||||
}
|
||||
} finally {
|
||||
RuntimeMutationGuard.enterSnapshotRenderMutation();
|
||||
try {
|
||||
sourceView.setAlpha(oldAlpha);
|
||||
sourceView.setVisibility(oldVisibility);
|
||||
} finally {
|
||||
RuntimeMutationGuard.exitSnapshotRenderMutation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1183,7 +1194,9 @@ final class SnapshotRenderer {
|
||||
view.getRight(),
|
||||
view.getBottom(),
|
||||
view.getMeasuredWidth(),
|
||||
view.getMeasuredHeight()));
|
||||
view.getMeasuredHeight(),
|
||||
view.getVisibility(),
|
||||
view.getAlpha()));
|
||||
if (view instanceof ViewGroup group) {
|
||||
for (int i = 0; i < group.getChildCount(); i++) {
|
||||
captureFrameState(group.getChildAt(i), state);
|
||||
@@ -1207,6 +1220,12 @@ final class SnapshotRenderer {
|
||||
View.MeasureSpec.makeMeasureSpec(frame.measuredHeight, View.MeasureSpec.EXACTLY));
|
||||
}
|
||||
view.layout(frame.left, frame.top, frame.right, frame.bottom);
|
||||
if (view.getAlpha() != frame.alpha) {
|
||||
view.setAlpha(frame.alpha);
|
||||
}
|
||||
if (view.getVisibility() != frame.visibility) {
|
||||
view.setVisibility(frame.visibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1221,7 +1240,9 @@ final class SnapshotRenderer {
|
||||
int right,
|
||||
int bottom,
|
||||
int measuredWidth,
|
||||
int measuredHeight
|
||||
int measuredHeight,
|
||||
int visibility,
|
||||
float alpha
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -21,6 +21,10 @@ final class UnlockedChipPlacementController {
|
||||
}
|
||||
|
||||
void clear() {
|
||||
resetMissingChipFallback();
|
||||
}
|
||||
|
||||
private void resetMissingChipFallback() {
|
||||
heldPlacements = null;
|
||||
lastCollisionBounds = null;
|
||||
lastRootWidth = 0;
|
||||
@@ -47,10 +51,11 @@ final class UnlockedChipPlacementController {
|
||||
return rawPlacements;
|
||||
}
|
||||
|
||||
ArrayList<SnapshotPlacement> placements = isAnyChipHidingEnabled(settings)
|
||||
boolean hasMetricSources = metricSources != null && !metricSources.isEmpty();
|
||||
ArrayList<SnapshotPlacement> placements = isAnyChipHidingEnabled(settings) || !hasMetricSources
|
||||
? new ArrayList<>()
|
||||
: heldPlacements(root);
|
||||
if (placements.isEmpty()) {
|
||||
if (placements.isEmpty() && hasMetricSources) {
|
||||
placements = emptyPlacement(root, metricSources);
|
||||
}
|
||||
return placements;
|
||||
|
||||
+26
-1
@@ -88,7 +88,13 @@ final class UnlockedLayoutPlanner {
|
||||
Bounds aodStatusbarBounds = scene != null && scene.isAod()
|
||||
? aodStatusbarBounds(root, settings, aodNotificationBounds, aodStatusAnchorBounds)
|
||||
: null;
|
||||
LayoutEdges edges = layoutEdges(root, settings, anchors, scene, aodStatusAnchorBounds);
|
||||
LayoutEdges edges = layoutEdges(
|
||||
root,
|
||||
settings,
|
||||
anchors,
|
||||
collectedIcons,
|
||||
scene,
|
||||
aodStatusAnchorBounds);
|
||||
int statusbarHeight = statusbarHeight(root, anchors, scene, aodStatusContentBounds);
|
||||
if (clockEnabledForScene(settings, scene) && clockLayout != null && clockLayout.width() > 0) {
|
||||
bands.add(UnlockedLayoutBand.clock(
|
||||
@@ -1393,6 +1399,7 @@ final class UnlockedLayoutPlanner {
|
||||
View root,
|
||||
SbtSettings settings,
|
||||
RootAnchors anchors,
|
||||
CollectedIcons collectedIcons,
|
||||
SceneKey scene,
|
||||
Bounds aodStatusAnchorBounds
|
||||
) {
|
||||
@@ -1419,11 +1426,29 @@ final class UnlockedLayoutPlanner {
|
||||
if (settings.layoutPaddingRightAddStock) {
|
||||
right -= stockInsets.right;
|
||||
}
|
||||
if (scene != null && scene.isUnlocked() && hasStatusChipSources(collectedIcons)) {
|
||||
LayoutEdges recentEdges = recentNonAodEdgesByRootWidth.get(rootWidth);
|
||||
if (isReusableUnlockedEdge(left, recentEdges)) {
|
||||
left = recentEdges.left();
|
||||
}
|
||||
}
|
||||
LayoutEdges edges = new LayoutEdges(left, right);
|
||||
rememberNonAodEdges(rootWidth, scene, edges);
|
||||
return edges;
|
||||
}
|
||||
|
||||
private boolean hasStatusChipSources(CollectedIcons icons) {
|
||||
return icons != null
|
||||
&& ((icons.statusChips != null && !icons.statusChips.isEmpty())
|
||||
|| (icons.statusChipMetrics != null && !icons.statusChipMetrics.isEmpty()));
|
||||
}
|
||||
|
||||
private boolean isReusableUnlockedEdge(int currentLeft, LayoutEdges recentEdges) {
|
||||
return recentEdges != null
|
||||
&& recentEdges.right() > recentEdges.left()
|
||||
&& Math.abs(currentLeft - recentEdges.left()) <= 8;
|
||||
}
|
||||
|
||||
private LayoutEdges stableAodEdges(int rootWidth, LayoutEdges aodEdges) {
|
||||
if (rootWidth <= 0) {
|
||||
return aodEdges;
|
||||
|
||||
Reference in New Issue
Block a user