add volume and brightness control
This commit is contained in:
@@ -7,7 +7,7 @@ A bottom desktop-environment panel for wlroots-based compositors, built on
|
||||
| ------- | ----------------------------------------------------------------- |
|
||||
| Left | Application menu built from `.desktop` entries, with search, and pinned quick-launch icons |
|
||||
| Middle | Open windows (task list), click to focus, middle-click to close |
|
||||
| Right | On-screen keyboard, wifi, bluetooth, and a session menu: log out, suspend, restart, shut down |
|
||||
| Right | On-screen keyboard, volume and brightness sliders, wifi, bluetooth, and a session menu: log out, suspend, restart, shut down |
|
||||
|
||||
No clock, no tray, no status readouts — it is designed to sit alongside a
|
||||
separate status bar.
|
||||
@@ -27,6 +27,13 @@ separate status bar.
|
||||
against — since the connection still goes through iwd underneath
|
||||
- squeekboard, as a systemd user unit, for the keyboard button — also optional;
|
||||
where the unit is not installed the button is absent
|
||||
- pipewire for the volume slider. Quickshell speaks to it directly, so there is
|
||||
no `wpctl` or `pactl` in the loop; without a default sink the slider is absent
|
||||
- `brightnessctl` for the brightness slider — bundled with the package, and
|
||||
optional in the sense that a machine with no controllable backlight (a
|
||||
desktop) simply does not get that row. It writes through logind where the
|
||||
session cannot write `/sys/class/backlight` itself, so no udev rule or setuid
|
||||
binary is needed
|
||||
|
||||
The window list uses the foreign-toplevel protocol rather than any single
|
||||
compositor's IPC, so it works the same everywhere — except under river 0.4,
|
||||
@@ -81,7 +88,7 @@ exec attwm
|
||||
|
||||
Either order works: whichever starts first waits for the other.
|
||||
|
||||
The `launcher`, `wifi`, `bluetooth` and `power` IPC targets each accept
|
||||
The `launcher`, `controls`, `wifi`, `bluetooth` and `power` IPC targets each accept
|
||||
`toggle`, `open` and `close`. When opened by keybind the menu appears on the screen holding the
|
||||
focused window. Only one menu is open at a time, so `close` closes whichever it
|
||||
is.
|
||||
@@ -93,6 +100,17 @@ which is what to bind to a hardware key or a tablet-mode switch:
|
||||
att_menu ipc call osk toggle
|
||||
```
|
||||
|
||||
The `volume` and `brightness` targets move the level without putting anything on
|
||||
screen, which is what the media keys want — `volume` takes `up`, `down` and
|
||||
`mute`, `brightness` takes `up` and `down`, each one step of the size configured
|
||||
in `volumeStep` / `brightnessStep`:
|
||||
|
||||
```sh
|
||||
att_menu ipc call volume up
|
||||
att_menu ipc call volume mute
|
||||
att_menu ipc call brightness down
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
**Placement.** The panel is a layer-shell surface anchored to the left, right and
|
||||
@@ -139,6 +157,30 @@ The keyboard also raises and lowers itself when a text field takes or loses
|
||||
focus, so the button follows squeekboard's own `Visible` property rather than
|
||||
remembering what it last asked for, and stays right either way.
|
||||
|
||||
**Volume and brightness.** One button carries the speaker and the volume of the
|
||||
default sink; clicking it opens a small panel holding both sliders. Drag or
|
||||
press anywhere along a slider to set it, scroll it to nudge it, and scroll the
|
||||
panel button itself to change the volume without opening anything. Clicking the
|
||||
speaker — on the button with the middle mouse button, or in the panel — mutes.
|
||||
`Up`/`Down` pick a slider, `Left`/`Right` move it a step, `Enter` mutes,
|
||||
`Escape` closes.
|
||||
|
||||
Volume goes through pipewire directly and follows the *default* sink, so
|
||||
plugging in a headset moves the slider with the sound. Moving the slider
|
||||
unmutes: a slider that changes a number and produces no sound reads as broken.
|
||||
|
||||
Brightness goes through `brightnessctl`, which falls back to logind when the
|
||||
session cannot write `/sys/class/backlight` itself. It never goes fully dark
|
||||
(`minBrightness`), since on most laptops the only way back from a black screen
|
||||
is a hardware key. sysfs raises no change events, so the current value is
|
||||
re-read on a timer — but only while the panel is open, and the panel is what
|
||||
sees the hardware keys move it. Rapid changes coalesce onto the newest, so a
|
||||
drag never queues up a hundred processes.
|
||||
|
||||
The volume row is absent where pipewire has no default sink, and the brightness
|
||||
row where there is no controllable backlight; with neither, the whole button
|
||||
goes.
|
||||
|
||||
**Wifi.** The button shows signal strength in the arcs and the SSID in use next
|
||||
to them, struck through when the radio is off. The menu lists the networks in
|
||||
range — connected first, then saved, then by strength — with the switch in the
|
||||
@@ -207,6 +249,12 @@ running with `qs --path .`).
|
||||
desktop file names without the extension (`ls /usr/share/applications`).
|
||||
- `showOsk` — set `false` to drop the on-screen keyboard button entirely.
|
||||
- `oskUnit` — the systemd user unit squeekboard runs as.
|
||||
- `showVolume` / `showBrightness` — set `false` to drop that slider. With both
|
||||
off the panel button goes too.
|
||||
- `volumeStep` / `brightnessStep` — one wheel notch, one arrow key, one
|
||||
`ipc call volume up`. `0.05` is five percent.
|
||||
- `minBrightness` — floor on the backlight, as a fraction of its maximum.
|
||||
- `controlsMenuWidth` — width of the slider panel, clamped to the screen.
|
||||
- `showWifi` — set `false` to drop the wifi button entirely.
|
||||
- `wifiLabelMaxWidth` — cap on the SSID shown on the panel.
|
||||
- `wifiMenuWidth` / `wifiMenuHeight` — also clamped to the screen.
|
||||
@@ -228,6 +276,8 @@ services/Session.qml Which menu is open, and on which screen
|
||||
services/AppLauncher.qml Desktop-entry launching
|
||||
services/Attwm.qml attwm's IPC socket, when there is one
|
||||
services/Osk.qml squeekboard: its unit, and its DBus state
|
||||
services/Audio.qml The default pipewire sink: volume and mute
|
||||
services/Brightness.qml The backlight: sysfs to read, brightnessctl to write
|
||||
modules/Bar.qml The panel window and its three sections
|
||||
modules/AppMenu.qml Left: launcher button
|
||||
modules/Launcher.qml The application menu overlay
|
||||
@@ -236,6 +286,8 @@ modules/QuickLaunch.qml Left: pinned app icons
|
||||
modules/WindowList.qml Middle: task list
|
||||
modules/WindowButton.qml One task button
|
||||
modules/OskMenu.qml Right: on-screen keyboard button
|
||||
modules/ControlsMenu.qml Right: volume button
|
||||
modules/ControlsPanel.qml The volume and brightness sliders overlay
|
||||
modules/WifiMenu.qml Right: wifi button
|
||||
modules/WifiPanel.qml The network list overlay
|
||||
modules/WifiNetworkEntry.qml One network row
|
||||
@@ -250,7 +302,11 @@ components/PanelButton.qml Shared hover/press surface
|
||||
components/BluetoothGlyph.qml The bluetooth rune, drawn
|
||||
components/WifiGlyph.qml The wifi fan, drawn
|
||||
components/KeyboardGlyph.qml The keyboard, drawn
|
||||
components/VolumeGlyph.qml The speaker, drawn
|
||||
components/BrightnessGlyph.qml The sun, drawn
|
||||
components/ToggleSwitch.qml On/off switch
|
||||
components/Slider.qml 0-1 slider, touch sized
|
||||
components/SliderRow.qml A slider with a glyph, label and reading
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
Reference in New Issue
Block a user