Skip to content

Commit 6c43bc1

Browse files
authored
fix: real electron support (mess) (#15)
1 parent 02ba4fb commit 6c43bc1

7 files changed

Lines changed: 256 additions & 233 deletions

File tree

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,35 @@ additional_clickable_roles = ["AXStaticText"]
284284

285285
### Electron & Chrome Support
286286

287+
> [!NOTE]
288+
> Electron, firefox and chrome support is a mess, and I'm not even sure if I am doing it correctly or not.
289+
> Feel free to help out if you know better about this...
290+
287291
GoVim includes built-in support for Electron apps (VS Code, Windsurf, Slack, etc.) and Chromium browsers.
288292

289293
- `accessibility.electron_support.enable` toggles automatic enabling of Electron accessibility hooks for legacy apps.
290294
- `accessibility.electron_support.additional_bundles` accepts exact bundle IDs or `prefix*` wildcards for extra Electron apps that require manual accessibility.
291295

296+
Built-in enabled apps:
297+
298+
- `org.mozilla.firefox` - Firefox
299+
- `com.microsoft.VSCode` - VS Code
300+
- `com.exafunction.windsurf` - Windsurf
301+
- `com.todesktop.230313mzl4w4u92` - Cursor
302+
- `com.tinyspeck.slackmacgap` - Slack
303+
- `com.spotify.client` - Spotify
304+
- `md.obsidian` - Obsidian
305+
- For other apps, you can add them to `accessibility.electron_support.additional_bundles` in your config, or just submit a PR to add into the source
306+
307+
Note that you don't have to add chromium bundles here. To support it, you need to:
308+
309+
1. Go to `chrome://accessibility`
310+
2. Turn on `Native accessibility API support`
311+
3. Turn on `Web accessibility`
312+
313+
> [!NOTE]
314+
> Not sure if there's a better way to do this... feel free to help out!
315+
292316
## CLI Usage
293317

294318
GoVim provides a comprehensive CLI with IPC (Inter-Process Communication) for controlling the running daemon.

cmd/govim/main.go

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,6 @@ func (a *App) registerHotkeys() error {
231231
}
232232

233233
// Note: Escape key for exiting modes is hardcoded in handleKeyPress, not registered as global hotkey
234-
235-
// ...existing code...
236-
237234
return nil
238235
}
239236

@@ -755,17 +752,17 @@ func (a *App) activateScrollMode() {
755752
// Update roles for the current focused app
756753
a.updateRolesForCurrentApp()
757754

755+
if a.config.Accessibility.ElectronSupport.Enable {
756+
accessibility.EnsureElectronSupport(a.config.Accessibility.ElectronSupport.AdditionalBundles)
757+
}
758+
758759
a.logger.Info("Initializing scroll controller")
759760
// Activate scroll mode
760761
if err := a.scrollController.Initialize(); err != nil {
761762
a.logger.Error("Failed to initialize scroll controller", zap.Error(err))
762763
return
763764
}
764765

765-
if a.config.Accessibility.ElectronSupport.Enable {
766-
accessibility.EnsureElectronSupport(a.config.Accessibility.ElectronSupport.AdditionalBundles)
767-
}
768-
769766
a.logger.Info("Getting scroll areas")
770767
// Get all scroll areas
771768
areas := a.scrollController.GetAllAreas()
@@ -858,15 +855,13 @@ func (a *App) exitMode() {
858855
a.eventTap.Disable()
859856
}
860857

861-
if a.config.Accessibility.ElectronSupport.Enable {
862-
accessibility.ResetElectronSupport()
863-
}
858+
// if a.config.Accessibility.ElectronSupport.Enable {
859+
// accessibility.ResetElectronSupport()
860+
// }
864861

865862
a.currentMode = ModeIdle
866863
}
867864

