Let the page reach the edges

86553d7 · Gabriel Morell · 2026-09-02 21:44

18 files +38 -1
Message
{commit_body(@commit)}

Files changed

modified clients/android/app/src/debug/java/io/neiam/apolloscrib/feed/OverlayHarnessActivity.kt
+5 −0
@@ -25,6 +25,11 @@ import com.google.android.libraries.launcherclient.ILauncherOverlayCallback
25 25 *
26 26 * This does what a launcher does: binds the service, hands over its own window
27 27 * token, and drives the scroll. Debug-only; it is a test rig, not a feature.
28 + *
29 + * The service keeps one panel and one callback, so while this is attached it
30 + * has the overlay -- a launcher that binds meanwhile finds its page opening
31 + * somewhere it cannot be seen. Only one thing attaches at a time in practice;
32 + * force-stop the app between testing here and testing on a launcher.
28 33 */
29 34 class OverlayHarnessActivity : Activity() {
30 35
modified clients/android/app/src/main/java/io/neiam/apolloscrib/feed/OverlayPanel.kt
+33 −1
@@ -3,6 +3,7 @@ package io.neiam.apolloscrib.feed
3 3 import android.animation.ValueAnimator
4 4 import android.content.Context
5 5 import android.graphics.PixelFormat
6 +import android.os.Build
6 7 import android.os.IBinder
7 8 import android.util.Log
8 9 import android.view.Gravity
@@ -76,7 +77,16 @@ class OverlayPanel(
76 77 }
77 78
78 79 val root = FrameLayout(context).apply {
79 − addView(content)
80 + // Explicitly: a FrameLayout child defaults to WRAP_CONTENT, and a
81 + // page that does not fill its window leaves the strips behind the
82 + // system bars showing whatever is under it.
83 + addView(
84 + content,
85 + FrameLayout.LayoutParams(
86 + FrameLayout.LayoutParams.MATCH_PARENT,
87 + FrameLayout.LayoutParams.MATCH_PARENT
88 + )
89 + )
80 90 // Off screen until the launcher says otherwise.
81 91 alpha = 0f
82 92 }
@@ -121,12 +131,34 @@ class OverlayPanel(
121 131 gravity = Gravity.START or Gravity.TOP
122 132 flags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
123 133 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or
134 + // Behind the status and navigation bars rather than between them.
135 + // A window of this type is otherwise laid out inside the content
136 + // area, and the wallpaper shows through the strips at top and
137 + // bottom -- the page reads as a card floating on the home screen
138 + // instead of as a page.
139 + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
140 + // Without this the system paints its own opaque backgrounds for
141 + // the status and navigation bars on top of the window -- the
142 + // frame is already full screen, and the strips came out black
143 + // anyway. Saying we draw them ourselves is what makes the page's
144 + // own colour reach the edges. The GSA overlay controller sets the
145 + // same flag for the same reason.
146 + WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
124 147 // Not focusable: the launcher keeps the key events, and this page
125 148 // has nothing to type into.
126 149 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
127 150 // Starts closed, so starts letting touches through to the launcher.
128 151 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
129 152 softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
153 + // Into the cutout too, so the notch area is the page's colour and not
154 + // a black bar.
155 + layoutInDisplayCutoutMode =
156 + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
157 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
158 + // Draw behind the bars; the Scaffold inside still keeps the
159 + // content itself clear of them.
160 + fitInsetsTypes = 0
161 + }
130 162 }
131 163
132 164 fun detach() {

Parents: 11d747a