Stabilize statusbar during privacy overlay

This commit is contained in:
ajp_anton
2026-06-22 20:00:14 +00:00
parent 1fa5fd24b1
commit ea3d8221b5
@@ -406,6 +406,9 @@ final class StockLayoutCanvasController {
Object target = chain.getThisObject(); Object target = chain.getThisObject();
Object alphaArg = firstArg(chain.getArgs()); Object alphaArg = firstArg(chain.getArgs());
if (target instanceof View view && alphaArg instanceof Float alpha) { if (target instanceof View view && alphaArg instanceof Float alpha) {
if (shouldSuppressPrivacyOverlayStatusBarAlpha(view, alpha)) {
return null;
}
if (shouldSuppressConflictingShadeHeaderAlpha(view, alpha)) { if (shouldSuppressConflictingShadeHeaderAlpha(view, alpha)) {
return null; return null;
} }
@@ -451,6 +454,16 @@ final class StockLayoutCanvasController {
} }
return chain.proceed(); return chain.proceed();
}); });
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), viewClass, "setTranslationX", chain -> {
Object target = chain.getThisObject();
Object translationArg = firstArg(chain.getArgs());
if (target instanceof View view && translationArg instanceof Float translationX) {
if (shouldSuppressPrivacyOverlayStatusBarTranslationX(view, translationX)) {
return null;
}
}
return chain.proceed();
});
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), viewClass, "layout", chain -> { XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), viewClass, "layout", chain -> {
Object target = chain.getThisObject(); Object target = chain.getThisObject();
List<Object> args = chain.getArgs(); List<Object> args = chain.getArgs();
@@ -3350,6 +3363,60 @@ final class StockLayoutCanvasController {
return true; return true;
} }
private boolean shouldSuppressPrivacyOverlayStatusBarAlpha(View view, float alpha) {
if (alpha >= 0.99f
|| ownHiddenViewAlphaWriteDepth > 0
|| !isPhoneStatusBarRoot(view)
|| !isLayoutEnabled(view.getContext())
|| ongoingPrivacyChipInRoot(view) == null) {
return false;
}
return true;
}
private boolean shouldSuppressPrivacyOverlayStatusBarTranslationX(View view, float translationX) {
if (Math.abs(translationX) < 0.5f
|| ownHiddenViewAlphaWriteDepth > 0
|| !isPhoneStatusBarRoot(view)
|| !isLayoutEnabled(view.getContext())
|| ongoingPrivacyChipInRoot(view) == null) {
return false;
}
return true;
}
private boolean isPhoneStatusBarRoot(View view) {
return view != null
&& view.getClass().getName().contains("PhoneStatusBarView");
}
private boolean isOngoingPrivacyChip(View view) {
return view != null
&& view.getClass().getName().contains("OngoingPrivacyChip")
&& "privacy_chip".equals(ViewIdNames.idName(view));
}
private View ongoingPrivacyChipInRoot(View view) {
View root = view != null ? view.getRootView() : null;
if (!(root instanceof ViewGroup group)) {
return null;
}
ArrayDeque<View> queue = new ArrayDeque<>();
queue.add(group);
while (!queue.isEmpty()) {
View current = queue.removeFirst();
if (isOngoingPrivacyChip(current)) {
return current;
}
if (current instanceof ViewGroup childGroup) {
for (int i = 0; i < childGroup.getChildCount(); i++) {
queue.addLast(childGroup.getChildAt(i));
}
}
}
return null;
}
private boolean isStatusChipSource(View view) { private boolean isStatusChipSource(View view) {
if (view == null || view.getVisibility() != View.VISIBLE) { if (view == null || view.getVisibility() != View.VISIBLE) {
return false; return false;