diff --git a/src/app.ts b/src/app.ts index 12dbf21..3e4da43 100644 --- a/src/app.ts +++ b/src/app.ts @@ -291,7 +291,7 @@ you should use the socket in the XDG_RUNTIME_DIR/colorshell.sock for a faster re this.#connections.set(Wireplumber.getDefault(), Wireplumber.getDefault().getDefaultSink().connect("notify::volume", () => !Windows.getDefault().isOpen("control-center") && - triggerOSD(OSDModes.SINK) + triggerOSD(OSDModes.sink) ) ); @@ -311,7 +311,7 @@ you should use the socket in the XDG_RUNTIME_DIR/colorshell.sock for a faster re this.#connections.set(defaultBk, defaultBk.connect("brightness-changed", () => !Windows.getDefault().isOpen("control-center") && - triggerOSD(OSDModes.BRIGHTNESS) + triggerOSD(OSDModes.brightness) )); }) ); diff --git a/src/modules/utils.ts b/src/modules/utils.ts index 821e405..0216606 100644 --- a/src/modules/utils.ts +++ b/src/modules/utils.ts @@ -6,7 +6,7 @@ import { getSymbolicIcon } from "./apps"; import GLib from "gi://GLib?version=2.0"; import Gio from "gi://Gio?version=2.0"; -import GObject from "ags/gobject"; +import GObject from "gi://GObject?version=2.0"; /** gnim doesn't export this, so we need to do it again */ @@ -301,3 +301,61 @@ export function secureBinding< } ); } + +/** securely bind to a property of a gobject accessor +* use this to securely bind to a property of a constantly +* updated variable that points to a gobject. +* +* It follows the same idea from secureBinding, it allows setting +* a default value to return when the base gobject is null. +* +* @param baseObject a binding to the constantly updated property +* that points to the gobject +* @param prop the property to bind +* @param defaultValue the value to return when the baseObject is +* null/undefined +* +* @returns a bind to the specified property of the constantly-updated +* object or the default value. +* */ +export function secureBaseBinding< + T extends GObject.Object = GObject.Object, + Prop extends keyof T = keyof T, + Default = any +>( + baseObject: Accessor, + prop: Prop, + defaultValue: Default +): Accessor { + let gobj: T|undefined = baseObject.get(); + let notify: () => void; + + const baseSub = baseObject.subscribe(() => { + const newBase = baseObject.get(); + + if(!newBase) { + gobj = undefined; + notify!(); + return; + } + }); + + const accessor = new Accessor( + () => gobj ? gobj[prop] : defaultValue, + (notifyFun) => { + notify = notifyFun; + + const id = gobj?.connect( + `notify::${(prop as string).replace(/[A-Z]/g, (s) => `-${s.toLowerCase()}`)}`, + () => notify() + ); + + return () => { + id && gobj?.disconnect(id); + baseSub(); + } + } + ); + + return accessor; +} diff --git a/src/window/osd/index.tsx b/src/window/osd/index.tsx index 0d04d0d..1f67272 100644 --- a/src/window/osd/index.tsx +++ b/src/window/osd/index.tsx @@ -3,7 +3,7 @@ import { createBinding, createState, With } from "ags"; import { Wireplumber } from "../../modules/volume"; import { Windows } from "../../windows"; import { Backlights } from "../../modules/backlight"; -import { secureBinding, variableToBoolean } from "../../modules/utils"; +import { secureBaseBinding, secureBinding, variableToBoolean } from "../../modules/utils"; import Pango from "gi://Pango?version=1.0"; import GLib from "gi://GLib?version=2.0"; @@ -13,18 +13,42 @@ import OSDMode from "./modules/osdmode"; export const OSDModes = { sink: new OSDMode({ - icon: secureBinding(AstalWp.get_default().defaultSpeaker, "volumeIcon", - "audio-volume-high-symbolic"), - value: secureBinding(Wireplumber.getWireplumber().defaultSpeaker, "volume", 50), - text: secureBinding(Wireplumber.getWireplumber().defaultSpeaker, "description", - "Unknown Speaker"), + available: secureBinding(AstalWp.get_default(), "defaultSpeaker", false).as((sink) => + Boolean(sink)), + icon: secureBaseBinding( + createBinding(AstalWp.get_default(), "defaultSpeaker"), + "volumeIcon", + "audio-volume-high-symbolic" + ), + value: secureBaseBinding( + createBinding(AstalWp.get_default(), "defaultSpeaker"), + "volume", + .5 + ), + text: secureBaseBinding( + createBinding(AstalWp.get_default(), "defaultSpeaker"), + "description", + "Unknown Speaker" + ), max: Wireplumber.getDefault().getMaxSinkVolume() / 100 }), brightness: new OSDMode({ icon: "display-brightness-symbolic", - value: secureBinding(Backlights.getDefault().default, "brightness", 100), - max: secureBinding(Backlights.getDefault().default, "maxBrightness", 100), - text: secureBinding(Backlights.getDefault().default, "name", "Unknown Backlight"), + value: secureBaseBinding( + createBinding(Backlights.getDefault(), "default"), + "brightness", + 100 + ), + max: secureBaseBinding( + createBinding(Backlights.getDefault(), "default"), + "maxBrightness", + 100 + ), + text: secureBaseBinding( + createBinding(Backlights.getDefault(), "default"), + "name", + "Unknown Backlight" + ), available: createBinding(Backlights.getDefault(), "available") }) }