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 2cc12b70d2
commit b60af507d7
22 changed files with 191 additions and 237 deletions
+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))
}