Watch
1
0
Fork
You've already forked souveraine
0

multitasking draws under a dwelling thumb

The overview loader was only active once missionControlOpen was already
true, so nothing existed during the pull and ZoneOverview.progress
following the rail was dead mid-drag. The cards appeared at release and
animated on their own clock — two motions, which is the seam TASK-60's
acceptance names.

missionPeek gates presentation only: visibility, mask, which body the
loader builds. Focus, dismissal and every commit path still read
missionControlOpen, so a preview draws and decides nothing. Masked to a
zero-size item while peeking so the in-flight gesture stays the rail's.

Dwell rather than any pull, so a flick to home never flashes the blur,
and it drops above the multitasking detent so the preview never shows a
destination the release would not commit.
This commit is contained in:
Fimeg 2026-08-07 08:42:00 -04:00
commit f699f57235
3 changed files with 42 additions and 6 deletions

View file

@ -181,6 +181,15 @@ Singleton {
// the edge where it started.
property real zonePullProgress: 0
// WRITER: navigation rail, while a pull dwells past the multitasking
// detent. The cards are DRAWN, nothing is committed release still decides.
// Gates presentation only (visibility, mask, which body the loader builds);
// never focus, dismissal or state, or a preview would be a decision.
//
// Dwell rather than any pull, so a fast flick to Home never flashes the
// blur on its way past.
property bool missionPeek: false
// WRITER: Dock.qml IPC (swipeDown). A rail swipe-down on a visible
// dock dismisses it in ANY state including pinned and
// shown-on-empty-desktop. Swipe up clears it.

View file

@ -49,6 +49,12 @@ Scope {
// about, and re-opening the drawer while already registered would re-add.
property bool panelDismissableRegistered: false
// Mission control is on the glass committed, or previewed under a dwelling
// thumb. Presentation gates read this; focus, dismissal and every commit
// path keep reading `missionControlOpen`, so a peek draws and decides
// nothing.
readonly property bool missionShown: GlobalStates.missionControlOpen || GlobalStates.missionPeek
PanelWindow {
id: panelWindow
property string searchingText: ""
@ -62,7 +68,7 @@ Scope {
//
// Mission control is the cards alone: no search, because it is a
// "switch to what is running" gesture, not a "find something" one.
visible: GlobalStates.overviewOpen || GlobalStates.missionControlOpen
visible: GlobalStates.overviewOpen || overviewScope.missionShown
WlrLayershell.namespace: "quickshell:overview"
// Overlay, not Top: the second-stage edge swipe must bring the
@ -84,7 +90,18 @@ Scope {
// Mission control covers the whole glass (the blurred home
// backdrop), so there it is the whole window or the cards take no
// taps at all.
item: GlobalStates.missionControlOpen ? missionBackdrop : panelBg
// A peek maps this surface while the thumb is still down on the
// rail. Masking to a zero-size item makes it take no input at all,
// so the in-flight gesture stays the rail's and cannot be stolen by
// a full-glass region appearing mid-drag.
item: GlobalStates.missionControlOpen ? missionBackdrop
: GlobalStates.missionPeek ? noInput : panelBg
}
Item {
id: noInput
width: 0
height: 0
}
anchors {
@ -226,7 +243,7 @@ Scope {
// The sheet under it is the known-good look if the effect no-ops.
Item {
id: missionBackdrop
visible: GlobalStates.missionControlOpen
visible: overviewScope.missionShown
anchors.fill: parent
z: -1
@ -270,7 +287,7 @@ Scope {
Rectangle {
id: panelBg
visible: columnLayout.visible && !GlobalStates.missionControlOpen
visible: columnLayout.visible && !overviewScope.missionShown
anchors.fill: columnLayout
// The sheet breathes past the column so the drawer reads as a
// panel, not as widgets floating on the wallpaper. The mask
@ -324,7 +341,7 @@ Scope {
Loader {
id: overviewLoader
anchors.horizontalCenter: parent.horizontalCenter
active: (GlobalStates.overviewOpen || GlobalStates.missionControlOpen)
active: (GlobalStates.overviewOpen || overviewScope.missionShown)
&& (Config?.options.overview.enable ?? true)
// Two ways in, two bodies TASK-14's split. The overview
// (Home) is the app drawer: search above (this file's
@ -334,7 +351,7 @@ Scope {
// keyboard (see `keyboardFocus` above). Previously this one
// body rendered the running cards for BOTH flags, which left
// Home showing what is running instead of what can run.
sourceComponent: GlobalStates.missionControlOpen
sourceComponent: overviewScope.missionShown
? windowOverviewComponent : appGridComponent
}

View file

@ -152,6 +152,16 @@ Item {
ViewtopControl.refreshWindows();
}
// A peek draws these cards without ever setting `open`, so it owes the same
// ask otherwise the preview is the 2 s poll's idea of what is running.
Connections {
target: GlobalStates
function onMissionPeekChanged() {
if (GlobalStates.missionPeek)
ViewtopControl.refreshWindows();
}
}
implicitWidth: parent ? parent.width : 540
implicitHeight: parent ? parent.height : 800