Skip to content

Commit c3aaea9

Browse files
ccrusiusy3owk1n
andauthored
feat(hints): add wl-kbptr contour-based hint strategy on Linux (#1543)
Co-authored-by: Kyle Wong <62775956+y3owk1n@users.noreply.github.com>
1 parent ed456c4 commit c3aaea9

25 files changed

Lines changed: 1296 additions & 26 deletions

docs/CLI.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ nothing.
302302
| `--hide-on-empty-search` | | none | `hints` | Hide all hints when search query is empty (requires --search) |
303303
| `--role` | | value, repeatable | `hints` | Filter by element role (comma-separated: button,link — the hints.clickable_roles vocabulary, see 'neru roles'). Repeat the flag to add more |
304304
| `--text` | | value, repeatable | `hints` | Filter elements by text content (comma-separated, case-insensitive substring match). Repeat the flag to add more |
305-
| `--strategy` | | value | `hints` | Element detection strategy: axtree (the platform accessibility tree) or vision (screen recognition: the Vision framework on macOS, tesseract OCR on Linux) |
305+
| `--strategy` | | value | `hints` | Element detection strategy: axtree (the platform accessibility tree), vision (screen recognition: the Vision framework on macOS, tesseract OCR on Linux), or wl-kbptr (contour detection via embedded C) |
306306
| `--label-direction` | | value | `hints` | Hint label enumeration: normal (default, prefix-avoidance, prefers shorter labels) or reverse (spreads labels across the alphabet) |
307307
| `--split-word` | | none | `hints` | Split detected text into word-level regions (requires vision strategy) |
308308
| `--zoom-to-depth` | | value | `recursive_grid` | Auto-zoom to the given depth (a non-negative integer) in recursive-grid at the current cursor position |

docs/CONFIGURATION.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ Explicit component colors override theme derivation. Omitted colors inherit from
765765

766766
## [hints]
767767

768-
Labels clickable UI elements with short overlay labels. By default uses the platform accessibility tree (`axtree` strategy). Optionally uses on-screen recognition (`vision` strategy) for apps whose accessibility tree is too thin to hint from — detects elements from a screen capture scoped to the focused window, through the Vision framework on macOS (text plus rectangles) and tesseract OCR on Linux (text only).
768+
Labels clickable UI elements with short overlay labels. By default uses the platform accessibility tree (`axtree` strategy). Optionally uses on-screen recognition (`vision` strategy) for apps whose accessibility tree is too thin to hint from — detects elements from a screen capture scoped to the focused window, through the Vision framework on macOS (text plus rectangles) and tesseract OCR on Linux (text only). On Linux, the `wl-kbptr` strategy detects buttons, icons, and text by running contour detection directly on the captured window buffer without external library dependencies.
769769

770770
Press `/` to text-search elements. `Space` for multi-word queries. `Return` confirms filtered hints (first is auto-selected). `Escape` cancels search.
771771

@@ -776,7 +776,7 @@ Start with search visible: `neru hints --search` (see [CLI.md](CLI.md#neru-hints
776776
| Option | Type | Default | Description |
777777
| ---------------------------------- | ------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
778778
| `enabled` | bool | `true` | Enable/disable hints mode |
779-
| `strategy` | string | `"axtree"` | Element detection strategy: `"axtree"` (the platform accessibility tree) or `"vision"` (screen recognition — Vision framework on macOS, tesseract OCR on Linux, unavailable on Windows). Vision mode detects the frontmost window content from a screen capture while still using the accessibility tree for system elements (menubar, dock, NC). Overridable per-app via `[hints.app_configs]`. |
779+
| `strategy` | string | `"axtree"` | Element detection strategy: `"axtree"` (the platform accessibility tree), `"vision"` (screen recognition — Vision framework on macOS, tesseract OCR on Linux, unavailable on Windows), or `"wl-kbptr"` (Linux only contour detection replicated from wl-kbptr). Vision and wl-kbptr modes detect the frontmost window content from a screen capture while still using the accessibility tree for system elements (menubar, dock, NC). Overridable per-app via `[hints.app_configs]`. |
780780
| `hint_characters` | string | `"asdfghjkl"` | Characters used for labels |
781781
| `label_direction` | string | `"normal"` | Hint label algorithm: `"normal"` (default, prefix-avoidance greedy) or `"reverse"` (reverse-order tiers). Empty value defaults to `"normal"`. Overridable per-app via `[hints.app_configs]` and per-activation via the `neru hints --label-direction` CLI flag. See [Choosing a label direction](#choosing-a-label-direction) below. |
782782
| `max_depth` | int | `50` | Max accessibility tree depth (0 = unlimited) |
@@ -1023,7 +1023,7 @@ You can also mix directions per-app via `[hints.app_configs]` or per-activation
10231023
| Field | Type | Description |
10241024
| ---------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
10251025
| `bundle_id` | string | App bundle ID |
1026-
| `strategy` | string | Override element detection strategy for this app (`"axtree"` or `"vision"`). Empty string = use global `hints.strategy`. |
1026+
| `strategy` | string | Override element detection strategy for this app (`"axtree"`, `"vision"`, or `"wl-kbptr"`). Empty string = use global `hints.strategy`. |
10271027
| `label_direction` | string | Override hint label algorithm for this app (`"normal"` or `"reverse"`). Empty string = use global `hints.label_direction`. See [Choosing a label direction](#choosing-a-label-direction). |
10281028
| `additional_clickable_roles` | array | Extra roles to treat as clickable, same vocabulary as [`clickable_roles`](#clickable-roles) |
10291029
| `ignore_clickable_check` | bool | Skip clickability heuristic for this app |

docs/CROSS_PLATFORM.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,12 @@ green in every cell while an option means nothing, which is exactly how
10341034
| `recursive_grid.app_configs.strategy = vision` | option |||| the vision strategy needs an element-detection engine, which macOS has in the Vision framework and Linux in tesseract; Windows has neither, so it finds nothing there and none of its settings are read; use axtree |
10351035
| `scroll.app_configs.strategy = vision` | option |||| the vision strategy needs an element-detection engine, which macOS has in the Vision framework and Linux in tesseract; Windows has neither, so it finds nothing there and none of its settings are read; use axtree |
10361036
| `app_configs.strategy = vision` | option |||| the vision strategy needs an element-detection engine, which macOS has in the Vision framework and Linux in tesseract; Windows has neither, so it finds nothing there and none of its settings are read; use axtree |
1037+
| `hints.strategy = wl-kbptr` | option |||| the wl-kbptr strategy detects UI elements via contour analysis of screen captures on Linux |
1038+
| `hints.app_configs.strategy = wl-kbptr` | option |||| the wl-kbptr strategy detects UI elements via contour analysis of screen captures on Linux |
1039+
| `grid.app_configs.strategy = wl-kbptr` | option |||| the wl-kbptr strategy detects UI elements via contour analysis of screen captures on Linux |
1040+
| `recursive_grid.app_configs.strategy = wl-kbptr` | option |||| the wl-kbptr strategy detects UI elements via contour analysis of screen captures on Linux |
1041+
| `scroll.app_configs.strategy = wl-kbptr` | option |||| the wl-kbptr strategy detects UI elements via contour analysis of screen captures on Linux |
1042+
| `app_configs.strategy = wl-kbptr` | option |||| the wl-kbptr strategy detects UI elements via contour analysis of screen captures on Linux |
10371043
| `recursive_grid.animation.enabled` | option |||| the Windows overlay backend has no grid transition animation |
10381044
| `recursive_grid.animation.duration_ms` | option |||| the Windows overlay backend has no grid transition animation |
10391045
| `monitor_select.enabled` | option |||| monitor_select needs the optional MonitorSelector overlay extension, which the Windows backend does not implement |
@@ -1068,6 +1074,7 @@ green in every cell while an option means nothing, which is exactly how
10681074
| `smooth_scroll.duration_per_pixel` | option |||| the Windows scroll is injected in one step; macOS and Linux animate it, and on X11 the steps are whole wheel notches because X has no smaller scroll to send |
10691075
| `--split-word` | mode flag |||| splitting detected text into words needs the vision strategy, which Windows has no engine for; there the flag is refused rather than ignored |
10701076
| `--strategy=vision` | mode flag |||| the vision strategy needs an element-detection engine, which macOS has in the Vision framework and Linux in tesseract; Windows has neither, so detection returns nothing and no hints appear; use axtree |
1077+
| `--strategy=wl-kbptr` | mode flag |||| the wl-kbptr strategy detects UI elements via contour analysis of screen captures on Linux |
10711078
| `hide_cursor` | action |||| a Wayland client may not hide another client's cursor, and the blessed Linux stack is Wayland; Windows has no equivalent either |
10721079
| `show_cursor` | action |||| a Wayland client may not hide another client's cursor, and the blessed Linux stack is Wayland; Windows has no equivalent either |
10731080
| `scroll_left` | action |||| the Windows wheel event carries no horizontal delta, so a sideways scroll injects nothing |

0 commit comments

Comments
 (0)