fix(input): normalize shifted letter keyvals
- commit
- f2001c937ac6c678b2b35b756856db2394331292
- author
- brice · · 2025-12-27 16:04 UTC
- parent
- 6d66691
- signature
- unsigned
2 files · +10 -2
M internal/ui/input/keyboard.go +8 -0
| @@ -139,6 +139,14 @@ func (h *KeyboardHandler) handleKeyPress(keyval, keycode uint, state gdk.Modifie | |||
| 139 | 139 | ||
| 140 | 140 | // Build KeyBinding from event | |
| 141 | 141 | modifiers := Modifier(state) & modifierMask | |
| 142 | + | ||
| 143 | + | // GTK reports shifted letters as uppercase keyvals (e.g. Shift+M -> gdk.KEY_M). | |
| 144 | + | // Normalize ASCII A-Z to lowercase so bindings can consistently use lowercase | |
| 145 | + | // keyvals and rely on ModShift to represent Shift. | |
| 146 | + | if keyval >= uint('A') && keyval <= uint('Z') { | |
| 147 | + | keyval = keyval + (uint('a') - uint('A')) | |
| 148 | + | } | |
| 149 | + | ||
| 142 | 150 | binding := KeyBinding{ | |
| 143 | 151 | Keyval: keyval, | |
| 144 | 152 | Modifiers: modifiers, | |
| @@ -139,6 +139,14 @@ func (h *KeyboardHandler) handleKeyPress(keyval, keycode uint, state gdk.Modifie | |||||
| 139 | 139 | ||||
| 140 | // Build KeyBinding from event | 140 | // Build KeyBinding from event | ||
| 141 | modifiers := Modifier(state) & modifierMask | 141 | modifiers := Modifier(state) & modifierMask | ||
| 142 | + | ||||
| 143 | + | // GTK reports shifted letters as uppercase keyvals (e.g. Shift+M -> gdk.KEY_M). | |||
| 144 | + | // Normalize ASCII A-Z to lowercase so bindings can consistently use lowercase | |||
| 145 | + | // keyvals and rely on ModShift to represent Shift. | |||
| 146 | + | if keyval >= uint('A') && keyval <= uint('Z') { | |||
| 147 | + | keyval = keyval + (uint('a') - uint('A')) | |||
| 148 | + | } | |||
| 149 | + | ||||
| 142 | binding := KeyBinding{ | 150 | binding := KeyBinding{ | ||
| 143 | Keyval: keyval, | 151 | Keyval: keyval, | ||
| 144 | Modifiers: modifiers, | 152 | Modifiers: modifiers, | ||
M internal/ui/input/shortcuts.go +2 -2
| @@ -356,7 +356,7 @@ func (s *ShortcutSet) registerStandardShortcuts() { | |||
| 356 | 356 | s.Global[KeyBinding{uint(gdk.KEY_g), ModCtrl}] = ActionFindNext | |
| 357 | 357 | s.Global[KeyBinding{uint(gdk.KEY_g), ModCtrl | ModShift}] = ActionFindPrev | |
| 358 | 358 | s.Global[KeyBinding{uint(gdk.KEY_r), ModCtrl}] = ActionReload | |
| 359 | - | s.Global[KeyBinding{uint(gdk.KEY_R), ModCtrl | ModShift}] = ActionHardReload | |
| 359 | + | s.Global[KeyBinding{uint('r'), ModCtrl | ModShift}] = ActionHardReload | |
| 360 | 360 | s.Global[KeyBinding{uint(gdk.KEY_F5), ModNone}] = ActionReload | |
| 361 | 361 | s.Global[KeyBinding{uint(gdk.KEY_F5), ModCtrl}] = ActionHardReload | |
| 362 | 362 | s.Global[KeyBinding{uint(gdk.KEY_F12), ModNone}] = ActionOpenDevTools | |
| @@ -368,7 +368,7 @@ func (s *ShortcutSet) registerStandardShortcuts() { | |||
| 368 | 368 | s.Global[KeyBinding{uint(gdk.KEY_0), ModCtrl}] = ActionZoomReset | |
| 369 | 369 | s.Global[KeyBinding{uint(gdk.KEY_q), ModCtrl}] = ActionQuit | |
| 370 | 370 | s.Global[KeyBinding{uint(gdk.KEY_F11), ModNone}] = ActionToggleFullscreen | |
| 371 | - | s.Global[KeyBinding{uint(gdk.KEY_C), ModCtrl | ModShift}] = ActionCopyURL | |
| 371 | + | s.Global[KeyBinding{uint('c'), ModCtrl | ModShift}] = ActionCopyURL | |
| 372 | 372 | // Session management - direct shortcut to open session manager | |
| 373 | 373 | s.Global[KeyBinding{uint(gdk.KEY_s), ModCtrl | ModShift}] = ActionOpenSessionManager | |
| 374 | 374 | } | |
| @@ -356,7 +356,7 @@ func (s *ShortcutSet) registerStandardShortcuts() { | |||||
| 356 | s.Global[KeyBinding{uint(gdk.KEY_g), ModCtrl}] = ActionFindNext | 356 | s.Global[KeyBinding{uint(gdk.KEY_g), ModCtrl}] = ActionFindNext | ||
| 357 | s.Global[KeyBinding{uint(gdk.KEY_g), ModCtrl | ModShift}] = ActionFindPrev | 357 | s.Global[KeyBinding{uint(gdk.KEY_g), ModCtrl | ModShift}] = ActionFindPrev | ||
| 358 | s.Global[KeyBinding{uint(gdk.KEY_r), ModCtrl}] = ActionReload | 358 | s.Global[KeyBinding{uint(gdk.KEY_r), ModCtrl}] = ActionReload | ||
| 359 | - | s.Global[KeyBinding{uint(gdk.KEY_R), ModCtrl | ModShift}] = ActionHardReload | 359 | + | s.Global[KeyBinding{uint('r'), ModCtrl | ModShift}] = ActionHardReload |
| 360 | s.Global[KeyBinding{uint(gdk.KEY_F5), ModNone}] = ActionReload | 360 | s.Global[KeyBinding{uint(gdk.KEY_F5), ModNone}] = ActionReload | ||
| 361 | s.Global[KeyBinding{uint(gdk.KEY_F5), ModCtrl}] = ActionHardReload | 361 | s.Global[KeyBinding{uint(gdk.KEY_F5), ModCtrl}] = ActionHardReload | ||
| 362 | s.Global[KeyBinding{uint(gdk.KEY_F12), ModNone}] = ActionOpenDevTools | 362 | s.Global[KeyBinding{uint(gdk.KEY_F12), ModNone}] = ActionOpenDevTools | ||
| @@ -368,7 +368,7 @@ func (s *ShortcutSet) registerStandardShortcuts() { | |||||
| 368 | s.Global[KeyBinding{uint(gdk.KEY_0), ModCtrl}] = ActionZoomReset | 368 | s.Global[KeyBinding{uint(gdk.KEY_0), ModCtrl}] = ActionZoomReset | ||
| 369 | s.Global[KeyBinding{uint(gdk.KEY_q), ModCtrl}] = ActionQuit | 369 | s.Global[KeyBinding{uint(gdk.KEY_q), ModCtrl}] = ActionQuit | ||
| 370 | s.Global[KeyBinding{uint(gdk.KEY_F11), ModNone}] = ActionToggleFullscreen | 370 | s.Global[KeyBinding{uint(gdk.KEY_F11), ModNone}] = ActionToggleFullscreen | ||
| 371 | - | s.Global[KeyBinding{uint(gdk.KEY_C), ModCtrl | ModShift}] = ActionCopyURL | 371 | + | s.Global[KeyBinding{uint('c'), ModCtrl | ModShift}] = ActionCopyURL |
| 372 | // Session management - direct shortcut to open session manager | 372 | // Session management - direct shortcut to open session manager | ||
| 373 | s.Global[KeyBinding{uint(gdk.KEY_s), ModCtrl | ModShift}] = ActionOpenSessionManager | 373 | s.Global[KeyBinding{uint(gdk.KEY_s), ModCtrl | ModShift}] = ActionOpenSessionManager | ||
| 374 | } | 374 | } | ||