1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-07 14:05:38 -05:00

fix modal unloading

This commit is contained in:
bbedward
2025-08-13 16:15:57 -04:00
parent 141dd7c66b
commit 79d69ed2b8
2 changed files with 1092 additions and 1087 deletions

View File

@@ -5,204 +5,206 @@ import Quickshell.Wayland
import qs.Common
PanelWindow {
id: root
id: root
property alias content: contentLoader.sourceComponent
property real width: 400
property real height: 300
readonly property real screenWidth: screen ? screen.width : 1920
readonly property real screenHeight: screen ? screen.height : 1080
property bool showBackground: true
property real backgroundOpacity: 0.5
property string positioning: "center"
property point customPosition: Qt.point(0, 0)
property string keyboardFocus: "ondemand"
property bool closeOnEscapeKey: true
property bool closeOnBackgroundClick: true
property string animationType: "scale"
property int animationDuration: Theme.mediumDuration
property var animationEasing: Theme.emphasizedEasing
property color backgroundColor: Theme.surfaceContainer
property color borderColor: Theme.outlineMedium
property real borderWidth: 1
property real cornerRadius: Theme.cornerRadius
property bool enableShadow: false
property alias content: contentLoader.sourceComponent
property real width: 400
property real height: 300
readonly property real screenWidth: screen ? screen.width : 1920
readonly property real screenHeight: screen ? screen.height : 1080
property bool showBackground: true
property real backgroundOpacity: 0.5
property string positioning: "center"
property point customPosition: Qt.point(0, 0)
property string keyboardFocus: "ondemand"
property bool closeOnEscapeKey: true
property bool closeOnBackgroundClick: true
property string animationType: "scale"
property int animationDuration: Theme.mediumDuration
property var animationEasing: Theme.emphasizedEasing
property color backgroundColor: Theme.surfaceContainer
property color borderColor: Theme.outlineMedium
property real borderWidth: 1
property real cornerRadius: Theme.cornerRadius
property bool enableShadow: false
// Expose the focusScope for external access
property alias modalFocusScope: focusScope
signal opened
signal dialogClosed
signal backgroundClicked
signal opened()
signal dialogClosed()
signal backgroundClicked()
function open() {
visible = true
}
function close() {
visible = false
}
function toggle() {
visible = !visible
}
color: "transparent"
WlrLayershell.layer: WlrLayershell.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
switch (root.keyboardFocus) {
case "exclusive":
return WlrKeyboardFocus.Exclusive
case "none":
return WlrKeyboardFocus.None
default:
return WlrKeyboardFocus.OnDemand
}
}
onVisibleChanged: {
if (root.visible) {
opened()
} else {
if (Qt.inputMethod) {
Qt.inputMethod.hide()
Qt.inputMethod.reset()
}
dialogClosed()
}
}
anchors {
top: true
left: true
right: true
bottom: true
}
Rectangle {
id: background
anchors.fill: parent
color: "black"
opacity: root.showBackground ? (root.visible ? root.backgroundOpacity : 0) : 0
visible: root.showBackground
MouseArea {
anchors.fill: parent
enabled: root.closeOnBackgroundClick
onClicked: mouse => {
var localPos = mapToItem(contentContainer, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentContainer.width
|| localPos.y < 0
|| localPos.y > contentContainer.height)
root.backgroundClicked()
}
function open() {
visible = true;
}
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: root.animationEasing
}
}
}
Rectangle {
id: contentContainer
width: root.width
height: root.height
anchors.centerIn: positioning === "center" ? parent : undefined
x: {
if (positioning === "top-right")
return Math.max(Theme.spacingL,
root.screenWidth - width - Theme.spacingL)
else if (positioning === "custom")
return root.customPosition.x
return 0 // Will be overridden by anchors.centerIn when positioning === "center"
}
y: {
if (positioning === "top-right")
return Theme.barHeight + Theme.spacingXS
else if (positioning === "custom")
return root.customPosition.y
return 0 // Will be overridden by anchors.centerIn when positioning === "center"
}
color: root.backgroundColor
radius: root.cornerRadius
border.color: root.borderColor
border.width: root.borderWidth
layer.enabled: root.enableShadow
opacity: root.visible ? 1 : 0
scale: {
if (root.animationType === "scale")
return root.visible ? 1 : 0.9
return 1
}
transform: root.animationType === "slide" ? slideTransform : null
Translate {
id: slideTransform
x: root.visible ? 0 : 15
y: root.visible ? 0 : -30
function close() {
visible = false;
}
Loader {
id: contentLoader
anchors.fill: parent
active: true
asynchronous: false
function toggle() {
visible = !visible;
}
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: root.animationEasing
}
color: "transparent"
WlrLayershell.layer: WlrLayershell.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
switch (root.keyboardFocus) {
case "exclusive":
return WlrKeyboardFocus.Exclusive;
case "none":
return WlrKeyboardFocus.None;
default:
return WlrKeyboardFocus.OnDemand;
}
}
Behavior on scale {
enabled: root.animationType === "scale"
NumberAnimation {
duration: root.animationDuration
easing.type: root.animationEasing
}
}
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
shadowVerticalOffset: 8
shadowBlur: 1
shadowColor: Theme.shadowStrong
shadowOpacity: 0.3
}
}
FocusScope {
id: focusScope
objectName: "modalFocusScope"
anchors.fill: parent
visible: root.visible // Only active when the modal is visible
focus: root.visible
Keys.onEscapePressed: event => {
if (root.closeOnEscapeKey) {
root.visible = false
event.accepted = true
}
}
onVisibleChanged: {
if (visible) {
Qt.callLater(function () {
focusScope.forceActiveFocus()
})
}
if (root.visible) {
opened();
} else {
if (Qt.inputMethod) {
Qt.inputMethod.hide();
Qt.inputMethod.reset();
}
dialogClosed();
}
}
anchors {
top: true
left: true
right: true
bottom: true
}
Rectangle {
id: background
anchors.fill: parent
color: "black"
opacity: root.showBackground ? (root.visible ? root.backgroundOpacity : 0) : 0
visible: root.showBackground
MouseArea {
anchors.fill: parent
enabled: root.closeOnBackgroundClick
onClicked: (mouse) => {
var localPos = mapToItem(contentContainer, mouse.x, mouse.y);
if (localPos.x < 0 || localPos.x > contentContainer.width || localPos.y < 0 || localPos.y > contentContainer.height)
root.backgroundClicked();
}
}
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: root.animationEasing
}
}
}
Rectangle {
id: contentContainer
width: root.width
height: root.height
anchors.centerIn: positioning === "center" ? parent : undefined
x: {
if (positioning === "top-right")
return Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL);
else if (positioning === "custom")
return root.customPosition.x;
return 0; // Will be overridden by anchors.centerIn when positioning === "center"
}
y: {
if (positioning === "top-right")
return Theme.barHeight + Theme.spacingXS;
else if (positioning === "custom")
return root.customPosition.y;
return 0; // Will be overridden by anchors.centerIn when positioning === "center"
}
color: root.backgroundColor
radius: root.cornerRadius
border.color: root.borderColor
border.width: root.borderWidth
layer.enabled: root.enableShadow
opacity: root.visible ? 1 : 0
scale: {
if (root.animationType === "scale")
return root.visible ? 1 : 0.9;
return 1;
}
transform: root.animationType === "slide" ? slideTransform : null
Translate {
id: slideTransform
x: root.visible ? 0 : 15
y: root.visible ? 0 : -30
}
Loader {
id: contentLoader
anchors.fill: parent
active: root.visible
asynchronous: false
}
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: root.animationEasing
}
}
Behavior on scale {
enabled: root.animationType === "scale"
NumberAnimation {
duration: root.animationDuration
easing.type: root.animationEasing
}
}
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
shadowVerticalOffset: 8
shadowBlur: 1
shadowColor: Theme.shadowStrong
shadowOpacity: 0.3
}
}
FocusScope {
id: focusScope
objectName: "modalFocusScope"
anchors.fill: parent
visible: root.visible // Only active when the modal is visible
focus: root.visible
Keys.onEscapePressed: (event) => {
if (root.closeOnEscapeKey) {
root.visible = false;
event.accepted = true;
}
}
onVisibleChanged: {
if (visible)
Qt.callLater(function() {
focusScope.forceActiveFocus();
});
}
}
}
// Expose the focusScope for external access
property alias modalFocusScope: focusScope
}

File diff suppressed because it is too large Load Diff