add multimonitor
This commit is contained in:
@@ -6,7 +6,8 @@ river 0.4 is *non-monolithic*: it ships no window management policy of its own
|
||||
`riverctl`, no `rivertile` — and instead hands the entire job to a single external
|
||||
client speaking `river-window-management-v1`. att_wm is that client. It gives you
|
||||
dwm's model on top of river: nine tags, a master/stack layout, monocle and tabbed
|
||||
layouts, and keybindings compiled into the binary.
|
||||
layouts, and keybindings compiled into the binary. On more than one monitor the
|
||||
tags are split across the screens, so every tag lives on exactly one of them.
|
||||
|
||||
Tag and window state is published as JSON lines on a unix socket so bars such as
|
||||
[quickshell](https://quickshell.org) can render it, and `att_wmctl` drives the same
|
||||
@@ -22,6 +23,9 @@ Verified working against river 0.4.5 / Zig 0.16 / quickshell 0.3.0:
|
||||
|
||||
- tags, master / monocle / tabbed layouts, floating and fullscreen windows
|
||||
- focus cycling, `zoom`, stack reordering, per-tag layout state
|
||||
- multiple monitors, with the tag set split across them: verified on a headless
|
||||
river with two outputs, driven over IPC — the split, moving between screens,
|
||||
windows following their tags across, and views clamped to the screen's own tags
|
||||
- the IPC socket, `att_wmctl`, and a quickshell bar that maps as a layer surface
|
||||
and whose exclusive zone correctly shrinks the tiling area
|
||||
|
||||
@@ -149,7 +153,7 @@ if you would rather not compete with applications that bind Alt themselves.
|
||||
| `Mod+j` / `Mod+k` | Focus next / previous window |
|
||||
| `Mod+Shift+j` / `Mod+Shift+k` | Move focused window down / up the stack |
|
||||
| `Mod+Return` | Zoom — promote focused window to master |
|
||||
| `Mod+h` / `Mod+l` | Shrink / grow the master area |
|
||||
| `Mod+,` / `Mod+.` | Shrink / grow the master area |
|
||||
| `Mod+i` / `Mod+d` | Increase / decrease windows in master |
|
||||
| `Mod+t` / `Mod+m` / `Mod+u` | Master / monocle / tabbed layout |
|
||||
| `Mod+space` | Toggle between current and previous layout |
|
||||
@@ -161,8 +165,8 @@ if you would rather not compete with applications that bind Alt themselves.
|
||||
| `Mod+Ctrl+Shift+1..9` | Toggle tag on focused window |
|
||||
| `Mod+0` / `Mod+Shift+0` | View all tags / put window on all tags |
|
||||
| `Mod+Tab` / `Mod+Esc` | Back to previously viewed tags |
|
||||
| `Mod+,` / `Mod+.` | Focus previous / next output |
|
||||
| `Mod+Shift+,` / `Mod+Shift+.` | Send window to previous / next output |
|
||||
| `Mod+h` / `Mod+l` | Focus the screen to the left / right |
|
||||
| `Mod+Shift+h` / `Mod+Shift+l` | Send window to the screen left / right |
|
||||
| `Mod+Left drag` | Move window (floats it) |
|
||||
| `Mod+Right drag` | Resize window |
|
||||
|
||||
@@ -212,6 +216,48 @@ keep theirs for the way back.
|
||||
|
||||
---
|
||||
|
||||
## Multiple monitors
|
||||
|
||||
The tag set is **split across the screens**: every tag lives on exactly one of
|
||||
them. With two monitors the left owns tags 1–5 and the right 6–9; with three
|
||||
they get 1–3, 4–6 and 7–9. Screens are ordered by where they sit in the output
|
||||
layout, left to right and then top to bottom — not by the order they were
|
||||
plugged in — so the arrangement follows the monitors on the desk rather than the
|
||||
cables behind it.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `Mod+h` / `Mod+l` | Move to the screen on the left / right |
|
||||
| `Mod+Shift+h` / `Mod+Shift+l` | Send the focused window there |
|
||||
| `Mod+7` | Go to the screen tag 7 lives on and show tag 7 |
|
||||
| `Mod+Shift+7` | Send the focused window to tag 7, wherever that is |
|
||||
|
||||
Because a tag names a screen as well as a workspace, `Mod+7` and `Mod+h` are two
|
||||
ways of doing the same thing, and the tag keys alone are enough to drive the
|
||||
whole desk. Sending a window away leaves you where you are, as dwm's `tagmon`
|
||||
does; the keyboard goes to whatever is left on the screen you are still on.
|
||||
|
||||
`Mod+0` means everything on *this* screen — a view is always clamped to the tags
|
||||
its screen owns, so no screen can be made to show another's tag.
|
||||
|
||||
Unplugging a monitor hands its tags to the screens that remain, and the windows
|
||||
wearing those tags follow them there rather than being stranded on a tag nothing
|
||||
can show. Plug it back in and they go home. A laptop with nothing attached owns
|
||||
all nine tags and behaves exactly as it did before, which is why none of this is
|
||||
visible until there is a second screen.
|
||||
|
||||
Set `split_tags = false` in `config.zig` for dwm's model instead: every screen
|
||||
gets a full set of nine tags of its own, and the tag keys never leave the screen
|
||||
you are on. `Mod+h`/`Mod+l` and `Mod+Shift+h`/`Mod+Shift+l` still move between
|
||||
screens and are then the only way to.
|
||||
|
||||
Layer surfaces (bars) that do not name an output land on the focused screen.
|
||||
`warp_cursor` is worth turning on here: it pulls the pointer along when the
|
||||
keyboard moves to another screen, including onto an empty one, where there is no
|
||||
window to warp to and the cursor would otherwise be left behind.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
att_wm is configured at compile time, like dwm. Edit `src/config.zig` and rebuild.
|
||||
@@ -390,6 +436,7 @@ quickshell config uses one socket for both, avoiding a process spawn per click.
|
||||
"name": "DP-1",
|
||||
"focused": true,
|
||||
"tags": 1,
|
||||
"owned_tags": 31,
|
||||
"occupied": 5,
|
||||
"layout": "master",
|
||||
"layout_symbol": "[]=",
|
||||
@@ -411,8 +458,12 @@ quickshell config uses one socket for both, avoiding a process spawn per click.
|
||||
}
|
||||
```
|
||||
|
||||
`tags` and `occupied` are bitmasks — `occupied` is the set of tags holding at
|
||||
least one window, which is what dwm's bar draws its corner squares from.
|
||||
`tags`, `owned_tags` and `occupied` are bitmasks. `occupied` is the set of tags
|
||||
holding at least one window, which is what dwm's bar draws its corner squares
|
||||
from. `owned_tags` is the slice of the tag set this screen owns — see
|
||||
[Multiple monitors](#multiple-monitors) — so a bar can draw its own screen's
|
||||
tags and leave the rest to the bar on the screen they belong to. It is all nine
|
||||
when `split_tags` is off, so a bar that honours it works either way.
|
||||
`usable` is the area left after layer-shell exclusive zones, i.e. where windows
|
||||
are actually laid out.
|
||||
|
||||
@@ -464,9 +515,13 @@ quickshell -p /path/to/att_wm/quickshell
|
||||
```
|
||||
|
||||
`AttWm.qml` is a singleton wrapping the socket — reconnecting if att_wm restarts,
|
||||
exposing `outputs`, `focusedOutput`, `focusedTitle`, `tagActive()` and
|
||||
`tagOccupied()`, plus `send()` for commands. Reuse it in your own bar and ignore
|
||||
`shell.qml`.
|
||||
exposing `outputs`, `focusedOutput`, `focusedTitle`, `tagActive()`,
|
||||
`tagOccupied()` and `tagOwned()`, plus `send()` for commands. Reuse it in your
|
||||
own bar and ignore `shell.qml`.
|
||||
|
||||
One bar is created per screen and each draws only the tags its screen owns, via
|
||||
`tagOwned()` — with the tag set split across monitors the other tags belong to
|
||||
the bar next door.
|
||||
|
||||
Note that **a bar only works because att_wm binds `river_layer_shell_v1`**. river
|
||||
refuses to map layer surfaces at all unless the window manager declares support
|
||||
@@ -489,7 +544,7 @@ river's identifier is shared between them.
|
||||
| --- | --- |
|
||||
| `src/Wm.zig` | Globals, the manage/render sequence state machine, actions, event loop |
|
||||
| `src/Window.zig` | Per-window state; handlers only mutate fields |
|
||||
| `src/Output.zig` | Output tags, the per-tag layout/nmaster/mfact, and the tab bar |
|
||||
| `src/Output.zig` | Output tags and which of them it owns, the per-tag layout/nmaster/mfact, and the tab bar |
|
||||
| `src/Seat.zig` | Focus, key and pointer bindings, interactive move/resize |
|
||||
| `src/InputManager.zig` | Input devices: keymaps, key repeat, libinput settings |
|
||||
| `src/layout.zig` | Pure tiling geometry — no Wayland, unit tested |
|
||||
|
||||
Reference in New Issue
Block a user