summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankPopout.qml
diff options
context:
space:
mode:
authorAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
committerAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
commit70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch)
treeab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankPopout.qml
parent5d94c0a7d44a2255b81815a52a7056a94a39842d (diff)
downloadRaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz
RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankPopout.qml')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankPopout.qml620
1 files changed, 620 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankPopout.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankPopout.qml
new file mode 100644
index 0000000..fb5f0b0
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankPopout.qml
@@ -0,0 +1,620 @@
+import QtQuick
+import Quickshell
+import Quickshell.Wayland
+import qs.Common
+import qs.Services
+
+Item {
+ id: root
+
+ property string layerNamespace: "dms:popout"
+ property alias content: contentLoader.sourceComponent
+ property alias contentLoader: contentLoader
+ property Component overlayContent: null
+ property alias overlayLoader: overlayLoader
+ property real popupWidth: 400
+ property real popupHeight: 300
+ property real triggerX: 0
+ property real triggerY: 0
+ property real triggerWidth: 40
+ property string triggerSection: ""
+ property string positioning: "center"
+ property int animationDuration: Theme.popoutAnimationDuration
+ property real animationScaleCollapsed: 0.96
+ property real animationOffset: Theme.spacingL
+ property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
+ property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
+ property bool suspendShadowWhileResizing: false
+ property bool shouldBeVisible: false
+ property var customKeyboardFocus: null
+ property bool backgroundInteractive: true
+ property bool contentHandlesKeys: false
+ property bool fullHeightSurface: false
+ property bool _primeContent: false
+ property bool _resizeActive: false
+ property real _surfaceMarginLeft: 0
+ property real _surfaceW: 0
+
+ property real storedBarThickness: Theme.barHeight - 4
+ property real storedBarSpacing: 4
+ property var storedBarConfig: null
+ property var adjacentBarInfo: ({
+ "topBar": 0,
+ "bottomBar": 0,
+ "leftBar": 0,
+ "rightBar": 0
+ })
+ property var screen: null
+
+ readonly property real effectiveBarThickness: {
+ const padding = storedBarConfig ? (storedBarConfig.innerPadding !== undefined ? storedBarConfig.innerPadding : 4) : 4;
+ return Math.max(26 + padding * 0.6, Theme.barHeight - 4 - (8 - padding)) + storedBarSpacing;
+ }
+
+ readonly property var barBounds: {
+ if (!screen)
+ return {
+ "x": 0,
+ "y": 0,
+ "width": 0,
+ "height": 0,
+ "wingSize": 0
+ };
+ return SettingsData.getBarBounds(screen, effectiveBarThickness, effectiveBarPosition, storedBarConfig);
+ }
+
+ readonly property real barX: barBounds.x
+ readonly property real barY: barBounds.y
+ readonly property real barWidth: barBounds.width
+ readonly property real barHeight: barBounds.height
+ readonly property real barWingSize: barBounds.wingSize
+
+ signal opened
+ signal popoutClosed
+ signal backgroundClicked
+
+ property var _lastOpenedScreen: null
+
+ property int effectiveBarPosition: 0
+ property real effectiveBarBottomGap: 0
+ readonly property string autoBarShadowDirection: {
+ const section = triggerSection || "center";
+ switch (effectiveBarPosition) {
+ case SettingsData.Position.Top:
+ if (section === "left")
+ return "topLeft";
+ if (section === "right")
+ return "topRight";
+ return "top";
+ case SettingsData.Position.Bottom:
+ if (section === "left")
+ return "bottomLeft";
+ if (section === "right")
+ return "bottomRight";
+ return "bottom";
+ case SettingsData.Position.Left:
+ if (section === "left")
+ return "topLeft";
+ if (section === "right")
+ return "bottomLeft";
+ return "left";
+ case SettingsData.Position.Right:
+ if (section === "left")
+ return "topRight";
+ if (section === "right")
+ return "bottomRight";
+ return "right";
+ default:
+ return "top";
+ }
+ }
+ readonly property string effectiveShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
+
+ // Snapshot mask geometry to prevent background damage on bar updates
+ property real _frozenMaskX: 0
+ property real _frozenMaskY: 0
+ property real _frozenMaskWidth: 0
+ property real _frozenMaskHeight: 0
+
+ function setBarContext(position, bottomGap) {
+ effectiveBarPosition = position !== undefined ? position : 0;
+ effectiveBarBottomGap = bottomGap !== undefined ? bottomGap : 0;
+ }
+
+ function primeContent() {
+ _primeContent = true;
+ }
+
+ function clearPrimedContent() {
+ _primeContent = false;
+ }
+
+ function setTriggerPosition(x, y, width, section, targetScreen, barPosition, barThickness, barSpacing, barConfig) {
+ triggerX = x;
+ triggerY = y;
+ triggerWidth = width;
+ triggerSection = section;
+ screen = targetScreen;
+
+ storedBarThickness = barThickness !== undefined ? barThickness : (Theme.barHeight - 4);
+ storedBarSpacing = barSpacing !== undefined ? barSpacing : 4;
+ storedBarConfig = barConfig;
+
+ const pos = barPosition !== undefined ? barPosition : 0;
+ const bottomGap = barConfig ? (barConfig.bottomGap !== undefined ? barConfig.bottomGap : 0) : 0;
+
+ adjacentBarInfo = SettingsData.getAdjacentBarInfo(targetScreen, pos, barConfig);
+ setBarContext(pos, bottomGap);
+ }
+
+ readonly property bool useBackgroundWindow: !CompositorService.isHyprland || CompositorService.useHyprlandFocusGrab
+
+ function updateSurfacePosition() {
+ if (useBackgroundWindow && shouldBeVisible) {
+ _surfaceMarginLeft = alignedX - shadowBuffer;
+ _surfaceW = alignedWidth + shadowBuffer * 2;
+ }
+ }
+
+ function open() {
+ if (!screen)
+ return;
+ closeTimer.stop();
+
+ // Snapshot mask geometry
+ _frozenMaskX = maskX;
+ _frozenMaskY = maskY;
+ _frozenMaskWidth = maskWidth;
+ _frozenMaskHeight = maskHeight;
+
+ if (_lastOpenedScreen !== null && _lastOpenedScreen !== screen) {
+ contentWindow.visible = false;
+ if (useBackgroundWindow)
+ backgroundWindow.visible = false;
+ }
+ _lastOpenedScreen = screen;
+
+ shouldBeVisible = true;
+ if (useBackgroundWindow) {
+ _surfaceMarginLeft = alignedX - shadowBuffer;
+ _surfaceW = alignedWidth + shadowBuffer * 2;
+ }
+ Qt.callLater(() => {
+ if (shouldBeVisible && screen) {
+ if (useBackgroundWindow)
+ backgroundWindow.visible = true;
+ contentWindow.visible = true;
+ PopoutManager.showPopout(root);
+ opened();
+ }
+ });
+ }
+
+ function close() {
+ shouldBeVisible = false;
+ _primeContent = false;
+ PopoutManager.popoutChanged();
+ closeTimer.restart();
+ }
+
+ function toggle() {
+ shouldBeVisible ? close() : open();
+ }
+
+ Connections {
+ target: Quickshell
+ function onScreensChanged() {
+ if (!shouldBeVisible || !screen)
+ return;
+ const currentScreenName = screen.name;
+ let screenStillExists = false;
+ for (let i = 0; i < Quickshell.screens.length; i++) {
+ if (Quickshell.screens[i].name === currentScreenName) {
+ screenStillExists = true;
+ break;
+ }
+ }
+ if (!screenStillExists) {
+ close();
+ }
+ }
+ }
+
+ Timer {
+ id: closeTimer
+ interval: animationDuration
+ onTriggered: {
+ if (!shouldBeVisible) {
+ contentWindow.visible = false;
+ if (useBackgroundWindow)
+ backgroundWindow.visible = false;
+ PopoutManager.hidePopout(root);
+ popoutClosed();
+ }
+ }
+ }
+
+ readonly property real screenWidth: screen ? screen.width : 0
+ readonly property real screenHeight: screen ? screen.height : 0
+ readonly property real dpr: screen ? screen.devicePixelRatio : 1
+
+ readonly property var shadowLevel: Theme.elevationLevel3
+ readonly property real shadowFallbackOffset: 6
+ readonly property real shadowRenderPadding: (Theme.elevationEnabled && SettingsData.popoutElevationEnabled) ? Theme.elevationRenderPadding(shadowLevel, effectiveShadowDirection, shadowFallbackOffset, 8, 16) : 0
+ readonly property real shadowMotionPadding: Math.max(0, animationOffset)
+ readonly property real shadowBuffer: Theme.snap(shadowRenderPadding + shadowMotionPadding, dpr)
+ readonly property real alignedWidth: Theme.px(popupWidth, dpr)
+ readonly property real alignedHeight: Theme.px(popupHeight, dpr)
+
+ onAlignedHeightChanged: {
+ if (!suspendShadowWhileResizing || !shouldBeVisible)
+ return;
+ _resizeActive = true;
+ resizeSettleTimer.restart();
+ }
+ onShouldBeVisibleChanged: {
+ if (!shouldBeVisible) {
+ _resizeActive = false;
+ resizeSettleTimer.stop();
+ }
+ }
+
+ Timer {
+ id: resizeSettleTimer
+ interval: 80
+ repeat: false
+ onTriggered: root._resizeActive = false
+ }
+
+ readonly property real alignedX: Theme.snap((() => {
+ const useAutoGaps = storedBarConfig?.popupGapsAuto !== undefined ? storedBarConfig.popupGapsAuto : true;
+ const manualGapValue = storedBarConfig?.popupGapsManual !== undefined ? storedBarConfig.popupGapsManual : 4;
+ const popupGap = useAutoGaps ? Math.max(4, storedBarSpacing) : manualGapValue;
+
+ switch (effectiveBarPosition) {
+ case SettingsData.Position.Left:
+ return Math.max(popupGap, Math.min(screenWidth - popupWidth - popupGap, triggerX));
+ case SettingsData.Position.Right:
+ return Math.max(popupGap, Math.min(screenWidth - popupWidth - popupGap, triggerX - popupWidth));
+ default:
+ const rawX = triggerX + (triggerWidth / 2) - (popupWidth / 2);
+ const minX = adjacentBarInfo.leftBar > 0 ? adjacentBarInfo.leftBar : popupGap;
+ const maxX = screenWidth - popupWidth - (adjacentBarInfo.rightBar > 0 ? adjacentBarInfo.rightBar : popupGap);
+ return Math.max(minX, Math.min(maxX, rawX));
+ }
+ })(), dpr)
+
+ readonly property real alignedY: Theme.snap((() => {
+ const useAutoGaps = storedBarConfig?.popupGapsAuto !== undefined ? storedBarConfig.popupGapsAuto : true;
+ const manualGapValue = storedBarConfig?.popupGapsManual !== undefined ? storedBarConfig.popupGapsManual : 4;
+ const popupGap = useAutoGaps ? Math.max(4, storedBarSpacing) : manualGapValue;
+
+ switch (effectiveBarPosition) {
+ case SettingsData.Position.Bottom:
+ return Math.max(popupGap, Math.min(screenHeight - popupHeight - popupGap, triggerY - popupHeight));
+ case SettingsData.Position.Top:
+ return Math.max(popupGap, Math.min(screenHeight - popupHeight - popupGap, triggerY));
+ default:
+ const rawY = triggerY - (popupHeight / 2);
+ const minY = adjacentBarInfo.topBar > 0 ? adjacentBarInfo.topBar : popupGap;
+ const maxY = screenHeight - popupHeight - (adjacentBarInfo.bottomBar > 0 ? adjacentBarInfo.bottomBar : popupGap);
+ return Math.max(minY, Math.min(maxY, rawY));
+ }
+ })(), 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: {
+ 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);
+ }
+
+ PanelWindow {
+ id: backgroundWindow
+ screen: root.screen
+ visible: false
+ color: "transparent"
+ Component.onCompleted: {
+ if (typeof updatesEnabled !== "undefined" && !root.overlayContent)
+ updatesEnabled = false;
+ }
+
+ WlrLayershell.namespace: root.layerNamespace + ":background"
+ WlrLayershell.layer: WlrLayershell.Top
+ WlrLayershell.exclusiveZone: -1
+ WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
+
+ anchors {
+ top: true
+ left: true
+ right: true
+ bottom: true
+ }
+
+ mask: Region {
+ item: maskRect
+ }
+
+ Rectangle {
+ id: maskRect
+ visible: false
+ color: "transparent"
+ x: root._frozenMaskX
+ y: root._frozenMaskY
+ width: (shouldBeVisible && backgroundInteractive) ? root._frozenMaskWidth : 0
+ height: (shouldBeVisible && backgroundInteractive) ? root._frozenMaskHeight : 0
+ }
+
+ MouseArea {
+ x: root._frozenMaskX
+ y: root._frozenMaskY
+ width: root._frozenMaskWidth
+ height: root._frozenMaskHeight
+ hoverEnabled: false
+ enabled: shouldBeVisible && backgroundInteractive
+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
+ onClicked: mouse => {
+ const clickX = mouse.x + root._frozenMaskX;
+ const clickY = mouse.y + root._frozenMaskY;
+ const outsideContent = clickX < root.alignedX || clickX > root.alignedX + root.alignedWidth || clickY < root.alignedY || clickY > root.alignedY + root.alignedHeight;
+
+ if (!outsideContent)
+ return;
+ backgroundClicked();
+ }
+ }
+
+ Loader {
+ id: overlayLoader
+ anchors.fill: parent
+ active: root.overlayContent !== null && backgroundWindow.visible
+ sourceComponent: root.overlayContent
+ }
+ }
+
+ PanelWindow {
+ id: contentWindow
+ screen: root.screen
+ visible: false
+ color: "transparent"
+
+ WindowBlur {
+ id: popoutBlur
+ targetWindow: contentWindow
+ readonly property real s: Math.min(1, contentContainer.scaleValue)
+ blurX: contentContainer.x + contentContainer.width * (1 - s) * 0.5 + Theme.snap(contentContainer.animX, root.dpr)
+ blurY: contentContainer.y + contentContainer.height * (1 - s) * 0.5 + Theme.snap(contentContainer.animY, root.dpr)
+ blurWidth: (shouldBeVisible && contentWrapper.opacity > 0) ? contentContainer.width * s : 0
+ blurHeight: (shouldBeVisible && contentWrapper.opacity > 0) ? contentContainer.height * s : 0
+ blurRadius: Theme.cornerRadius
+ }
+
+ WlrLayershell.namespace: root.layerNamespace
+ WlrLayershell.layer: {
+ switch (Quickshell.env("DMS_POPOUT_LAYER")) {
+ case "bottom":
+ console.warn("DankPopout: 'bottom' layer is not valid for popouts. Defaulting to 'top' layer.");
+ return WlrLayershell.Top;
+ case "background":
+ console.warn("DankPopout: 'background' layer is not valid for popouts. Defaulting to 'top' layer.");
+ return WlrLayershell.Top;
+ case "overlay":
+ return WlrLayershell.Overlay;
+ default:
+ return WlrLayershell.Top;
+ }
+ }
+ WlrLayershell.exclusiveZone: -1
+ WlrLayershell.keyboardFocus: {
+ if (customKeyboardFocus !== null)
+ return customKeyboardFocus;
+ if (!shouldBeVisible)
+ return WlrKeyboardFocus.None;
+ if (CompositorService.useHyprlandFocusGrab)
+ return WlrKeyboardFocus.OnDemand;
+ return WlrKeyboardFocus.Exclusive;
+ }
+
+ readonly property bool _fullHeight: useBackgroundWindow && root.fullHeightSurface
+
+ anchors {
+ left: true
+ top: true
+ right: !useBackgroundWindow
+ bottom: _fullHeight || !useBackgroundWindow
+ }
+
+ WlrLayershell.margins {
+ left: useBackgroundWindow ? root._surfaceMarginLeft : 0
+ top: (useBackgroundWindow && !_fullHeight) ? (root.alignedY - shadowBuffer) : 0
+ }
+
+ implicitWidth: useBackgroundWindow ? root._surfaceW : 0
+ implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
+
+ mask: useBackgroundWindow ? contentInputMask : null
+
+ Region {
+ id: contentInputMask
+ item: contentMaskRect
+ }
+
+ Item {
+ id: contentMaskRect
+ visible: false
+ x: contentContainer.x
+ y: contentContainer.y
+ width: shouldBeVisible ? root.alignedWidth : 0
+ height: shouldBeVisible ? root.alignedHeight : 0
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ enabled: !useBackgroundWindow && shouldBeVisible && backgroundInteractive
+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
+ z: -1
+ onClicked: mouse => {
+ const clickX = mouse.x;
+ const clickY = mouse.y;
+ const outsideContent = clickX < root.alignedX || clickX > root.alignedX + root.alignedWidth || clickY < root.alignedY || clickY > root.alignedY + root.alignedHeight;
+ if (!outsideContent)
+ return;
+ backgroundClicked();
+ }
+ }
+
+ Item {
+ id: contentContainer
+ x: useBackgroundWindow ? shadowBuffer : root.alignedX
+ y: (useBackgroundWindow && !contentWindow._fullHeight) ? shadowBuffer : root.alignedY
+ width: root.alignedWidth
+ height: root.alignedHeight
+
+ readonly property bool barTop: effectiveBarPosition === SettingsData.Position.Top
+ readonly property bool barBottom: effectiveBarPosition === SettingsData.Position.Bottom
+ readonly property bool barLeft: effectiveBarPosition === SettingsData.Position.Left
+ readonly property bool barRight: effectiveBarPosition === SettingsData.Position.Right
+ readonly property real offsetX: barLeft ? root.animationOffset : (barRight ? -root.animationOffset : 0)
+ readonly property real offsetY: barBottom ? -root.animationOffset : (barTop ? root.animationOffset : 0)
+
+ property real animX: 0
+ property real animY: 0
+ property real scaleValue: root.animationScaleCollapsed
+
+ onOffsetXChanged: animX = Theme.snap(root.shouldBeVisible ? 0 : offsetX, root.dpr)
+ onOffsetYChanged: animY = Theme.snap(root.shouldBeVisible ? 0 : offsetY, root.dpr)
+
+ Connections {
+ target: root
+ function onShouldBeVisibleChanged() {
+ contentContainer.animX = Theme.snap(root.shouldBeVisible ? 0 : contentContainer.offsetX, root.dpr);
+ contentContainer.animY = Theme.snap(root.shouldBeVisible ? 0 : contentContainer.offsetY, root.dpr);
+ contentContainer.scaleValue = root.shouldBeVisible ? 1.0 : root.animationScaleCollapsed;
+ }
+ }
+
+ Behavior on animX {
+ NumberAnimation {
+ duration: root.animationDuration
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
+ }
+ }
+
+ Behavior on animY {
+ NumberAnimation {
+ duration: root.animationDuration
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
+ }
+ }
+
+ Behavior on scaleValue {
+ NumberAnimation {
+ duration: root.animationDuration
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
+ }
+ }
+
+ ElevationShadow {
+ id: shadowSource
+ width: parent.width
+ height: parent.height
+ opacity: contentWrapper.opacity
+ scale: contentWrapper.scale
+ x: contentWrapper.x
+ y: contentWrapper.y
+ level: root.shadowLevel
+ direction: root.effectiveShadowDirection
+ fallbackOffset: root.shadowFallbackOffset
+ targetRadius: Theme.cornerRadius
+ targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
+ shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
+ }
+
+ Item {
+ id: contentWrapper
+ anchors.centerIn: parent
+ width: parent.width
+ height: parent.height
+ opacity: shouldBeVisible ? 1 : 0
+ visible: opacity > 0
+ scale: contentContainer.scaleValue
+ x: Theme.snap(contentContainer.animX + (parent.width - width) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
+ y: Theme.snap(contentContainer.animY + (parent.height - height) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
+
+ layer.enabled: contentWrapper.opacity < 1
+ layer.smooth: false
+ layer.textureSize: root.dpr > 1 ? Qt.size(Math.ceil(width * root.dpr), Math.ceil(height * root.dpr)) : Qt.size(0, 0)
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: animationDuration
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
+ }
+ }
+
+ Loader {
+ id: contentLoader
+ anchors.fill: parent
+ active: root._primeContent || shouldBeVisible || contentWindow.visible
+ asynchronous: false
+ }
+ }
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ x: contentWrapper.x
+ y: contentWrapper.y
+ opacity: contentWrapper.opacity
+ scale: contentWrapper.scale
+ visible: contentWrapper.visible
+ radius: Theme.cornerRadius
+ color: "transparent"
+ border.color: BlurService.enabled ? BlurService.borderColor : Theme.outlineMedium
+ border.width: BlurService.borderWidth
+ z: 100
+ }
+ }
+
+ Item {
+ id: focusHelper
+ parent: contentContainer
+ anchors.fill: parent
+ visible: !root.contentHandlesKeys
+ enabled: !root.contentHandlesKeys
+ focus: !root.contentHandlesKeys
+ Keys.onPressed: event => {
+ if (root.contentHandlesKeys)
+ return;
+ if (event.key === Qt.Key_Escape) {
+ close();
+ event.accepted = true;
+ }
+ }
+ }
+ }
+}