Android 15 (API 35) / Qt 6.9.1: SafeArea=0 at startup in plain Window; content under notch/nav until TextField focus
-
Problem
I want a simple Qt Quick app that does NOT draw under the notch / status bar / nav bar. I’m not going for immersive; I’m not setting
Qt.ExpandedClientAreaHint
. I bind my layout margins toSafeArea.margins.*
(similar to the Qt 6.9 blog post “Expanded Client Areas & Safe Areas” by Tor Arne Vestbø).Issue: On Android (targetSdk 35), at cold start my content still shows under the system bars. Debug logs show
SafeArea.margins = 0
. As soon as I tap a TextField (IME shows), SafeArea updates to non-zero and the layout snaps to the correct padded position.So it seems
SafeArea
isn’t initialized with valid insets until the first insets/resize event.Minimal-ish Repro (closer to my real app)
import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtCore Window { id: root visible: true width: 360 height: 640 title: "Demo" // design padding in addition to SafeArea property int designPadding: 12 // SafeArea bindings property real safeTop: SafeArea.margins.top property real safeBottom: SafeArea.margins.bottom property real safeLeft: SafeArea.margins.left property real safeRight: SafeArea.margins.right // Debug: watch SafeArea Timer { interval: 500; running: true; repeat: true onTriggered: console.log("[safe]", root.safeTop, root.safeBottom, root.safeLeft, root.safeRight) } // Pretend persistent settings (trimmed) Settings { id: saved property string host: "" property string port: "" } // Layout that should be padded out of unsafe areas ColumnLayout { anchors.fill: parent anchors.topMargin: root.designPadding + root.safeTop anchors.bottomMargin: root.designPadding + root.safeBottom anchors.leftMargin: root.designPadding + root.safeLeft anchors.rightMargin: root.designPadding + root.safeRight spacing: 10 Label { text: "App" font.pixelSize: 24 Layout.alignment: Qt.AlignHCenter } TextField { id: hostInput Layout.fillWidth: true placeholderText: "Host" text: saved.host } TextField { id: portInput Layout.fillWidth: true placeholderText: "Port" text: saved.port.length ? saved.port : "5300" } Item { Layout.fillHeight: true } Button { text: "Connect" Layout.fillWidth: true } } }
Observed logs:
• Before tapping input: all SafeArea margins 0; content under status bar.
• After tapping input (IME): SafeArea margins become non-zero; layout correct.⸻
Extra: I tried forcing a 1-px geometry “nudge” after visible (resize there & back) to provoke inset delivery; did not help reliably.
Is this expected behavior for SafeArea on Android with a plain Window?
Should I be waiting for a specific signal, or just switch to ApplicationWindow for early safe-area padding?
If this looks like a bug/regression, happy to file a Qt bug report — let me know what data would help.Thanks!
-
Problem
I want a simple Qt Quick app that does NOT draw under the notch / status bar / nav bar. I’m not going for immersive; I’m not setting
Qt.ExpandedClientAreaHint
. I bind my layout margins toSafeArea.margins.*
(similar to the Qt 6.9 blog post “Expanded Client Areas & Safe Areas” by Tor Arne Vestbø).Issue: On Android (targetSdk 35), at cold start my content still shows under the system bars. Debug logs show
SafeArea.margins = 0
. As soon as I tap a TextField (IME shows), SafeArea updates to non-zero and the layout snaps to the correct padded position.So it seems
SafeArea
isn’t initialized with valid insets until the first insets/resize event.Minimal-ish Repro (closer to my real app)
import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtCore Window { id: root visible: true width: 360 height: 640 title: "Demo" // design padding in addition to SafeArea property int designPadding: 12 // SafeArea bindings property real safeTop: SafeArea.margins.top property real safeBottom: SafeArea.margins.bottom property real safeLeft: SafeArea.margins.left property real safeRight: SafeArea.margins.right // Debug: watch SafeArea Timer { interval: 500; running: true; repeat: true onTriggered: console.log("[safe]", root.safeTop, root.safeBottom, root.safeLeft, root.safeRight) } // Pretend persistent settings (trimmed) Settings { id: saved property string host: "" property string port: "" } // Layout that should be padded out of unsafe areas ColumnLayout { anchors.fill: parent anchors.topMargin: root.designPadding + root.safeTop anchors.bottomMargin: root.designPadding + root.safeBottom anchors.leftMargin: root.designPadding + root.safeLeft anchors.rightMargin: root.designPadding + root.safeRight spacing: 10 Label { text: "App" font.pixelSize: 24 Layout.alignment: Qt.AlignHCenter } TextField { id: hostInput Layout.fillWidth: true placeholderText: "Host" text: saved.host } TextField { id: portInput Layout.fillWidth: true placeholderText: "Port" text: saved.port.length ? saved.port : "5300" } Item { Layout.fillHeight: true } Button { text: "Connect" Layout.fillWidth: true } } }
Observed logs:
• Before tapping input: all SafeArea margins 0; content under status bar.
• After tapping input (IME): SafeArea margins become non-zero; layout correct.⸻
Extra: I tried forcing a 1-px geometry “nudge” after visible (resize there & back) to provoke inset delivery; did not help reliably.
Is this expected behavior for SafeArea on Android with a plain Window?
Should I be waiting for a specific signal, or just switch to ApplicationWindow for early safe-area padding?
If this looks like a bug/regression, happy to file a Qt bug report — let me know what data would help.Thanks!
@Pann this is a known bug for 6.9.1 see my bugreport https://bugreports.qt.io/browse/QTBUG-135808
here's my ugly workaround:ApplicationWindow { ... contentOrientation: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation .. Component.onCompleted: { console.log("Orientation: ",contentOrientation) }
now there's a short flicker, but SafeArea gets the values
should be fixed for 6.9.2 and probably 6.10.0 Beta2 -
@Pann this is a known bug for 6.9.1 see my bugreport https://bugreports.qt.io/browse/QTBUG-135808
here's my ugly workaround:ApplicationWindow { ... contentOrientation: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation .. Component.onCompleted: { console.log("Orientation: ",contentOrientation) }
now there's a short flicker, but SafeArea gets the values
should be fixed for 6.9.2 and probably 6.10.0 Beta2@ekkescorner said in Android 15 (API 35) / Qt 6.9.1: SafeArea=0 at startup in plain Window; content under notch/nav until TextField focus:
@Pann this is a known bug for 6.9.1 see my bugreport https://bugreports.qt.io/browse/QTBUG-135808
here's my ugly workaround:ApplicationWindow { ... contentOrientation: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation .. Component.onCompleted: { console.log("Orientation: ",contentOrientation) }
now there's a short flicker, but SafeArea gets the values
should be fixed for 6.9.2 and probably 6.10.0 Beta2Thanks, @ekkescorner
Unfortunately for me is not working, hope 6.9.2 will be released soon.
Thanks! -
@ekkescorner said in Android 15 (API 35) / Qt 6.9.1: SafeArea=0 at startup in plain Window; content under notch/nav until TextField focus:
@Pann this is a known bug for 6.9.1 see my bugreport https://bugreports.qt.io/browse/QTBUG-135808
here's my ugly workaround:ApplicationWindow { ... contentOrientation: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation .. Component.onCompleted: { console.log("Orientation: ",contentOrientation) }
now there's a short flicker, but SafeArea gets the values
should be fixed for 6.9.2 and probably 6.10.0 Beta2Thanks, @ekkescorner
Unfortunately for me is not working, hope 6.9.2 will be released soon.
Thanks!@Pann sorry I forgot these lines
in ApplicationWindow:flags: Qt.platform.os === "android"? Qt.Window : Qt.ExpandedClientAreaHint | Qt.NoTitleBarBackgroundHint
and Component.onCompleted:
if(Qt.platform.os === "android") { window.flags = Qt.ExpandedClientAreaHint | Qt.NoTitleBarBackgroundHint window.visibility = Window.Windowed }