feat(qt): immersive root overlay, header band, entry/exit chrome (B2)

Root overlay self-gated on QbzImmersive.open with the load-bearing
click-blocker, 6s auto-hide with the VNC hover-storm delta guard,
fullscreen guard, exit paths 2-4, seek arrows, the header band (view
menu in Slint order, search field on the inert B1 surface, window
controls with the first FullScreen write in the Qt frontend), the
ViewModeMenu Immersive row live, Shift+I in Main.qml with the
text-input gate, QbzLineEdit fieldActive seam (D16). Panels are stubs;
B3/B4/B5 replace them. RFB evidence in scratchpad/immersive-b2/.

km
This commit is contained in:
vicrodh committed 2026-08-02 20:48:40 -06:00
1 parent 3c721a448e
commit 8bc255269d
7 files changed
+727 -10

No files matched your search

+13
View File
@@ -15,6 +15,7 @@
import QtQuick
import com.blitzfc.qbz
import "../controls"
import "../immersive"
import "../theme"
Rectangle {
@@ -615,6 +616,18 @@ Rectangle {
anchors.fill: parent
}
// Immersive mode root overlay (2026-08-02 immersive-port contract §5.1):
// plain Item, LAST-child class like its Slint twin (a Popup would grab
// the pointer and kill typing in the immersive search field — the
// cortinilla doctrine, Cortinilla.qml:1-5). Self-gates on
// QbzImmersive.open, so while closed it is an invisible, non-interactive
// Item. Sits AFTER QbzToast and BEFORE ArtPreviewOverlay/QbzTooltip so
// those two keep painting above it; covering the content pane's rounded
// corners is correct for a window-level overlay (:555-563 above).
ImmersiveView {
anchors.fill: parent
}
// LAST child = above every surface, exactly like ArtPreviewOverlay.slint's
// mount in AppShell.slint. Non-interactive, so it never steals the hover
// that is keeping it open (see the file header).
+26 -10
View File
@@ -1,8 +1,8 @@
// Now-Playing-view mode menu (PlayerBar.slint layout-menu, phase 18) —
// one QbzContextMenu shared by the full PlayerBar and the Small bar:
// New / Classic / Small / Large (with the current mode checked), then the
// inert window-mode rows (Miniplayer / Immersive / Kiosk — the Slint has
// them; the POC has no such surfaces, POC-NOTE).
// window-mode rows. Immersive is LIVE (2026-08-02 immersive-port §7, B2);
// Miniplayer / Kiosk stay inert (kiosk goes live in the kiosk contract §8).
import QtQuick
import QtQuick.Controls
@@ -81,8 +81,8 @@ QbzContextMenu {
}
}
// Divider + the window-mode rows (Miniplayer / Immersive / Kiosk —
// present in the Slint menu; inert in the POC (no such surfaces).
// Divider + the window-mode rows (Miniplayer / Immersive / Kiosk).
// Immersive is live (below); the other two stay inert.
Item {
width: parent ? parent.width : 0
height: 7
@@ -95,18 +95,24 @@ QbzContextMenu {
}
}
Repeater {
// Window-mode rows. `live` flips per-row inside the shared delegate
// (2026-08-02 immersive-port §7): only the Immersive row is wired in
// B2 — it loses the 0.45 dim and gains the openFromMenu click.
// Miniplayer + Kiosk stay inert (kiosk goes live in the
// 2026-08-02-kiosk-port contract §8 — do not touch it).
model: [
{ "label": QbzSession.tr("Miniplayer", QbzSession.trRev), "icon": "picture-in-picture-2" },
{ "label": QbzSession.tr("Immersive", QbzSession.trRev), "icon": "maximize-2" },
{ "label": QbzSession.tr("Kiosk mode", QbzSession.trRev), "icon": "hard-drive" },
{ "label": QbzSession.tr("Miniplayer", QbzSession.trRev), "icon": "picture-in-picture-2", "live": false },
{ "label": QbzSession.tr("Immersive", QbzSession.trRev), "icon": "maximize-2", "live": true },
{ "label": QbzSession.tr("Kiosk mode", QbzSession.trRev), "icon": "hard-drive", "live": false },
]
delegate: Rectangle {
required property var modelData
width: parent ? parent.width : 0
height: 33
radius: 5
opacity: 0.45
color: "transparent"
opacity: modelData.live ? 1.0 : 0.45
color: (modelData.live && modeArea.containsMouse)
? theme.surfaceHover : "transparent"
Row {
anchors.fill: parent
anchors.leftMargin: 8
@@ -120,7 +126,17 @@ QbzContextMenu {
verticalAlignment: Text.AlignVCenter
}
}
// Inert (POC-NOTE): no miniplayer/immersive/kiosk surfaces.
MouseArea {
id: modeArea
anchors.fill: parent
enabled: modelData.live
hoverEnabled: true
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
root.close()
QbzImmersive.openFromMenu()
}
}
}
}
}