docs(config): document the experimental hint mode
3 files · +58 -0
M README.md +1 -0
| @@ -281,6 +281,7 @@ bind.cmd+shift+f = toggle-fullscreen | |||
| 281 | 281 | bind.cmd+s = toggle-stash-visible | |
| 282 | 282 | bind.cmd+shift+s = toggle-window-stash | |
| 283 | 283 | bind.cmd+o = toggle-overview | |
| 284 | + | # bind.cmd+g = hint | |
| 284 | 285 | bind.cmd+tab = switch-column-next | |
| 285 | 286 | bind.cmd+shift+tab = switch-column-prev | |
| 286 | 287 | ||
| @@ -281,6 +281,7 @@ bind.cmd+shift+f = toggle-fullscreen | |||||
| 281 | bind.cmd+s = toggle-stash-visible | 281 | bind.cmd+s = toggle-stash-visible | ||
| 282 | bind.cmd+shift+s = toggle-window-stash | 282 | bind.cmd+shift+s = toggle-window-stash | ||
| 283 | bind.cmd+o = toggle-overview | 283 | bind.cmd+o = toggle-overview | ||
| 284 | + | # bind.cmd+g = hint | |||
| 284 | bind.cmd+tab = switch-column-next | 285 | bind.cmd+tab = switch-column-next | ||
| 285 | bind.cmd+shift+tab = switch-column-prev | 286 | bind.cmd+shift+tab = switch-column-prev | ||
| 286 | 287 | ||||
M docs/config.md +50 -0
| @@ -55,6 +55,12 @@ See [examples/config](../examples/config) for every key with its default. | |||
| 55 | 55 | | `focus.flash-opacity` | `0.6` | Starting opacity of the flash, `0.1` to `1` | | |
| 56 | 56 | | `focus.flash-duration` | `200ms` | Fade duration, `50ms` to `1s`; not scaled by `animations.speed` | | |
| 57 | 57 | | `focus.flash-color` | `border.active` | Flash color `#rrggbb`; empty uses `border.active` | | |
| 58 | + | | `hint.enable` | `off` | Turn on the experimental [hint mode](#hint-mode) (restart required) | | |
| 59 | + | | `hint.targets` | `clickable` | What [hint mode](#hint-mode) labels: `clickable` (links, URLs and buttons) or `links` (links and URLs only) | | |
| 60 | + | | `hint.text-click` | `ctrl+shift` | Modifiers held for clicks on links found by OCR (terminals open links on a modified click); `none` sends a plain click | | |
| 61 | + | | `hint.size` | `auto` | Label text size in logical pixels (6 to 72), or `auto` for screen pixel density | | |
| 62 | + | | `hint.background` | empty | Label background (`#rrggbb`); empty uses `border.active` | | |
| 63 | + | | `hint.foreground` | empty | Label text (`#rrggbb`); empty chooses a contrasting colour | | |
| 58 | 64 | | `workspace.<name>.monitor` | focused output | Home monitor of a named workspace | | |
| 59 | 65 | | `workspace.<name>.size` | `inherit` | [Smaller viewport](#workspace-size), e.g. `1920x1080` | | |
| 60 | 66 | | `workspace.<name>.max-columns`, `.overflow` | output values | Per-workspace layout | | |
| @@ -191,6 +197,7 @@ bind.XF86MonBrightnessDown = spawn brightnessctl set 5%- | |||
| 191 | 197 | | `toggle-window-stash` | Move the focused window to the [stash](#stash), or back to its column | | |
| 192 | 198 | | `toggle-stash-visible` | Show or hide the stash | | |
| 193 | 199 | | `toggle-overview` | Open or close the [overview](#overview) | | |
| 200 | + | | `hint` | Label the links and buttons on the focused screen, then click the one you type ([hint mode](#hint-mode)) | | |
| 194 | 201 | | `switch-column-next` / `-prev` | Switch to the previously used column. Hold `cmd` and press again to go further back | | |
| 195 | 202 | | `maximize-column` | Toggle full width for the focused column | | |
| 196 | 203 | | `cycle-column-width` | Grow the focused column by one [cell](#column-widths), then back to equal widths | | |
| @@ -295,3 +302,46 @@ A workspace's stash shows as a pile of cards. Selecting the pile unfolds it into | |||
| 295 | 302 | With `layout.overflow = cascade`, workspaces sit side by side, each band of columns is a lane, and the stash sits under the lanes. Down (or fingers down on the touchpad, with natural scroll off) moves to the lane below; past the last lane it unfolds the stash. Left/right walk the cards; where the carousel does not wrap round, they go to the neighbor workspace past either end. Up leaves the stash for the last lane, at the column you came from. | |
| 296 | 303 | ||
| 297 | 304 | Otherwise, left from the first column unfolds the stash. Up/down walk the cards, the focus-workspace binds change workspace, and right goes back to the columns. | |
| 305 | + | ||
| 306 | + | ## Hint mode | |
| 307 | + | ||
| 308 | + | Hint mode is experimental and off by default: set `hint.enable = on` and restart NeferWL. | |
| 309 | + | While it is off, nothing of hint mode runs or uses memory, and the `hint` bind | |
| 310 | + | logs a notice once and does nothing. A reload does not change it. | |
| 311 | + | ||
| 312 | + | `hint` labels the links and buttons on the focused output. Type a label to | |
| 313 | + | click its target; BackSpace erases a letter, Escape cancels. No bind is set | |
| 314 | + | by default; for example `bind.cmd+g = hint`. | |
| 315 | + | ||
| 316 | + | Labels use the `border.active` colour with a contrasting text colour, and | |
| 317 | + | their size follows the screen's pixel density. Each label sits just outside | |
| 318 | + | the top-left corner of its target. Links found by OCR (terminal text) are | |
| 319 | + | clicked with the `hint.text-click` modifiers held, which is how terminals open | |
| 320 | + | a link; accessibility targets get a plain click. | |
| 321 | + | ||
| 322 | + | ### Where targets come from | |
| 323 | + | ||
| 324 | + | | Source | Apps | Accuracy | Speed | | |
| 325 | + | |---|---|---|---| | |
| 326 | + | | Accessibility tree (AT-SPI) | Firefox, Chromium, GTK, Qt, Electron | Exact: the app reports its own links and buttons | A few milliseconds | | |
| 327 | + | | Text recognition (OCR) | Everything else: terminals, apps without accessibility | Best effort: URLs, domains and underlined text written on screen | 150 ms or more, more on large screens | | |
| 328 | + | ||
| 329 | + | NeferWL asks the accessibility tree first. Windows it does not cover are read | |
| 330 | + | with OCR, which finds visible URLs, domains, email addresses and underlined | |
| 331 | + | text. Underlined words get a plain click, and the words of one continuous | |
| 332 | + | underline form one target; URLs keep the `hint.text-click` modifiers. OCR | |
| 333 | + | cannot see a link whose address is hidden behind plain text, and it can misread | |
| 334 | + | small or low-contrast text. | |
| 335 | + | ||
| 336 | + | ### Requirements | |
| 337 | + | ||
| 338 | + | - Accessibility: NeferWL turns it on at startup. Some apps need a flag: | |
| 339 | + | - Chromium: `--force-renderer-accessibility` | |
| 340 | + | - Electron: `ACCESSIBILITY_ENABLED=1` | |
| 341 | + | - Qt: `QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1` | |
| 342 | + | - OCR: `tesseract` and `tesseract-data-eng`. Without tesseract, OCR is off | |
| 343 | + | and hint mode labels only apps that expose the accessibility tree. | |
| 344 | + | ||
| 345 | + | ### Debugging hint mode | |
| 346 | + | ||
| 347 | + | With `hint.enable = on` and `NEFERWL_HINT_DEBUG=1` set when NeferWL starts (for example `NEFERWL_HINT_DEBUG=1 make tty`, or the variable in the launch environment), every successful scan writes three files to `$XDG_STATE_HOME/neferwl/hints/` (`~/.local/state/neferwl/hints/` when unset): `<time>-<output>.png`, the frame as scanned; `<time>-<output>.annotated.png`, the same with each target outlined (OCR links green, accessibility targets magenta, OCR window crops grey); and `<time>-<output>.json`, the targets (with their `source`, `atspi` or `ocr`) and timings. NeferWL keeps the 50 most recent scans and logs a warning at startup. The files contain the screen in clear: delete them after use. | |
| @@ -55,6 +55,12 @@ See [examples/config](../examples/config) for every key with its default. | |||||
| 55 | | `focus.flash-opacity` | `0.6` | Starting opacity of the flash, `0.1` to `1` | | 55 | | `focus.flash-opacity` | `0.6` | Starting opacity of the flash, `0.1` to `1` | | ||
| 56 | | `focus.flash-duration` | `200ms` | Fade duration, `50ms` to `1s`; not scaled by `animations.speed` | | 56 | | `focus.flash-duration` | `200ms` | Fade duration, `50ms` to `1s`; not scaled by `animations.speed` | | ||
| 57 | | `focus.flash-color` | `border.active` | Flash color `#rrggbb`; empty uses `border.active` | | 57 | | `focus.flash-color` | `border.active` | Flash color `#rrggbb`; empty uses `border.active` | | ||
| 58 | + | | `hint.enable` | `off` | Turn on the experimental [hint mode](#hint-mode) (restart required) | | |||
| 59 | + | | `hint.targets` | `clickable` | What [hint mode](#hint-mode) labels: `clickable` (links, URLs and buttons) or `links` (links and URLs only) | | |||
| 60 | + | | `hint.text-click` | `ctrl+shift` | Modifiers held for clicks on links found by OCR (terminals open links on a modified click); `none` sends a plain click | | |||
| 61 | + | | `hint.size` | `auto` | Label text size in logical pixels (6 to 72), or `auto` for screen pixel density | | |||
| 62 | + | | `hint.background` | empty | Label background (`#rrggbb`); empty uses `border.active` | | |||
| 63 | + | | `hint.foreground` | empty | Label text (`#rrggbb`); empty chooses a contrasting colour | | |||
| 58 | | `workspace.<name>.monitor` | focused output | Home monitor of a named workspace | | 64 | | `workspace.<name>.monitor` | focused output | Home monitor of a named workspace | | ||
| 59 | | `workspace.<name>.size` | `inherit` | [Smaller viewport](#workspace-size), e.g. `1920x1080` | | 65 | | `workspace.<name>.size` | `inherit` | [Smaller viewport](#workspace-size), e.g. `1920x1080` | | ||
| 60 | | `workspace.<name>.max-columns`, `.overflow` | output values | Per-workspace layout | | 66 | | `workspace.<name>.max-columns`, `.overflow` | output values | Per-workspace layout | | ||
| @@ -191,6 +197,7 @@ bind.XF86MonBrightnessDown = spawn brightnessctl set 5%- | |||||
| 191 | | `toggle-window-stash` | Move the focused window to the [stash](#stash), or back to its column | | 197 | | `toggle-window-stash` | Move the focused window to the [stash](#stash), or back to its column | | ||
| 192 | | `toggle-stash-visible` | Show or hide the stash | | 198 | | `toggle-stash-visible` | Show or hide the stash | | ||
| 193 | | `toggle-overview` | Open or close the [overview](#overview) | | 199 | | `toggle-overview` | Open or close the [overview](#overview) | | ||
| 200 | + | | `hint` | Label the links and buttons on the focused screen, then click the one you type ([hint mode](#hint-mode)) | | |||
| 194 | | `switch-column-next` / `-prev` | Switch to the previously used column. Hold `cmd` and press again to go further back | | 201 | | `switch-column-next` / `-prev` | Switch to the previously used column. Hold `cmd` and press again to go further back | | ||
| 195 | | `maximize-column` | Toggle full width for the focused column | | 202 | | `maximize-column` | Toggle full width for the focused column | | ||
| 196 | | `cycle-column-width` | Grow the focused column by one [cell](#column-widths), then back to equal widths | | 203 | | `cycle-column-width` | Grow the focused column by one [cell](#column-widths), then back to equal widths | | ||
| @@ -295,3 +302,46 @@ A workspace's stash shows as a pile of cards. Selecting the pile unfolds it into | |||||
| 295 | With `layout.overflow = cascade`, workspaces sit side by side, each band of columns is a lane, and the stash sits under the lanes. Down (or fingers down on the touchpad, with natural scroll off) moves to the lane below; past the last lane it unfolds the stash. Left/right walk the cards; where the carousel does not wrap round, they go to the neighbor workspace past either end. Up leaves the stash for the last lane, at the column you came from. | 302 | With `layout.overflow = cascade`, workspaces sit side by side, each band of columns is a lane, and the stash sits under the lanes. Down (or fingers down on the touchpad, with natural scroll off) moves to the lane below; past the last lane it unfolds the stash. Left/right walk the cards; where the carousel does not wrap round, they go to the neighbor workspace past either end. Up leaves the stash for the last lane, at the column you came from. | ||
| 296 | 303 | ||||
| 297 | Otherwise, left from the first column unfolds the stash. Up/down walk the cards, the focus-workspace binds change workspace, and right goes back to the columns. | 304 | Otherwise, left from the first column unfolds the stash. Up/down walk the cards, the focus-workspace binds change workspace, and right goes back to the columns. | ||
| 305 | + | ||||
| 306 | + | ## Hint mode | |||
| 307 | + | ||||
| 308 | + | Hint mode is experimental and off by default: set `hint.enable = on` and restart NeferWL. | |||
| 309 | + | While it is off, nothing of hint mode runs or uses memory, and the `hint` bind | |||
| 310 | + | logs a notice once and does nothing. A reload does not change it. | |||
| 311 | + | ||||
| 312 | + | `hint` labels the links and buttons on the focused output. Type a label to | |||
| 313 | + | click its target; BackSpace erases a letter, Escape cancels. No bind is set | |||
| 314 | + | by default; for example `bind.cmd+g = hint`. | |||
| 315 | + | ||||
| 316 | + | Labels use the `border.active` colour with a contrasting text colour, and | |||
| 317 | + | their size follows the screen's pixel density. Each label sits just outside | |||
| 318 | + | the top-left corner of its target. Links found by OCR (terminal text) are | |||
| 319 | + | clicked with the `hint.text-click` modifiers held, which is how terminals open | |||
| 320 | + | a link; accessibility targets get a plain click. | |||
| 321 | + | ||||
| 322 | + | ### Where targets come from | |||
| 323 | + | ||||
| 324 | + | | Source | Apps | Accuracy | Speed | | |||
| 325 | + | |---|---|---|---| | |||
| 326 | + | | Accessibility tree (AT-SPI) | Firefox, Chromium, GTK, Qt, Electron | Exact: the app reports its own links and buttons | A few milliseconds | | |||
| 327 | + | | Text recognition (OCR) | Everything else: terminals, apps without accessibility | Best effort: URLs, domains and underlined text written on screen | 150 ms or more, more on large screens | | |||
| 328 | + | ||||
| 329 | + | NeferWL asks the accessibility tree first. Windows it does not cover are read | |||
| 330 | + | with OCR, which finds visible URLs, domains, email addresses and underlined | |||
| 331 | + | text. Underlined words get a plain click, and the words of one continuous | |||
| 332 | + | underline form one target; URLs keep the `hint.text-click` modifiers. OCR | |||
| 333 | + | cannot see a link whose address is hidden behind plain text, and it can misread | |||
| 334 | + | small or low-contrast text. | |||
| 335 | + | ||||
| 336 | + | ### Requirements | |||
| 337 | + | ||||
| 338 | + | - Accessibility: NeferWL turns it on at startup. Some apps need a flag: | |||
| 339 | + | - Chromium: `--force-renderer-accessibility` | |||
| 340 | + | - Electron: `ACCESSIBILITY_ENABLED=1` | |||
| 341 | + | - Qt: `QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1` | |||
| 342 | + | - OCR: `tesseract` and `tesseract-data-eng`. Without tesseract, OCR is off | |||
| 343 | + | and hint mode labels only apps that expose the accessibility tree. | |||
| 344 | + | ||||
| 345 | + | ### Debugging hint mode | |||
| 346 | + | ||||
| 347 | + | With `hint.enable = on` and `NEFERWL_HINT_DEBUG=1` set when NeferWL starts (for example `NEFERWL_HINT_DEBUG=1 make tty`, or the variable in the launch environment), every successful scan writes three files to `$XDG_STATE_HOME/neferwl/hints/` (`~/.local/state/neferwl/hints/` when unset): `<time>-<output>.png`, the frame as scanned; `<time>-<output>.annotated.png`, the same with each target outlined (OCR links green, accessibility targets magenta, OCR window crops grey); and `<time>-<output>.json`, the targets (with their `source`, `atspi` or `ocr`) and timings. NeferWL keeps the 50 most recent scans and logs a warning at startup. The files contain the screen in clear: delete them after use. | |||
M examples/config +7 -0
| @@ -94,6 +94,11 @@ focus.flash-width = 2 | |||
| 94 | 94 | focus.flash-opacity = 0.6 | |
| 95 | 95 | focus.flash-duration = 200ms | |
| 96 | 96 | focus.flash-color = | |
| 97 | + | # Hint mode is experimental and off: turn it on here (restart required). | |
| 98 | + | # hint.enable = off | |
| 99 | + | # Hint mode labels the links, URLs and buttons on the focused screen: | |
| 100 | + | # clickable (links, URLs and buttons) or links (links and URLs only). | |
| 101 | + | # hint.targets = clickable | |
| 97 | 102 | ||
| 98 | 103 | # Named workspaces are outside the numbered list and require a bind. The bind | |
| 99 | 104 | # shows one; pressing it again returns to the previous workspace. | |
| @@ -195,6 +200,8 @@ bind.cmd+shift+f = toggle-fullscreen | |||
| 195 | 200 | bind.cmd+s = toggle-stash-visible | |
| 196 | 201 | bind.cmd+shift+s = toggle-window-stash | |
| 197 | 202 | bind.cmd+o = toggle-overview | |
| 203 | + | # Label the links and buttons on screen and click one by typing its label. | |
| 204 | + | # bind.cmd+g = hint | |
| 198 | 205 | bind.cmd+q = close-window | |
| 199 | 206 | bind.ctrl+alt+backspace = quit | |
| 200 | 207 | bind.ctrl+cmd+space = spawn fuzzel | |
| @@ -94,6 +94,11 @@ focus.flash-width = 2 | |||||
| 94 | focus.flash-opacity = 0.6 | 94 | focus.flash-opacity = 0.6 | ||
| 95 | focus.flash-duration = 200ms | 95 | focus.flash-duration = 200ms | ||
| 96 | focus.flash-color = | 96 | focus.flash-color = | ||
| 97 | + | # Hint mode is experimental and off: turn it on here (restart required). | |||
| 98 | + | # hint.enable = off | |||
| 99 | + | # Hint mode labels the links, URLs and buttons on the focused screen: | |||
| 100 | + | # clickable (links, URLs and buttons) or links (links and URLs only). | |||
| 101 | + | # hint.targets = clickable | |||
| 97 | 102 | ||||
| 98 | # Named workspaces are outside the numbered list and require a bind. The bind | 103 | # Named workspaces are outside the numbered list and require a bind. The bind | ||
| 99 | # shows one; pressing it again returns to the previous workspace. | 104 | # shows one; pressing it again returns to the previous workspace. | ||
| @@ -195,6 +200,8 @@ bind.cmd+shift+f = toggle-fullscreen | |||||
| 195 | bind.cmd+s = toggle-stash-visible | 200 | bind.cmd+s = toggle-stash-visible | ||
| 196 | bind.cmd+shift+s = toggle-window-stash | 201 | bind.cmd+shift+s = toggle-window-stash | ||
| 197 | bind.cmd+o = toggle-overview | 202 | bind.cmd+o = toggle-overview | ||
| 203 | + | # Label the links and buttons on screen and click one by typing its label. | |||
| 204 | + | # bind.cmd+g = hint | |||
| 198 | bind.cmd+q = close-window | 205 | bind.cmd+q = close-window | ||
| 199 | bind.ctrl+alt+backspace = quit | 206 | bind.ctrl+alt+backspace = quit | ||
| 200 | bind.ctrl+cmd+space = spawn fuzzel | 207 | bind.ctrl+cmd+space = spawn fuzzel | ||