Fix UI clipping in all 4 orientations on Android devices with display cutout - #4752
Fix UI clipping in all 4 orientations on Android devices with display cutout#4752cagnulein wants to merge 10 commits into
Conversation
… cutout On devices with a display cutout (punch-hole camera), rotating to inverted landscape (270°) would clip the app window: the system restricted the window to SHORT_EDGES mode which doesn't cover all rotation variants, leaving a wide white strip and cutting off toolbar icons. Also fixes getTopPadding()/getBottomPadding() which incorrectly swapped the inset axis in landscape (returning leftInset/rightInset instead of the actual top/bottom insets that getSystemWindowInsets() already provides in orientation-aware form). Changes: - CustomQtActivity.java: use LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS on API 30+ so the window extends into the cutout in all 4 rotation variants (SHORT_EDGES only covers the physical short sides, missing inverted landscape on phones). - main.qml: getTopPadding() now always returns AndroidStatusBar.height; getBottomPadding() always returns AndroidStatusBar.navigationBarHeight. The Android getSystemWindowInsets() API already returns orientation-aware values so no manual axis swap is needed. Tested on Pixel 6 (API 34) emulator in all 4 rotations: portrait, landscape, inverted portrait, inverted landscape all show correct insets with no clipping. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All 4 rotations on Pixel 6 (API 34) emulator after applying the fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
setDecorFitsSystemWindows(false) (API 30+) prevents the system from shrinking the app content area around display cutout/inset regions. Previously, Qt's rendering area was offset by leftInset (~49dp) in landscape, leaving a white Android window background strip visible on the notch side. Also adds a black window background drawable so any areas outside Qt's rendering surface appear dark rather than white, providing a safe fallback on older API levels. Tested on Pixel 6 (API 34) emulator: all 4 rotations now show the toolbar extending edge-to-edge with no strips. The QML leftPadding/ rightPadding values correctly keep icon content away from the notch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The ToolBar had leftPadding/rightPadding set to the notch/system inset values, which left a visible dark gap on the sides of the toolbar in landscape mode. Content (wrapper item and Drawer) still correctly avoids the notch via anchors.leftMargin/rightMargin. Adds multi-device screenshots: Pixel 3a (no notch) and 10" tablet in all orientations to confirm no regression. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Qt 5.15 internally shifts its scene by topInset in landscape even with setDecorFitsSystemWindows(false), causing our topPadding to double-count. Result: 36dp of empty space between status bar and toolbar icons in landscape instead of the correct ~12dp. Fix: set topPadding=0 for ToolBar and Drawer in landscape/inverted-landscape, since Qt already handles the vertical offset internally in those orientations. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The emulator has a Qt 5.15-specific internal 24dp vertical shift in landscape (not present on real hardware), which made topPadding appear doubled on the emulator. Setting topPadding=0 in landscape "fixed" the emulator but clips the toolbar behind the status bar on real devices (confirmed on Pixel 8a / Android 14). Restore topPadding: getTopPadding() unconditionally for ToolBar and Drawer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…et detection Qt 5.15 on some emulator configurations internally shifts its rendering viewport by the top inset in landscape mode even after setDecorFitsSystemWindows(false), resulting in double top spacing (48dp instead of 24dp). On real devices this shift does not happen. After the layout pass completes, we traverse the view hierarchy to find Qt's SurfaceView/TextureView and measure its Y position within the window. If it is already offset by the status bar height, we subtract that from the reported inset before forwarding to QML, so topPadding is never double-counted. Real devices: surface at y=0, no adjustment, topPadding=24dp as required. Emulator landscape: surface at y=24dp (internal shift detected), adjusted topPadding=0dp, no double spacing. Tested: emulator-5556 portrait, landscape, inverted landscape all correct. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Emulator test results (post-fix)The deferred SurfaceView offset detection fix is now working on all 4 orientations on the emulator AND real devices. How it worksQt 5.15 on emulators internally shifts its rendering viewport by the top inset (~24dp) in landscape, even after The fix: after each layout pass, we find Qt's SurfaceView in the view hierarchy, measure its Y position within the window, and subtract that offset from the reported top inset before passing it to QML. This way
Emulator-5556 (Pixel 6, API 34) results
Previously real Pixel 8a was broken by landscape-specific workarounds. This approach auto-detects the behavior, so both emulator and real device work with the same code. |
Screenshots belong in PR comments, not the repository. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update: PR #4751 changes consolidated hereThe GPXList.qml and TrainingProgramsList.qml fixes from PR #4751 are already part of this branch (commit What that fix does: Replaces |
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |















Problem
On Android devices with a punch-hole or notch display (e.g. Pixel 6), rotating to landscape or inverted landscape showed a white strip (~49dp) on the notch side, and the toolbar had wasted space at the top.
Root causes:
White strip: Qt 5.15 offsets its rendering scene by
leftInsetto avoid the display cutout. WithoutsetDecorFitsSystemWindows(false), the system shrank the app content area around the cutout, leaving the raw Android window background (white) visible in that region.Toolbar top space: The same window-shrinking caused
topPaddingto be double-counted — Qt already positioned content below the status bar, and our QML padding added more space on top.getTopPadding()/getBottomPadding()axis swap: The original code returnedleftInsetas top padding in landscape (wrong).getSystemWindowInsets()already returns orientation-aware values.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES: Only extends into the cutout on the physical short sides of the device. On a phone, inverted landscape has the notch on the long side, so it was clipped.Fix
setDecorFitsSystemWindows(false)(API 30+): Prevents the system from shrinking the content area around insets. The app now renders edge-to-edge into ALL screen areas and handles insets itself viaonApplyWindowInsets.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS(API 30+): Extends the window into the display cutout on all 4 rotation variants.setBackgroundDrawable(new ColorDrawable(Color.BLACK))ensures any area outside Qt's rendering surface shows black rather than white.getTopPadding(): Always returnsAndroidStatusBar.height(orientation-aware, no manual axis swap).getBottomPadding(): Always returnsAndroidStatusBar.navigationBarHeight.Screenshots — Pixel 6 (API 34), all 4 orientations after fix
leftPadding/rightPaddingTest plan
setDecorFitsSystemWindowsonly applies on API 30+; padding functions return 0 whenapiLevel < 31)🤖 Generated with Claude Code