detached 82bed32

fix(accent-picker): regain focus on mouse hover for escape to work

commit
82bed3262731e4b2186c044601be22d542852e8b
author
brice · · 2025-12-29 17:50 UTC
committer
brice · · 2025-12-30 13:48 UTC
parent
4372359
signature
unsigned
1 file · +23 -0
M internal/ui/component/accent_picker.go +23 -0
@@ -76,6 +76,9 @@ func NewAccentPicker(factory layout.WidgetFactory) *AccentPicker {
7676 // Set up key event handling
7777 ap.setupKeyboardHandling()
7878
79+ // Set up hover-to-focus: regain focus when mouse enters
80+ ap.setupHoverFocus()
81+
7982 return ap
8083 }
8184
@@ -209,6 +212,26 @@ func (ap *AccentPicker) setupKeyboardHandling() {
209212 ap.container.AddController(&keyCtrl.EventController)
210213 }
211214
215+// setupHoverFocus sets up mouse hover to regain focus.
216+// This ensures the picker regains focus when the mouse enters,
217+// so keyboard navigation (including Escape) continues to work.
218+func (ap *AccentPicker) setupHoverFocus() {
219+ motionCtrl := gtk.NewEventControllerMotion()
220+
221+ enterCb := func(_ gtk.EventControllerMotion, _ float64, _ float64) {
222+ ap.mu.Lock()
223+ visible := ap.visible
224+ ap.mu.Unlock()
225+
226+ if visible {
227+ ap.container.GrabFocus()
228+ }
229+ }
230+
231+ motionCtrl.ConnectEnter(&enterCb)
232+ ap.container.AddController(&motionCtrl.EventController)
233+}
234+
212235 // handleKeyPress processes a key press event.
213236 // Returns true if the key was handled.
214237 func (ap *AccentPicker) handleKeyPress(keyval uint) bool {
@@ -76,6 +76,9 @@ func NewAccentPicker(factory layout.WidgetFactory) *AccentPicker {
76 // Set up key event handling76 // Set up key event handling
77 ap.setupKeyboardHandling()77 ap.setupKeyboardHandling()
78 78
79+ // Set up hover-to-focus: regain focus when mouse enters
80+ ap.setupHoverFocus()
81+
79 return ap82 return ap
80 }83 }
81 84
@@ -209,6 +212,26 @@ func (ap *AccentPicker) setupKeyboardHandling() {
209 ap.container.AddController(&keyCtrl.EventController)212 ap.container.AddController(&keyCtrl.EventController)
210 }213 }
211 214
215+// setupHoverFocus sets up mouse hover to regain focus.
216+// This ensures the picker regains focus when the mouse enters,
217+// so keyboard navigation (including Escape) continues to work.
218+func (ap *AccentPicker) setupHoverFocus() {
219+ motionCtrl := gtk.NewEventControllerMotion()
220+
221+ enterCb := func(_ gtk.EventControllerMotion, _ float64, _ float64) {
222+ ap.mu.Lock()
223+ visible := ap.visible
224+ ap.mu.Unlock()
225+
226+ if visible {
227+ ap.container.GrabFocus()
228+ }
229+ }
230+
231+ motionCtrl.ConnectEnter(&enterCb)
232+ ap.container.AddController(&motionCtrl.EventController)
233+}
234+
212 // handleKeyPress processes a key press event.235 // handleKeyPress processes a key press event.
213 // Returns true if the key was handled.236 // Returns true if the key was handled.
214 func (ap *AccentPicker) handleKeyPress(keyval uint) bool {237 func (ap *AccentPicker) handleKeyPress(keyval uint) bool {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close