mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-03 19:12:11 -04:00
frame(Motion): Restore fluid motion & Update component connections
This commit is contained in:
@@ -185,8 +185,15 @@ Singleton {
|
|||||||
onAnimationVariantChanged: saveSettings()
|
onAnimationVariantChanged: saveSettings()
|
||||||
property int motionEffect: SettingsData.AnimationEffect.Standard
|
property int motionEffect: SettingsData.AnimationEffect.Standard
|
||||||
onMotionEffectChanged: saveSettings()
|
onMotionEffectChanged: saveSettings()
|
||||||
property int directionalAnimationMode: 0
|
property int directionalAnimationMode: 1
|
||||||
onDirectionalAnimationModeChanged: saveSettings()
|
onDirectionalAnimationModeChanged: {
|
||||||
|
const normalized = directionalAnimationMode === 3 ? 3 : 1;
|
||||||
|
if (directionalAnimationMode !== normalized) {
|
||||||
|
directionalAnimationMode = normalized;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
property bool m3ElevationEnabled: true
|
property bool m3ElevationEnabled: true
|
||||||
onM3ElevationEnabledChanged: saveSettings()
|
onM3ElevationEnabledChanged: saveSettings()
|
||||||
property int m3ElevationIntensity: 12
|
property int m3ElevationIntensity: 12
|
||||||
@@ -246,7 +253,13 @@ Singleton {
|
|||||||
onFrameLauncherEmergeSideChanged: saveSettings()
|
onFrameLauncherEmergeSideChanged: saveSettings()
|
||||||
readonly property string frameModalEmergeSide: frameLauncherEmergeSide === "top" ? "bottom" : "top"
|
readonly property string frameModalEmergeSide: frameLauncherEmergeSide === "top" ? "bottom" : "top"
|
||||||
property int previousDirectionalMode: 1
|
property int previousDirectionalMode: 1
|
||||||
onPreviousDirectionalModeChanged: saveSettings()
|
onPreviousDirectionalModeChanged: {
|
||||||
|
if (previousDirectionalMode !== 1) {
|
||||||
|
previousDirectionalMode = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
property var connectedFrameBarStyleBackups: ({})
|
property var connectedFrameBarStyleBackups: ({})
|
||||||
onConnectedFrameBarStyleBackupsChanged: saveSettings()
|
onConnectedFrameBarStyleBackupsChanged: saveSettings()
|
||||||
readonly property bool connectedFrameModeActive: frameEnabled && motionEffect === SettingsData.AnimationEffect.Directional && directionalAnimationMode === 3
|
readonly property bool connectedFrameModeActive: frameEnabled && motionEffect === SettingsData.AnimationEffect.Directional && directionalAnimationMode === 3
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ var SPEC = {
|
|||||||
enableRippleEffects: { def: true },
|
enableRippleEffects: { def: true },
|
||||||
animationVariant: { def: 0 },
|
animationVariant: { def: 0 },
|
||||||
motionEffect: { def: 0 },
|
motionEffect: { def: 0 },
|
||||||
directionalAnimationMode: { def: 0 },
|
directionalAnimationMode: { def: 1 },
|
||||||
previousDirectionalMode: { def: 1 },
|
previousDirectionalMode: { def: 1 },
|
||||||
m3ElevationEnabled: { def: true },
|
m3ElevationEnabled: { def: true },
|
||||||
m3ElevationIntensity: { def: 12 },
|
m3ElevationIntensity: { def: 12 },
|
||||||
|
|||||||
@@ -334,7 +334,6 @@ Item {
|
|||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
DankDashPopout {
|
DankDashPopout {
|
||||||
id: dankDashPopout
|
id: dankDashPopout
|
||||||
onPopoutClosed: PopoutService.unloadDankDash()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -586,8 +586,6 @@ Item {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2 && Theme.isDirectionalEffect)
|
|
||||||
return 0;
|
|
||||||
if (slide && !directionalEffect && !depthEffect)
|
if (slide && !directionalEffect && !depthEffect)
|
||||||
return 15;
|
return 15;
|
||||||
if (directionalEffect) {
|
if (directionalEffect) {
|
||||||
@@ -630,8 +628,6 @@ Item {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2 && Theme.isDirectionalEffect)
|
|
||||||
return 0;
|
|
||||||
if (slide && !directionalEffect && !depthEffect)
|
if (slide && !directionalEffect && !depthEffect)
|
||||||
return -30;
|
return -30;
|
||||||
if (directionalEffect) {
|
if (directionalEffect) {
|
||||||
@@ -674,7 +670,7 @@ Item {
|
|||||||
onAnimYChanged: if (root.frameOwnsConnectedChrome)
|
onAnimYChanged: if (root.frameOwnsConnectedChrome)
|
||||||
root._syncModalAnim()
|
root._syncModalAnim()
|
||||||
|
|
||||||
readonly property real computedScaleCollapsed: (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2 && Theme.isDirectionalEffect) ? 0.0 : root.animationScaleCollapsed
|
readonly property real computedScaleCollapsed: root.animationScaleCollapsed
|
||||||
property real scaleValue: root.shouldBeVisible ? 1.0 : computedScaleCollapsed
|
property real scaleValue: root.shouldBeVisible ? 1.0 : computedScaleCollapsed
|
||||||
|
|
||||||
Behavior on animX {
|
Behavior on animX {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|||||||
@@ -713,7 +713,7 @@ Item {
|
|||||||
// Declarative bindings — snap applied at render layer (contentWrapper x/y)
|
// Declarative bindings — snap applied at render layer (contentWrapper x/y)
|
||||||
property real animX: root._motionActive ? 0 : root._frozenMotionX
|
property real animX: root._motionActive ? 0 : root._frozenMotionX
|
||||||
property real animY: root._motionActive ? 0 : root._frozenMotionY
|
property real animY: root._motionActive ? 0 : root._frozenMotionY
|
||||||
property real scaleValue: root._motionActive ? 1.0 : (Theme.isDirectionalEffect && typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2 ? Theme.effectScaleCollapsed : (Theme.isDirectionalEffect ? 1 : Theme.effectScaleCollapsed))
|
property real scaleValue: root._motionActive ? 1.0 : Theme.effectScaleCollapsed
|
||||||
|
|
||||||
onAnimXChanged: if (root.frameOwnsConnectedChrome)
|
onAnimXChanged: if (root.frameOwnsConnectedChrome)
|
||||||
root._syncModalAnim()
|
root._syncModalAnim()
|
||||||
@@ -737,7 +737,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Behavior on scaleValue {
|
Behavior on scaleValue {
|
||||||
enabled: root.animationsEnabled && (!Theme.isDirectionalEffect || (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2))
|
enabled: root.animationsEnabled
|
||||||
DankAnim {
|
DankAnim {
|
||||||
duration: Theme.variantDuration(root.launcherAnimationDuration, root._motionActive)
|
duration: Theme.variantDuration(root.launcherAnimationDuration, root._motionActive)
|
||||||
easing.bezierCurve: root._motionActive ? root.launcherEnterCurve : root.launcherExitCurve
|
easing.bezierCurve: root._motionActive ? root.launcherEnterCurve : root.launcherExitCurve
|
||||||
|
|||||||
@@ -61,6 +61,20 @@ Item {
|
|||||||
readonly property int modalHeight: Math.min(baseHeight, screenHeight - 100)
|
readonly property int modalHeight: Math.min(baseHeight, screenHeight - 100)
|
||||||
readonly property real modalX: (screenWidth - modalWidth) / 2
|
readonly property real modalX: (screenWidth - modalWidth) / 2
|
||||||
readonly property real modalY: (screenHeight - modalHeight) / 2
|
readonly property real modalY: (screenHeight - modalHeight) / 2
|
||||||
|
readonly property var shadowLevel: Theme.elevationLevel3
|
||||||
|
readonly property real shadowFallbackOffset: 6
|
||||||
|
readonly property real shadowRenderPadding: (Theme.elevationEnabled && SettingsData.modalElevationEnabled) ? Theme.elevationRenderPadding(shadowLevel, Theme.elevationLightDirection, shadowFallbackOffset, 8, 16) : 0
|
||||||
|
readonly property real shadowPad: Theme.snap(shadowRenderPadding, dpr)
|
||||||
|
readonly property real alignedWidth: Theme.px(modalWidth, dpr)
|
||||||
|
readonly property real alignedHeight: Theme.px(modalHeight, dpr)
|
||||||
|
readonly property real alignedX: Theme.snap(modalX, dpr)
|
||||||
|
readonly property real alignedY: Theme.snap(modalY, dpr)
|
||||||
|
readonly property real windowX: Math.max(0, Theme.snap(alignedX - shadowPad, dpr))
|
||||||
|
readonly property real windowY: Math.max(0, Theme.snap(alignedY - shadowPad, dpr))
|
||||||
|
readonly property real contentX: Theme.snap(alignedX - windowX, dpr)
|
||||||
|
readonly property real contentY: Theme.snap(alignedY - windowY, dpr)
|
||||||
|
readonly property real windowWidth: alignedWidth + contentX + shadowPad
|
||||||
|
readonly property real windowHeight: alignedHeight + contentY + shadowPad
|
||||||
|
|
||||||
readonly property color backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
readonly property color backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
readonly property real cornerRadius: Theme.cornerRadius
|
readonly property real cornerRadius: Theme.cornerRadius
|
||||||
@@ -277,6 +291,57 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PanelWindow {
|
||||||
|
id: clickCatcher
|
||||||
|
screen: launcherWindow.screen
|
||||||
|
visible: spotlightOpen
|
||||||
|
color: "transparent"
|
||||||
|
updatesEnabled: false
|
||||||
|
|
||||||
|
WlrLayershell.namespace: "dms:spotlight:clickcatcher"
|
||||||
|
WlrLayershell.layer: WlrLayershell.Top
|
||||||
|
WlrLayershell.exclusiveZone: -1
|
||||||
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
top: true
|
||||||
|
bottom: true
|
||||||
|
left: true
|
||||||
|
right: true
|
||||||
|
}
|
||||||
|
|
||||||
|
mask: Region {
|
||||||
|
item: outsideClickMask
|
||||||
|
|
||||||
|
Region {
|
||||||
|
item: outsideClickHole
|
||||||
|
intersection: Intersection.Subtract
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: outsideClickMask
|
||||||
|
visible: false
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: outsideClickHole
|
||||||
|
visible: false
|
||||||
|
color: "transparent"
|
||||||
|
x: root.alignedX
|
||||||
|
y: root.alignedY
|
||||||
|
width: root.alignedWidth
|
||||||
|
height: root.alignedHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: spotlightOpen
|
||||||
|
onClicked: root.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: launcherWindow
|
id: launcherWindow
|
||||||
visible: spotlightOpen || isClosing
|
visible: spotlightOpen || isClosing
|
||||||
@@ -286,10 +351,10 @@ Item {
|
|||||||
WindowBlur {
|
WindowBlur {
|
||||||
targetWindow: launcherWindow
|
targetWindow: launcherWindow
|
||||||
readonly property real s: Math.min(1, modalContainer.scale)
|
readonly property real s: Math.min(1, modalContainer.scale)
|
||||||
blurX: root.modalX + root.modalWidth * (1 - s) * 0.5
|
blurX: modalContainer.x + modalContainer.width * (1 - s) * 0.5
|
||||||
blurY: root.modalY + root.modalHeight * (1 - s) * 0.5
|
blurY: modalContainer.y + modalContainer.height * (1 - s) * 0.5
|
||||||
blurWidth: (contentVisible && modalContainer.opacity > 0) ? root.modalWidth * s : 0
|
blurWidth: (contentVisible && modalContainer.opacity > 0) ? modalContainer.width * s : 0
|
||||||
blurHeight: (contentVisible && modalContainer.opacity > 0) ? root.modalHeight * s : 0
|
blurHeight: (contentVisible && modalContainer.opacity > 0) ? modalContainer.height * s : 0
|
||||||
blurRadius: root.cornerRadius
|
blurRadius: root.cornerRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,60 +373,44 @@ Item {
|
|||||||
return WlrLayershell.Top;
|
return WlrLayershell.Top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
WlrLayershell.exclusiveZone: -1
|
||||||
WlrLayershell.keyboardFocus: keyboardActive ? (root.useHyprlandFocusGrab ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive) : WlrKeyboardFocus.None
|
WlrLayershell.keyboardFocus: keyboardActive ? (root.useHyprlandFocusGrab ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive) : WlrKeyboardFocus.None
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
top: true
|
top: true
|
||||||
bottom: true
|
|
||||||
left: true
|
left: true
|
||||||
right: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WlrLayershell.margins {
|
||||||
|
left: root.windowX
|
||||||
|
top: root.windowY
|
||||||
|
right: 0
|
||||||
|
bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: root.windowWidth
|
||||||
|
implicitHeight: root.windowHeight
|
||||||
|
|
||||||
mask: Region {
|
mask: Region {
|
||||||
item: spotlightOpen ? fullScreenMask : null
|
item: launcherInputMask
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: fullScreenMask
|
|
||||||
anchors.fill: parent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: backgroundDarken
|
id: launcherInputMask
|
||||||
anchors.fill: parent
|
visible: false
|
||||||
color: "black"
|
color: "transparent"
|
||||||
opacity: contentVisible && SettingsData.modalDarkenBackground ? 0.5 : 0
|
x: modalContainer.x
|
||||||
visible: contentVisible || opacity > 0
|
y: modalContainer.y
|
||||||
|
width: modalContainer.width
|
||||||
Behavior on opacity {
|
height: modalContainer.height
|
||||||
DankAnim {
|
|
||||||
duration: Theme.modalAnimationDuration
|
|
||||||
easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
enabled: spotlightOpen
|
|
||||||
onClicked: mouse => {
|
|
||||||
var contentX = modalContainer.x;
|
|
||||||
var contentY = modalContainer.y;
|
|
||||||
var contentW = modalContainer.width;
|
|
||||||
var contentH = modalContainer.height;
|
|
||||||
|
|
||||||
if (mouse.x < contentX || mouse.x > contentX + contentW || mouse.y < contentY || mouse.y > contentY + contentH) {
|
|
||||||
root.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: modalContainer
|
id: modalContainer
|
||||||
x: root.modalX
|
x: root.contentX
|
||||||
y: root.modalY
|
y: root.contentY
|
||||||
width: root.modalWidth
|
width: root.alignedWidth
|
||||||
height: root.modalHeight
|
height: root.alignedHeight
|
||||||
visible: contentVisible || opacity > 0
|
visible: contentVisible || opacity > 0
|
||||||
|
|
||||||
opacity: contentVisible ? 1 : 0
|
opacity: contentVisible ? 1 : 0
|
||||||
@@ -385,8 +434,8 @@ Item {
|
|||||||
ElevationShadow {
|
ElevationShadow {
|
||||||
id: launcherShadowLayer
|
id: launcherShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
level: Theme.elevationLevel3
|
level: root.shadowLevel
|
||||||
fallbackOffset: 6
|
fallbackOffset: root.shadowFallbackOffset
|
||||||
targetColor: root.backgroundColor
|
targetColor: root.backgroundColor
|
||||||
borderColor: root.borderColor
|
borderColor: root.borderColor
|
||||||
borderWidth: root.borderWidth
|
borderWidth: root.borderWidth
|
||||||
|
|||||||
@@ -86,14 +86,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
popupWidth: 550
|
popupWidth: 550
|
||||||
popupHeight: {
|
popupHeight: targetPopupHeight
|
||||||
if (SettingsData.connectedFrameModeActive)
|
|
||||||
return targetPopupHeight;
|
|
||||||
const screenHeight = (triggerScreen?.height ?? 1080);
|
|
||||||
const maxHeight = screenHeight - 100;
|
|
||||||
const contentHeight = contentLoader.item && contentLoader.item.implicitHeight > 0 ? contentLoader.item.implicitHeight + 20 : 400;
|
|
||||||
return Math.min(maxHeight, contentHeight);
|
|
||||||
}
|
|
||||||
triggerWidth: 80
|
triggerWidth: 80
|
||||||
positioning: ""
|
positioning: ""
|
||||||
screen: triggerScreen
|
screen: triggerScreen
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ DankPopout {
|
|||||||
function __hideDropdowns() {
|
function __hideDropdowns() {
|
||||||
__volumeCloseTimer.stop();
|
__volumeCloseTimer.stop();
|
||||||
__dropdownType = 0;
|
__dropdownType = 0;
|
||||||
__mediaTabRef?.resetDropdownStates();
|
if (__mediaTabRef && typeof __mediaTabRef.resetDropdownStates === "function")
|
||||||
|
__mediaTabRef.resetDropdownStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
function __startCloseTimer() {
|
function __startCloseTimer() {
|
||||||
@@ -74,7 +75,11 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
overlayContent: Component {
|
overlayContent: shouldBeVisible ? mediaDropdownOverlayComponent : null
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: mediaDropdownOverlayComponent
|
||||||
|
|
||||||
MediaDropdownOverlay {
|
MediaDropdownOverlay {
|
||||||
dropdownType: root.__dropdownType
|
dropdownType: root.__dropdownType
|
||||||
anchorPos: root.__dropdownAnchor
|
anchorPos: root.__dropdownAnchor
|
||||||
@@ -182,11 +187,8 @@ DankPopout {
|
|||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
function onShouldBeVisibleChanged() {
|
function onShouldBeVisibleChanged() {
|
||||||
if (root.shouldBeVisible) {
|
if (root.shouldBeVisible)
|
||||||
Qt.callLater(function () {
|
mainContainer.forceActiveFocus();
|
||||||
mainContainer.forceActiveFocus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +380,10 @@ DankPopout {
|
|||||||
section: root.triggerSection
|
section: root.triggerSection
|
||||||
barPosition: root.effectiveBarPosition
|
barPosition: root.effectiveBarPosition
|
||||||
Component.onCompleted: root.__mediaTabRef = this
|
Component.onCompleted: root.__mediaTabRef = this
|
||||||
|
Component.onDestruction: {
|
||||||
|
if (root.__mediaTabRef === this)
|
||||||
|
root.__mediaTabRef = null;
|
||||||
|
}
|
||||||
onShowVolumeDropdown: (pos, screen, rightEdge, player, players) => {
|
onShowVolumeDropdown: (pos, screen, rightEdge, player, players) => {
|
||||||
root.__showVolumeDropdown(pos, rightEdge, player, players);
|
root.__showVolumeDropdown(pos, rightEdge, player, players);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,11 +50,9 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function volumeAreaExited() {
|
function volumeAreaExited() {
|
||||||
__volumeHoverCount--;
|
__volumeHoverCount = Math.max(0, __volumeHoverCount - 1);
|
||||||
Qt.callLater(() => {
|
if (__volumeHoverCount === 0)
|
||||||
if (__volumeHoverCount <= 0)
|
panelExited();
|
||||||
panelExited();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property Item __activePanel: {
|
readonly property Item __activePanel: {
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ Item {
|
|||||||
SettingsDropdownRow {
|
SettingsDropdownRow {
|
||||||
visible: SettingsData.motionEffect === 1
|
visible: SettingsData.motionEffect === 1
|
||||||
tab: "typography"
|
tab: "typography"
|
||||||
tags: ["animation", "directional", "behavior", "overlap", "sticky", "roll", "connected"]
|
tags: ["animation", "directional", "behavior", "fluid", "connected"]
|
||||||
settingKey: "directionalAnimationMode"
|
settingKey: "directionalAnimationMode"
|
||||||
text: I18n.tr("Directional Behavior")
|
text: I18n.tr("Directional Behavior")
|
||||||
description: {
|
description: {
|
||||||
@@ -211,30 +211,24 @@ Item {
|
|||||||
return I18n.tr("Popouts emerge flush from the bar edge as a single continuous piece, with corner connectors bridging the junction");
|
return I18n.tr("Popouts emerge flush from the bar edge as a single continuous piece, with corner connectors bridging the junction");
|
||||||
return I18n.tr("How the popout emerges from the DankBar");
|
return I18n.tr("How the popout emerges from the DankBar");
|
||||||
}
|
}
|
||||||
options: SettingsData.frameEnabled ? [I18n.tr("Overlap"), I18n.tr("Slide"), I18n.tr("Roll"), I18n.tr("Connected")] : [I18n.tr("Overlap"), I18n.tr("Slide"), I18n.tr("Roll")]
|
options: SettingsData.frameEnabled ? [I18n.tr("Fluid"), I18n.tr("Connected")] : [I18n.tr("Fluid")]
|
||||||
currentValue: {
|
currentValue: {
|
||||||
switch (SettingsData.directionalAnimationMode) {
|
switch (SettingsData.directionalAnimationMode) {
|
||||||
case 1:
|
|
||||||
return I18n.tr("Slide");
|
|
||||||
case 2:
|
|
||||||
return I18n.tr("Roll");
|
|
||||||
case 3:
|
case 3:
|
||||||
return SettingsData.frameEnabled ? I18n.tr("Connected") : I18n.tr("Slide");
|
return SettingsData.frameEnabled ? I18n.tr("Connected") : I18n.tr("Fluid");
|
||||||
default:
|
default:
|
||||||
return I18n.tr("Overlap");
|
return I18n.tr("Fluid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onValueChanged: value => {
|
onValueChanged: value => {
|
||||||
if (value === I18n.tr("Slide"))
|
if (value === I18n.tr("Fluid"))
|
||||||
SettingsData.set("directionalAnimationMode", 1);
|
SettingsData.set("directionalAnimationMode", 1);
|
||||||
else if (value === I18n.tr("Roll"))
|
|
||||||
SettingsData.set("directionalAnimationMode", 2);
|
|
||||||
else if (value === I18n.tr("Connected") && SettingsData.frameEnabled) {
|
else if (value === I18n.tr("Connected") && SettingsData.frameEnabled) {
|
||||||
if (SettingsData.directionalAnimationMode !== 3)
|
if (SettingsData.directionalAnimationMode !== 3)
|
||||||
SettingsData.set("previousDirectionalMode", SettingsData.directionalAnimationMode);
|
SettingsData.set("previousDirectionalMode", 1);
|
||||||
SettingsData.set("directionalAnimationMode", 3);
|
SettingsData.set("directionalAnimationMode", 3);
|
||||||
} else
|
} else
|
||||||
SettingsData.set("directionalAnimationMode", 0);
|
SettingsData.set("directionalAnimationMode", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,10 +202,9 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function unloadDankDash() {
|
function unloadDankDash() {
|
||||||
if (!dankDashPopoutLoader)
|
// DankDash is intentionally kept alive after first use. Destroying this
|
||||||
return;
|
// lazy popout during its close signal can invalidate connected overlay
|
||||||
dankDashPopout = null;
|
// bindings while Qt is still unwinding the signal stack.
|
||||||
dankDashPopoutLoader.active = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleDankDash(tabIndex, x, y, width, section, screen) {
|
function toggleDankDash(tabIndex, x, y, width, section, screen) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -16,10 +17,10 @@ Item {
|
|||||||
property string triggerSection: ""
|
property string triggerSection: ""
|
||||||
property string positioning: "center"
|
property string positioning: "center"
|
||||||
property int animationDuration: Theme.popoutAnimationDuration
|
property int animationDuration: Theme.popoutAnimationDuration
|
||||||
property real animationScaleCollapsed: 0.96
|
property real animationScaleCollapsed: Theme.effectScaleCollapsed
|
||||||
property real animationOffset: Theme.spacingL
|
property real animationOffset: Theme.effectAnimOffset
|
||||||
property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
|
property list<real> animationEnterCurve: Theme.variantPopoutEnterCurve
|
||||||
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
property list<real> animationExitCurve: Theme.variantPopoutExitCurve
|
||||||
property bool suspendShadowWhileResizing: false
|
property bool suspendShadowWhileResizing: false
|
||||||
property bool shouldBeVisible: false
|
property bool shouldBeVisible: false
|
||||||
property var customKeyboardFocus: null
|
property var customKeyboardFocus: null
|
||||||
@@ -73,6 +74,7 @@ Item {
|
|||||||
readonly property real barY: impl.item ? impl.item.barY : 0
|
readonly property real barY: impl.item ? impl.item.barY : 0
|
||||||
readonly property real barWidth: impl.item ? impl.item.barWidth : 0
|
readonly property real barWidth: impl.item ? impl.item.barWidth : 0
|
||||||
readonly property real barHeight: impl.item ? impl.item.barHeight : 0
|
readonly property real barHeight: impl.item ? impl.item.barHeight : 0
|
||||||
|
readonly property bool useConnectedBackend: SettingsData.connectedFrameModeActive && !!screen && SettingsData.isScreenInPreferences(screen, SettingsData.frameScreenPreferences)
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
if (impl.item)
|
if (impl.item)
|
||||||
@@ -118,7 +120,8 @@ Item {
|
|||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: impl
|
id: impl
|
||||||
sourceComponent: SettingsData.connectedFrameModeActive ? connectedComp : standaloneComp
|
active: root.screen !== null
|
||||||
|
sourceComponent: root.useConnectedBackend ? connectedComp : standaloneComp
|
||||||
onItemChanged: if (item)
|
onItemChanged: if (item)
|
||||||
root._wireBackend(item)
|
root._wireBackend(item)
|
||||||
}
|
}
|
||||||
@@ -166,16 +169,7 @@ Item {
|
|||||||
it.effectiveBarPosition = Qt.binding(() => root.effectiveBarPosition);
|
it.effectiveBarPosition = Qt.binding(() => root.effectiveBarPosition);
|
||||||
it.effectiveBarBottomGap = Qt.binding(() => root.effectiveBarBottomGap);
|
it.effectiveBarBottomGap = Qt.binding(() => root.effectiveBarBottomGap);
|
||||||
|
|
||||||
// shouldBeVisible is two-way — backend's open()/close() flips it internally.
|
|
||||||
it.shouldBeVisible = root.shouldBeVisible;
|
it.shouldBeVisible = root.shouldBeVisible;
|
||||||
it.shouldBeVisibleChanged.connect(function () {
|
|
||||||
if (root.shouldBeVisible !== it.shouldBeVisible)
|
|
||||||
root.shouldBeVisible = it.shouldBeVisible;
|
|
||||||
});
|
|
||||||
|
|
||||||
it.opened.connect(root.opened);
|
|
||||||
it.popoutClosed.connect(root.popoutClosed);
|
|
||||||
it.backgroundClicked.connect(root.backgroundClicked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function primeContent() {
|
function primeContent() {
|
||||||
@@ -197,4 +191,26 @@ Item {
|
|||||||
impl.item.shouldBeVisible = root.shouldBeVisible;
|
impl.item.shouldBeVisible = root.shouldBeVisible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Connections {
|
||||||
|
target: impl.item
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onShouldBeVisibleChanged() {
|
||||||
|
if (impl.item && root.shouldBeVisible !== impl.item.shouldBeVisible)
|
||||||
|
root.shouldBeVisible = impl.item.shouldBeVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOpened() {
|
||||||
|
root.opened();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPopoutClosed() {
|
||||||
|
root.popoutClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onBackgroundClicked() {
|
||||||
|
root.backgroundClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ Item {
|
|||||||
property int _connectedChromeSerial: 0
|
property int _connectedChromeSerial: 0
|
||||||
property real _chromeAnimTravelX: 1
|
property real _chromeAnimTravelX: 1
|
||||||
property real _chromeAnimTravelY: 1
|
property real _chromeAnimTravelY: 1
|
||||||
|
property bool _fullSyncQueued: false
|
||||||
|
|
||||||
property real storedBarThickness: Theme.barHeight - 4
|
property real storedBarThickness: Theme.barHeight - 4
|
||||||
property real storedBarSpacing: 4
|
property real storedBarSpacing: 4
|
||||||
@@ -262,7 +263,14 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _queueFullSync() {
|
function _queueFullSync() {
|
||||||
_syncPopoutChromeState();
|
if (_fullSyncQueued)
|
||||||
|
return;
|
||||||
|
_fullSyncQueued = true;
|
||||||
|
Qt.callLater(() => {
|
||||||
|
root._fullSyncQueued = false;
|
||||||
|
if (typeof root._syncPopoutChromeState === "function")
|
||||||
|
root._syncPopoutChromeState();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onAlignedXChanged: _queueFullSync()
|
onAlignedXChanged: _queueFullSync()
|
||||||
@@ -272,8 +280,8 @@ Item {
|
|||||||
onContentAnimYChanged: _syncPopoutAnim("y")
|
onContentAnimYChanged: _syncPopoutAnim("y")
|
||||||
onRenderedAlignedYChanged: _syncPopoutBody()
|
onRenderedAlignedYChanged: _syncPopoutBody()
|
||||||
onRenderedAlignedHeightChanged: _syncPopoutBody()
|
onRenderedAlignedHeightChanged: _syncPopoutBody()
|
||||||
onScreenChanged: _syncPopoutChromeState()
|
onScreenChanged: _queueFullSync()
|
||||||
onEffectiveBarPositionChanged: _syncPopoutChromeState()
|
onEffectiveBarPositionChanged: _queueFullSync()
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: contentWindow
|
target: contentWindow
|
||||||
@@ -493,8 +501,8 @@ Item {
|
|||||||
if (Theme.isConnectedEffect)
|
if (Theme.isConnectedEffect)
|
||||||
return Math.max(storedBarSpacing + Theme.connectedCornerRadius + 4, 40);
|
return Math.max(storedBarSpacing + Theme.connectedCornerRadius + 4, 40);
|
||||||
if (Theme.isDirectionalEffect) {
|
if (Theme.isDirectionalEffect) {
|
||||||
if (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode !== 0)
|
if (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode > 0)
|
||||||
return 16; // Slide Behind and Roll Out do not add animationOffset, enabling strict Wayland clipping.
|
return 16; // Fluid uses strict Wayland clipping instead of extra motion padding.
|
||||||
return Math.max(0, animationOffset) + 16;
|
return Math.max(0, animationOffset) + 16;
|
||||||
}
|
}
|
||||||
if (Theme.isDepthEffect)
|
if (Theme.isDepthEffect)
|
||||||
@@ -662,7 +670,7 @@ Item {
|
|||||||
blurEnabled: root.effectiveSurfaceBlurEnabled && !root.frameOwnsConnectedChrome
|
blurEnabled: root.effectiveSurfaceBlurEnabled && !root.frameOwnsConnectedChrome
|
||||||
|
|
||||||
readonly property real s: Math.min(1, contentContainer.scaleValue)
|
readonly property real s: Math.min(1, contentContainer.scaleValue)
|
||||||
readonly property bool trackBlurFromBarEdge: Theme.isConnectedEffect || (typeof SettingsData !== "undefined" && Theme.isDirectionalEffect && SettingsData.directionalAnimationMode !== 2)
|
readonly property bool trackBlurFromBarEdge: Theme.isConnectedEffect || Theme.isDirectionalEffect
|
||||||
|
|
||||||
// Directional popouts clip to the bar edge, so the blur needs to grow from
|
// Directional popouts clip to the bar edge, so the blur needs to grow from
|
||||||
// that same edge instead of translating through the bar before settling.
|
// that same edge instead of translating through the bar before settling.
|
||||||
@@ -790,8 +798,6 @@ Item {
|
|||||||
|
|
||||||
readonly property real offsetX: {
|
readonly property real offsetX: {
|
||||||
if (directionalEffect) {
|
if (directionalEffect) {
|
||||||
if (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2)
|
|
||||||
return 0;
|
|
||||||
if (barLeft)
|
if (barLeft)
|
||||||
return -directionalTravelX;
|
return -directionalTravelX;
|
||||||
if (barRight)
|
if (barRight)
|
||||||
@@ -813,8 +819,6 @@ Item {
|
|||||||
}
|
}
|
||||||
readonly property real offsetY: {
|
readonly property real offsetY: {
|
||||||
if (directionalEffect) {
|
if (directionalEffect) {
|
||||||
if (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2)
|
|
||||||
return 0;
|
|
||||||
if (barBottom)
|
if (barBottom)
|
||||||
return directionalTravelY;
|
return directionalTravelY;
|
||||||
if (barTop)
|
if (barTop)
|
||||||
@@ -838,7 +842,7 @@ Item {
|
|||||||
property real animX: 0
|
property real animX: 0
|
||||||
property real animY: 0
|
property real animY: 0
|
||||||
|
|
||||||
readonly property real computedScaleCollapsed: (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2 && Theme.isDirectionalEffect) ? 0.0 : root.animationScaleCollapsed
|
readonly property real computedScaleCollapsed: root.animationScaleCollapsed
|
||||||
property real scaleValue: computedScaleCollapsed
|
property real scaleValue: computedScaleCollapsed
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -932,19 +936,17 @@ Item {
|
|||||||
return parent.height + clipOversize * 2;
|
return parent.height + clipOversize * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Roll-out clips a wrapper while content and shadow keep full-size geometry.
|
|
||||||
Item {
|
Item {
|
||||||
id: rollOutAdjuster
|
id: rollOutAdjuster
|
||||||
readonly property real baseWidth: contentContainer.width
|
readonly property real baseWidth: contentContainer.width
|
||||||
readonly property real baseHeight: contentContainer.height
|
readonly property real baseHeight: contentContainer.height
|
||||||
readonly property bool isRollOut: typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2 && Theme.isDirectionalEffect
|
|
||||||
|
|
||||||
x: directionalClipMask.x !== 0 ? -directionalClipMask.x : 0
|
x: directionalClipMask.x !== 0 ? -directionalClipMask.x : 0
|
||||||
y: directionalClipMask.y !== 0 ? -directionalClipMask.y : 0
|
y: directionalClipMask.y !== 0 ? -directionalClipMask.y : 0
|
||||||
width: isRollOut && (contentContainer.barLeft || contentContainer.barRight) ? Math.max(0, baseWidth * contentContainer.scaleValue) : baseWidth
|
width: baseWidth
|
||||||
height: isRollOut && (contentContainer.barTop || contentContainer.barBottom) ? Math.max(0, baseHeight * contentContainer.scaleValue) : baseHeight
|
height: baseHeight
|
||||||
|
|
||||||
clip: isRollOut
|
clip: false
|
||||||
|
|
||||||
ElevationShadow {
|
ElevationShadow {
|
||||||
id: shadowSource
|
id: shadowSource
|
||||||
@@ -1028,7 +1030,7 @@ Item {
|
|||||||
opacity: Theme.isDirectionalEffect ? 1 : (shouldBeVisible ? 1 : 0)
|
opacity: Theme.isDirectionalEffect ? 1 : (shouldBeVisible ? 1 : 0)
|
||||||
visible: opacity > 0
|
visible: opacity > 0
|
||||||
|
|
||||||
scale: rollOutAdjuster.isRollOut ? 1.0 : contentContainer.scaleValue
|
scale: contentContainer.scaleValue
|
||||||
x: Theme.snap(contentContainer.animX + (rollOutAdjuster.baseWidth - width) * (1 - scale) * 0.5, root.dpr)
|
x: Theme.snap(contentContainer.animX + (rollOutAdjuster.baseWidth - width) * (1 - scale) * 0.5, root.dpr)
|
||||||
y: Theme.snap(contentContainer.animY + (rollOutAdjuster.baseHeight - height) * (1 - scale) * 0.5, root.dpr)
|
y: Theme.snap(contentContainer.animY + (rollOutAdjuster.baseHeight - height) * (1 - scale) * 0.5, root.dpr)
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ Item {
|
|||||||
property string triggerSection: ""
|
property string triggerSection: ""
|
||||||
property string positioning: "center"
|
property string positioning: "center"
|
||||||
property int animationDuration: Theme.popoutAnimationDuration
|
property int animationDuration: Theme.popoutAnimationDuration
|
||||||
property real animationScaleCollapsed: 0.96
|
property real animationScaleCollapsed: Theme.effectScaleCollapsed
|
||||||
property real animationOffset: Theme.spacingL
|
property real animationOffset: Theme.effectAnimOffset
|
||||||
property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
|
property list<real> animationEnterCurve: Theme.variantPopoutEnterCurve
|
||||||
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
property list<real> animationExitCurve: Theme.variantPopoutExitCurve
|
||||||
property bool suspendShadowWhileResizing: false
|
property bool suspendShadowWhileResizing: false
|
||||||
property bool shouldBeVisible: false
|
property bool shouldBeVisible: false
|
||||||
property bool isClosing: false
|
property bool isClosing: false
|
||||||
|
property bool animationsEnabled: true
|
||||||
property var customKeyboardFocus: null
|
property var customKeyboardFocus: null
|
||||||
property bool backgroundInteractive: true
|
property bool backgroundInteractive: true
|
||||||
property bool contentHandlesKeys: false
|
property bool contentHandlesKeys: false
|
||||||
@@ -36,7 +37,13 @@ Item {
|
|||||||
property bool _primeContent: false
|
property bool _primeContent: false
|
||||||
property bool _resizeActive: false
|
property bool _resizeActive: false
|
||||||
property real _surfaceMarginLeft: 0
|
property real _surfaceMarginLeft: 0
|
||||||
|
property real _surfaceMarginTop: 0
|
||||||
property real _surfaceW: 0
|
property real _surfaceW: 0
|
||||||
|
property real _surfaceH: 0
|
||||||
|
property real _surfaceBodyX: 0
|
||||||
|
property real _surfaceBodyY: 0
|
||||||
|
property real _surfaceBodyW: 0
|
||||||
|
property real _surfaceBodyH: 0
|
||||||
|
|
||||||
property real storedBarThickness: Theme.barHeight - 4
|
property real storedBarThickness: Theme.barHeight - 4
|
||||||
property real storedBarSpacing: 4
|
property real storedBarSpacing: 4
|
||||||
@@ -48,6 +55,26 @@ Item {
|
|||||||
"rightBar": 0
|
"rightBar": 0
|
||||||
})
|
})
|
||||||
property var screen: null
|
property var screen: null
|
||||||
|
readonly property bool frameOnlyNoConnected: SettingsData.frameEnabled && !!screen && SettingsData.isScreenInPreferences(screen, SettingsData.frameScreenPreferences)
|
||||||
|
readonly property bool fluidStandaloneActive: Theme.isDirectionalEffect
|
||||||
|
readonly property bool backgroundDismissWindowRequired: backgroundInteractive
|
||||||
|
readonly property bool backgroundWindowRequired: backgroundDismissWindowRequired || root.overlayContent !== null
|
||||||
|
|
||||||
|
function _frameEdgeInset(side) {
|
||||||
|
if (!screen)
|
||||||
|
return 0;
|
||||||
|
return SettingsData.frameEdgeInsetForSide(screen, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _frameGapMargin(side) {
|
||||||
|
return _frameEdgeInset(side) + Theme.popupDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _edgeClearance(side, popupGap, adjacentInset) {
|
||||||
|
if (frameOnlyNoConnected)
|
||||||
|
return Math.max(adjacentInset, _frameGapMargin(side));
|
||||||
|
return adjacentInset > 0 ? adjacentInset : popupGap;
|
||||||
|
}
|
||||||
|
|
||||||
readonly property real effectiveBarThickness: {
|
readonly property real effectiveBarThickness: {
|
||||||
const padding = storedBarConfig ? (storedBarConfig.innerPadding !== undefined ? storedBarConfig.innerPadding : 4) : 4;
|
const padding = storedBarConfig ? (storedBarConfig.innerPadding !== undefined ? storedBarConfig.innerPadding : 4) : 4;
|
||||||
@@ -150,13 +177,60 @@ Item {
|
|||||||
setBarContext(pos, bottomGap);
|
setBarContext(pos, bottomGap);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property bool useBackgroundWindow: !CompositorService.isHyprland || CompositorService.useHyprlandFocusGrab
|
function _setSurfaceGeometry(bodyX, bodyY, bodyW, bodyH) {
|
||||||
|
_surfaceBodyX = Theme.snap(bodyX, dpr);
|
||||||
|
_surfaceBodyY = Theme.snap(bodyY, dpr);
|
||||||
|
_surfaceBodyW = Theme.snap(bodyW, dpr);
|
||||||
|
_surfaceBodyH = Theme.snap(bodyH, dpr);
|
||||||
|
_surfaceMarginLeft = _surfaceBodyX - shadowBuffer;
|
||||||
|
_surfaceMarginTop = _surfaceBodyY - shadowBuffer;
|
||||||
|
_surfaceW = _surfaceBodyW + shadowBuffer * 2;
|
||||||
|
_surfaceH = _surfaceBodyH + shadowBuffer * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _setSettledSurfaceGeometry() {
|
||||||
|
if (shouldBeVisible) {
|
||||||
|
_setSurfaceGeometry(alignedX, alignedY, alignedWidth, alignedHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _setAnimatedSurfaceEnvelope() {
|
||||||
|
if (!shouldBeVisible)
|
||||||
|
return;
|
||||||
|
if (!fluidStandaloneActive) {
|
||||||
|
_setSettledSurfaceGeometry();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentY = renderedAlignedY;
|
||||||
|
const currentBottom = renderedAlignedY + renderedAlignedHeight;
|
||||||
|
const targetY = alignedY;
|
||||||
|
const targetBottom = alignedY + alignedHeight;
|
||||||
|
const existingY = _surfaceBodyH > 0 ? _surfaceBodyY : currentY;
|
||||||
|
const existingBottom = _surfaceBodyH > 0 ? _surfaceBodyY + _surfaceBodyH : currentBottom;
|
||||||
|
const envelopeY = Math.min(currentY, targetY, existingY);
|
||||||
|
const envelopeBottom = Math.max(currentBottom, targetBottom, existingBottom);
|
||||||
|
_setSurfaceGeometry(alignedX, envelopeY, alignedWidth, Math.max(0, envelopeBottom - envelopeY));
|
||||||
|
surfaceSettleTimer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
function updateSurfacePosition() {
|
function updateSurfacePosition() {
|
||||||
if (useBackgroundWindow && shouldBeVisible) {
|
_setSettledSurfaceGeometry();
|
||||||
_surfaceMarginLeft = alignedX - shadowBuffer;
|
}
|
||||||
_surfaceW = alignedWidth + shadowBuffer * 2;
|
|
||||||
}
|
onAlignedXChanged: {
|
||||||
|
if (shouldBeVisible)
|
||||||
|
_setAnimatedSurfaceEnvelope();
|
||||||
|
}
|
||||||
|
|
||||||
|
onAlignedYChanged: {
|
||||||
|
if (shouldBeVisible)
|
||||||
|
_setAnimatedSurfaceEnvelope();
|
||||||
|
}
|
||||||
|
|
||||||
|
onAlignedWidthChanged: {
|
||||||
|
if (shouldBeVisible)
|
||||||
|
_setAnimatedSurfaceEnvelope();
|
||||||
}
|
}
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
@@ -164,6 +238,8 @@ Item {
|
|||||||
return;
|
return;
|
||||||
closeTimer.stop();
|
closeTimer.stop();
|
||||||
isClosing = false;
|
isClosing = false;
|
||||||
|
animationsEnabled = false;
|
||||||
|
_primeContent = true;
|
||||||
|
|
||||||
_frozenMaskX = maskX;
|
_frozenMaskX = maskX;
|
||||||
_frozenMaskY = maskY;
|
_frozenMaskY = maskY;
|
||||||
@@ -172,20 +248,24 @@ Item {
|
|||||||
|
|
||||||
if (_lastOpenedScreen !== null && _lastOpenedScreen !== screen) {
|
if (_lastOpenedScreen !== null && _lastOpenedScreen !== screen) {
|
||||||
contentWindow.visible = false;
|
contentWindow.visible = false;
|
||||||
if (useBackgroundWindow)
|
backgroundWindow.visible = false;
|
||||||
backgroundWindow.visible = false;
|
|
||||||
}
|
}
|
||||||
_lastOpenedScreen = screen;
|
_lastOpenedScreen = screen;
|
||||||
|
|
||||||
shouldBeVisible = true;
|
if (contentContainer) {
|
||||||
if (useBackgroundWindow) {
|
contentContainer.animX = Theme.snap(contentContainer.offsetX, root.dpr);
|
||||||
_surfaceMarginLeft = alignedX - shadowBuffer;
|
contentContainer.animY = Theme.snap(contentContainer.offsetY, root.dpr);
|
||||||
_surfaceW = alignedWidth + shadowBuffer * 2;
|
contentContainer.scaleValue = contentContainer.computedScaleCollapsed;
|
||||||
}
|
}
|
||||||
if (shouldBeVisible && screen) {
|
|
||||||
if (useBackgroundWindow)
|
_setSurfaceGeometry(alignedX, alignedY, alignedWidth, alignedHeight);
|
||||||
backgroundWindow.visible = true;
|
if (backgroundWindowRequired)
|
||||||
contentWindow.visible = true;
|
backgroundWindow.visible = true;
|
||||||
|
contentWindow.visible = true;
|
||||||
|
|
||||||
|
animationsEnabled = true;
|
||||||
|
shouldBeVisible = true;
|
||||||
|
if (screen) {
|
||||||
PopoutManager.showPopout(popoutHandle);
|
PopoutManager.showPopout(popoutHandle);
|
||||||
opened();
|
opened();
|
||||||
}
|
}
|
||||||
@@ -224,13 +304,12 @@ Item {
|
|||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: closeTimer
|
id: closeTimer
|
||||||
interval: animationDuration
|
interval: Theme.variantCloseInterval(animationDuration)
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (!shouldBeVisible) {
|
if (!shouldBeVisible) {
|
||||||
isClosing = false;
|
isClosing = false;
|
||||||
contentWindow.visible = false;
|
contentWindow.visible = false;
|
||||||
if (useBackgroundWindow)
|
backgroundWindow.visible = false;
|
||||||
backgroundWindow.visible = false;
|
|
||||||
PopoutManager.hidePopout(popoutHandle);
|
PopoutManager.hidePopout(popoutHandle);
|
||||||
popoutClosed();
|
popoutClosed();
|
||||||
}
|
}
|
||||||
@@ -244,12 +323,35 @@ Item {
|
|||||||
readonly property var shadowLevel: Theme.elevationLevel3
|
readonly property var shadowLevel: Theme.elevationLevel3
|
||||||
readonly property real shadowFallbackOffset: 6
|
readonly property real shadowFallbackOffset: 6
|
||||||
readonly property real shadowRenderPadding: (Theme.elevationEnabled && SettingsData.popoutElevationEnabled) ? Theme.elevationRenderPadding(shadowLevel, effectiveShadowDirection, shadowFallbackOffset, 8, 16) : 0
|
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 shadowMotionPadding: fluidStandaloneActive ? 0 : Math.max(0, animationOffset)
|
||||||
readonly property real shadowBuffer: Theme.snap(shadowRenderPadding + shadowMotionPadding, dpr)
|
readonly property real shadowBuffer: Theme.snap(shadowRenderPadding + shadowMotionPadding, dpr)
|
||||||
readonly property real alignedWidth: Theme.px(popupWidth, dpr)
|
readonly property real alignedWidth: Theme.px(popupWidth, dpr)
|
||||||
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
||||||
|
property real renderedAlignedY: alignedY
|
||||||
|
property real renderedAlignedHeight: alignedHeight
|
||||||
|
readonly property bool renderedGeometryGrowing: alignedHeight >= renderedAlignedHeight
|
||||||
|
|
||||||
|
Behavior on renderedAlignedY {
|
||||||
|
enabled: root.animationsEnabled && fluidStandaloneActive && contentWindow.visible && root.shouldBeVisible
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.variantDuration(root.animationDuration, root.renderedGeometryGrowing)
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: root.renderedGeometryGrowing ? root.animationEnterCurve : root.animationExitCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on renderedAlignedHeight {
|
||||||
|
enabled: root.animationsEnabled && fluidStandaloneActive && contentWindow.visible && root.shouldBeVisible
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.variantDuration(root.animationDuration, root.renderedGeometryGrowing)
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: root.renderedGeometryGrowing ? root.animationEnterCurve : root.animationExitCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onAlignedHeightChanged: {
|
onAlignedHeightChanged: {
|
||||||
|
if (shouldBeVisible)
|
||||||
|
_setAnimatedSurfaceEnvelope();
|
||||||
if (!suspendShadowWhileResizing || !shouldBeVisible)
|
if (!suspendShadowWhileResizing || !shouldBeVisible)
|
||||||
return;
|
return;
|
||||||
_resizeActive = true;
|
_resizeActive = true;
|
||||||
@@ -261,6 +363,10 @@ Item {
|
|||||||
resizeSettleTimer.stop();
|
resizeSettleTimer.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onBackgroundWindowRequiredChanged: {
|
||||||
|
if (shouldBeVisible)
|
||||||
|
backgroundWindow.visible = backgroundWindowRequired;
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: resizeSettleTimer
|
id: resizeSettleTimer
|
||||||
@@ -269,20 +375,29 @@ Item {
|
|||||||
onTriggered: root._resizeActive = false
|
onTriggered: root._resizeActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: surfaceSettleTimer
|
||||||
|
interval: Math.max(0, Theme.variantDuration(root.animationDuration, root.renderedGeometryGrowing) + 32)
|
||||||
|
repeat: false
|
||||||
|
onTriggered: root._setSettledSurfaceGeometry()
|
||||||
|
}
|
||||||
|
|
||||||
readonly property real alignedX: Theme.snap((() => {
|
readonly property real alignedX: Theme.snap((() => {
|
||||||
const useAutoGaps = storedBarConfig?.popupGapsAuto !== undefined ? storedBarConfig.popupGapsAuto : true;
|
const useAutoGaps = storedBarConfig?.popupGapsAuto !== undefined ? storedBarConfig.popupGapsAuto : true;
|
||||||
const manualGapValue = storedBarConfig?.popupGapsManual !== undefined ? storedBarConfig.popupGapsManual : 4;
|
const manualGapValue = storedBarConfig?.popupGapsManual !== undefined ? storedBarConfig.popupGapsManual : 4;
|
||||||
const popupGap = useAutoGaps ? Math.max(4, storedBarSpacing) : manualGapValue;
|
const popupGap = useAutoGaps ? Math.max(4, storedBarSpacing) : manualGapValue;
|
||||||
|
const leftGap = _edgeClearance("left", popupGap, adjacentBarInfo.leftBar > 0 ? adjacentBarInfo.leftBar : 0);
|
||||||
|
const rightGap = _edgeClearance("right", popupGap, adjacentBarInfo.rightBar > 0 ? adjacentBarInfo.rightBar : 0);
|
||||||
|
|
||||||
switch (effectiveBarPosition) {
|
switch (effectiveBarPosition) {
|
||||||
case SettingsData.Position.Left:
|
case SettingsData.Position.Left:
|
||||||
return Math.max(popupGap, Math.min(screenWidth - popupWidth - popupGap, triggerX));
|
return Math.max(leftGap, Math.min(screenWidth - popupWidth - rightGap, triggerX));
|
||||||
case SettingsData.Position.Right:
|
case SettingsData.Position.Right:
|
||||||
return Math.max(popupGap, Math.min(screenWidth - popupWidth - popupGap, triggerX - popupWidth));
|
return Math.max(leftGap, Math.min(screenWidth - popupWidth - rightGap, triggerX - popupWidth));
|
||||||
default:
|
default:
|
||||||
const rawX = triggerX + (triggerWidth / 2) - (popupWidth / 2);
|
const rawX = triggerX + (triggerWidth / 2) - (popupWidth / 2);
|
||||||
const minX = adjacentBarInfo.leftBar > 0 ? adjacentBarInfo.leftBar : popupGap;
|
const minX = leftGap;
|
||||||
const maxX = screenWidth - popupWidth - (adjacentBarInfo.rightBar > 0 ? adjacentBarInfo.rightBar : popupGap);
|
const maxX = screenWidth - popupWidth - rightGap;
|
||||||
return Math.max(minX, Math.min(maxX, rawX));
|
return Math.max(minX, Math.min(maxX, rawX));
|
||||||
}
|
}
|
||||||
})(), dpr)
|
})(), dpr)
|
||||||
@@ -291,16 +406,18 @@ Item {
|
|||||||
const useAutoGaps = storedBarConfig?.popupGapsAuto !== undefined ? storedBarConfig.popupGapsAuto : true;
|
const useAutoGaps = storedBarConfig?.popupGapsAuto !== undefined ? storedBarConfig.popupGapsAuto : true;
|
||||||
const manualGapValue = storedBarConfig?.popupGapsManual !== undefined ? storedBarConfig.popupGapsManual : 4;
|
const manualGapValue = storedBarConfig?.popupGapsManual !== undefined ? storedBarConfig.popupGapsManual : 4;
|
||||||
const popupGap = useAutoGaps ? Math.max(4, storedBarSpacing) : manualGapValue;
|
const popupGap = useAutoGaps ? Math.max(4, storedBarSpacing) : manualGapValue;
|
||||||
|
const topGap = _edgeClearance("top", popupGap, adjacentBarInfo.topBar > 0 ? adjacentBarInfo.topBar : 0);
|
||||||
|
const bottomGap = _edgeClearance("bottom", popupGap, adjacentBarInfo.bottomBar > 0 ? adjacentBarInfo.bottomBar : 0);
|
||||||
|
|
||||||
switch (effectiveBarPosition) {
|
switch (effectiveBarPosition) {
|
||||||
case SettingsData.Position.Bottom:
|
case SettingsData.Position.Bottom:
|
||||||
return Math.max(popupGap, Math.min(screenHeight - popupHeight - popupGap, triggerY - popupHeight));
|
return Math.max(topGap, Math.min(screenHeight - popupHeight - bottomGap, triggerY - popupHeight));
|
||||||
case SettingsData.Position.Top:
|
case SettingsData.Position.Top:
|
||||||
return Math.max(popupGap, Math.min(screenHeight - popupHeight - popupGap, triggerY));
|
return Math.max(topGap, Math.min(screenHeight - popupHeight - bottomGap, triggerY));
|
||||||
default:
|
default:
|
||||||
const rawY = triggerY - (popupHeight / 2);
|
const rawY = triggerY - (popupHeight / 2);
|
||||||
const minY = adjacentBarInfo.topBar > 0 ? adjacentBarInfo.topBar : popupGap;
|
const minY = topGap;
|
||||||
const maxY = screenHeight - popupHeight - (adjacentBarInfo.bottomBar > 0 ? adjacentBarInfo.bottomBar : popupGap);
|
const maxY = screenHeight - popupHeight - bottomGap;
|
||||||
return Math.max(minY, Math.min(maxY, rawY));
|
return Math.max(minY, Math.min(maxY, rawY));
|
||||||
}
|
}
|
||||||
})(), dpr)
|
})(), dpr)
|
||||||
@@ -355,35 +472,38 @@ Item {
|
|||||||
|
|
||||||
mask: Region {
|
mask: Region {
|
||||||
item: maskRect
|
item: maskRect
|
||||||
|
Region {
|
||||||
|
item: contentHoleRect
|
||||||
|
intersection: Intersection.Subtract
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: maskRect
|
id: maskRect
|
||||||
visible: false
|
visible: false
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
x: root._frozenMaskX
|
x: root.backgroundDismissWindowRequired ? root._frozenMaskX : 0
|
||||||
y: root._frozenMaskY
|
y: root.backgroundDismissWindowRequired ? root._frozenMaskY : 0
|
||||||
width: (shouldBeVisible && backgroundInteractive) ? root._frozenMaskWidth : 0
|
width: (root.backgroundDismissWindowRequired && shouldBeVisible && backgroundInteractive) ? root._frozenMaskWidth : 0
|
||||||
height: (shouldBeVisible && backgroundInteractive) ? root._frozenMaskHeight : 0
|
height: (root.backgroundDismissWindowRequired && shouldBeVisible && backgroundInteractive) ? root._frozenMaskHeight : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: contentHoleRect
|
||||||
|
visible: false
|
||||||
|
color: "transparent"
|
||||||
|
x: root.backgroundDismissWindowRequired ? root._surfaceBodyX : 0
|
||||||
|
y: root.backgroundDismissWindowRequired ? root._surfaceBodyY : 0
|
||||||
|
width: (root.backgroundDismissWindowRequired && shouldBeVisible) ? root._surfaceBodyW : 0
|
||||||
|
height: (root.backgroundDismissWindowRequired && shouldBeVisible) ? root._surfaceBodyH : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
x: root._frozenMaskX
|
anchors.fill: parent
|
||||||
y: root._frozenMaskY
|
|
||||||
width: root._frozenMaskWidth
|
|
||||||
height: root._frozenMaskHeight
|
|
||||||
hoverEnabled: false
|
hoverEnabled: false
|
||||||
enabled: shouldBeVisible && backgroundInteractive
|
enabled: root.backgroundDismissWindowRequired && shouldBeVisible && backgroundInteractive
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||||
onClicked: mouse => {
|
onClicked: backgroundClicked()
|
||||||
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 {
|
Loader {
|
||||||
@@ -399,15 +519,18 @@ Item {
|
|||||||
screen: root.screen
|
screen: root.screen
|
||||||
visible: false
|
visible: false
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
readonly property bool closeVisualActive: root.shouldBeVisible || root.isClosing
|
||||||
|
|
||||||
WindowBlur {
|
WindowBlur {
|
||||||
id: popoutBlur
|
id: popoutBlur
|
||||||
targetWindow: contentWindow
|
targetWindow: contentWindow
|
||||||
readonly property real s: Math.min(1, contentContainer.scaleValue)
|
readonly property real s: Math.min(1, contentContainer.scaleValue)
|
||||||
blurX: contentContainer.x + contentContainer.width * (1 - s) * 0.5 + Theme.snap(contentContainer.animX, root.dpr)
|
readonly property bool trackBlurFromBarEdge: root.fluidStandaloneActive
|
||||||
blurY: contentContainer.y + contentContainer.height * (1 - s) * 0.5 + Theme.snap(contentContainer.animY, root.dpr)
|
|
||||||
blurWidth: (shouldBeVisible && contentWrapper.opacity > 0) ? contentContainer.width * s : 0
|
blurX: trackBlurFromBarEdge ? contentContainer.x + contentContainer.revealX : contentContainer.x + contentContainer.width * (1 - s) * 0.5 + Theme.snap(contentContainer.animX, root.dpr)
|
||||||
blurHeight: (shouldBeVisible && contentWrapper.opacity > 0) ? contentContainer.height * s : 0
|
blurY: trackBlurFromBarEdge ? contentContainer.y + contentContainer.revealY : contentContainer.y + contentContainer.height * (1 - s) * 0.5 + Theme.snap(contentContainer.animY, root.dpr)
|
||||||
|
blurWidth: (contentWindow.closeVisualActive && contentWrapper.opacity > 0) ? (trackBlurFromBarEdge ? contentContainer.revealWidth : contentContainer.width * s) : 0
|
||||||
|
blurHeight: (contentWindow.closeVisualActive && contentWrapper.opacity > 0) ? (trackBlurFromBarEdge ? contentContainer.revealHeight : contentContainer.height * s) : 0
|
||||||
blurRadius: Theme.cornerRadius
|
blurRadius: Theme.cornerRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,24 +560,20 @@ Item {
|
|||||||
return WlrKeyboardFocus.Exclusive;
|
return WlrKeyboardFocus.Exclusive;
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property bool _fullHeight: useBackgroundWindow && root.fullHeightSurface
|
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
left: true
|
left: true
|
||||||
top: true
|
top: true
|
||||||
right: !useBackgroundWindow
|
|
||||||
bottom: _fullHeight || !useBackgroundWindow
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WlrLayershell.margins {
|
WlrLayershell.margins {
|
||||||
left: useBackgroundWindow ? root._surfaceMarginLeft : 0
|
left: root._surfaceMarginLeft
|
||||||
top: (useBackgroundWindow && !_fullHeight) ? (root.alignedY - shadowBuffer) : 0
|
top: root._surfaceMarginTop
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitWidth: useBackgroundWindow ? root._surfaceW : 0
|
implicitWidth: root._surfaceW
|
||||||
implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
|
implicitHeight: root._surfaceH
|
||||||
|
|
||||||
mask: useBackgroundWindow ? contentInputMask : null
|
mask: contentInputMask
|
||||||
|
|
||||||
Region {
|
Region {
|
||||||
id: contentInputMask
|
id: contentInputMask
|
||||||
@@ -466,140 +585,234 @@ Item {
|
|||||||
visible: false
|
visible: false
|
||||||
x: contentContainer.x
|
x: contentContainer.x
|
||||||
y: contentContainer.y
|
y: contentContainer.y
|
||||||
width: shouldBeVisible ? root.alignedWidth : 0
|
width: contentWindow.closeVisualActive ? root.alignedWidth : 0
|
||||||
height: shouldBeVisible ? root.alignedHeight : 0
|
height: contentWindow.closeVisualActive ? (root.fluidStandaloneActive ? root.renderedAlignedHeight : 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 {
|
Item {
|
||||||
id: contentContainer
|
id: contentContainer
|
||||||
x: useBackgroundWindow ? shadowBuffer : root.alignedX
|
x: shadowBuffer + root.alignedX - root._surfaceBodyX
|
||||||
y: (useBackgroundWindow && !contentWindow._fullHeight) ? shadowBuffer : root.alignedY
|
y: shadowBuffer + (root.fluidStandaloneActive ? root.renderedAlignedY : root.alignedY) - root._surfaceBodyY
|
||||||
width: root.alignedWidth
|
width: root.alignedWidth
|
||||||
height: root.alignedHeight
|
height: root.fluidStandaloneActive ? root.renderedAlignedHeight : root.alignedHeight
|
||||||
|
|
||||||
readonly property bool barTop: effectiveBarPosition === SettingsData.Position.Top
|
readonly property bool barTop: effectiveBarPosition === SettingsData.Position.Top
|
||||||
readonly property bool barBottom: effectiveBarPosition === SettingsData.Position.Bottom
|
readonly property bool barBottom: effectiveBarPosition === SettingsData.Position.Bottom
|
||||||
readonly property bool barLeft: effectiveBarPosition === SettingsData.Position.Left
|
readonly property bool barLeft: effectiveBarPosition === SettingsData.Position.Left
|
||||||
readonly property bool barRight: effectiveBarPosition === SettingsData.Position.Right
|
readonly property bool barRight: effectiveBarPosition === SettingsData.Position.Right
|
||||||
readonly property string connectedBarSide: barTop ? "top" : (barBottom ? "bottom" : (barLeft ? "left" : "right"))
|
readonly property string connectedBarSide: barTop ? "top" : (barBottom ? "bottom" : (barLeft ? "left" : "right"))
|
||||||
readonly property real offsetX: barLeft ? root.animationOffset : (barRight ? -root.animationOffset : 0)
|
readonly property bool directionalEffect: Theme.isDirectionalEffect
|
||||||
readonly property real offsetY: barBottom ? -root.animationOffset : (barTop ? root.animationOffset : 0)
|
readonly property bool depthEffect: Theme.isDepthEffect
|
||||||
|
readonly property real directionalTravelX: Math.max(root.animationOffset, root.alignedWidth + Theme.spacingL)
|
||||||
|
readonly property real directionalTravelY: Math.max(root.animationOffset, root.alignedHeight + Theme.spacingL)
|
||||||
|
readonly property real depthTravel: Math.max(root.animationOffset * 0.7, 28)
|
||||||
|
readonly property real sectionTilt: (triggerSection === "left" ? -1 : (triggerSection === "right" ? 1 : 0))
|
||||||
|
readonly property real offsetX: {
|
||||||
|
if (directionalEffect) {
|
||||||
|
if (barLeft)
|
||||||
|
return -directionalTravelX;
|
||||||
|
if (barRight)
|
||||||
|
return directionalTravelX;
|
||||||
|
if (barTop || barBottom)
|
||||||
|
return 0;
|
||||||
|
return sectionTilt * directionalTravelX * 0.2;
|
||||||
|
}
|
||||||
|
if (depthEffect) {
|
||||||
|
if (barLeft)
|
||||||
|
return -depthTravel;
|
||||||
|
if (barRight)
|
||||||
|
return depthTravel;
|
||||||
|
if (barTop || barBottom)
|
||||||
|
return 0;
|
||||||
|
return sectionTilt * depthTravel * 0.2;
|
||||||
|
}
|
||||||
|
return barLeft ? root.animationOffset : (barRight ? -root.animationOffset : 0);
|
||||||
|
}
|
||||||
|
readonly property real offsetY: {
|
||||||
|
if (directionalEffect) {
|
||||||
|
if (barBottom)
|
||||||
|
return directionalTravelY;
|
||||||
|
if (barTop)
|
||||||
|
return -directionalTravelY;
|
||||||
|
if (barLeft || barRight)
|
||||||
|
return 0;
|
||||||
|
return directionalTravelY;
|
||||||
|
}
|
||||||
|
if (depthEffect) {
|
||||||
|
if (barBottom)
|
||||||
|
return depthTravel;
|
||||||
|
if (barTop)
|
||||||
|
return -depthTravel;
|
||||||
|
if (barLeft || barRight)
|
||||||
|
return 0;
|
||||||
|
return depthTravel;
|
||||||
|
}
|
||||||
|
return barBottom ? -root.animationOffset : (barTop ? root.animationOffset : 0);
|
||||||
|
}
|
||||||
|
|
||||||
property real animX: 0
|
property real animX: 0
|
||||||
property real animY: 0
|
property real animY: 0
|
||||||
property real scaleValue: root.animationScaleCollapsed
|
readonly property real computedScaleCollapsed: root.animationScaleCollapsed
|
||||||
|
property real scaleValue: computedScaleCollapsed
|
||||||
|
readonly property real clampedAnimX: Math.max(-width, Math.min(animX, width))
|
||||||
|
readonly property real clampedAnimY: Math.max(-height, Math.min(animY, height))
|
||||||
|
readonly property real revealWidth: {
|
||||||
|
if (!root.fluidStandaloneActive)
|
||||||
|
return width;
|
||||||
|
if (barLeft)
|
||||||
|
return Theme.snap(Math.max(0, width + clampedAnimX), root.dpr);
|
||||||
|
if (barRight)
|
||||||
|
return Theme.snap(Math.max(0, width - clampedAnimX), root.dpr);
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
readonly property real revealHeight: {
|
||||||
|
if (!root.fluidStandaloneActive)
|
||||||
|
return height;
|
||||||
|
if (barTop)
|
||||||
|
return Theme.snap(Math.max(0, height + clampedAnimY), root.dpr);
|
||||||
|
if (barBottom)
|
||||||
|
return Theme.snap(Math.max(0, height - clampedAnimY), root.dpr);
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
readonly property real revealX: root.fluidStandaloneActive && barRight ? Theme.snap(width - revealWidth, root.dpr) : 0
|
||||||
|
readonly property real revealY: root.fluidStandaloneActive && barBottom ? Theme.snap(height - revealHeight, root.dpr) : 0
|
||||||
|
|
||||||
onOffsetXChanged: animX = Theme.snap(root.shouldBeVisible ? 0 : offsetX, root.dpr)
|
Component.onCompleted: {
|
||||||
onOffsetYChanged: animY = Theme.snap(root.shouldBeVisible ? 0 : offsetY, root.dpr)
|
animX = Theme.snap(root.shouldBeVisible ? 0 : offsetX, root.dpr);
|
||||||
|
animY = Theme.snap(root.shouldBeVisible ? 0 : offsetY, root.dpr);
|
||||||
|
scaleValue = root.shouldBeVisible ? 1.0 : computedScaleCollapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
onOffsetXChanged: {
|
||||||
|
if (!root.shouldBeVisible)
|
||||||
|
animX = Theme.snap(offsetX, root.dpr);
|
||||||
|
}
|
||||||
|
onOffsetYChanged: {
|
||||||
|
if (!root.shouldBeVisible)
|
||||||
|
animY = Theme.snap(offsetY, root.dpr);
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
function onShouldBeVisibleChanged() {
|
function onShouldBeVisibleChanged() {
|
||||||
contentContainer.animX = Theme.snap(root.shouldBeVisible ? 0 : contentContainer.offsetX, root.dpr);
|
contentContainer.animX = Theme.snap(root.shouldBeVisible ? 0 : contentContainer.offsetX, root.dpr);
|
||||||
contentContainer.animY = Theme.snap(root.shouldBeVisible ? 0 : contentContainer.offsetY, root.dpr);
|
contentContainer.animY = Theme.snap(root.shouldBeVisible ? 0 : contentContainer.offsetY, root.dpr);
|
||||||
contentContainer.scaleValue = root.shouldBeVisible ? 1.0 : root.animationScaleCollapsed;
|
contentContainer.scaleValue = root.shouldBeVisible ? 1.0 : contentContainer.computedScaleCollapsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on animX {
|
Behavior on animX {
|
||||||
|
enabled: root.animationsEnabled
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: root.animationDuration
|
duration: Theme.variantDuration(root.animationDuration, root.shouldBeVisible)
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on animY {
|
Behavior on animY {
|
||||||
|
enabled: root.animationsEnabled
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: root.animationDuration
|
duration: Theme.variantDuration(root.animationDuration, root.shouldBeVisible)
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on scaleValue {
|
Behavior on scaleValue {
|
||||||
|
enabled: root.animationsEnabled
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: root.animationDuration
|
duration: Theme.variantDuration(root.animationDuration, root.shouldBeVisible)
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
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 {
|
Item {
|
||||||
id: contentWrapper
|
id: directionalClipMask
|
||||||
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
|
readonly property bool shouldClip: root.fluidStandaloneActive
|
||||||
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 {
|
clip: shouldClip
|
||||||
NumberAnimation {
|
x: shouldClip ? contentContainer.revealX : 0
|
||||||
duration: animationDuration
|
y: shouldClip ? contentContainer.revealY : 0
|
||||||
easing.type: Easing.BezierSpline
|
width: shouldClip ? contentContainer.revealWidth : parent.width
|
||||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
height: shouldClip ? contentContainer.revealHeight : parent.height
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: rollOutAdjuster
|
||||||
|
readonly property real baseWidth: contentContainer.width
|
||||||
|
readonly property real baseHeight: contentContainer.height
|
||||||
|
|
||||||
|
x: directionalClipMask.x !== 0 ? -directionalClipMask.x : 0
|
||||||
|
y: directionalClipMask.y !== 0 ? -directionalClipMask.y : 0
|
||||||
|
width: baseWidth
|
||||||
|
height: baseHeight
|
||||||
|
clip: false
|
||||||
|
|
||||||
|
ElevationShadow {
|
||||||
|
id: shadowSource
|
||||||
|
width: rollOutAdjuster.baseWidth
|
||||||
|
height: rollOutAdjuster.baseHeight
|
||||||
|
opacity: contentWrapper.opacity
|
||||||
|
scale: root.fluidStandaloneActive ? 1 : contentWrapper.scale
|
||||||
|
x: root.fluidStandaloneActive ? 0 : contentWrapper.x
|
||||||
|
y: root.fluidStandaloneActive ? 0 : 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
|
||||||
|
width: rollOutAdjuster.baseWidth
|
||||||
|
height: rollOutAdjuster.baseHeight
|
||||||
|
opacity: Theme.isDirectionalEffect ? 1 : (shouldBeVisible ? 1 : 0)
|
||||||
|
visible: opacity > 0
|
||||||
|
scale: contentContainer.scaleValue
|
||||||
|
transformOrigin: Item.Center
|
||||||
|
x: Theme.snap(contentContainer.animX + (rollOutAdjuster.baseWidth - width) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
|
||||||
|
y: Theme.snap(contentContainer.animY + (rollOutAdjuster.baseHeight - 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 {
|
||||||
|
enabled: !Theme.isDirectionalEffect
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Math.round(Theme.variantDuration(root.animationDuration, root.shouldBeVisible) * Theme.variantOpacityDurationScale)
|
||||||
|
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: rollOutAdjuster.baseWidth
|
||||||
|
height: rollOutAdjuster.baseHeight
|
||||||
|
x: root.fluidStandaloneActive ? 0 : contentWrapper.x
|
||||||
|
y: root.fluidStandaloneActive ? 0 : contentWrapper.y
|
||||||
|
opacity: contentWrapper.opacity
|
||||||
|
scale: root.fluidStandaloneActive ? 1 : contentWrapper.scale
|
||||||
|
visible: contentWrapper.visible
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: "transparent"
|
||||||
|
border.color: BlurService.enabled ? BlurService.borderColor : Theme.outlineMedium
|
||||||
|
border.width: BlurService.borderWidth
|
||||||
|
z: 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user