From 5abc944b8143f685888e977198b132eacb8ef90a Mon Sep 17 00:00:00 2001 From: matt1432 Date: Tue, 29 Oct 2024 00:11:37 -0400 Subject: [PATCH] feat(agsV2): add Brightness service --- nixosModules/ags/default.nix | 9 +- nixosModules/ags/v2/app.ts | 18 +++ nixosModules/ags/v2/lib.ts | 13 +- nixosModules/ags/v2/services/brightness.ts | 156 +++++++++++++++++++++ 4 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 nixosModules/ags/v2/services/brightness.ts diff --git a/nixosModules/ags/default.nix b/nixosModules/ags/default.nix index 26e61e64..430bc858 100644 --- a/nixosModules/ags/default.nix +++ b/nixosModules/ags/default.nix @@ -142,6 +142,7 @@ in { wayland.windowManager.hyprland = let runAgs = cmd: "pgrep ags -a | grep '/bin/gjs' && ags ${cmd} || agsV2 ${cmd}"; + runAgsJs = cmd: "pgrep ags -a | grep '/bin/gjs' && ags -r ${cmd} || agsV2 -m ${cmd}"; in { settings = { animations = { @@ -178,11 +179,11 @@ in { ]; binde = [ ## Brightness control - ", XF86MonBrightnessUp , exec, ${runAgs "-r 'Brightness.screen += 0.05'"}" - ", XF86MonBrightnessDown, exec, ${runAgs "-r 'Brightness.screen -= 0.05'"}" + ", XF86MonBrightnessUp , exec, ${runAgsJs "'Brightness.screen += 0.05'"}" + ", XF86MonBrightnessDown, exec, ${runAgsJs "'Brightness.screen -= 0.05'"}" ]; - bindn = [" , Escape , exec, ${runAgs "-r 'closeAll()'"}"]; - bindr = ["CAPS, Caps_Lock, exec, ${runAgs "-r 'Brightness.fetchCapsState()'"}"]; + bindn = [" , Escape , exec, ${runAgsJs "'closeAll()'"}"]; + bindr = ["CAPS, Caps_Lock, exec, ${runAgsJs "'Brightness.fetchCapsState()'"}"]; }; }; }) diff --git a/nixosModules/ags/v2/app.ts b/nixosModules/ags/v2/app.ts index 828e52e3..5dab4e54 100644 --- a/nixosModules/ags/v2/app.ts +++ b/nixosModules/ags/v2/app.ts @@ -14,10 +14,20 @@ import { NotifPopups, NotifCenter } from './widgets/notifs/main'; import PowerMenu from './widgets/powermenu/main'; import Screenshot from './widgets/screenshot/main'; +import { closeAll as closeAllFunc } from './lib'; +import BrightnessService from './services/brightness'; import MonitorClicks from './services/monitor-clicks'; import Lockscreen from './widgets/lockscreen/main'; +declare global { + function closeAll(): void; + // eslint-disable-next-line + var Brightness: typeof BrightnessService; +} +globalThis.closeAll = closeAllFunc; +globalThis.Brightness = BrightnessService; + const CONF = GLib.getenv('CONF'); @@ -39,6 +49,10 @@ switch (CONF) { App.start({ css: style, + requestHandler(js, res) { + App.eval(js).then(res).catch(res); + }, + main: () => { AppLauncher(); Bar(); @@ -51,6 +65,10 @@ switch (CONF) { PowerMenu(); Screenshot(); + Brightness.initService({ + kbd: 'tpacpi::kbd_backlight', + caps: 'input1::capslock', + }); new MonitorClicks(); }, }); diff --git a/nixosModules/ags/v2/lib.ts b/nixosModules/ags/v2/lib.ts index c5a54c71..84fe0fee 100644 --- a/nixosModules/ags/v2/lib.ts +++ b/nixosModules/ags/v2/lib.ts @@ -1,9 +1,10 @@ -import { Gdk } from 'astal/gtk3'; +import { App, Gdk } from 'astal/gtk3'; import AstalHyprland from 'gi://AstalHyprland'; const Hyprland = AstalHyprland.get_default(); /* Types */ +import type { PopupWindow } from './widgets/misc/popup-window'; export interface Layer { address: string x: number @@ -109,3 +110,13 @@ export const centerCursor = async(): Promise => { await hyprMessage(`dispatch movecursor ${x} ${y}`); }; + +export const closeAll = () => { + (App.get_windows() as PopupWindow[]) + .filter((w) => w && + w.close_on_unfocus && + w.close_on_unfocus !== 'stay') + .forEach((w) => { + App.get_window(w.name)?.set_visible(false); + }); +}; diff --git a/nixosModules/ags/v2/services/brightness.ts b/nixosModules/ags/v2/services/brightness.ts new file mode 100644 index 00000000..25817dec --- /dev/null +++ b/nixosModules/ags/v2/services/brightness.ts @@ -0,0 +1,156 @@ +import { execAsync, interval } from 'astal'; +import GObject, { register, property } from 'astal/gobject'; + + +const SCREEN_ICONS: Record = { + 90: 'display-brightness-high-symbolic', + 70: 'display-brightness-medium-symbolic', + 20: 'display-brightness-low-symbolic', + 5: 'display-brightness-off-symbolic', +}; + +const INTERVAL = 500; + + +@register() +class Brightness extends GObject.Object { + declare private _kbd: string; + declare private _caps: string; + + declare private _screen: number; + + @property(Number) + get screen() { + return this._screen; + }; + + set screen(percent) { + if (percent < 0) { + percent = 0; + } + + if (percent > 1) { + percent = 1; + } + + percent = parseFloat(percent.toFixed(2)); + + execAsync(`brightnessctl s ${percent * 100}% -q`) + .then(() => { + this._screen = percent; + this.notify('screen'); + this._getScreenIcon(); + }) + .catch(console.error); + } + + declare private _screenIcon: string; + + @property(String) + get screenIcon() { + return this._screenIcon; + } + + declare private _kbdMax: number; + declare private _kbdLevel: number; + + @property(Number) + get kbdLevel() { + return this._kbdLevel; + } + + set kbdLevel(value) { + if (value < 0 || value > this._kbdMax) { + return; + } + + execAsync(`brightnessctl -d ${this._kbd} s ${value} -q`) + .then(() => { + this._kbdLevel = value; + this.notify('kbd-level'); + }) + .catch(console.error); + } + + declare private _capsLevel: number; + + @property(Number) + get capsLevel() { + return this._capsLevel; + } + + declare private _capsIcon: string; + + @property(String) + get capsIcon() { + return this._capsIcon; + } + + /** + * This is to basically have the constructor run when I want and + * still export this to wherever I need to. + * + * @param o params + * @param o.kbd name of kbd in brightnessctl + * @param o.caps name of caps_lock in brightnessctl + */ + public async initService({ kbd = '', caps = '' }) { + this._kbd = kbd; + this._caps = caps; + try { + this._monitorKbdState(); + this._kbdMax = Number(await execAsync(`brightnessctl -d ${this._kbd} m`)); + + this._screen = Number(await execAsync('brightnessctl g')) / + Number(await execAsync('brightnessctl m')); + } + catch (_e) { + console.error('missing dependancy: brightnessctl'); + } + } + + private _getScreenIcon() { + const brightness = this._screen * 100; + + // eslint-disable-next-line + for (const threshold of [4, 19, 69, 89]) { + if (brightness > threshold + 1) { + this._screenIcon = SCREEN_ICONS[threshold + 1]; + this.notify('screen-icon'); + } + } + } + + private _monitorKbdState() { + const timer = interval(INTERVAL, () => { + execAsync(`brightnessctl -d ${this._kbd} g`).then( + (out) => { + if (parseInt(out) !== this._kbdLevel) { + this._kbdLevel = parseInt(out); + this.notify('kbd-level'); + } + }, + ).catch(() => { + timer?.cancel(); + }); + }); + } + + public fetchCapsState() { + execAsync(`brightnessctl -d ${this._caps} g`) + .then((out) => { + this._capsLevel = Number(out); + this._capsIcon = this._capsLevel ? + 'caps-lock-symbolic' : + 'capslock-disabled-symbolic'; + + this.notify('caps-icon'); + this.notify('caps-level'); + }) + .catch(logError); + } +} + +const brightnessService = new Brightness(); + +export default brightnessService;