diff options
| author | nippy <you@example.com> | 2026-04-18 13:49:56 +0200 |
|---|---|---|
| committer | nippy <you@example.com> | 2026-04-18 13:49:56 +0200 |
| commit | 5d94c0a7d44a2255b81815a52a7056a94a39842d (patch) | |
| tree | 759bdea9645c6a62f9e1e4c001f7d81cccd120d2 /raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/dbus-service/action.js | |
| parent | e79cdf210b267f21a186255ce1a4d50029439d54 (diff) | |
| download | RaveOS-PKGBUILD-5d94c0a7d44a2255b81815a52a7056a94a39842d.tar.gz RaveOS-PKGBUILD-5d94c0a7d44a2255b81815a52a7056a94a39842d.zip | |
update Raveos themes
Diffstat (limited to 'raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/dbus-service/action.js')
| -rw-r--r-- | raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/dbus-service/action.js | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/dbus-service/action.js b/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/dbus-service/action.js new file mode 100644 index 0000000..4b5bf9f --- /dev/null +++ b/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/dbus-service/action.js @@ -0,0 +1,217 @@ +// SPDX-FileCopyrightText: 2023 Deminder <tremminder@gmail.com> +// SPDX-License-Identifier: GPL-3.0-or-later + +import Gio from 'gi://Gio'; +import * as Control from './control.js'; +import { proxyPromise } from '../modules/util.js'; +import { pgettext as C_, gettext as _ } from '../modules/translation.js'; +import { logDebug } from '../modules/util.js'; + +export const ACTIONS = { + PowerOff: 0, + Reboot: 1, + Suspend: 2, + SuspendThenHibernate: 3, + Hibernate: 4, + HybridSleep: 5, + Halt: 6, +}; + +export const WAKE_ACTIONS = { wake: 100, 'no-wake': 101 }; + +/** + * Get supported actions. + * In order to show an error when shutdown or reboot are not supported + * they are always included here. */ +export async function* supportedActions() { + const actionDbus = new Action(); + for await (const action of Object.keys(ACTIONS).map(async a => + ['PowerOff', 'Reboot'].includes(a) || + (await actionDbus.canShutdownAction(a)) + ? a + : null + )) { + if (action) { + yield action; + } + } +} + +export class UnsupportedActionError extends Error {} + +export class Action { + #cancellable = new Gio.Cancellable(); + #cookie = null; + + #loginProxy = proxyPromise( + 'org.freedesktop.login1.Manager', + Gio.DBus.system, + 'org.freedesktop.login1', + '/org/freedesktop/login1', + this.#cancellable + ); + + #screenSaverProxy = proxyPromise( + 'org.gnome.ScreenSaver', + Gio.DBus.session, + 'org.gnome.ScreenSaver', + '/org/gnome/ScreenSaver', + this.#cancellable + ); + + #sessionProxy = proxyPromise( + 'org.gnome.SessionManager', + Gio.DBus.session, + 'org.gnome.SessionManager', + '/org/gnome/SessionManager', + this.#cancellable + ); + + destroy() { + if (this.#cancellable !== null) { + this.#cancellable.cancel(); + this.#cancellable = null; + } + } + + #poweroffOrReboot(action) { + return [ACTIONS.PowerOff, ACTIONS.Reboot].includes(ACTIONS[action]); + } + + /** + * Perform the shutdown action. + * + * @param {string} action the shutdown action + * @param {boolean} showEndSessionDialog show the end session dialog or directly shutdown + * + * @returns {Promise} resolves on action completion + */ + async shutdownAction(action, showEndSessionDialog) { + if (!(action in ACTIONS)) + throw new Error(`Unknown shutdown action: ${action}`); + logDebug('[shutdownAction]', action); + + await this.uninhibitSuspend(); + + const screenSaverProxy = await this.#screenSaverProxy; + const [screenSaverActive] = await screenSaverProxy.GetActiveAsync(); + if ( + showEndSessionDialog && + !screenSaverActive && + this.#poweroffOrReboot(action) + ) { + const sessionProxy = await this.#sessionProxy; + if (action === 'PowerOff') { + await sessionProxy.ShutdownAsync(); + } else { + await sessionProxy.RebootAsync(); + } + } else { + const loginProxy = await this.#loginProxy; + if (await this.canShutdownAction(action)) { + await loginProxy[`${action}Async`](true); + } else if (this.#poweroffOrReboot(action)) { + await Control.shutdown('now', ACTIONS[action] === ACTIONS.Reboot); + } else { + throw new UnsupportedActionError(); + } + } + } + + /** + * Check if a shutdown action can be performed (without authentication). + * + * @returns {Promise} resolves to `true` if action can be performed, otherwise `false`. + */ + async canShutdownAction(action) { + const loginProxy = await this.#loginProxy; + if (!(action in ACTIONS)) + throw new Error(`Unknown shutdown action: ${action}`); + const [result] = await loginProxy[`Can${action}Async`](); + return result === 'yes'; + } + + /** + * Schedule a wake after some minutes or cancel + * + * @param {boolean} wake + * @param {number} minutes + */ + async wakeAction(wake, minutes) { + if (wake) { + await Control.wake(minutes); + } else { + await Control.wakeCancel(); + } + } + + async inhibitSuspend() { + if (this.#cookie === null) { + const sessionProxy = await this.#sessionProxy; + const [cookie] = await sessionProxy.InhibitAsync( + 'user', + 0, + 'Inhibit by Shutdown Timer (GNOME-Shell extension)', + /* Suspend flag */ 4 + ); + this.#cookie = cookie; + } + } + + async uninhibitSuspend() { + if (this.#cookie !== null) { + const sessionProxy = await this.#sessionProxy; + await sessionProxy.UninhibitAsync(this.#cookie); + this.#cookie = null; + } + } +} + +/** + * Get the translated action label + * + * @param action + */ +export function actionLabel(action) { + return { + SuspendThenHibernate: _('Suspend then Hibernate'), + HybridSleep: _('Hybrid Sleep'), + Hibernate: _('Hibernate'), + Halt: _('Halt'), + Suspend: _('Suspend'), + PowerOff: _('Power Off'), + Reboot: _('Restart'), + wake: _('Wake'), + 'no-wake': _('No Wake'), + }[action]; +} + +export function untilText(action) { + return { + SuspendThenHibernate: C_('untiltext', 'suspend and hibernate'), + HybridSleep: C_('untiltext', 'hybrid sleep'), + Hibernate: C_('untiltext', 'hibernate'), + Halt: C_('untiltext', 'halt'), + Suspend: C_('untiltext', 'suspend'), + PowerOff: C_('untiltext', 'shutdown'), + Reboot: C_('untiltext', 'reboot'), + wake: C_('untiltext', 'wakeup'), + }[action]; +} + +export function mapLegacyAction(action) { + return action in ACTIONS || ['wake', ''].includes(action) + ? action + : { + poweroff: 'PowerOff', + shutdown: 'PowerOff', + reboot: 'Reboot', + suspend: 'Suspend', + }[action] ?? + { + p: 'PowerOff', + r: 'Reboot', + s: 'Suspend', + h: 'SuspendThenHibernate', + }[action[0].toLowerCase()]; +} |