ags: implement per-monitor brightness control

This commit is contained in:
MoetaYuko
2024-05-01 15:23:30 +08:00
parent de0d5ffdf0
commit 7d45e9dc1b
6 changed files with 81 additions and 26 deletions
+65 -12
View File
@@ -1,10 +1,11 @@
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
import Service from 'resource:///com/github/Aylur/ags/service.js';
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
const { exec, execAsync } = Utils;
import { clamp } from '../modules/.miscutils/mathfuncs.js';
class BrightnessService extends Service {
class BrightnessServiceBase extends Service {
static {
Service.register(
this,
@@ -23,7 +24,7 @@ class BrightnessService extends Service {
percent = clamp(percent, 0, 1);
this._screenValue = percent;
Utils.execAsync(`brightnessctl s ${percent * 100}% -q`)
Utils.execAsync(this.setBrightnessCmd(percent))
.then(() => {
// signals has to be explicity emitted
this.emit('screen-changed', percent);
@@ -35,13 +36,6 @@ class BrightnessService extends Service {
.catch(print);
}
constructor() {
super();
const current = Number(exec('brightnessctl g'));
const max = Number(exec('brightnessctl m'));
this._screenValue = current / max;
}
// overwriting connectWidget method, lets you
// change the default event that widgets connect to
connectWidget(widget, callback, event = 'screen-changed') {
@@ -49,11 +43,70 @@ class BrightnessService extends Service {
}
}
class BrightnessCtlService extends BrightnessServiceBase {
static {
Service.register(this);
}
constructor() {
super();
const current = Number(exec('brightnessctl g'));
const max = Number(exec('brightnessctl m'));
this._screenValue = current / max;
}
setBrightnessCmd(percent) {
return `brightnessctl s ${percent * 100}% -q`;
}
}
class BrightnessDdcService extends BrightnessServiceBase {
static {
Service.register(this);
}
constructor(monitor = 0) {
super();
// don't use Hyprland.getMonitor(id), Hyprland monitor id isn't consistent
// with Gdk, but the Array ordering is (magically)
this._sn = Hyprland.monitors[monitor].serial;
Utils.execAsync(`ddcutil --sn ${this._sn} getvcp 10 --brief`)
.then((out) => {
// only the last line is useful
out = out.split('\n');
out = out[out.length - 1];
out = out.split(' ');
const current = Number(out[3]);
const max = Number(out[4]);
this._screenValue = current / max;
})
.catch(print);
}
setBrightnessCmd(percent) {
return `ddcutil --sn ${this._sn} setvcp 10 ${Math.round(percent * 100)}`;
}
}
// the singleton instance
const service = new BrightnessService();
const numMonitors = Hyprland.monitors.length;
const service = Array(numMonitors);
switch (userOptions.brightness.controller) {
case "brightnessctl":
service.fill(new BrightnessCtlService());
break;
case "ddcutil":
for (let i = 0; i < numMonitors; i++) {
service[i] = new BrightnessDdcService(i);
}
break;
default:
throw new Error(`Unknown brightness controller ${userOptions.brightness.controller}`);
}
// make it global for easy use with cli
globalThis.brightness = service;
globalThis.brightness = service[0];
// export to use in other modules
export default service;
export default service;