simplify things by moving popups into a new layer

This commit is contained in:
lucy 2026-08-28 17:45:45 +02:00
commit 4410d41fb3
10 changed files with 223 additions and 199 deletions

View file

@ -0,0 +1,15 @@
pragma Singleton
import Quickshell
Singleton {
id: root
property string current: ""
property ShellScreen screen: null
function toggle(name, scr) {
current = (current === name && screen === scr) ? "" : name;
screen = scr;
}
function close() {
current = "";
}
}

View file

@ -5,116 +5,87 @@ import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import QtQuick import QtQuick
import qs.widgets import qs.widgets
import qs
import qs.modules.Services import qs.modules.Services
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Controls import QtQuick.Controls
WlrLayershell { Rectangle {
id: win id: root
focus: true
required property ShellScreen barScreen color: Colors.barBg
screen: barScreen radius: Config.cfg.appearance.rounding
Keys.onEscapePressed: event => {
visible: false win.visible = false;
color: 'transparent' event.accepted = true;
layer: WlrLayer.Overlay
exclusionMode: ExclusionMode.Ignore
keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
anchors {
top: true
right: true
}
margins {
top: Config.cfg.bar.height + (Config.cfg.bar.floating ? 20 : 10)
right: Config.cfg.bar.floating ? 10 : 0
} }
implicitWidth: audioLayout.implicitWidth + 10
implicitHeight: audioLayout.implicitHeight + 10
implicitWidth: audioLayout.implicitWidth + 20 ColumnLayout {
implicitHeight: audioLayout.implicitHeight + 20 id: audioLayout
onVisibleChanged: { anchors.centerIn: parent
if (visible) spacing: 8
root.forceActiveFocus();
}
Rectangle { Repeater {
id: root id: audioRep
anchors.fill: parent model: Audio.sinks
focus: true
color: Colors.barBg
radius: Config.cfg.appearance.rounding
Keys.onEscapePressed: event => { delegate: Rectangle {
win.visible = false; id: audioDelContainer
event.accepted = true; Layout.fillWidth: true
} color: Colors.moduleBg
radius: Config.cfg.appearance.rounding / 1.5
required property var modelData
implicitHeight: audioRow.implicitHeight + 8
implicitWidth: audioRow.implicitWidth
ColumnLayout { RowLayout {
id: audioLayout id: audioRow
anchors.centerIn: parent anchors.fill: parent
spacing: 8
Repeater { StyledText {
id: audioRep text: audioDelContainer.modelData.nickname
model: Audio.sinks Layout.leftMargin: 10
Layout.fillWidth: true
delegate: Rectangle { Layout.maximumWidth: 200
id: audioDelContainer elide: Text.ElideRight
Layout.fillWidth: true }
color: Colors.moduleBg StyledIcon {
radius: Config.cfg.appearance.rounding Layout.leftMargin: 10
required property var modelData iconName: Audio.getVolumeIcon(audioDelContainer.modelData)
implicitHeight: audioRow.implicitHeight + 8 MouseArea {
implicitWidth: audioRow.implicitWidth anchors.fill: parent
cursorShape: Qt.PointingHandCursor
RowLayout { acceptedButtons: Qt.LeftButton
id: audioRow onClicked: {
anchors.fill: parent audioDelContainer.modelData.audio.muted = !audioDelContainer.modelData.audio.muted;
StyledText {
text: audioDelContainer.modelData.nickname
Layout.leftMargin: 10
Layout.fillWidth: true
Layout.maximumWidth: 200
elide: Text.ElideRight
}
StyledIcon {
Layout.leftMargin: 10
iconName: Audio.getVolumeIcon(audioDelContainer.modelData)
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton
onClicked: {
audioDelContainer.modelData.audio.muted = !audioDelContainer.modelData.audio.muted;
}
} }
} }
StyledIcon { }
readonly property bool isDefault: audioDelContainer.modelData === Audio.defaultAudio StyledIcon {
readonly property bool isPreferred: audioDelContainer.modelData === Audio.preferredAudio readonly property bool isDefault: audioDelContainer.modelData === Audio.defaultAudio
iconName: isDefault ? "radio-checked-symbolic" : "radio-symbolic" readonly property bool isPreferred: audioDelContainer.modelData === Audio.preferredAudio
opacity: (isPreferred && !isDefault) ? 0.5 : 1.0 iconName: isDefault ? "radio-checked-symbolic" : "radio-symbolic"
MouseArea { opacity: (isPreferred && !isDefault) ? 0.5 : 1.0
anchors.fill: parent MouseArea {
cursorShape: Qt.PointingHandCursor anchors.fill: parent
acceptedButtons: Qt.LeftButton cursorShape: Qt.PointingHandCursor
onClicked: { acceptedButtons: Qt.LeftButton
Audio.setDefaultSink(audioDelContainer.modelData); onClicked: {
} Audio.setDefaultSink(audioDelContainer.modelData);
} }
} }
Slider { }
Layout.rightMargin: 10 Slider {
Layout.rightMargin: 10
focusPolicy: Qt.NoFocus focusPolicy: Qt.NoFocus
value: audioDelContainer.modelData.audio.volume value: audioDelContainer.modelData.audio.volume
from: 0 from: 0
to: 1 to: 1
onMoved: { onMoved: {
audioDelContainer.modelData.audio.volume = value; audioDelContainer.modelData.audio.volume = value;
}
} }
} }
} }

View file

@ -1,107 +1,65 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Wayland
import Quickshell.Widgets import Quickshell.Widgets
import QtQuick import QtQuick
import Qt.labs.folderlistmodel 2.11 import Qt.labs.folderlistmodel 2.11
import qs import qs
import qs.settings import qs.settings
import qs.widgets
BarComponent { Rectangle {
id: main id: wallPicker
implicitWidth: implicitHeight color: "transparent"
required property int screenHeight Rectangle {
StyledIcon { id: container
iconName: "preferences-desktop-wallpaper-symbolic" focus: true
anchors.centerIn: parent anchors.fill: parent
} color: Colors.base02
MouseArea { radius: Config.cfg.appearance.rounding
id: clickHandler GridView {
anchors.fill: main id: wallpaperLayout
acceptedButtons: Qt.LeftButton clip: true
cursorShape: Qt.PointingHandCursor snapMode: GridView.SnapOneRow
onClicked: { flow: GridView.FlowTopToBottom
wallPicker.visible = !wallPicker.visible; cellHeight: container.height
} cellWidth: container.width / 8
}
WlrLayershell {
id: wallPicker
visible: false
exclusionMode: ExclusionMode.Ignore
keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
implicitHeight: main.screenHeight / 8
color: 'transparent'
anchors {
bottom: true
left: true
right: true
}
margins {
bottom: 20
left: 20
right: 20
}
onVisibleChanged: {
if (wallPicker.visible)
container.forceActiveFocus();
}
Rectangle {
id: container
focus: true
Keys.onEscapePressed: {
wallPicker.visible = false;
}
anchors.fill: parent anchors.fill: parent
color: Colors.base02 anchors.centerIn: parent
radius: Config.cfg.appearance.rounding anchors.margins: 10
GridView { model: wallpaperList
id: wallpaperLayout delegate: ClippingRectangle {
id: wallTile
clip: true clip: true
snapMode: GridView.SnapOneRow required property var modelData
flow: GridView.FlowTopToBottom radius: Config.cfg.appearance.rounding / 1.5
cellHeight: container.height color: 'transparent'
cellWidth: container.width / 8 implicitWidth: wallpaperLayout.cellWidth - 20
anchors.fill: parent implicitHeight: wallpaperLayout.cellHeight - 20
anchors.centerIn: parent Image {
anchors.margins: 10 id: wallpaper
model: wallpaperList anchors.fill: parent
delegate: ClippingRectangle { source: wallTile.modelData.filePath
id: wallTile sourceSize.width: 16 * 30
clip: true sourceSize.height: 9 * 30
required property var modelData asynchronous: true
radius: Config.cfg.appearance.rounding / 1.5 cache: true
color: 'transparent' }
implicitWidth: wallpaperLayout.cellWidth - 20 MouseArea {
implicitHeight: wallpaperLayout.cellHeight - 20 id: wpClickHandler
Image { anchors.fill: parent
id: wallpaper cursorShape: Qt.PointingHandCursor
anchors.fill: parent acceptedButtons: Qt.LeftButton
source: wallTile.modelData.filePath hoverEnabled: true
sourceSize.width: 16 * 30 onClicked: {
sourceSize.height: 9 * 30 Config.cfg.wallpaper.wallpaper = wallTile.modelData.filePath;
asynchronous: true Config.save();
cache: true
}
MouseArea {
id: wpClickHandler
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton
hoverEnabled: true
onClicked: {
Config.cfg.wallpaper.wallpaper = wallTile.modelData.filePath;
Config.save();
}
} }
} }
} }
FolderListModel { }
id: wallpaperList FolderListModel {
folder: Qt.resolvedUrl(Config.cfg.wallpaper.wallDir) id: wallpaperList
nameFilters: ["*.png"] folder: Qt.resolvedUrl(Config.cfg.wallpaper.wallDir)
} nameFilters: ["*.png"]
} }
} }
} }

View file

@ -16,7 +16,7 @@ Variants {
left: true left: true
right: true right: true
} }
color: 'transparent' color: 'transparent'
implicitHeight: Config.cfg.bar.height implicitHeight: Config.cfg.bar.height
margins.top: Config.cfg.bar.floating ? 10 : 0 margins.top: Config.cfg.bar.floating ? 10 : 0
@ -46,11 +46,11 @@ Variants {
Mpris {} Mpris {}
Bat {} Bat {}
Tray {} Tray {}
WallPicker { WallPickerButton {barScreen: root.modelData}
screenHeight: root.screen.height
}
Pw {barScreen: root.modelData} Pw {
barScreen: root.modelData
}
Netstatus {} Netstatus {}
} }
} }

View file

@ -30,10 +30,7 @@ BarComponent {
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
anchors.fill: root anchors.fill: root
onClicked: volPopup.visible = !volPopup.visible onClicked: WidgetTracker.toggle("volume", root.barScreen)
}
VolPopup {
barScreen: root.barScreen
id: volPopup
} }
} }

