quickshell: dock fullscreen fallback via HyprlandData IPC, wallpaper folder browsing
This commit is contained in:
parent
db6d732e32
commit
0d06cbb983
2 changed files with 106 additions and 11 deletions
|
|
@ -61,7 +61,15 @@ Scope { // Scope
|
|||
ws => ws.monitor && ws.monitor.name === Hyprland.focusedMonitor?.name)
|
||||
readonly property var activeFullscreenWorkspace: root.focusedWorkspaces.filter(
|
||||
ws => ws.active && ws.toplevels.values.filter(w => w.wayland?.fullscreen)[0] !== undefined)[0]
|
||||
// The workspace scan above walks ext-foreign-toplevel-list, which never
|
||||
// sees standalone `qs -p` windows (souveraine-settings): Hyprland has them
|
||||
// fullscreen but the workspace reports zero toplevels. HyprlandData polls
|
||||
// `hyprctl activewindow -j` — Hyprland's own IPC, the source of truth — so
|
||||
// fall back to it. `fullscreen === 2` is Hyprland's real (not maximized)
|
||||
// fullscreen mode. Primary check stays first: no IPC round-trip when it
|
||||
// already answers.
|
||||
readonly property bool activeMonitorHasFullscreen: root.activeFullscreenWorkspace !== undefined
|
||||
|| HyprlandData.activeWindow?.fullscreen === 2
|
||||
|
||||
function computeDockState() {
|
||||
if (root.activeMonitorHasFullscreen)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,14 @@ import qs.modules.common.widgets
|
|||
ContentPage {
|
||||
forceWidth: true
|
||||
|
||||
readonly property string wallpaperDir: Quickshell.env("HOME") + "/Pictures/Wallpapers"
|
||||
readonly property string homeDir: Quickshell.env("HOME")
|
||||
property string currentDir: homeDir + "/Pictures/Wallpapers"
|
||||
property var quickDirs: [
|
||||
{ name: "Wallpapers", path: homeDir + "/Pictures/Wallpapers", icon: "wallpaper" },
|
||||
{ name: "Pictures", path: homeDir + "/Pictures", icon: "image" },
|
||||
{ name: "Downloads", path: homeDir + "/Downloads", icon: "download" },
|
||||
{ name: "Home", path: homeDir, icon: "home" }
|
||||
]
|
||||
|
||||
ContentSection {
|
||||
icon: "wallpaper"
|
||||
|
|
@ -29,6 +36,54 @@ ContentPage {
|
|||
elide: Text.ElideMiddle
|
||||
}
|
||||
|
||||
// Quick directory buttons
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
spacing: 6
|
||||
|
||||
Repeater {
|
||||
model: quickDirs
|
||||
|
||||
RippleButton {
|
||||
required property var modelData
|
||||
property bool isCurrent: currentDir === modelData.path
|
||||
padding: 8
|
||||
buttonRadius: Appearance.rounding.small
|
||||
toggled: isCurrent
|
||||
colBackgroundToggled: Appearance.colors.colSecondaryContainer
|
||||
colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover
|
||||
colRippleToggled: Appearance.colors.colSecondaryContainerActive
|
||||
|
||||
onClicked: {
|
||||
currentDir = modelData.path;
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: 4
|
||||
MaterialSymbol {
|
||||
iconSize: 16
|
||||
text: modelData.icon
|
||||
color: isCurrent ? Appearance.colors.colOnSecondaryContainer : Appearance.colors.colOnLayer1
|
||||
}
|
||||
StyledText {
|
||||
font.pixelSize: Appearance.font.pixelSize.small
|
||||
text: modelData.name
|
||||
color: isCurrent ? Appearance.colors.colOnSecondaryContainer : Appearance.colors.colOnLayer1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current path display
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
text: currentDir.replace(homeDir, "~")
|
||||
color: Appearance.colors.colSubtext
|
||||
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
|
||||
GridView {
|
||||
id: grid
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -42,14 +97,18 @@ ContentPage {
|
|||
|
||||
model: FolderListModel {
|
||||
id: folderModel
|
||||
folder: "file://" + wallpaperDir
|
||||
nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.webp"]
|
||||
showDirs: false
|
||||
folder: "file://" + currentDir
|
||||
nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.webp", "*.avif"]
|
||||
showDirs: true
|
||||
showDotAndDotDot: false
|
||||
showOnlyReadable: true
|
||||
sortField: FolderListModel.Name
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
required property string filePath
|
||||
required property string fileName
|
||||
required property bool fileIsDir
|
||||
width: grid.cellWidth
|
||||
height: grid.cellHeight
|
||||
|
||||
|
|
@ -58,26 +117,54 @@ ContentPage {
|
|||
anchors.margins: 5
|
||||
radius: Appearance.rounding.small
|
||||
color: Appearance.colors.colLayer1
|
||||
border.width: Config.options.background.wallpaperPath === filePath ? 3 : 0
|
||||
border.width: (!fileIsDir && Config.options.background.wallpaperPath === filePath) ? 3 : 0
|
||||
border.color: Appearance.colors.colPrimary
|
||||
clip: true
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 3
|
||||
source: "file://" + filePath
|
||||
source: fileIsDir ? "" : "file://" + filePath
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
sourceSize.width: 240
|
||||
visible: !fileIsDir
|
||||
}
|
||||
|
||||
// Directory indicator
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
visible: fileIsDir
|
||||
spacing: 4
|
||||
|
||||
MaterialSymbol {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
iconSize: 32
|
||||
text: "folder"
|
||||
color: Appearance.colors.colPrimary
|
||||
}
|
||||
StyledText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||
text: fileName
|
||||
color: Appearance.colors.colOnLayer1
|
||||
elide: Text.ElideRight
|
||||
width: grid.cellWidth - 16
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
// Shell process owns selection + theming.
|
||||
Quickshell.execDetached(["qs", "-c", "souveraine",
|
||||
"ipc", "call", "wallpapers", "apply", filePath]);
|
||||
Config.options.background.wallpaperPath = filePath;
|
||||
if (fileIsDir) {
|
||||
currentDir = filePath;
|
||||
} else {
|
||||
// Shell process owns selection + theming.
|
||||
Quickshell.execDetached(["qs", "-c", "souveraine",
|
||||
"ipc", "call", "wallpapers", "apply", filePath]);
|
||||
Config.options.background.wallpaperPath = filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -87,7 +174,7 @@ ContentPage {
|
|||
StyledText {
|
||||
visible: folderModel.count === 0
|
||||
Layout.fillWidth: true
|
||||
text: Translation.tr("No images in %1").arg(wallpaperDir)
|
||||
text: Translation.tr("No images in %1").arg(currentDir.replace(homeDir, "~"))
|
||||
color: Appearance.colors.colSubtext
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue