Skip to content

Commit d51398e

Browse files
authored
fix(android): improve home press reliability
1 parent b2f3d38 commit d51398e

4 files changed

Lines changed: 809 additions & 77 deletions

File tree

android/src/main/java/com/margelo/nitro/cover/CoverBlurRenderer.kt

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,32 @@ internal object CoverBlurRenderer {
2323
/// one is open) at 1/4 scale, blur it via `RenderEffect`, and apply
2424
/// to the target ImageView. Falls back to a flat tinted background
2525
/// on API < 31. No-op when the source view has no laid-out size.
26-
fun render(target: ImageView, activity: Activity, style: CoverBlurStyle, intensity: Float) {
26+
///
27+
/// `alsoExclude` is the cover's WindowManager-attached root view —
28+
/// distinct from `target.rootView` on the SCVH path, where the
29+
/// SCVH-hosted FrameLayout (containing `target`) is NOT in
30+
/// `WindowManagerGlobal.mViews`, but the wrapping `SurfaceView`
31+
/// is. Without this exclude the blur source resolves to that
32+
/// SurfaceView, and software-drawing a SurfaceView produces a
33+
/// transparent bitmap (its content lives in a separate hardware
34+
/// surface) — leaving the blur cover translucent and the activity
35+
/// content visible through it.
36+
fun render(
37+
target: ImageView,
38+
activity: Activity,
39+
style: CoverBlurStyle,
40+
intensity: Float,
41+
alsoExclude: View? = null,
42+
) {
2743
// Capturing the activity's decor alone would blur only what's
2844
// behind the modal, leaving the modal's content sharp under our
2945
// cover. Using the topmost host view fixes that. Falls back to the
3046
// activity decor when nothing else is in front.
31-
val source = CoverWindowAttachment.topmostHostViewFor(activity, exclude = target.rootView)
32-
?: activity.window?.decorView ?: return
47+
val source = CoverWindowAttachment.topmostHostViewFor(
48+
activity,
49+
exclude = target.rootView,
50+
exclude2 = alsoExclude,
51+
) ?: activity.window?.decorView ?: return
3352
// 1/4 scale: cuts the bitmap allocation 16× and the GPU upscale on
3453
// display is hidden behind the blur.
3554
val bitmap = captureViewBitmap(source, scale = 0.25f) ?: return

android/src/main/java/com/margelo/nitro/cover/CoverWindowAttachment.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,19 @@ internal object CoverWindowAttachment {
4949
@Volatile private var cachedMViewsField: Field? = null
5050
@Volatile private var reflectionInitFailed: Boolean = false
5151

52-
fun topmostHostViewFor(activity: Activity, exclude: View? = null): View? {
52+
fun topmostHostViewFor(
53+
activity: Activity,
54+
exclude: View? = null,
55+
exclude2: View? = null,
56+
): View? {
5357
val views = readWindowManagerViews() ?: return null
5458
// Iterate in reverse: in WindowManagerGlobal the last entry is
5559
// the most recently attached, and on a single-activity stack
5660
// that maps to the topmost window.
5761
for (i in views.indices.reversed()) {
5862
val v = views[i]
5963
if (v === exclude) continue
64+
if (v === exclude2) continue
6065
if (v.windowToken == null) continue
6166
// Reject views that have been detached from their ViewRootImpl
6267
// but are still lingering in mViews (mDyingViews entries — see

0 commit comments

Comments
 (0)