fix(accent-picker): resolve deadlock when selecting accent with Enter/Escape
- commit
- 0a598e1271d4ea015b1ae5b9af739dc4f798cebc
- author
- brice · · 2026-01-08 10:48 UTC
- committer
- brice · · 2026-01-08 13:04 UTC
- parent
- 172cc2c
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +8 -6
M CHANGELOG.md +2 -0
| @@ -13,6 +13,8 @@ All notable changes to this project will be documented in this file. | |||
| 13 | 13 | - **Navigation shortcuts**: `Ctrl+Left/Right` now triggers back/forward navigation, `Alt+Left/Right` moves focus between panes. Fixes #98. | |
| 14 | 14 | ||
| 15 | 15 | ### Fixed | |
| 16 | + | - **Accent picker freeze**: Fixed UI freeze when selecting an accent by pressing Enter or Escape. The deadlock was caused by the callback (which calls `Hide()`) being invoked while holding the mutex that `Hide()` also needs to acquire. | |
| 17 | + | - **Stacked pane title mismatch**: Fixed title bar showing wrong page title after closing panes in a stack. Refactored stacked pane management to use proper use cases, ensuring domain model stays in sync with UI. | |
| 16 | 18 | - **Flatpak favicons**: Fixed favicons not displaying in omnibox for Flatpak installs by ensuring cache directory exists before saving. Fixes #105. | |
| 17 | 19 | - **Flatpak desktop launcher**: Fixed .desktop file not launching application from app launchers by adding locale environment variables. Fixes #104. | |
| 18 | 20 | - **Flatpak update notifications**: Skip GitHub update checks for Flatpak and AUR installs (use package manager instead). Fixes #107. | |
| @@ -13,6 +13,8 @@ All notable changes to this project will be documented in this file. | |||||
| 13 | - **Navigation shortcuts**: `Ctrl+Left/Right` now triggers back/forward navigation, `Alt+Left/Right` moves focus between panes. Fixes #98. | 13 | - **Navigation shortcuts**: `Ctrl+Left/Right` now triggers back/forward navigation, `Alt+Left/Right` moves focus between panes. Fixes #98. | ||
| 14 | 14 | ||||
| 15 | ### Fixed | 15 | ### Fixed | ||
| 16 | + | - **Accent picker freeze**: Fixed UI freeze when selecting an accent by pressing Enter or Escape. The deadlock was caused by the callback (which calls `Hide()`) being invoked while holding the mutex that `Hide()` also needs to acquire. | |||
| 17 | + | - **Stacked pane title mismatch**: Fixed title bar showing wrong page title after closing panes in a stack. Refactored stacked pane management to use proper use cases, ensuring domain model stays in sync with UI. | |||
| 16 | - **Flatpak favicons**: Fixed favicons not displaying in omnibox for Flatpak installs by ensuring cache directory exists before saving. Fixes #105. | 18 | - **Flatpak favicons**: Fixed favicons not displaying in omnibox for Flatpak installs by ensuring cache directory exists before saving. Fixes #105. | ||
| 17 | - **Flatpak desktop launcher**: Fixed .desktop file not launching application from app launchers by adding locale environment variables. Fixes #104. | 19 | - **Flatpak desktop launcher**: Fixed .desktop file not launching application from app launchers by adding locale environment variables. Fixes #104. | ||
| 18 | - **Flatpak update notifications**: Skip GitHub update checks for Flatpak and AUR installs (use package manager instead). Fixes #107. | 20 | - **Flatpak update notifications**: Skip GitHub update checks for Flatpak and AUR installs (use package manager instead). Fixes #107. | ||
M internal/ui/component/accent_picker.go +6 -6
| @@ -177,9 +177,9 @@ func (ap *AccentPicker) selectAccent(index int) { | |||
| 177 | 177 | return | |
| 178 | 178 | } | |
| 179 | 179 | accent := ap.accents[index] | |
| 180 | - | // Invoke callback while holding lock to avoid race with Hide() clearing callbacks | |
| 181 | - | ap.selectedCb(accent) | |
| 182 | - | ap.mu.Unlock() | |
| 180 | + | cb := ap.selectedCb // Copy callback reference before unlocking | |
| 181 | + | ap.mu.Unlock() // Release lock BEFORE calling callback to avoid deadlock | |
| 182 | + | cb(accent) // Callback may call Hide() which needs to acquire ap.mu | |
| 183 | 183 | } | |
| 184 | 184 | ||
| 185 | 185 | // cancel cancels the accent picker. | |
| @@ -189,9 +189,9 @@ func (ap *AccentPicker) cancel() { | |||
| 189 | 189 | ap.mu.Unlock() | |
| 190 | 190 | return | |
| 191 | 191 | } | |
| 192 | - | // Invoke callback while holding lock to avoid race with Hide() clearing callbacks | |
| 193 | - | ap.cancelCb() | |
| 194 | - | ap.mu.Unlock() | |
| 192 | + | cb := ap.cancelCb // Copy callback reference before unlocking | |
| 193 | + | ap.mu.Unlock() // Release lock BEFORE calling callback to avoid deadlock | |
| 194 | + | cb() // Callback may call Hide() which needs to acquire ap.mu | |
| 195 | 195 | } | |
| 196 | 196 | ||
| 197 | 197 | // setupKeyboardHandling sets up key event handling for navigation. | |
| @@ -177,9 +177,9 @@ func (ap *AccentPicker) selectAccent(index int) { | |||||
| 177 | return | 177 | return | ||
| 178 | } | 178 | } | ||
| 179 | accent := ap.accents[index] | 179 | accent := ap.accents[index] | ||
| 180 | - | // Invoke callback while holding lock to avoid race with Hide() clearing callbacks | 180 | + | cb := ap.selectedCb // Copy callback reference before unlocking |
| 181 | - | ap.selectedCb(accent) | 181 | + | ap.mu.Unlock() // Release lock BEFORE calling callback to avoid deadlock |
| 182 | - | ap.mu.Unlock() | 182 | + | cb(accent) // Callback may call Hide() which needs to acquire ap.mu |
| 183 | } | 183 | } | ||
| 184 | 184 | ||||
| 185 | // cancel cancels the accent picker. | 185 | // cancel cancels the accent picker. | ||
| @@ -189,9 +189,9 @@ func (ap *AccentPicker) cancel() { | |||||
| 189 | ap.mu.Unlock() | 189 | ap.mu.Unlock() | ||
| 190 | return | 190 | return | ||
| 191 | } | 191 | } | ||
| 192 | - | // Invoke callback while holding lock to avoid race with Hide() clearing callbacks | 192 | + | cb := ap.cancelCb // Copy callback reference before unlocking |
| 193 | - | ap.cancelCb() | 193 | + | ap.mu.Unlock() // Release lock BEFORE calling callback to avoid deadlock |
| 194 | - | ap.mu.Unlock() | 194 | + | cb() // Callback may call Hide() which needs to acquire ap.mu |
| 195 | } | 195 | } | ||
| 196 | 196 | ||||
| 197 | // setupKeyboardHandling sets up key event handling for navigation. | 197 | // setupKeyboardHandling sets up key event handling for navigation. | ||