View file

@ -0,0 +1,24 @@
import QtQuick
import qs.widgets
import qs.modules.Services
import Quickshell
BarComponent {
id: main
implicitWidth: implicitHeight
required property ShellScreen barScreen
StyledIcon {
iconName: "preferences-desktop-wallpaper-symbolic"
anchors.centerIn: parent
}
MouseArea {
id: clickHandler
anchors.fill: main
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor
onClicked: {
WidgetTracker.toggle("wallpapers", main.barScreen);
}
}
}

58
modules/overlays/Top.qml Normal file
View file

@ -0,0 +1,58 @@
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.modules.Services
import qs.modules.applets
import qs.settings
Variants {
model: Quickshell.screens
delegate: PanelWindow {
required property ShellScreen modelData
aboveWindows: true
screen: modelData
anchors {
top: true
left: true
bottom: true
right: true
}
exclusionMode: ExclusionMode.Ignore
color: 'transparent'
visible: WidgetTracker.current !== "" && WidgetTracker.screen === modelData
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
Item {
anchors.fill: parent
focus: true
Keys.onEscapePressed: event => {
WidgetTracker.close();
event.accepted = true;
}
VolPopup {
z: 1
visible: WidgetTracker.current === "volume"
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: Config.cfg.bar.floating ? Config.cfg.bar.height + 20 : Config.cfg.bar.height
anchors.rightMargin: 10
}
WallPicker {
z: 1
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 20
implicitWidth: 1000
implicitHeight: 200
visible: WidgetTracker.current === "wallpapers"
}
MouseArea {
z: 0
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: WidgetTracker.close()
}
}
}
}

View file

@ -12,6 +12,6 @@
}, },
"wallpaper": { "wallpaper": {
"wallDir": "/home/lucy/.walls/", "wallDir": "/home/lucy/.walls/",
"wallpaper": "/home/lucy/.walls/frierensuff.png" "wallpaper": "/home/lucy/.walls/walkingcastle.png"
} }
} }

View file

@ -2,12 +2,13 @@
//@ pragma IconTheme Papirus-Dark //@ pragma IconTheme Papirus-Dark
import Quickshell import Quickshell
import qs.modules.bar import qs.modules.bar
import qs.modules.wallpaper
import qs.modules.notifications import qs.modules.notifications
import qs.modules.overlays
import qs.modules.Services import qs.modules.Services
ShellRoot { ShellRoot {
Bar {} Bar {}
Wallpaper {}
NotiPopup {} NotiPopup {}
Bottom {}
Top {}
} }