@@ -65,7 +65,7 @@ reference implementation, and a gap on this platform is a bug.
6565
6666** Beta** — good for daily driving. Every navigation mode works and behaves the
6767same as it does on a stable platform; what is missing sits around the edges
68- (notifications, alerts, a few animations) rather than in your way.
68+ (a few animations, the OCR hint strategy ) rather than in your way.
6969
7070** Alpha** — worth trying, not yet worth switching to. Core navigation works, but
7171hint coverage is incomplete and per-app config does not re-apply on focus
@@ -157,8 +157,8 @@ that is what [Known Gaps](#known-gaps) tracks, per
157157| ** Dark mode detection** | ✅ Cocoa appearance | ✅ xdg appearance portal | ✅ xdg appearance portal | ✅ kdeglobals + portal | ✅ registry |
158158| ** Font resolution** | ✅ NSFont | ✅ fontconfig | ✅ fontconfig | ✅ fontconfig | ⚠️ generic-alias map only ² |
159159| ** System tray** | ✅ NSStatusItem | ✅ D-Bus StatusNotifierItem | ✅ StatusNotifierItem | ✅ StatusNotifierItem | ✅ Win32 notification area |
160- | ** Native alerts** | ✅ NSAlert | 🟡 | 🟡 | 🟡 | ✅ ` MessageBoxW ` |
161- | ** Native notifications** | ✅ UNNotification | 🟡 | 🟡 | 🟡 | 🟡 |
160+ | ** Native alerts** | ✅ NSAlert | ⚠️ D-Bus, not modal | ⚠️ D-Bus, not modal | ⚠️ D-Bus, not modal | ✅ ` MessageBoxW ` |
161+ | ** Native notifications** | ✅ UNNotification | ✅ ` org.freedesktop.Notifications ` | ✅ ` org.freedesktop.Notifications ` | ✅ ` org.freedesktop.Notifications ` | 🟡 |
162162| ** Secure input detection** | ✅ | ➖ always false | ➖ always false | ➖ always false | ➖ always false |
163163| ** System cursor hide** | ✅ ` CGDisplayHideCursor ` | ➖ | ➖ | ➖ | ➖ |
164164| ** ` monitor_select ` mode** | ✅ native panels | ✅ Cairo panels | ✅ Cairo panels | ✅ Cairo panels | 🟡 ` CodeNotSupported ` |
@@ -250,6 +250,24 @@ binary was compiled. Both name the same fallback — bind `neru <mode>` as a
250250compositor keybinding. While a mode is active the in-mode event tap grabs the
251251same devices, so the listener naturally goes quiet until the mode exits.
252252
253+ ** Native alerts on Linux.** Notifications and alerts both go to the session's
254+ freedesktop notification daemon over D-Bus — the same session bus the tray's
255+ StatusNotifierItem uses, in pure Go, so a ` CGO_ENABLED=0 ` build shows them too.
256+ An alert differs from a notification only in insistence: critical urgency and no
257+ expiry, which the specification requires a daemon to leave on screen until it is
258+ dismissed. What it is * not* is modal. macOS's ` NSAlert ` stops the world and
259+ returns which button was pressed; no ordinary Wayland or X11 client can do that,
260+ so a Linux alert informs rather than asks, and callers that would have branched
261+ on the answer take the safe default. The two startup alerts are where that shows
262+ up: a missing config file starts Neru on built-in defaults and says so, instead
263+ of offering create / defaults / quit. Delivery depends on the session having a
264+ notification daemon (mako, dunst, or the desktop's own) — either running, or
265+ registered with the bus to be started on demand, which is how most desktops ship
266+ theirs and which ` neru doctor ` counts as present. With none, ` ShowNotification `
267+ and ` ShowAlert ` report ` CodeNotSupported ` naming what is absent, ` neru doctor `
268+ probes the session and downgrades the notifications row with a line saying what
269+ to install, and the two startup alerts fall back to stderr.
270+
253271** Smooth cursor animation on Linux.** Off by default; opt in with
254272` smooth_cursor.move_mouse_enabled ` (the same cross-platform ` SmoothCursorConfig `
255273macOS uses). When enabled, ` SystemAdapter.MoveCursorToPoint ` routes through
@@ -751,49 +769,45 @@ command — that means less here than it does on macOS, whether or not the
751769
752770** Linux**
753771
754- 1 . Native notifications and alerts — both stubs; target freedesktop D-Bus
755- notifications. ` ShowNotification ` has an empty body and no error to carry,
756- ` ShowAlert ` returns ` CodeNotSupported ` , and the config-onboarding and
757- validation-error alerts silently return defaults instead of prompting
758- 2 . ` neru services ` — no systemd user unit, so install/uninstall/start/stop/
772+ 1 . ` neru services ` — no systemd user unit, so install/uninstall/start/stop/
759773 restart/status all return ` CodeNotSupported ` where macOS writes a launchd
760774 plist. Scope is systemd; other init systems stay ` CodeNotSupported `
761- 3 . ` neru docs ` — returns ` CodeNotSupported ` although the tray already opens
775+ 2 . ` neru docs ` — returns ` CodeNotSupported ` although the tray already opens
762776 URLs through ` xdg-open ` in the same repo
763- 4 . Smooth scroll animation — not implemented, and ` smooth_scroll.* ` is parsed,
777+ 3 . Smooth scroll animation — not implemented, and ` smooth_scroll.* ` is parsed,
764778 validated and then silently ignored. Spike ` REL_WHEEL_HI_RES ` (uinput),
765779 continuous ` wl_pointer ` axis values and libei scroll deltas before
766780 committing
767- 5 . Hints search input badge — not drawn; the overlay manager reports
781+ 4 . Hints search input badge — not drawn; the overlay manager reports
768782 ` CodeNotSupported ` and the query goes on reaching hints through the event
769783 tap's key stream
770- 6 . Screen capture — no code path anywhere in the tree. Prerequisite for the OCR
784+ 5 . Screen capture — no code path anywhere in the tree. Prerequisite for the OCR
771785 strategy below and the missing half of ` ports.Vision ` . Take it per backend:
772786 ` wlr-screencopy ` on wlroots, ` XGetImage ` on X11, the portal only for KDE
773- 7 . ` vision ` hint strategy — no engine. Met by linking one through
787+ 6 . ` vision ` hint strategy — no engine. Met by linking one through
774788 ` #cgo pkg-config ` , as every other native dependency here is, with the engine
775789 added to the required Linux library list and its language data checked at
776790 use so a missing ` tessdata ` reports ` CodeNotSupported ` naming what is
777791 absent. Note the strategy is wider than OCR: macOS also runs rectangle
778792 detection and saliency, which no OCR engine answers, so
779793 ` hints.vision.detect_rectangles ` and the four ` rectangle_* ` options are
780- declared macOS-only and Linux ` vision ` is text-only. Needs 6
781- 8 . X11 unmodified scroll — a scroll with no ` --modifier ` presses nothing, so the
794+ declared macOS-only and Linux ` vision ` is text-only. Needs 5
795+ 7 . X11 unmodified scroll — a scroll with no ` --modifier ` presses nothing, so the
782796 ` XTestFakeButtonEvent ` still carries whatever the X server records the user as
783797 physically holding. Binding ` Ctrl+J ` to a plain ` scroll_down ` therefore sends
784798 ctrl+scroll for as long as ctrl is down. macOS forces the empty set onto the
785799 event instead; a real-key backend has no per-event field to zero, so closing
786800 this means reading the live key state through ` XQueryKeymap ` in the C bridge
787- 9 . KDE RemoteDesktop portal grant — does not survive a daemon restart, so the
801+ 8 . KDE RemoteDesktop portal grant — does not survive a daemon restart, so the
788802 consent prompt returns on every start
789- 10 . Grid virtual-pointer indicator — a no-op on Linux, while recursive grid
790- draws it on all three platforms
791- 11 . ` FocusedWindowBounds ` — returns not-found on KWin, so callers silently fall
803+ 9 . Grid virtual-pointer indicator — a no-op on Linux, while recursive grid
804+ draws it on all three platforms
805+ 10 . ` FocusedWindowBounds ` — returns not-found on KWin, so callers silently fall
792806 back to the active screen
793- 12 . Wayland global hotkeys — a setup requirement rather than missing code: they
807+ 11 . Wayland global hotkeys — a setup requirement rather than missing code: they
794808 need ` input ` -group membership and a CGO build. Failing loudly with the
795809 remedy, and documenting it as a first-class setup step, is the work
796- 13 . Tail — the tray tooltip is a no-op (dbusmenu carries no such property), the
810+ 12 . Tail — the tray tooltip is a no-op (dbusmenu carries no such property), the
797811 tray has one icon for both running and paused states where macOS has two,
798812 and the ` CGO_ENABLED=0 ` build should announce its boundary once at startup
799813 rather than failing feature by feature
0 commit comments