Split display layout into its own widget and fix installer early exit
This commit is contained in:
@@ -37,3 +37,4 @@ Card 1.0 Card.qml
|
||||
CardHeader 1.0 CardHeader.qml
|
||||
StatRow 1.0 StatRow.qml
|
||||
CardIconButton 1.0 CardIconButton.qml
|
||||
Chip 1.0 Chip.qml
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Ui
|
||||
import "DisplayModel.js" as DisplayModel
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var shell: null
|
||||
property var manifest: null
|
||||
property bool opened: false
|
||||
|
||||
readonly property string pluginId: (manifest && manifest.id) || "blob.display-layout"
|
||||
readonly property int snapThreshold: 60
|
||||
|
||||
property var monitors: []
|
||||
property string selectedName: ""
|
||||
property bool layoutDirty: false
|
||||
|
||||
readonly property var selectedMonitor: {
|
||||
for (var i = 0; i < root.monitors.length; i++)
|
||||
if (root.monitors[i].name === root.selectedName) return root.monitors[i]
|
||||
return null
|
||||
}
|
||||
|
||||
function open(payloadJson) {
|
||||
root.opened = true
|
||||
root.refresh()
|
||||
}
|
||||
|
||||
function close() {
|
||||
root.opened = false
|
||||
}
|
||||
|
||||
function dismiss() {
|
||||
root.opened = false
|
||||
if (root.shell && typeof root.shell.hide === "function")
|
||||
root.shell.hide(root.pluginId)
|
||||
}
|
||||
|
||||
function run(command) {
|
||||
Quickshell.execDetached(["bash", "-c", command])
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
if (!monitorProc.running) monitorProc.running = true
|
||||
}
|
||||
|
||||
function loadMonitors(raw) {
|
||||
var parsed = DisplayModel.parseMonitors(raw)
|
||||
root.monitors = parsed
|
||||
root.layoutDirty = false
|
||||
if (root.selectedName.length > 0) {
|
||||
for (var i = 0; i < parsed.length; i++)
|
||||
if (parsed[i].name === root.selectedName) return
|
||||
}
|
||||
root.selectedName = parsed.length > 0 ? parsed[0].name : ""
|
||||
}
|
||||
|
||||
// Mutating the array in place would not retrigger the bindings the canvas
|
||||
// reads, so every edit rebuilds it.
|
||||
function replaceMonitor(name, changes) {
|
||||
var next = []
|
||||
for (var i = 0; i < root.monitors.length; i++) {
|
||||
var monitor = root.monitors[i]
|
||||
if (monitor.name !== name) {
|
||||
next.push(monitor)
|
||||
continue
|
||||
}
|
||||
var copy = ({})
|
||||
for (var key in monitor) copy[key] = monitor[key]
|
||||
for (var change in changes) copy[change] = changes[change]
|
||||
next.push(copy)
|
||||
}
|
||||
root.monitors = next
|
||||
root.layoutDirty = true
|
||||
}
|
||||
|
||||
function moveMonitor(name, x, y) {
|
||||
var snapped = DisplayModel.snapPosition(root.monitors, name, x, y, root.snapThreshold)
|
||||
root.replaceMonitor(name, { x: snapped.x, y: snapped.y })
|
||||
}
|
||||
|
||||
function applyMonitor(name) {
|
||||
for (var i = 0; i < root.monitors.length; i++) {
|
||||
if (root.monitors[i].name !== name) continue
|
||||
root.run("blob-display-arrange apply "
|
||||
+ Util.shellQuote(DisplayModel.monitorKeyword(root.monitors[i])))
|
||||
reloadTimer.restart()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function applyLayout() {
|
||||
var keywords = DisplayModel.keywordsFor(root.monitors)
|
||||
var quoted = []
|
||||
for (var i = 0; i < keywords.length; i++) quoted.push(Util.shellQuote(keywords[i]))
|
||||
root.run("blob-display-arrange apply " + quoted.join(" "))
|
||||
root.layoutDirty = false
|
||||
reloadTimer.restart()
|
||||
}
|
||||
|
||||
function resetLayout() {
|
||||
root.run("blob-display-arrange reset")
|
||||
reloadTimer.restart()
|
||||
}
|
||||
|
||||
Process {
|
||||
id: monitorProc
|
||||
command: ["hyprctl", "monitors", "all", "-j"]
|
||||
stdout: StdioCollector { onStreamFinished: root.loadMonitors(text) }
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: reloadTimer
|
||||
interval: 400
|
||||
onTriggered: root.refresh()
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 4000
|
||||
running: root.opened && !root.layoutDirty
|
||||
repeat: true
|
||||
onTriggered: root.refresh()
|
||||
}
|
||||
|
||||
onOpenedChanged: if (root.opened) root.refresh()
|
||||
|
||||
PanelWindow {
|
||||
visible: root.opened
|
||||
anchors { top: true; bottom: true; left: true; right: true }
|
||||
color: "transparent"
|
||||
WlrLayershell.namespace: "blob-display-layout"
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.dismiss()
|
||||
}
|
||||
|
||||
Card {
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: Style.spaceReal(720)
|
||||
implicitHeight: Style.spaceReal(540)
|
||||
fillColor: Util.alpha(Color.background, Style.panelFillAlpha)
|
||||
spacing: Style.spaceReal(10)
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
implicitHeight: Math.max(title.implicitHeight, closeButton.implicitHeight)
|
||||
|
||||
Text {
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Display layout"
|
||||
textFormat: Text.PlainText
|
||||
color: Color.foreground
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.body
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
CardIconButton {
|
||||
id: closeButton
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon: ""
|
||||
onActivated: root.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
text: "Drag a monitor to move it. Edges snap to a neighbour. Changes apply as you drop and last until the session ends."
|
||||
textFormat: Text.PlainText
|
||||
color: Util.alpha(Color.foreground, 0.6)
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
}
|
||||
|
||||
MonitorCanvas {
|
||||
width: parent.width
|
||||
height: Style.spaceReal(220)
|
||||
monitors: root.monitors
|
||||
selectedName: root.selectedName
|
||||
onSelected: function(name) { root.selectedName = name }
|
||||
onMonitorMoved: function(name, x, y) { root.moveMonitor(name, x, y) }
|
||||
onLayoutSettled: root.applyMonitor(root.selectedName)
|
||||
}
|
||||
|
||||
MonitorControls {
|
||||
width: parent.width
|
||||
monitor: root.selectedMonitor
|
||||
monitors: root.monitors
|
||||
onScaleRequested: function(scale) {
|
||||
root.replaceMonitor(root.selectedName, { scale: scale })
|
||||
root.applyMonitor(root.selectedName)
|
||||
}
|
||||
onModeRequested: function(mode) {
|
||||
root.replaceMonitor(root.selectedName, { mode: mode })
|
||||
root.applyMonitor(root.selectedName)
|
||||
}
|
||||
onEnabledRequested: function(enabled) {
|
||||
root.replaceMonitor(root.selectedName, { disabled: !enabled })
|
||||
root.applyMonitor(root.selectedName)
|
||||
}
|
||||
onMirrorRequested: function(target) {
|
||||
root.replaceMonitor(root.selectedName, { mirrorOf: target })
|
||||
root.applyMonitor(root.selectedName)
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Style.spaceReal(6)
|
||||
|
||||
Chip {
|
||||
label: root.layoutDirty ? "Apply all" : "Re-apply all"
|
||||
active: root.layoutDirty
|
||||
onActivated: root.applyLayout()
|
||||
}
|
||||
|
||||
Chip {
|
||||
label: "Reset to monitors.lua"
|
||||
onActivated: root.resetLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"name": "Display layout",
|
||||
"version": "1.0.0",
|
||||
"author": "Blob",
|
||||
"description": "Arrange monitors by dragging, and set their mode, scale, and mirroring",
|
||||
"id": "blob.display-layout",
|
||||
"kinds": [
|
||||
"overlay"
|
||||
],
|
||||
"keepLoaded": true,
|
||||
"entryPoints": {
|
||||
"overlay": "DisplayLayout.qml"
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Ui
|
||||
import "DisplayModel.js" as DisplayModel
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -14,19 +13,14 @@ Item {
|
||||
property bool opened: false
|
||||
|
||||
readonly property string pluginId: (manifest && manifest.id) || "blob.displays"
|
||||
readonly property string home: Quickshell.env("HOME")
|
||||
|
||||
property var monitors: []
|
||||
property var outputs: []
|
||||
property string selectedName: ""
|
||||
property string activeTab: "monitors"
|
||||
property var assignments: ({})
|
||||
property bool layoutDirty: false
|
||||
|
||||
readonly property var selectedMonitor: {
|
||||
for (var i = 0; i < root.monitors.length; i++)
|
||||
if (root.monitors[i].name === root.selectedName) return root.monitors[i]
|
||||
return null
|
||||
}
|
||||
readonly property bool globalMode: root.selectedName === ""
|
||||
readonly property string assignedPath: root.globalMode
|
||||
? "" : String(root.assignments[root.selectedName] || "")
|
||||
|
||||
function open(payloadJson) {
|
||||
root.opened = true
|
||||
@@ -48,19 +42,18 @@ Item {
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
if (!monitorProc.running) monitorProc.running = true
|
||||
if (!outputProc.running) outputProc.running = true
|
||||
if (!assignmentProc.running) assignmentProc.running = true
|
||||
}
|
||||
|
||||
function loadMonitors(raw) {
|
||||
var parsed = DisplayModel.parseMonitors(raw)
|
||||
root.monitors = parsed
|
||||
root.layoutDirty = false
|
||||
if (root.selectedName.length > 0) {
|
||||
for (var i = 0; i < parsed.length; i++)
|
||||
if (parsed[i].name === root.selectedName) return
|
||||
function loadOutputs(raw) {
|
||||
var names = []
|
||||
var lines = String(raw || "").split("\n")
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var line = lines[i].trim()
|
||||
if (line.length > 0) names.push(line)
|
||||
}
|
||||
root.selectedName = parsed.length > 0 ? parsed[0].name : ""
|
||||
root.outputs = names
|
||||
}
|
||||
|
||||
function loadAssignments(raw) {
|
||||
@@ -76,55 +69,13 @@ Item {
|
||||
root.assignments = next
|
||||
}
|
||||
|
||||
// Mutating the array in place would not retrigger the bindings the canvas
|
||||
// reads, so every edit rebuilds it.
|
||||
function replaceMonitor(name, changes) {
|
||||
var next = []
|
||||
for (var i = 0; i < root.monitors.length; i++) {
|
||||
var monitor = root.monitors[i]
|
||||
if (monitor.name !== name) {
|
||||
next.push(monitor)
|
||||
continue
|
||||
}
|
||||
var copy = ({})
|
||||
for (var key in monitor) copy[key] = monitor[key]
|
||||
for (var change in changes) copy[change] = changes[change]
|
||||
next.push(copy)
|
||||
}
|
||||
root.monitors = next
|
||||
root.layoutDirty = true
|
||||
}
|
||||
|
||||
function moveMonitor(name, x, y) {
|
||||
var snapped = DisplayModel.snapPosition(root.monitors, name, x, y, 60)
|
||||
root.replaceMonitor(name, { x: snapped.x, y: snapped.y })
|
||||
}
|
||||
|
||||
function applyMonitor(name) {
|
||||
for (var i = 0; i < root.monitors.length; i++) {
|
||||
if (root.monitors[i].name !== name) continue
|
||||
root.run("blob-display-arrange apply " + Util.shellQuote(DisplayModel.monitorKeyword(root.monitors[i])))
|
||||
function choose(path) {
|
||||
if (root.globalMode) {
|
||||
root.run("blob-bg-set " + Util.shellQuote(path))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function applyLayout() {
|
||||
var keywords = DisplayModel.keywordsFor(root.monitors)
|
||||
var quoted = []
|
||||
for (var i = 0; i < keywords.length; i++) quoted.push(Util.shellQuote(keywords[i]))
|
||||
root.run("blob-display-arrange apply " + quoted.join(" "))
|
||||
root.layoutDirty = false
|
||||
reloadTimer.restart()
|
||||
}
|
||||
|
||||
function resetLayout() {
|
||||
root.run("blob-display-arrange reset")
|
||||
reloadTimer.restart()
|
||||
}
|
||||
|
||||
function assignWallpaper(path) {
|
||||
if (root.selectedName.length === 0) return
|
||||
root.run("blob-bg-monitor " + Util.shellQuote(root.selectedName) + " " + Util.shellQuote(path))
|
||||
root.run("blob-bg-monitor " + Util.shellQuote(root.selectedName)
|
||||
+ " " + Util.shellQuote(path))
|
||||
var next = ({})
|
||||
for (var key in root.assignments) next[key] = root.assignments[key]
|
||||
next[root.selectedName] = path
|
||||
@@ -132,7 +83,7 @@ Item {
|
||||
}
|
||||
|
||||
function clearAssignment() {
|
||||
if (root.selectedName.length === 0) return
|
||||
if (root.globalMode) return
|
||||
root.run("blob-bg-monitor " + Util.shellQuote(root.selectedName) + " --clear")
|
||||
var next = ({})
|
||||
for (var key in root.assignments)
|
||||
@@ -140,14 +91,10 @@ Item {
|
||||
root.assignments = next
|
||||
}
|
||||
|
||||
function setGlobalWallpaper(path) {
|
||||
root.run("blob-bg-set " + Util.shellQuote(path))
|
||||
}
|
||||
|
||||
Process {
|
||||
id: monitorProc
|
||||
command: ["hyprctl", "monitors", "all", "-j"]
|
||||
stdout: StdioCollector { onStreamFinished: root.loadMonitors(text) }
|
||||
id: outputProc
|
||||
command: ["bash", "-c", "hyprctl monitors -j | jq -r '.[].name'"]
|
||||
stdout: StdioCollector { onStreamFinished: root.loadOutputs(text) }
|
||||
}
|
||||
|
||||
Process {
|
||||
@@ -159,24 +106,13 @@ Item {
|
||||
stdout: StdioCollector { onStreamFinished: root.loadAssignments(text) }
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: reloadTimer
|
||||
interval: 400
|
||||
onTriggered: root.refresh()
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 4000
|
||||
running: root.opened && !root.layoutDirty
|
||||
repeat: true
|
||||
onTriggered: root.refresh()
|
||||
}
|
||||
onOpenedChanged: if (root.opened) root.refresh()
|
||||
|
||||
PanelWindow {
|
||||
visible: root.opened
|
||||
anchors { top: true; bottom: true; left: true; right: true }
|
||||
color: "transparent"
|
||||
WlrLayershell.namespace: "blob-displays"
|
||||
WlrLayershell.namespace: "blob-wallpapers"
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
@@ -188,20 +124,20 @@ Item {
|
||||
|
||||
Card {
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: Style.spaceReal(760)
|
||||
implicitHeight: Style.spaceReal(560)
|
||||
implicitWidth: Style.spaceReal(720)
|
||||
implicitHeight: Style.spaceReal(520)
|
||||
fillColor: Util.alpha(Color.background, Style.panelFillAlpha)
|
||||
spacing: Style.spaceReal(10)
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
implicitHeight: Math.max(title.implicitHeight, tabs.implicitHeight)
|
||||
implicitHeight: Math.max(title.implicitHeight, closeButton.implicitHeight)
|
||||
|
||||
Text {
|
||||
id: title
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Displays"
|
||||
text: "Wallpapers"
|
||||
textFormat: Text.PlainText
|
||||
color: Color.foreground
|
||||
font.family: Style.font.family
|
||||
@@ -209,136 +145,73 @@ Item {
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Row {
|
||||
id: tabs
|
||||
CardIconButton {
|
||||
id: closeButton
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Style.spaceReal(6)
|
||||
|
||||
Chip {
|
||||
label: "Monitors"
|
||||
active: root.activeTab === "monitors"
|
||||
onActivated: root.activeTab = "monitors"
|
||||
}
|
||||
|
||||
Chip {
|
||||
label: "Wallpapers"
|
||||
active: root.activeTab === "wallpapers"
|
||||
onActivated: root.activeTab = "wallpapers"
|
||||
}
|
||||
|
||||
CardIconButton {
|
||||
icon: ""
|
||||
onActivated: root.dismiss()
|
||||
}
|
||||
icon: ""
|
||||
onActivated: root.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
MonitorCanvas {
|
||||
Flow {
|
||||
width: parent.width
|
||||
height: Style.spaceReal(200)
|
||||
monitors: root.monitors
|
||||
selectedName: root.selectedName
|
||||
onSelected: function(name) { root.selectedName = name }
|
||||
onMonitorMoved: function(name, x, y) { root.moveMonitor(name, x, y) }
|
||||
onLayoutSettled: root.applyMonitor(root.selectedName)
|
||||
spacing: Style.spaceReal(4)
|
||||
|
||||
Chip {
|
||||
label: "All monitors"
|
||||
active: root.globalMode
|
||||
onActivated: root.selectedName = ""
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.outputs
|
||||
|
||||
Chip {
|
||||
required property var modelData
|
||||
label: root.assignments[modelData]
|
||||
? String(modelData) + " *" : String(modelData)
|
||||
active: root.selectedName === modelData
|
||||
onActivated: root.selectedName = String(modelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: Style.spaceReal(250)
|
||||
implicitHeight: status.implicitHeight
|
||||
|
||||
MonitorControls {
|
||||
anchors.fill: parent
|
||||
visible: root.activeTab === "monitors"
|
||||
monitor: root.selectedMonitor
|
||||
monitors: root.monitors
|
||||
onScaleRequested: function(scale) {
|
||||
root.replaceMonitor(root.selectedName, { scale: scale })
|
||||
root.applyMonitor(root.selectedName)
|
||||
}
|
||||
onModeRequested: function(mode) {
|
||||
root.replaceMonitor(root.selectedName, { mode: mode })
|
||||
root.applyMonitor(root.selectedName)
|
||||
}
|
||||
onEnabledRequested: function(enabled) {
|
||||
root.replaceMonitor(root.selectedName, { disabled: !enabled })
|
||||
root.applyMonitor(root.selectedName)
|
||||
}
|
||||
onMirrorRequested: function(target) {
|
||||
root.replaceMonitor(root.selectedName, { mirrorOf: target })
|
||||
root.applyMonitor(root.selectedName)
|
||||
}
|
||||
Text {
|
||||
id: status
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.globalMode
|
||||
? "Setting the wallpaper for every monitor without its own"
|
||||
: (root.assignedPath.length > 0
|
||||
? root.selectedName + ": " + root.assignedPath.replace(/^.*\//, "")
|
||||
: root.selectedName + ": following the global wallpaper")
|
||||
textFormat: Text.PlainText
|
||||
color: Util.alpha(Color.foreground, 0.7)
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
visible: root.activeTab === "wallpapers"
|
||||
spacing: Style.spaceReal(8)
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
implicitHeight: assignedLabel.implicitHeight
|
||||
|
||||
Text {
|
||||
id: assignedLabel
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.selectedName.length > 0
|
||||
? (root.assignments[root.selectedName]
|
||||
? root.selectedName + ": " + String(root.assignments[root.selectedName]).replace(/^.*\//, "")
|
||||
: root.selectedName + ": following the global wallpaper")
|
||||
: "Select a monitor above"
|
||||
textFormat: Text.PlainText
|
||||
color: Util.alpha(Color.foreground, 0.8)
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
}
|
||||
|
||||
Chip {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
label: "Clear"
|
||||
enabled: root.selectedName.length > 0 && !!root.assignments[root.selectedName]
|
||||
onActivated: root.clearAssignment()
|
||||
}
|
||||
}
|
||||
|
||||
WallpaperGrid {
|
||||
width: parent.width
|
||||
height: parent.height - assignedLabel.implicitHeight - Style.spaceReal(8)
|
||||
polling: root.opened && root.activeTab === "wallpapers"
|
||||
assignedPath: root.selectedName.length > 0
|
||||
? String(root.assignments[root.selectedName] || "") : ""
|
||||
onChosen: function(path) { root.assignWallpaper(path) }
|
||||
}
|
||||
Chip {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
label: "Clear"
|
||||
enabled: !root.globalMode && root.assignedPath.length > 0
|
||||
onActivated: root.clearAssignment()
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
WallpaperGrid {
|
||||
width: parent.width
|
||||
spacing: Style.spaceReal(6)
|
||||
|
||||
Chip {
|
||||
label: root.layoutDirty ? "Apply all" : "Re-apply all"
|
||||
active: root.layoutDirty
|
||||
onActivated: root.applyLayout()
|
||||
}
|
||||
|
||||
Chip {
|
||||
label: "Reset to monitors.lua"
|
||||
onActivated: root.resetLayout()
|
||||
}
|
||||
|
||||
Chip {
|
||||
label: "Set globally"
|
||||
enabled: root.activeTab === "wallpapers" && root.selectedName.length > 0
|
||||
&& !!root.assignments[root.selectedName]
|
||||
onActivated: root.setGlobalWallpaper(String(root.assignments[root.selectedName]))
|
||||
}
|
||||
height: Style.spaceReal(340)
|
||||
polling: root.opened
|
||||
assignedPath: root.globalMode ? "" : root.assignedPath
|
||||
onChosen: function(path) { root.choose(path) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpenedChanged: if (root.opened) root.refresh()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"name": "Displays",
|
||||
"name": "Wallpapers",
|
||||
"version": "1.0.0",
|
||||
"author": "Blob",
|
||||
"description": "Arrange monitors and assign wallpapers per monitor",
|
||||
"description": "Pick wallpapers, globally or per monitor",
|
||||
"id": "blob.displays",
|
||||
"kinds": [
|
||||
"overlay"
|
||||
|
||||
Reference in New Issue
Block a user