Add --fit OSD option and use it for system shutdown/reboot/logout

This commit is contained in:
David Heinemeier Hansson
2026-07-22 16:33:54 -07:00
parent 36329cee7a
commit 60a550a646
7 changed files with 57 additions and 16 deletions
+22 -7
View File
@@ -17,18 +17,24 @@ Item {
property int maxValue: 100
property bool hasProgress: true
property int duration: 1200
property bool fit: false
readonly property int cardWidth: Style.space(269)
readonly property int mediaCardWidth: Math.round(cardWidth * 1.5)
readonly property int messageWidth: Style.space(190)
readonly property int mediaMessageWidth: messageWidth + mediaCardWidth - cardWidth
readonly property bool mediaOsd: iconKey.indexOf("media") === 0 || iconKey.indexOf("player") === 0
readonly property bool textOnlyOsd: root.fit && !root.hasProgress && !root.mediaOsd
readonly property int fitMessageWidth: root.message === "" ? 0 : Math.round(messageMetrics.boundingRect.width) + Style.space(4)
readonly property int fitCardWidth: root.message === "" || root.fitMessageWidth === 0
? card.borderLeft + Style.space(16) + Style.space(28) + Style.space(16) + card.borderRight
: card.borderLeft + Style.space(16) + Style.space(28) + Style.space(16) + root.fitMessageWidth + Style.space(16) + card.borderRight
function iconFor(name, percent) {
return OsdModel.iconFor(name, percent)
}
function show(iconName, rawMessage, rawValue, rawMax, rawProgressText, rawDuration) {
var next = OsdModel.stateForShow(iconName, rawMessage, rawValue, rawMax, rawProgressText, rawDuration)
function show(iconName, rawMessage, rawValue, rawMax, rawProgressText, rawDuration, rawFit) {
var next = OsdModel.stateForShow(iconName, rawMessage, rawValue, rawMax, rawProgressText, rawDuration, rawFit)
iconKey = next.iconKey
maxValue = next.maxValue
hasProgress = next.hasProgress
@@ -36,6 +42,7 @@ Item {
message = next.message
icon = next.icon
duration = next.duration
fit = next.fit
opened = true
if (duration > 0) hideTimer.restart()
else hideTimer.stop()
@@ -44,7 +51,7 @@ Item {
function open(payloadJson) {
try {
var p = JSON.parse(payloadJson || "{}")
show(p.icon || "", p.message || "", p.value === undefined ? "" : String(p.value), p.max === undefined ? "100" : String(p.max), p.progressText || "", p.duration === undefined ? "1200" : String(p.duration))
show(p.icon || "", p.message || "", p.value === undefined ? "" : String(p.value), p.max === undefined ? "100" : String(p.max), p.progressText || "", p.duration === undefined ? "1200" : String(p.duration), p.fit === undefined ? false : p.fit)
} catch (e) {}
}
@@ -56,6 +63,14 @@ Item {
onTriggered: root.opened = false
}
TextMetrics {
id: messageMetrics
font.family: Style.font.family
font.bold: true
font.pixelSize: Style.font.title
text: root.message
}
IpcHandler {
target: "osd"
function show(payloadJson: string): string {
@@ -82,7 +97,7 @@ Item {
BorderSurface {
id: card
width: root.mediaOsd ? root.mediaCardWidth : root.cardWidth
width: root.textOnlyOsd ? root.fitCardWidth : (root.mediaOsd ? root.mediaCardWidth : root.cardWidth)
height: Math.max(Style.space(68), Style.font.displayLarge + Style.spacing.panelGap)
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
@@ -121,16 +136,16 @@ Item {
}
}
Text {
width: root.hasProgress ? Style.space(41) : (root.mediaOsd ? root.mediaMessageWidth : root.messageWidth)
width: root.textOnlyOsd ? root.fitMessageWidth : (root.hasProgress ? Style.space(41) : (root.mediaOsd ? root.mediaMessageWidth : root.messageWidth))
anchors.verticalCenter: parent.verticalCenter
text: root.message
font.family: Style.font.family
font.bold: true
font.pixelSize: Style.font.title
color: Color.popups.text
elide: Text.ElideRight
elide: root.textOnlyOsd ? Text.ElideNone : Text.ElideRight
maximumLineCount: 1
clip: true
clip: !root.textOnlyOsd
}
}
}
+5 -2
View File
@@ -16,6 +16,7 @@ function iconFor(name, percent) {
if (n === "touch" || n === "touchscreen") return "󰝁"
if (n === "reboot" || n === "restart") return "󰜉"
if (n === "shutdown" || n === "power" || n === "poweroff") return "󰐥"
if (n === "logout" || n === "sign-out" || n === "leave") return "󰍃"
if (n === "media" || n === "player") return "󰝚"
if (n === "media-source" || n === "player-source") return "󰝚"
if (n === "media-play" || n === "player-play") return "󰐊"
@@ -29,13 +30,14 @@ function iconFor(name, percent) {
return ""
}
function stateForShow(iconName, rawMessage, rawValue, rawMax, rawProgressText, rawDuration) {
function stateForShow(iconName, rawMessage, rawValue, rawMax, rawProgressText, rawDuration, rawFit) {
var maxValue = Math.max(1, parseInt(rawMax || "100", 10))
var parsedValue = parseInt(rawValue || "0", 10)
var hasProgress = rawValue !== "" && !isNaN(parsedValue) && rawMessage === ""
var value = hasProgress ? clamp(parsedValue, 0, maxValue) : 0
var percent = hasProgress ? Math.round(value * 100 / maxValue) : -1
var parsedDuration = parseInt(rawDuration || "1200", 10)
var fit = rawFit === true || rawFit === 1 || rawFit === "1" || rawFit === "true"
return {
iconKey: String(iconName || "").toLowerCase(),
@@ -44,7 +46,8 @@ function stateForShow(iconName, rawMessage, rawValue, rawMax, rawProgressText, r
value: value,
message: String(rawMessage || (hasProgress ? (rawProgressText || percent + "%") : "")),
icon: iconFor(iconName, percent),
duration: isNaN(parsedDuration) ? 1200 : Math.max(0, parsedDuration)
duration: isNaN(parsedDuration) ? 1200 : Math.max(0, parsedDuration),
fit: fit
}
}