1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-15 15:45:20 -04:00

refactor: implement keyboard focus management

This commit is contained in:
purian23
2026-06-10 18:52:45 -04:00
parent 283a256898
commit 9d046847fa
22 changed files with 191 additions and 237 deletions
+44
View File
@@ -0,0 +1,44 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Services
// Manages keyboard focus policy for popouts, modals, and Hyprland focus grabs
Singleton {
id: root
function keyboardFocus(active, customFocus) {
if (PopoutManager.screenshotActive)
return WlrKeyboardFocus.None;
if (customFocus !== null && customFocus !== undefined)
return customFocus;
if (!active)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
function wantsGrab(active, customFocus) {
return CompositorService.useHyprlandFocusGrab && keyboardFocus(active, customFocus) === WlrKeyboardFocus.OnDemand;
}
property list<var> barWindows: []
function registerBarWindow(window) {
if (!window || barWindows.indexOf(window) !== -1)
return;
barWindows = barWindows.concat([window]);
}
function unregisterBarWindow(window) {
const idx = barWindows.indexOf(window);
if (idx === -1)
return;
const next = barWindows.slice();
next.splice(idx, 1);
barWindows = next;
}
}
@@ -1,5 +1,4 @@
import QtQuick
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -11,11 +10,6 @@ DankModal {
layerNamespace: "dms:bluetooth-pairing"
HyprlandFocusGrab {
windows: [root.contentWindow]
active: root.useHyprlandFocusGrab && root.shouldHaveFocus
}
property string deviceName: ""
property string deviceAddress: ""
property string requestType: ""
@@ -1,7 +1,6 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Clipboard
import qs.Modals.Common
@@ -12,11 +11,6 @@ DankModal {
layerNamespace: "dms:clipboard"
HyprlandFocusGrab {
windows: [clipboardHistoryModal.contentWindow]
active: clipboardHistoryModal.useHyprlandFocusGrab && clipboardHistoryModal.shouldHaveFocus
}
function toggle() {
if (shouldBeVisible) {
hide();
+17
View File
@@ -1,4 +1,5 @@
import QtQuick
import Quickshell.Hyprland
import qs.Common
import qs.Services
@@ -52,6 +53,22 @@ Item {
focus: true
anchors.fill: parent
}
// One focus grab for every modal; on Hyprland this is what delivers
// keyboard focus to the OnDemand surface, identically in both modes.
// The clickCatcher is whitelisted so an outside click is delivered to
// it (closing the modal) instead of being consumed clearing the grab.
HyprlandFocusGrab {
windows: {
const list = [];
if (root.contentWindow)
list.push(root.contentWindow);
if (root.clickCatcher)
list.push(root.clickCatcher);
return list;
}
active: KeyboardFocus.wantsGrab(root.shouldHaveFocus, root.customKeyboardFocus)
}
readonly property var contentWindow: impl.item ? impl.item.contentWindow : null
readonly property var clickCatcher: impl.item ? impl.item.clickCatcher : null
readonly property var effectiveScreen: impl.item ? impl.item.effectiveScreen : null
@@ -509,15 +509,7 @@ Item {
"error": true
})
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (customKeyboardFocus !== null)
return customKeyboardFocus;
if (!shouldHaveFocus)
return WlrKeyboardFocus.None;
if (root.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(shouldHaveFocus, customKeyboardFocus)
anchors {
left: true
@@ -259,15 +259,7 @@ Item {
"error": true
})
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (customKeyboardFocus !== null)
return customKeyboardFocus;
if (!shouldHaveFocus)
return WlrKeyboardFocus.None;
if (root.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(shouldHaveFocus, customKeyboardFocus)
anchors {
left: true
@@ -1,6 +1,5 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
@@ -13,11 +12,6 @@ DankModal {
layerNamespace: "dms:color-picker"
HyprlandFocusGrab {
windows: [root.contentWindow]
active: root.useHyprlandFocusGrab && root.shouldHaveFocus
}
property string pickerTitle: I18n.tr("Choose Color")
property color selectedColor: SessionData.recentColors.length > 0 ? SessionData.recentColors[0] : Theme.primary
property var onColorSelectedCallback: null
@@ -441,8 +441,6 @@ Item {
spotlightOpen = true;
backgroundWindow.visible = true;
contentWindow.visible = true;
if (useHyprlandFocusGrab)
focusGrab.active = true;
// Load content and initialize (but no forceActiveFocus — that's deferred)
_ensureContentLoadedAndInitialize(query || "", mode || "");
@@ -485,7 +483,6 @@ Item {
keyboardActive = false;
spotlightOpen = false;
focusGrab.active = false;
ModalManager.closeModal(modalHandle);
closeCleanupTimer.start();
}
@@ -541,7 +538,7 @@ Item {
HyprlandFocusGrab {
id: focusGrab
windows: [contentWindow]
active: false
active: root.useHyprlandFocusGrab && root.spotlightOpen
onCleared: {
if (spotlightOpen) {
@@ -685,7 +682,7 @@ Item {
WlrLayershell.namespace: "dms:spotlight"
WlrLayershell.layer: root.effectiveLauncherLayer
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: PopoutManager.screenshotActive ? WlrKeyboardFocus.None : (keyboardActive ? (root.useHyprlandFocusGrab ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive) : WlrKeyboardFocus.None)
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(keyboardActive, null)
anchors {
left: true
@@ -164,8 +164,6 @@ Item {
openedFromOverview = false;
keyboardActive = true;
ModalManager.openModal(modalHandle);
if (useHyprlandFocusGrab)
focusGrab.active = true;
_ensureContentLoadedAndInitialize(query || "", mode || "");
}
@@ -201,7 +199,6 @@ Item {
contentVisible = false;
keyboardActive = false;
spotlightOpen = false;
focusGrab.active = false;
ModalManager.closeModal(modalHandle);
closeCleanupTimer.start();
}
@@ -231,7 +228,7 @@ Item {
HyprlandFocusGrab {
id: focusGrab
windows: [launcherWindow]
active: false
active: root.useHyprlandFocusGrab && root.keyboardActive
onCleared: {
if (spotlightOpen)
hide();
@@ -337,7 +334,7 @@ Item {
WlrLayershell.namespace: "dms:spotlight"
WlrLayershell.layer: root.effectiveLauncherLayer
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: PopoutManager.screenshotActive ? WlrKeyboardFocus.None : (keyboardActive ? (root.useHyprlandFocusGrab ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive) : WlrKeyboardFocus.None)
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(keyboardActive, null)
anchors {
top: true
@@ -172,8 +172,6 @@ Item {
keyboardActive = true;
ModalManager.openModal(modalHandle);
if (useHyprlandFocusGrab)
focusGrab.active = true;
_ensureContentLoadedAndInitialize(query || "", mode || "");
}
@@ -211,7 +209,6 @@ Item {
keyboardActive = false;
spotlightOpen = false;
focusGrab.active = false;
ModalManager.closeModal(modalHandle);
closeCleanupTimer.start();
@@ -262,7 +259,7 @@ Item {
HyprlandFocusGrab {
id: focusGrab
windows: [launcherWindow]
active: false
active: root.useHyprlandFocusGrab && root.keyboardActive
onCleared: {
if (spotlightOpen) {
@@ -373,7 +370,7 @@ Item {
WlrLayershell.namespace: "dms:spotlight"
WlrLayershell.layer: root.effectiveLauncherLayer
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: PopoutManager.screenshotActive ? WlrKeyboardFocus.None : (keyboardActive ? (root.useHyprlandFocusGrab ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive) : WlrKeyboardFocus.None)
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(keyboardActive, null)
anchors {
top: true
-6
View File
@@ -1,7 +1,6 @@
import QtQml
import QtQuick
import QtQuick.Layouts
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -29,11 +28,6 @@ DankModal {
KeybindsService.loadCheatsheet();
}
HyprlandFocusGrab {
windows: [root.contentWindow]
active: root.useHyprlandFocusGrab && root.shouldHaveFocus
}
function scrollDown() {
if (!root.activeFlickable)
return;
-7
View File
@@ -3,7 +3,6 @@ pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Hyprland
import Quickshell.Io
import Quickshell
import qs.Common
@@ -45,12 +44,6 @@ DankModal {
}
}
HyprlandFocusGrab {
id: grab
windows: [muxModal.contentWindow]
active: CompositorService.isHyprland && muxModal.shouldHaveFocus
}
function toggle() {
if (shouldBeVisible) {
hide();
-6
View File
@@ -1,5 +1,4 @@
import QtQuick
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
@@ -11,11 +10,6 @@ DankModal {
layerNamespace: "dms:notification-center-modal"
HyprlandFocusGrab {
windows: [notificationModal.contentWindow]
active: notificationModal.useHyprlandFocusGrab && notificationModal.shouldHaveFocus
}
property bool notificationModalOpen: false
property var notificationListRef: null
property var historyListRef: null
-6
View File
@@ -1,7 +1,6 @@
import QtQuick
import QtQuick.Effects
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -13,11 +12,6 @@ DankModal {
layerNamespace: "dms:power-menu"
keepPopoutsOpen: true
HyprlandFocusGrab {
windows: [root.contentWindow]
active: root.useHyprlandFocusGrab && root.shouldHaveFocus
}
property int selectedIndex: 0
property int selectedRow: 0
property int selectedCol: 0
@@ -109,15 +109,7 @@ DankPopout {
close();
}
customKeyboardFocus: {
if (!shouldBeVisible)
return WlrKeyboardFocus.None;
if (anyModalOpen)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
customKeyboardFocus: anyModalOpen ? WlrKeyboardFocus.None : null
onBackgroundClicked: close()
+9 -1
View File
@@ -9,6 +9,8 @@ PanelWindow {
id: barWindow
readonly property var log: Log.scoped("DankBarWindow")
Component.onDestruction: KeyboardFocus.unregisterBarWindow(barWindow)
required property var rootWindow
required property var barConfig
property var modelData: item
@@ -555,6 +557,7 @@ PanelWindow {
color: "transparent"
Component.onCompleted: {
KeyboardFocus.registerBarWindow(barWindow);
updateGpuTempConfig();
_updateBackgroundAlpha();
_updateHasMaximizedToplevel();
@@ -956,8 +959,13 @@ PanelWindow {
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: {
const screenName = barWindow.screen?.name;
if (screenName && PopoutManager.currentPopoutsByScreen[screenName])
if (!screenName)
return;
if (PopoutManager.currentPopoutsByScreen[screenName])
PopoutManager.closeAllPopouts();
if (ModalManager.currentModalsByScreen[screenName])
ModalManager.closeAllModalsExcept(null);
TrayMenuManager.closeAllMenus();
}
}
@@ -38,15 +38,7 @@ DankPopout {
backgroundInteractive: !anyModalOpen
customKeyboardFocus: {
if (!shouldBeVisible)
return WlrKeyboardFocus.None;
if (anyModalOpen)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
customKeyboardFocus: anyModalOpen ? WlrKeyboardFocus.None : null
Connections {
target: SystemUpdateService
@@ -980,21 +980,13 @@ BasePill {
screen: root.parentScreen
WlrLayershell.layer: root.barUsesOverlayLayer ? WlrLayershell.Overlay : WlrLayershell.Top
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (PopoutManager.screenshotActive)
return WlrKeyboardFocus.None;
if (!root.menuOpen)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(root.menuOpen, null)
WlrLayershell.namespace: "dms:tray-overflow-menu"
color: "transparent"
HyprlandFocusGrab {
windows: [overflowMenu]
active: CompositorService.useHyprlandFocusGrab && root.useOverflowPopup && root.menuOpen
windows: [overflowMenu].concat(KeyboardFocus.barWindows)
active: root.useOverflowPopup && KeyboardFocus.wantsGrab(root.menuOpen, null)
}
Connections {
@@ -1051,32 +1043,21 @@ BasePill {
"leftBar": 0,
"rightBar": 0
})
readonly property real effectiveBarSize: root.barThickness + root.barSpacing
readonly property real maskX: _overflowDismissZone.x
readonly property real maskY: _overflowDismissZone.y
readonly property real maskWidth: _overflowDismissZone.width
readonly property real maskHeight: _overflowDismissZone.height
readonly property real maskX: {
const triggeringBarX = (barPosition === 2) ? effectiveBarSize : 0;
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
return Math.max(triggeringBarX, adjacentLeftBar);
}
readonly property real maskY: {
const triggeringBarY = (barPosition === 0) ? effectiveBarSize : 0;
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
return Math.max(triggeringBarY, adjacentTopBar);
}
readonly property real maskWidth: {
const triggeringBarRight = (barPosition === 3) ? effectiveBarSize : 0;
const adjacentRightBar = adjacentBarInfo?.rightBar ?? 0;
const rightExclusion = Math.max(triggeringBarRight, adjacentRightBar);
return Math.max(100, width - maskX - rightExclusion);
}
readonly property real maskHeight: {
const triggeringBarBottom = (barPosition === 1) ? effectiveBarSize : 0;
const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 0;
const bottomExclusion = Math.max(triggeringBarBottom, adjacentBottomBar);
return Math.max(100, height - maskY - bottomExclusion);
DismissZone {
id: _overflowDismissZone
barPosition: overflowMenu.barPosition
barX: overflowMenu.barX
barY: overflowMenu.barY
barWidth: overflowMenu.barWidth
barHeight: overflowMenu.barHeight
screenWidth: overflowMenu.width
screenHeight: overflowMenu.height
adjacentBarInfo: overflowMenu.adjacentBarInfo
}
mask: Region {
@@ -1444,20 +1425,12 @@ BasePill {
screen: menuRoot.parentScreen
WlrLayershell.layer: root.barUsesOverlayLayer ? WlrLayershell.Overlay : WlrLayershell.Top
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (PopoutManager.screenshotActive)
return WlrKeyboardFocus.None;
if (!menuRoot.showMenu)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(menuRoot.showMenu, null)
color: "transparent"
HyprlandFocusGrab {
windows: [menuWindow]
active: CompositorService.useHyprlandFocusGrab && menuRoot.showMenu
windows: [menuWindow].concat(KeyboardFocus.barWindows)
active: KeyboardFocus.wantsGrab(menuRoot.showMenu, null)
}
anchors {
@@ -1496,32 +1469,21 @@ BasePill {
"leftBar": 0,
"rightBar": 0
})
readonly property real effectiveBarSize: root.barThickness + root.barSpacing
readonly property real maskX: _menuDismissZone.x
readonly property real maskY: _menuDismissZone.y
readonly property real maskWidth: _menuDismissZone.width
readonly property real maskHeight: _menuDismissZone.height
readonly property real maskX: {
const triggeringBarX = (barPosition === 2) ? effectiveBarSize : 0;
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
return Math.max(triggeringBarX, adjacentLeftBar);
}
readonly property real maskY: {
const triggeringBarY = (barPosition === 0) ? effectiveBarSize : 0;
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
return Math.max(triggeringBarY, adjacentTopBar);
}
readonly property real maskWidth: {
const triggeringBarRight = (barPosition === 3) ? effectiveBarSize : 0;
const adjacentRightBar = adjacentBarInfo?.rightBar ?? 0;
const rightExclusion = Math.max(triggeringBarRight, adjacentRightBar);
return Math.max(100, width - maskX - rightExclusion);
}
readonly property real maskHeight: {
const triggeringBarBottom = (barPosition === 1) ? effectiveBarSize : 0;
const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 0;
const bottomExclusion = Math.max(triggeringBarBottom, adjacentBottomBar);
return Math.max(100, height - maskY - bottomExclusion);
DismissZone {
id: _menuDismissZone
barPosition: menuWindow.barPosition
barX: menuWindow.barX
barY: menuWindow.barY
barWidth: menuWindow.barWidth
barHeight: menuWindow.barHeight
screenWidth: menuWindow.width
screenHeight: menuWindow.height
adjacentBarInfo: menuWindow.adjacentBarInfo
}
mask: Region {
+19
View File
@@ -1,4 +1,5 @@
import QtQuick
import Quickshell.Hyprland
import qs.Common
import qs.Services
@@ -50,6 +51,24 @@ Item {
readonly property var contentLoader: impl.item ? impl.item.contentLoader : _fallbackContentLoader
readonly property var overlayLoader: impl.item ? impl.item.overlayLoader : _fallbackOverlayLoader
readonly property var backgroundWindow: impl.item ? impl.item.backgroundWindow : null
readonly property var contentWindow: impl.item ? impl.item.contentWindow : null
// On Hyprland the OnDemand content surface only receives keyboard focus
// through a grab; everywhere else Exclusive focus covers this. Both
// popout windows plus every bar are whitelisted so clicks on them are
// delivered normally (dismiss MouseAreas, widget-to-widget transfer)
// instead of being consumed clearing the grab.
HyprlandFocusGrab {
windows: {
const list = [];
if (root.contentWindow)
list.push(root.contentWindow);
if (root.backgroundWindow && root.backgroundWindow !== root.contentWindow)
list.push(root.backgroundWindow);
return list.concat(KeyboardFocus.barWindows);
}
active: KeyboardFocus.wantsGrab(root.shouldBeVisible, root.customKeyboardFocus)
}
Loader {
id: _fallbackContentLoader
+16 -35
View File
@@ -17,6 +17,7 @@ Item {
property Component overlayContent: null
property alias overlayLoader: overlayLoader
readonly property alias backgroundWindow: contentWindow
readonly property alias contentWindow: contentWindow
property real popupWidth: 400
property real popupHeight: 300
property real triggerX: 0
@@ -758,31 +759,21 @@ Item {
}
})(), dpr)
readonly property real triggeringBarLeftExclusion: (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? Math.max(0, barX + barWidth) : 0
readonly property real triggeringBarTopExclusion: (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? Math.max(0, barY + barHeight) : 0
readonly property real triggeringBarRightExclusion: (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? Math.max(0, screenWidth - barX) : 0
readonly property real triggeringBarBottomExclusion: (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? Math.max(0, screenHeight - barY) : 0
readonly property real maskX: _dismissZone.x
readonly property real maskY: _dismissZone.y
readonly property real maskWidth: _dismissZone.width
readonly property real maskHeight: _dismissZone.height
readonly property real maskX: {
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
return Math.max(triggeringBarLeftExclusion, adjacentLeftBar);
}
readonly property real maskY: {
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
return Math.max(triggeringBarTopExclusion, adjacentTopBar);
}
readonly property real maskWidth: {
const adjacentRightBar = adjacentBarInfo?.rightBar ?? 0;
const rightExclusion = Math.max(triggeringBarRightExclusion, adjacentRightBar);
return Math.max(100, screenWidth - maskX - rightExclusion);
}
readonly property real maskHeight: {
const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 0;
const bottomExclusion = Math.max(triggeringBarBottomExclusion, adjacentBottomBar);
return Math.max(100, screenHeight - maskY - bottomExclusion);
DismissZone {
id: _dismissZone
barPosition: root.effectiveBarPosition
barX: root.barX
barY: root.barY
barWidth: root.barWidth
barHeight: root.barHeight
screenWidth: root.screenWidth
screenHeight: root.screenHeight
adjacentBarInfo: root.adjacentBarInfo
}
PanelWindow {
@@ -814,17 +805,7 @@ Item {
WlrLayershell.namespace: root.layerNamespace
WlrLayershell.layer: root.effectivePopoutLayer
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (PopoutManager.screenshotActive)
return WlrKeyboardFocus.None;
if (customKeyboardFocus !== null)
return customKeyboardFocus;
if (!shouldBeVisible)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(shouldBeVisible, customKeyboardFocus)
readonly property bool _fullHeight: root.fullHeightSurface
anchors {
+16 -35
View File
@@ -18,6 +18,7 @@ Item {
property Component overlayContent: null
property alias overlayLoader: overlayLoader
readonly property alias backgroundWindow: backgroundWindow
readonly property alias contentWindow: contentWindow
property real popupWidth: 400
property real popupHeight: 300
property real triggerX: 0
@@ -494,31 +495,21 @@ Item {
}
})(), dpr)
readonly property real triggeringBarLeftExclusion: (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? Math.max(0, barX + barWidth) : 0
readonly property real triggeringBarTopExclusion: (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? Math.max(0, barY + barHeight) : 0
readonly property real triggeringBarRightExclusion: (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? Math.max(0, screenWidth - barX) : 0
readonly property real triggeringBarBottomExclusion: (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? Math.max(0, screenHeight - barY) : 0
readonly property real maskX: _dismissZone.x
readonly property real maskY: _dismissZone.y
readonly property real maskWidth: _dismissZone.width
readonly property real maskHeight: _dismissZone.height
readonly property real maskX: {
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
return Math.max(triggeringBarLeftExclusion, adjacentLeftBar);
}
readonly property real maskY: {
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
return Math.max(triggeringBarTopExclusion, adjacentTopBar);
}
readonly property real maskWidth: {
const adjacentRightBar = adjacentBarInfo?.rightBar ?? 0;
const rightExclusion = Math.max(triggeringBarRightExclusion, adjacentRightBar);
return Math.max(100, screenWidth - maskX - rightExclusion);
}
readonly property real maskHeight: {
const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 0;
const bottomExclusion = Math.max(triggeringBarBottomExclusion, adjacentBottomBar);
return Math.max(100, screenHeight - maskY - bottomExclusion);
DismissZone {
id: _dismissZone
barPosition: root.effectiveBarPosition
barX: root.barX
barY: root.barY
barWidth: root.barWidth
barHeight: root.barHeight
screenWidth: root.screenWidth
screenHeight: root.screenHeight
adjacentBarInfo: root.adjacentBarInfo
}
PanelWindow {
@@ -612,17 +603,7 @@ Item {
WlrLayershell.namespace: root.layerNamespace
WlrLayershell.layer: root.effectivePopoutLayer
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (PopoutManager.screenshotActive)
return WlrKeyboardFocus.None;
if (customKeyboardFocus !== null)
return customKeyboardFocus;
if (!shouldBeVisible)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(shouldBeVisible, customKeyboardFocus)
anchors {
left: true
+26
View File
@@ -0,0 +1,26 @@
import QtQuick
import qs.Common
// Defines the screen area (excluding bars) that dismisses popouts
QtObject {
id: root
property int barPosition: 0
property real barX: 0
property real barY: 0
property real barWidth: 0
property real barHeight: 0
property real screenWidth: 0
property real screenHeight: 0
property var adjacentBarInfo: null
readonly property real _leftExclusion: (barPosition === SettingsData.Position.Left && barWidth > 0) ? Math.max(0, barX + barWidth) : 0
readonly property real _topExclusion: (barPosition === SettingsData.Position.Top && barHeight > 0) ? Math.max(0, barY + barHeight) : 0
readonly property real _rightExclusion: (barPosition === SettingsData.Position.Right && barWidth > 0) ? Math.max(0, screenWidth - barX) : 0
readonly property real _bottomExclusion: (barPosition === SettingsData.Position.Bottom && barHeight > 0) ? Math.max(0, screenHeight - barY) : 0
readonly property real x: Math.max(_leftExclusion, adjacentBarInfo?.leftBar ?? 0)
readonly property real y: Math.max(_topExclusion, adjacentBarInfo?.topBar ?? 0)
readonly property real width: Math.max(100, screenWidth - x - Math.max(_rightExclusion, adjacentBarInfo?.rightBar ?? 0))
readonly property real height: Math.max(100, screenHeight - y - Math.max(_bottomExclusion, adjacentBarInfo?.bottomBar ?? 0))
}