868-
// ...existing code...
869-
870865
// getModeString returns the current mode as a string
871866
func (a *App) getModeString() string {
872867
switch a.currentMode {

configs/default-config.toml

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,35 +38,14 @@ scrollable_roles = [
3838
# The roles defined here are ADDED to the global roles above (not replaced)
3939
# To find an app's bundle ID, run: osascript -e 'id of app "AppName"'
4040

41-
# Example: Add custom roles for Safari
41+
# For example, in `Mail.app`, lots of element are `AXStaticText` and they should be clickable. In this case, we don't want to add to the global one, as it will causes lots of unclickable hints, especially in browser space.
4242
# [[accessibility.app_configs]]
43-
# bundle_id = "com.apple.Safari"
44-
# additional_clickable_roles = ["AXGroup", "AXImage"]
45-
# additional_scrollable_roles = ["AXWebArea"]
46-
47-
# Example: Add custom roles for Firefox
48-
# [[accessibility.app_configs]]
49-
# bundle_id = "org.mozilla.firefox"
50-
# additional_clickable_roles = ["AXGroup"]
51-
# additional_scrollable_roles = []
52-
53-
# Example: Add custom roles for VS Code
54-
# [[accessibility.app_configs]]
55-
# bundle_id = "com.microsoft.VSCode"
43+
# bundle_id = "com.apple.mail"
5644
# additional_clickable_roles = ["AXStaticText"]
57-
# additional_scrollable_roles = ["AXGroup"]
5845

5946
[accessibility.electron_support]
6047
enable = true
61-
# Add Chrome and Chromium-based browsers for web app support
62-
# Windsurf is already included in the default list
63-
additional_bundles = [
64-
"com.google.Chrome",
65-
"com.google.Chrome.canary",
66-
"com.brave.Browser",
67-
"com.microsoft.edgemac",
68-
"org.chromium.Chromium",
69-
]
48+
additional_bundles = []
7049

7150
[hotkeys]
7251
# all hotkeys can be disabled by either setting the key to "" or just commenting it out
@@ -80,7 +59,6 @@ activate_hint_mode_with_actions = "Cmd+Shift+A"
8059
# Activate scroll mode for vim-style scrolling
8160
activate_scroll_mode = "Cmd+Shift+J"
8261

83-
8462
# Note: Escape key is hardcoded to exit any active mode
8563

8664
[hints]

internal/accessibility/accessible_apps.go

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,15 @@ package accessibility
22

33
import "strings"
44

5-
var (
6-
// KnownElectronPrefixes lists bundle identifier prefixes commonly backed by Electron.
7-
KnownElectronPrefixes = []string{
8-
"com.microsoft.vscode",
9-
"com.microsoft.vscodeinsiders",
10-
"com.slack.",
11-
"com.github.",
12-
"com.todesktop.",
13-
"com.zoom.",
14-
"md.obsidian",
15-
}
16-
17-
// KnownElectronExact matches bundle identifiers observed to require manual accessibility.
18-
KnownElectronExact = []string{
19-
"com.sindresorhus.helium",
20-
"com.sindresorhus.helium2",
21-
"com.tinyspeck.slackmacgap",
22-
"com.microsoft.teams",
23-
"com.exafunction.windsurf",
24-
}
25-
)
5+
var KnownElectronBundles = []string{
6+
"org.mozilla.firefox", // NOTE: why is this here? It's not an electron app, but the same logic to enable `AXEnhancedUserInterface`. Put it here first until we have a better manager for this.
7+
"com.microsoft.VSCode",
8+
"com.exafunction.windsurf",
9+
"com.todesktop.230313mzl4w4u92",
10+
"com.tinyspeck.slackmacgap",
11+
"com.spotify.client",
12+
"md.obsidian",
13+
}
2614

2715
// ShouldEnableElectronSupport determines if the provided bundle identifier
2816
// should have Electron accessibility manually toggled based on defaults and
@@ -47,23 +35,12 @@ func IsLikelyElectronBundle(bundleID string) bool {
4735
return false
4836
}
4937

50-
for _, exact := range KnownElectronExact {
38+
for _, exact := range KnownElectronBundles {
5139
if strings.EqualFold(strings.TrimSpace(exact), lower) {
5240
return true
5341
}
5442
}
5543

56-
for _, prefix := range KnownElectronPrefixes {
57-
p := strings.ToLower(strings.TrimSpace(prefix))
58-
if p == "" {
59-
continue
60-
}
61-
p = strings.TrimSuffix(p, "*")
62-
if strings.HasPrefix(lower, p) {
63-
return true
64-
}
65-
}
66-
6744
return false
6845
}
6946

internal/accessibility/accessible_apps_test.go

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,14 @@ func TestIsLikelyElectronBundle(t *testing.T) {
88
bundleID string
99
want bool
1010
}{
11-
// Exact matches
11+
{"Firefox", "org.mozilla.firefox", true},
1212
{"Windsurf", "com.exafunction.windsurf", true},
13-
{"Teams", "com.microsoft.teams", true},
14-
{"Helium", "com.sindresorhus.helium", true},
15-
{"Slack", "com.tinyspeck.slackmacgap", true},
16-
17-
// Prefix matches
18-
{"VS Code", "com.microsoft.VSCode", true},
19-
{"VS Code Insiders", "com.microsoft.VSCodeInsiders", true},
20-
{"Slack Desktop", "com.slack.Slack", true},
21-
{"GitHub Desktop", "com.github.GitHubClient", true},
22-
{"Zoom", "com.zoom.us.Zoom", true},
23-
{"Obsidian", "md.obsidian", true},
24-
{"ToDesktop App", "com.todesktop.myapp", true},
13+
{"Visual Studio Code", "com.microsoft.VSCode", true},
2514

2615
// Non-Electron apps
2716
{"Safari", "com.apple.Safari", false},
2817
{"Finder", "com.apple.finder", false},
2918
{"Chrome", "com.google.Chrome", false},
30-
{"Firefox", "org.mozilla.firefox", false},
3119

3220
// Edge cases
3321
{"Empty", "", false},

internal/accessibility/element.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package accessibility
77
88
*/
99
import "C"
10+
1011
import (
1112
"fmt"
1213
"image"
@@ -25,7 +26,10 @@ type Element struct {
2526
ref unsafe.Pointer
2627
}
2728

28-
const electronAttributeName = "AXManualAccessibility"
29+
const (
30+
electronAttributeName = "AXManualAccessibility"
31+
enhancedAttributeName = "AXEnhancedUserInterface"
32+
)
2933

3034
var (
3135
clickableRoles = make(map[string]struct{})
@@ -513,16 +517,26 @@ func ensureElectronAccessibility(pid int, bundleID string) bool {
513517
return true
514518
}
515519

516-
if !bridge.SetApplicationAttribute(pid, electronAttributeName, true) {
517-
logger.Warn("Failed to enable Electron accessibility", zap.Int("pid", pid), zap.String("bundle_id", bundleID))
520+
successSetElectron := bridge.SetApplicationAttribute(pid, electronAttributeName, true)
521+
522+
if successSetElectron {
523+
logger.Debug("Enabled AXManualAccessibility", zap.Int("pid", pid), zap.String("bundle_id", bundleID))
524+
}
525+
526+
successSetEnhanced := bridge.SetApplicationAttribute(pid, enhancedAttributeName, true)
527+
528+
if successSetEnhanced {
529+
logger.Debug("Enabled AXEnhancedUserInterface", zap.Int("pid", pid), zap.String("bundle_id", bundleID))
530+
}
531+
532+
if !successSetEnhanced && !successSetElectron {
533+
logger.Warn("Failed to enable AXManualAccessibility or AXEnhancedUserInterface", zap.Int("pid", pid), zap.String("bundle_id", bundleID))
518534
return false
519535
}
520536

521537
electronPIDsMu.Lock()
522538
electronEnabledPIDs[pid] = struct{}{}
523539
electronPIDsMu.Unlock()
524-
525-
logger.Debug("Enabled AXManualAccessibility", zap.Int("pid", pid), zap.String("bundle_id", bundleID))
526540
return true
527541
}
528542

0 commit comments

Comments
 (0)