test popouts

This commit is contained in:
2026-04-16 03:10:20 +02:00
parent 0df32b9e95
commit 55b497f132
10 changed files with 84 additions and 105 deletions
-3
View File
@@ -72,9 +72,6 @@ CustomMouseArea {
} }
} }
onPositionChanged: event => { onPositionChanged: event => {
if (popouts.isDetached)
return;
const x = event.x; const x = event.x;
const y = event.y; const y = event.y;
const dragX = x - dragStart.x; const dragX = x - dragStart.x;
+2 -8
View File
@@ -26,7 +26,8 @@ Item {
readonly property alias launcher: launcher readonly property alias launcher: launcher
readonly property alias notifications: notifications readonly property alias notifications: notifications
readonly property alias osd: osd readonly property alias osd: osd
readonly property alias popouts: popouts readonly property alias popouts: popouts.content
readonly property alias popoutsWrapper: popouts
readonly property alias resources: resources readonly property alias resources: resources
required property ShellScreen screen required property ShellScreen screen
readonly property alias settings: settings readonly property alias settings: settings
@@ -73,13 +74,6 @@ Item {
anchors.top: parent.top anchors.top: parent.top
screen: root.screen screen: root.screen
x: {
const off = currentCenter - nonAnimWidth / 2;
const diff = root.width - Math.floor(off + nonAnimWidth);
if (diff < 0)
return off + diff;
return Math.floor(Math.max(off, 0));
}
} }
Toasts.Toasts { Toasts.Toasts {
+20 -4
View File
@@ -5,6 +5,7 @@ import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Hyprland import Quickshell.Hyprland
import ZShell.Blobs
import qs.Daemons import qs.Daemons
import qs.Components import qs.Components
import qs.Modules import qs.Modules
@@ -161,7 +162,7 @@ Variants {
borderBottom: Config.barConfig.border - anchors.margins borderBottom: Config.barConfig.border - anchors.margins
borderLeft: Config.barConfig.border - anchors.margins borderLeft: Config.barConfig.border - anchors.margins
borderRight: Config.barConfig.border - anchors.margins borderRight: Config.barConfig.border - anchors.margins
borderTop: Config.barConfig.border - anchors.margins borderTop: bar.implicitHeight - anchors.margins
group: blobGroup group: blobGroup
radius: Config.barConfig.rounding radius: Config.barConfig.rounding
} }
@@ -171,6 +172,7 @@ Variants {
deformAmount: 0.1 deformAmount: 0.1
panel: panels.dashboard panel: panels.dashboard
radius: Appearance.rounding.normal
} }
PanelBg { PanelBg {
@@ -178,12 +180,13 @@ Variants {
deformAmount: 0.1 deformAmount: 0.1
panel: panels.launcher panel: panels.launcher
radius: Appearance.rounding.smallest + 5
} }
PanelBg { PanelBg {
id: sidebarBg id: sidebarBg
bottomLeftRadius: Math.max(0, Math.min(1, panels.sidebar.offsetScale / 0.3)) * radius bottomLeftRadius: 0
deformAmount: 0.03 deformAmount: 0.03
exclude: panels.sidebar.offsetscale > 0.08 ? [] : [utilsBg] exclude: panels.sidebar.offsetscale > 0.08 ? [] : [utilsBg]
implicitHeight: panel.height * (1 / rawDeformMatrix.m22) + 2 implicitHeight: panel.height * (1 / rawDeformMatrix.m22) + 2
@@ -195,6 +198,7 @@ Variants {
deformAmount: 0.25 deformAmount: 0.25
panel: panels.osd panel: panels.osd
radius: 20
} }
PanelBg { PanelBg {
@@ -209,7 +213,7 @@ Variants {
deformAmount: panels.sidebar.visible ? 0.1 : 0.15 deformAmount: panels.sidebar.visible ? 0.1 : 0.15
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [sidebarBg] exclude: panels.sidebar.offsetScale > 0.08 ? [] : [sidebarBg]
panel: panels.utilities panel: panels.utilities
topLeftRadius: Math.max(0, Math.min(1, panels.sidebar.offsetScale / 0.3)) * radius topLeftRadius: 0
} }
PanelBg { PanelBg {
@@ -217,7 +221,15 @@ Variants {
deformAmount: 0.15 deformAmount: 0.15
implicitWidth: panels.popouts.width implicitWidth: panels.popouts.width
panel: panels.popouts panel: panels.popoutsWrapper
}
PanelBg {
id: resourcesBg
deformAmount: 0.15
panel: panels.resources
radius: Appearance.rounding.normal
} }
} }
@@ -275,6 +287,9 @@ Variants {
popouts.transform: Matrix4x4 { popouts.transform: Matrix4x4 {
matrix: popoutBg.deformMatrix matrix: popoutBg.deformMatrix
} }
resources.transform: Matrix4x4 {
matrix: resourcesBg.deformMatrix
}
sidebar.transform: Matrix4x4 { sidebar.transform: Matrix4x4 {
matrix: sidebarBg.deformMatrix matrix: sidebarBg.deformMatrix
} }
@@ -289,6 +304,7 @@ Variants {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
popouts: panels.popouts popouts: panels.popouts
popoutsWrapper: panels.popoutsWrapper
screen: scope.modelData screen: scope.modelData
visibilities: visibilities visibilities: visibilities
} }
+1
View File
@@ -16,6 +16,7 @@ RowLayout {
id: root id: root
required property Wrapper popouts required property Wrapper popouts
required property ClipWrapper popoutsWrapper
required property ShellScreen screen required property ShellScreen screen
readonly property int vPadding: 6 readonly property int vPadding: 6
required property PersistentProperties visibilities required property PersistentProperties visibilities
+2
View File
@@ -20,6 +20,7 @@ Item {
property bool isHovered property bool isHovered
readonly property int padding: Math.max(Appearance.padding.smaller, Config.barConfig.border) readonly property int padding: Math.max(Appearance.padding.smaller, Config.barConfig.border)
required property Wrapper popouts required property Wrapper popouts
required property ClipWrapper popoutsWrapper
required property ShellScreen screen required property ShellScreen screen
readonly property bool shouldBeVisible: (!Config.barConfig.autoHide || visibilities.bar || isHovered) readonly property bool shouldBeVisible: (!Config.barConfig.autoHide || visibilities.bar || isHovered)
readonly property int vPadding: 6 readonly property int vPadding: 6
@@ -76,6 +77,7 @@ Item {
sourceComponent: Bar { sourceComponent: Bar {
height: root.contentHeight height: root.contentHeight
popouts: root.popouts popouts: root.popouts
popoutsWrapper: root.popoutsWrapper
screen: root.screen screen: root.screen
visibilities: root.visibilities visibilities: root.visibilities
} }
+13 -6
View File
@@ -9,13 +9,20 @@ Item {
id: root id: root
readonly property alias content: content readonly property alias content: content
property real offsetScale: x > 0 || content.hasCurrent ? 0 : 1 property real offsetScale: y > 0 || content.hasCurrent ? 0 : 1
required property ShellScreen screen required property ShellScreen screen
clip: true clip: true
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight * (1 - offsetScale)
implicitWidth: content.implicitWidth * (1 - offsetScale) implicitWidth: content.implicitWidth
visible: width > 0 && height > 0 visible: width > 0 && height > 0
x: {
const off = content.currentCenter - content.nonAnimWidth / 2;
const diff = parent.width - Math.floor(off + content.nonAnimWidth);
if (diff < 0)
return off + diff;
return Math.floor(Math.max(off, 0));
}
Behavior on offsetScale { Behavior on offsetScale {
Anim { Anim {
@@ -41,9 +48,9 @@ Item {
Wrapper { Wrapper {
id: content id: content
anchors.left: parent.left anchors.horizontalCenter: parent.horizontalCenter
anchors.leftMargin: (-implicitWidth - 5) * root.offsetScale anchors.top: parent.top
anchors.verticalCenter: parent.verticalCenter anchors.topMargin: (-implicitHeight - 5) * root.offsetScale
offsetScale: root.offsetScale offsetScale: root.offsetScale
screen: root.screen screen: root.screen
} }
+8 -17
View File
@@ -15,7 +15,7 @@ Item {
readonly property Item current: currentPopout?.item ?? null readonly property Item current: currentPopout?.item ?? null
readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null
required property Item wrapper required property PopoutState popouts
implicitHeight: (currentPopout?.implicitHeight ?? 0) + 5 * 2 implicitHeight: (currentPopout?.implicitHeight ?? 0) + 5 * 2
implicitWidth: (currentPopout?.implicitWidth ?? 0) + 5 * 2 implicitWidth: (currentPopout?.implicitWidth ?? 0) + 5 * 2
@@ -49,40 +49,31 @@ Item {
Connections { Connections {
function onHasCurrentChanged(): void { function onHasCurrentChanged(): void {
if (root.wrapper.hasCurrent && trayMenu.shouldBeActive) { if (root.popouts.hasCurrent && trayMenu.shouldBeActive) {
trayMenu.sourceComponent = null; trayMenu.sourceComponent = null;
trayMenu.sourceComponent = trayMenuComponent; trayMenu.sourceComponent = trayMenuComponent;
} }
} }
target: root.wrapper target: root.popouts
} }
Component { Component {
id: trayMenuComponent id: trayMenuComponent
TrayMenuPopout { TrayMenuPopout {
popouts: root.wrapper popouts: root.popouts
trayItem: trayMenu.modelData.menu trayItem: trayMenu.modelData.menu
} }
} }
} }
} }
Popout {
name: "overview"
sourceComponent: OverviewPopout {
screen: root.wrapper.screen
wrapper: root.wrapper
}
}
Popout { Popout {
name: "upower" name: "upower"
sourceComponent: UPowerPopout { sourceComponent: UPowerPopout {
wrapper: root.wrapper wrapper: root.popouts
} }
} }
@@ -90,7 +81,7 @@ Item {
name: "network" name: "network"
sourceComponent: NetworkPopout { sourceComponent: NetworkPopout {
wrapper: root.wrapper wrapper: root.popouts
} }
} }
@@ -98,7 +89,7 @@ Item {
name: "updates" name: "updates"
sourceComponent: UpdatesPopout { sourceComponent: UpdatesPopout {
wrapper: root.wrapper wrapper: root.popouts
} }
} }
} }
@@ -107,7 +98,7 @@ Item {
id: popout id: popout
required property string name required property string name
readonly property bool shouldBeActive: root.wrapper.currentName === name readonly property bool shouldBeActive: root.popouts.currentName === name
active: false active: false
anchors.centerIn: parent anchors.centerIn: parent
+8
View File
@@ -0,0 +1,8 @@
import QtQuick
QtObject {
property string currentName
property bool hasCurrent
signal detachRequested(mode: string)
}
+4 -3
View File
@@ -1,18 +1,19 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.Components
import qs.Config
import Quickshell import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Effects import QtQuick.Effects
import qs.Components
import qs.Modules
import qs.Config
StackView { StackView {
id: root id: root
property int biggestWidth: 0 property int biggestWidth: 0
required property Item popouts required property PopoutState popouts
property int rootWidth: 0 property int rootWidth: 0
required property QsMenuHandle trayItem required property QsMenuHandle trayItem
+26 -64
View File
@@ -11,19 +11,16 @@ Item {
property list<real> animCurve: Appearance.anim.curves.expressiveDefaultSpatial property list<real> animCurve: Appearance.anim.curves.expressiveDefaultSpatial
property int animLength: Appearance.anim.durations.expressiveDefaultSpatial property int animLength: Appearance.anim.durations.expressiveDefaultSpatial
readonly property alias content: content readonly property alias content: content
readonly property alias controlCenter: controlCenter
readonly property Item current: (content.item as Content)?.current ?? null readonly property Item current: (content.item as Content)?.current ?? null
property real currentCenter property real currentCenter
property alias currentName: popoutState.currentName property alias currentName: popoutState.currentName
property string detachedMode property string detachedMode
property alias hasCurrent: popoutState.hasCurrent property alias hasCurrent: popoutState.hasCurrent
readonly property bool isDetached: detachedMode.length > 0
readonly property real nonAnimHeight: children.find(c => c.shouldBeActive)?.implicitHeight ?? content.implicitHeight readonly property real nonAnimHeight: children.find(c => c.shouldBeActive)?.implicitHeight ?? content.implicitHeight
readonly property real nonAnimWidth: children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth readonly property real nonAnimWidth: children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth
required property real offsetScale required property real offsetScale
property string queuedMode property string queuedMode
required property ShellScreen screen required property ShellScreen screen
readonly property alias winfo: winfo
function close(): void { function close(): void {
hasCurrent = false; hasCurrent = false;
@@ -67,49 +64,14 @@ Item {
} }
} }
Keys.onEscapePressed: {
// Forward escape to password popout if active, otherwise close
if (currentName === "wirelesspassword" && content.item) {
const passwordPopout = (content.item as Content)?.children.find(c => c.name === "wirelesspassword");
if (passwordPopout && passwordPopout.item) {
passwordPopout.item.closeDialog();
return;
}
}
close();
}
Keys.onPressed: event => {
// Don't intercept keys when password popout is active - let it handle them
if (currentName === "wirelesspassword") {
event.accepted = false;
}
}
PopoutState { PopoutState {
id: popoutState id: popoutState
onDetachRequested: mode => root.detach(mode)
}
HyprlandFocusGrab {
active: root.isDetached
windows: [QsWindow.window]
onCleared: root.close()
}
Binding {
property: "WlrLayershell.keyboardFocus"
target: QsWindow.window
value: WlrKeyboardFocus.OnDemand
when: root.isDetached || (root.hasCurrent && root.currentName === "wirelesspassword")
} }
Comp { Comp {
id: content id: content
anchors.right: parent.right anchors.centerIn: parent
anchors.verticalCenter: parent.verticalCenter
shouldBeActive: root.hasCurrent && !root.detachedMode shouldBeActive: root.hasCurrent && !root.detachedMode
sourceComponent: Content { sourceComponent: Content {
@@ -117,31 +79,31 @@ Item {
} }
} }
Comp { // Comp {
id: winfo // id: winfo
//
anchors.centerIn: parent // anchors.centerIn: parent
shouldBeActive: root.detachedMode === "winfo" // shouldBeActive: root.detachedMode === "winfo"
//
sourceComponent: WindowInfo { // sourceComponent: WindowInfo {
client: Hypr.activeToplevel // client: Hypr.activeToplevel
screen: root.screen // screen: root.screen
} // }
} // }
//
Comp { // Comp {
id: controlCenter // id: controlCenter
//
anchors.centerIn: parent // anchors.centerIn: parent
shouldBeActive: root.detachedMode === "any" // shouldBeActive: root.detachedMode === "any"
//
sourceComponent: ControlCenter { // sourceComponent: ControlCenter {
active: root.queuedMode // active: root.queuedMode
screen: root.screen // screen: root.screen
//
onClose: root.close() // onClose: root.close()
} // }
} // }
component Comp: Loader { component Comp: Loader {
id: comp id: comp