Keep the display layout widget within its card

This commit is contained in:
SirBlob committed 2026-09-24 02:48:01 +00:00
1 parent 96325ff74d
commit 8b0ce5baf3
5 files changed
+72 -29

No files matched your search

+3 -1
View File
@@ -70,7 +70,9 @@ or the Blob menu's Display layout row.
A scaled picture of the desktop, one draggable rectangle per monitor. Dropping A scaled picture of the desktop, one draggable rectangle per monitor. Dropping
one applies the new position immediately. Edges snap to a neighbour's edge one applies the new position immediately. Edges snap to a neighbour's edge
within 60 logical pixels, so monitors end up touching exactly. Per-monitor within 60 logical pixels, so monitors end up touching exactly. Per-monitor
controls: mode, scale, enable or disable, and mirror. controls: mode, scale, enable or disable, and mirror. The panel
shrinks to fit the screen, and when a monitor reports more modes than fit, the
controls scroll while the canvas and the apply buttons stay in view.
**Scale options are filtered, not free.** Hyprland steps fractional scaling in **Scale options are filtered, not free.** Hyprland steps fractional scaling in
1/120 and rejects a scale that does not land on a whole number of physical 1/120 and rejects a scale that does not land on a whole number of physical
+4
View File
@@ -35,8 +35,12 @@ Item {
} }
Text { Text {
anchors.left: labelText.right
anchors.leftMargin: Style.spaceReal(8)
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
elide: Text.ElideRight
text: root.value text: root.value
textFormat: Text.PlainText textFormat: Text.PlainText
color: Color.foreground color: Color.foreground
@@ -130,6 +130,7 @@ Item {
onOpenedChanged: if (root.opened) root.refresh() onOpenedChanged: if (root.opened) root.refresh()
PanelWindow { PanelWindow {
id: panelWindow
visible: root.opened visible: root.opened
anchors { top: true; bottom: true; left: true; right: true } anchors { top: true; bottom: true; left: true; right: true }
color: "transparent" color: "transparent"
@@ -144,22 +145,32 @@ Item {
} }
Card { Card {
id: layoutCard
readonly property real screenMargin: Style.spaceReal(20)
readonly property real maxHeight: panelWindow.height - screenMargin * 2
readonly property real fixedContentHeight: header.height + hint.height + canvas.height
+ actions.height + spacing * 4 + padding * 2
anchors.centerIn: parent anchors.centerIn: parent
implicitWidth: Style.spaceReal(720) implicitWidth: Math.min(Style.spaceReal(720), panelWindow.width - screenMargin * 2)
implicitHeight: Style.spaceReal(540)
fillColor: Util.alpha(Color.background, Style.panelFillAlpha) fillColor: Util.alpha(Color.background, Style.panelFillAlpha)
spacing: Style.spaceReal(10) spacing: Style.spaceReal(10)
Item { Item {
id: header
width: parent.width width: parent.width
implicitHeight: Math.max(title.implicitHeight, closeButton.implicitHeight) implicitHeight: Math.max(title.implicitHeight, closeButton.implicitHeight)
Text { Text {
id: title id: title
anchors.left: parent.left anchors.left: parent.left
anchors.right: closeButton.left
anchors.rightMargin: Style.spaceReal(8)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: "Display layout" text: "Display layout"
textFormat: Text.PlainText textFormat: Text.PlainText
elide: Text.ElideRight
color: Color.foreground color: Color.foreground
font.family: Style.font.family font.family: Style.font.family
font.pixelSize: Style.font.body font.pixelSize: Style.font.body
@@ -170,12 +181,13 @@ Item {
id: closeButton id: closeButton
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
icon: "" icon: "\uf00d"
onActivated: root.dismiss() onActivated: root.dismiss()
} }
} }
Text { Text {
id: hint
width: parent.width width: parent.width
wrapMode: Text.WordWrap 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." text: "Drag a monitor to move it. Edges snap to a neighbour. Changes apply as you drop and last until the session ends."
@@ -186,6 +198,7 @@ Item {
} }
MonitorCanvas { MonitorCanvas {
id: canvas
width: parent.width width: parent.width
height: Style.spaceReal(220) height: Style.spaceReal(220)
monitors: root.monitors monitors: root.monitors
@@ -195,29 +208,42 @@ Item {
onLayoutSettled: root.applyMonitor(root.selectedName) onLayoutSettled: root.applyMonitor(root.selectedName)
} }
MonitorControls { Flickable {
id: controlsScroll
width: parent.width width: parent.width
monitor: root.selectedMonitor height: Math.max(0, Math.min(controls.implicitHeight, layoutCard.maxHeight - layoutCard.fixedContentHeight))
monitors: root.monitors contentWidth: width
onScaleRequested: function(scale) { contentHeight: controls.implicitHeight
root.replaceMonitor(root.selectedName, { scale: scale }) clip: true
root.applyMonitor(root.selectedName) boundsBehavior: Flickable.StopAtBounds
} interactive: contentHeight > height
onModeRequested: function(mode) {
root.replaceMonitor(root.selectedName, { mode: mode }) MonitorControls {
root.applyMonitor(root.selectedName) id: controls
} width: controlsScroll.width
onEnabledRequested: function(enabled) { monitor: root.selectedMonitor
root.replaceMonitor(root.selectedName, { disabled: !enabled }) monitors: root.monitors
root.applyMonitor(root.selectedName) onScaleRequested: function(scale) {
} root.replaceMonitor(root.selectedName, { scale: scale })
onMirrorRequested: function(target) { root.applyMonitor(root.selectedName)
root.replaceMonitor(root.selectedName, { mirrorOf: target }) }
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 { Flow {
id: actions
width: parent.width width: parent.width
spacing: Style.spaceReal(6) spacing: Style.spaceReal(6)
@@ -29,13 +29,17 @@ Rectangle {
: Util.alpha(Color.background, Style.cardFillAlpha) : Util.alpha(Color.background, Style.cardFillAlpha)
border.width: Style.cardBorderWidth border.width: Style.cardBorderWidth
border.color: root.selected ? Color.accent : Util.alpha(Color.blue, Style.cardBorderAlpha) border.color: root.selected ? Color.accent : Util.alpha(Color.blue, Style.cardBorderAlpha)
clip: true
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
width: Math.max(0, root.width - Style.spaceReal(8))
spacing: Style.spaceReal(2) spacing: Style.spaceReal(2)
Text { Text {
anchors.horizontalCenter: parent.horizontalCenter width: parent.width
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
text: root.name text: root.name
textFormat: Text.PlainText textFormat: Text.PlainText
color: Color.foreground color: Color.foreground
@@ -45,7 +49,9 @@ Rectangle {
} }
Text { Text {
anchors.horizontalCenter: parent.horizontalCenter width: parent.width
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
visible: root.height > Style.spaceReal(44) visible: root.height > Style.spaceReal(44)
text: root.monitor ? root.monitor.width + "x" + root.monitor.height : "" text: root.monitor ? root.monitor.width + "x" + root.monitor.height : ""
textFormat: Text.PlainText textFormat: Text.PlainText
@@ -55,7 +61,9 @@ Rectangle {
} }
Text { Text {
anchors.horizontalCenter: parent.horizontalCenter width: parent.width
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
visible: root.monitor && root.monitor.focused && root.height > Style.spaceReal(58) visible: root.monitor && root.monitor.focused && root.height > Style.spaceReal(58)
text: "focused" text: "focused"
textFormat: Text.PlainText textFormat: Text.PlainText
@@ -20,8 +20,10 @@ Column {
visible: !!monitor visible: !!monitor
Text { Text {
width: parent.width
text: root.monitor ? root.monitor.name : "" text: root.monitor ? root.monitor.name : ""
textFormat: Text.PlainText textFormat: Text.PlainText
elide: Text.ElideRight
color: Color.foreground color: Color.foreground
font.family: Style.font.family font.family: Style.font.family
font.pixelSize: Style.font.body font.pixelSize: Style.font.body
@@ -40,14 +42,14 @@ Column {
StatRow { StatRow {
width: parent.width width: parent.width
icon: "" icon: "\uf047"
label: "Position" label: "Position"
value: root.monitor ? root.monitor.x + ", " + root.monitor.y : "" value: root.monitor ? root.monitor.x + ", " + root.monitor.y : ""
} }
StatRow { StatRow {
width: parent.width width: parent.width
icon: "" icon: "\uf108"
label: "Logical size" label: "Logical size"
value: root.monitor ? root.monitor.width + "x" + root.monitor.height : "" value: root.monitor ? root.monitor.width + "x" + root.monitor.height : ""
} }
@@ -110,7 +112,8 @@ Column {
font.pixelSize: Style.font.bodySmall font.pixelSize: Style.font.bodySmall
} }
Row { Flow {
width: parent.width
spacing: Style.spaceReal(6) spacing: Style.spaceReal(6)
Chip { Chip {