allow setting a timeout to manual sleep inhibitor

This commit is contained in:
shouya
2025-10-21 01:35:40 +09:00
parent ec328f348c
commit d85f426b15
4 changed files with 158 additions and 20 deletions
+2 -2
View File
@@ -1813,10 +1813,10 @@
"close": "Close",
"connect-disconnect-devices": "Left click to connect. Right click to forget.",
"delete-notification": "Delete notification",
"disable-keep-awake": "Disable keep awake",
"disable-keep-awake": "Click to disable keep awake.\nScroll to adjust timeout.",
"do-not-disturb-disabled": "'Do not disturb' disabled",
"do-not-disturb-enabled": "'Do not disturb' enabled",
"enable-keep-awake": "Enable keep awake",
"enable-keep-awake": "Click to enable keep awake.\nScroll to adjust timeout.",
"forget-network": "Forget network",
"home": "Home",
"input-muted": "Toggle input mute",
+55 -12
View File
@@ -5,21 +5,64 @@ import qs.Commons
import qs.Services.Power
import qs.Services.UI
import qs.Widgets
import qs.Modules.Bar.Extras
NIconButton {
Item {
id: root
property ShellScreen screen
baseSize: Style.capsuleHeight
applyUiScale: false
density: Settings.data.bar.density
icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off"
tooltipText: IdleInhibitorService.isInhibited ? I18n.tr("tooltips.disable-keep-awake") : I18n.tr("tooltips.enable-keep-awake")
tooltipDirection: BarService.getTooltipDirection()
colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mOnSurface
colorBorder: Color.transparent
colorBorderHover: Color.transparent
onClicked: IdleInhibitorService.manualToggle()
// Widget properties passed from Bar.qml for per-instance settings
property string widgetId: ""
property string section: ""
property int sectionWidgetIndex: -1
property int sectionWidgetsCount: 0
property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId]
property var widgetSettings: {
if (section && sectionWidgetIndex >= 0) {
var widgets = Settings.data.bar.widgets[section]
if (widgets && sectionWidgetIndex < widgets.length) {
return widgets[sectionWidgetIndex]
}
}
return {}
}
readonly property bool isBarVertical: Settings.data.bar.position === "left" || Settings.data.bar.position === "right"
implicitWidth: pill.width
implicitHeight: pill.height
BarPill {
id: pill
text: IdleInhibitorService.timeout == null ? "" :
Time.formatVagueHumanReadableDuration(IdleInhibitorService.timeout)
density: Settings.data.bar.density
oppositeDirection: BarService.getPillDirection(root)
icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off"
tooltipText: IdleInhibitorService.isInhibited ?
I18n.tr("tooltips.disable-keep-awake") :
I18n.tr("tooltips.enable-keep-awake")
onClicked: IdleInhibitorService.manualToggle()
forceOpen: IdleInhibitorService.timeout !== null
onWheel: function (delta) {
var sign = delta > 0 ? 1 : -1
// the offset makes scrolling down feel symmetrical to scrolling up
var timeout = IdleInhibitorService.timeout - (delta < 0 ? 60 : 0)
if (timeout == null || timeout < 600) {
delta = 60 // <= 10m, increment at 1m interval
} else if (timeout >= 600 && timeout < 1800) {
delta = 300 // >= 10m, increment at 5m interval
} else if (timeout >= 1800 && timeout < 3600) {
delta = 600 // >= 30m, increment at 10m interval
} else if (timeout >= 3600) {
delta = 1800 // > 1h, increment at 30m interval
}
IdleInhibitorService.changeTimeout(delta * sign)
}
}
}
+99 -6
View File
@@ -12,6 +12,7 @@ Singleton {
property bool isInhibited: false
property string reason: I18n.tr("system.user-requested")
property var activeInhibitors: []
property var timeout: null // in seconds
// Different inhibitor strategies
property string strategy: "systemd" // "systemd", "wayland", or "auto"
@@ -152,21 +153,113 @@ Singleton {
}
}
Timer {
id: inhibitorTimeout
repeat: true
interval: 1000 // 1 second
onTriggered: function () {
if (timeout == null) {
inhibitorTimeout.stop()
return
}
timeout -= 1
if (timeout <= 0) {
removeManualInhibitor()
return
}
}
}
// Manual toggle for user control
function manualToggle() {
// clear any existing timeout
timeout = null
if (activeInhibitors.includes("manual")) {
removeInhibitor("manual")
ToastService.showNotice(I18n.tr("tooltips.keep-awake"), I18n.tr("toast.keep-awake.disabled"), "keep-awake-off")
Logger.i("IdleInhibitor", "Manual inhibition disabled")
removeManualInhibitor()
return false
} else {
addInhibitor("manual", "Manually activated by user")
ToastService.showNotice(I18n.tr("tooltips.keep-awake"), I18n.tr("toast.keep-awake.enabled"), "keep-awake-on")
Logger.i("IdleInhibitor", "Manual inhibition enabled (will reset on next session)")
addManualInhibitor(null)
return true
}
}
function changeTimeout(delta) {
if (timeout == null && delta < 0) {
// no inhibitor, ignored
return;
}
if (timeout == null && delta > 0) {
// enable manual inhibitor and set timeout
addManualInhibitor(timeout + delta);
return;
}
if (timeout + delta <= 0) {
// disable manual inhibitor
removeManualInhibitor();
return;
}
if (timeout + delta > 0) {
// change timeout
addManualInhibitor(timeout + delta);
return;
}
}
function removeManualInhibitor() {
if (timeout !== null) {
timeout = null
if (inhibitorTimeout.running) {
inhibitorTimeout.stop()
}
}
if (activeInhibitors.includes("manual")) {
removeInhibitor("manual")
ToastService.showNotice(
I18n.tr("tooltips.keep-awake"),
I18n.tr("toast.keep-awake.disabled"),
"keep-awake-off"
)
Logger.i("IdleInhibitor", "Manual inhibition disabled")
}
}
function addManualInhibitor(timeoutSec) {
if (!activeInhibitors.includes("manual")) {
addInhibitor("manual", "Manually activated by user")
ToastService.showNotice(
I18n.tr("tooltips.keep-awake"),
I18n.tr("toast.keep-awake.enabled"),
"keep-awake-on"
)
}
if (timeoutSec === null && timeout === null) {
Logger.i("IdleInhibitor", "Manual inhibition enabled")
return
} else if (timeoutSec !== null && timeout === null) {
timeout = timeoutSec
inhibitorTimeout.start()
Logger.i("IdleInhibitor", "Manual inhibition enabled with timeout:", timeoutSec)
return
} else if (timeoutSec !== null && timeout !== null) {
timeout = timeoutSec
Logger.i("IdleInhibitor", "Manual inhibition timeout changed to:", timeoutSec)
return
} else if (timeoutSec === null && timeout !== null) {
timeout = null
inhibitorTimeout.stop()
Logger.i("IdleInhibitor", "Manual inhibition timeout cleared")
return
}
}
// Clean up on shutdown
Component.onDestruction: {
stopInhibition()
+2
View File
@@ -30,6 +30,7 @@ Rectangle {
signal clicked
signal rightClicked
signal middleClicked
signal wheel
implicitWidth: applyUiScale ? Math.round(baseSize * Style.uiScaleRatio) : Math.round(baseSize)
implicitHeight: applyUiScale ? Math.round(baseSize * Style.uiScaleRatio) : Math.round(baseSize)
@@ -108,5 +109,6 @@ Rectangle {
root.middleClicked()
}
}
onWheel: wheel => root.wheel(wheel.angleDelta.y)
}
}