diff --git a/README.md b/README.md new file mode 100644 index 0000000..4b2990f --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# DDC Brightness Control + +This project aims to be a simple and easy to use DDC brightness control plugin for Gnome + +![img.png](attachments/panel.png) + +## Features + +- Brightness control via panel +- Adjustable keybindings for brightness controls + - Active screen detection + - By default, keybinding is alt+shift+f1/f2 for down/up on the active display +- Display linking if you want to adjust all displays at once + +## Planned Features? + +- Would be nice to get this added to the system status menu at some point isntead of its own dot +- Support for direct i2c or better ddc controllers (not ddcutil) +- You tell me + +## Installation + +(Examples use arch, but all packages should be available on other distros as well) + +Be sure to have [ddcutil](https://www.ddcutil.com/) installed it is a hard requirement for now + +Also, if installing from source install just which is the chosen command runner for this project + +```bash +sudo pacman -Syu ddcutil just +``` + +Add your user to the i2c group so it can use i2c without root and reboot/login+out + +```bash +sudo usermod -aG i2c $USER +reboot +``` + +Now install the extension from version control +(until we get to the gnome extension store) + +```bash + +``` + + diff --git a/attachments/panel.png b/attachments/panel.png new file mode 100644 index 0000000..1f5c27d Binary files /dev/null and b/attachments/panel.png differ diff --git a/justfile b/justfile index 73741a7..fc4b1e1 100644 --- a/justfile +++ b/justfile @@ -38,5 +38,8 @@ live-debug: lint: pnpm run lint +lint-fix: + pnpm run lint --fix + clean: pnpm run clean diff --git a/metadata.json b/metadata.json index 721b7a0..8da039f 100644 --- a/metadata.json +++ b/metadata.json @@ -1,12 +1,9 @@ { - "name": "ddc-brightness-control", + "name": "DDC Brightness Controller", "description": "Control display brightness via DDC/CI using ddcutil. Bind keyboard shortcuts or use the panel menu to adjust monitor brightness.", "uuid": "ddcbrightness@lucaso.io", "settings-schema": "org.gnome.shell.extensions.ddcbrightness", "shell-version": [ - "47", - "48", - "49", "50" ] } diff --git a/src/constants.ts b/src/constants.ts index 4272320..9799eb1 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,10 +4,6 @@ export const SCHEMA_ID = 'org.gnome.shell.extensions.ddcbrightness'; /** VCP feature code used when none is configured (10 = brightness). */ export const DEFAULT_VCP_CODE = '10'; -/** - * Scales the mandatory I2C delays ddcutil inserts around DDC/CI transactions. - * Lower = faster but less tolerant of flaky monitors. Tune per hardware. - */ export const DDCUTIL_SLEEP_MULTIPLIER = '0.5'; /** Prefix for all console logging from this extension. */ diff --git a/src/displays.ts b/src/displays.ts index 8294790..13b3570 100644 --- a/src/displays.ts +++ b/src/displays.ts @@ -1,10 +1,9 @@ import Gio from 'gi://Gio'; import St from 'gi://St'; import * as Slider from 'resource:///org/gnome/shell/ui/slider.js'; -import { DEFAULT_VCP_CODE, LOG_PREFIX } from './constants.js'; +import {DEFAULT_VCP_CODE, LOG_PREFIX} from './constants.js'; import * as Ddcutil from './ddcutil.js'; -/** A detected display plus the UI refs and runtime state attached to it. */ export interface DisplayInfo { bus: string; name: string; @@ -13,30 +12,18 @@ export interface DisplayInfo { currentValue: number; slider: Slider.Slider | null; valueLabel: St.Label | null; - // Reconciliation state for writes: `sentValue` is the value of the most - // recent write handed to ddcutil; `inFlight` is true while that write runs. sentValue: number; inFlight: boolean; reading: boolean; updatingFromCode: boolean; } -/** - * Owns the set of detected displays and all brightness operations on them - * (detection, monitor mapping, reads, and writes via ddcutil). - * - * Writes use a reconciliation model rather than debouncing: `currentValue` is - * the user's target and at most one write per display is ever in flight. When a - * write finishes, if the target has since moved we immediately send the latest - * value — so intermediate values are coalesced and we never queue stale writes. - */ export class DisplayController { private _settings: Gio.Settings; private _displays: DisplayInfo[] = []; private _detectComplete = false; private _disposed = false; - /** Invoked after detection finishes so the UI can rebuild itself. */ onDetectComplete: (() => void) | null = null; constructor(settings: Gio.Settings) { @@ -55,18 +42,15 @@ export class DisplayController { return this._settings.get_string('vcp-code') || DEFAULT_VCP_CODE; } - /** Clear all state back to the pre-detection condition. */ reset(): void { this._displays = []; this._detectComplete = false; } - /** Stop issuing further writes. Call before disposal. */ cleanup(): void { this._disposed = true; } - /** Detect displays, map them to monitors, then read their brightness. */ detect(): void { Ddcutil.detectDisplays((parsed) => { this._displays = parsed.map((p) => ({ @@ -117,7 +101,10 @@ export class DisplayController { return global.display.get_primary_monitor(); } - /** The display to act on for global actions, honoring "link displays". */ + /** + * The display to act on for global actions, honoring "link displays". + * This should grab the display that the active window is part of for adjusting when not linked + */ getActiveDisplay(): DisplayInfo | null { if (this._settings.get_boolean('link-displays')) { return this._displays[0] ?? null; diff --git a/src/indicator.ts b/src/indicator.ts index c2c3146..b814ce5 100644 --- a/src/indicator.ts +++ b/src/indicator.ts @@ -42,7 +42,6 @@ export class BrightnessIndicator { this.rebuildMenu(); } - /** The underlying panel button, for adding to the status area. */ get button(): PanelMenu.Button { return this._button; } diff --git a/src/keybindings.ts b/src/keybindings.ts index 92fb199..e6af6d9 100644 --- a/src/keybindings.ts +++ b/src/keybindings.ts @@ -3,16 +3,11 @@ import Meta from 'gi://Meta'; import Shell from 'gi://Shell'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -/** Map of settings key -> callback to run when the shortcut fires. */ export type KeybindingActions = Record void>; -/** - * Registers the extension's keyboard shortcuts with the window manager and - * keeps them in sync as their settings change. - */ export class KeybindingManager { - private _settings: Gio.Settings; - private _actions: KeybindingActions; + private readonly _settings: Gio.Settings; + private readonly _actions: KeybindingActions; private _bindings: Map = new Map(); constructor(settings: Gio.Settings, actions: KeybindingActions) { diff --git a/stylesheet.css b/stylesheet.css index 9b9ddeb..ddb3922 100644 --- a/stylesheet.css +++ b/stylesheet.css @@ -1,8 +1,5 @@ -/* DDC Brightness Control styling */ - .ddc-brightness-slider-box { padding: 8px 12px; - spacing: 8px; } .ddc-brightness-value-label { @@ -13,7 +10,6 @@ text-align: right; } -/* Custom slider */ .slider { height: 24px; border-radius: 12px;