detached 67bb8aa

fix(ui): prevent early GTK notify::position from overwriting restored split ratios

commit
67bb8aa9372319e8c8792c818af103b6f67fd7a4
author
brice · · 2025-12-26 07:52 UTC
parent
19bb708
signature
unsigned
1 file · +30 -0
M internal/ui/layout/split.go +30 -0
@@ -24,6 +24,9 @@ type SplitView struct {
2424 pendingNotifyRatio float64
2525 notifyDebounceTimer *time.Timer
2626
27+ hasAppliedRatio bool
28+ suppressNotifyUntil time.Time
29+
2730 mu sync.RWMutex
2831 }
2932
@@ -81,6 +84,21 @@ func NewSplitView(
8184 return
8285 }
8386
87+ now := time.Now()
88+
89+ sv.mu.Lock()
90+ // Ignore early notifications before we've applied the snapshot ratio.
91+ // GTK often emits an initial notify::position (typically 50/50) during allocation.
92+ if !sv.hasAppliedRatio {
93+ sv.mu.Unlock()
94+ return
95+ }
96+ if !sv.suppressNotifyUntil.IsZero() && now.Before(sv.suppressNotifyUntil) {
97+ sv.mu.Unlock()
98+ return
99+ }
100+ sv.mu.Unlock()
101+
84102 ratio := clampRatio(float64(position) / float64(totalSize))
85103
86104 sv.mu.Lock()
@@ -204,7 +222,19 @@ func (sv *SplitView) ApplyRatio() bool {
204222 Float64("ratio", ratio).
205223 Int("position", position).
206224 Msg("ApplyRatio: setting position")
225+
226+ // Avoid treating programmatic SetPosition as a user resize.
227+ // We suppress notify::position briefly; GTK may emit during/after SetPosition.
228+ sv.mu.Lock()
229+ sv.suppressNotifyUntil = time.Now().Add(50 * time.Millisecond)
230+ sv.mu.Unlock()
231+
207232 sv.paned.SetPosition(position)
233+
234+ sv.mu.Lock()
235+ sv.hasAppliedRatio = true
236+ sv.mu.Unlock()
237+
208238 return true
209239 }
210240
@@ -24,6 +24,9 @@ type SplitView struct {
24 pendingNotifyRatio float6424 pendingNotifyRatio float64
25 notifyDebounceTimer *time.Timer25 notifyDebounceTimer *time.Timer
26 26
27+ hasAppliedRatio bool
28+ suppressNotifyUntil time.Time
29+
27 mu sync.RWMutex30 mu sync.RWMutex
28 }31 }
29 32
@@ -81,6 +84,21 @@ func NewSplitView(
81 return84 return
82 }85 }
83 86
87+ now := time.Now()
88+
89+ sv.mu.Lock()
90+ // Ignore early notifications before we've applied the snapshot ratio.
91+ // GTK often emits an initial notify::position (typically 50/50) during allocation.
92+ if !sv.hasAppliedRatio {
93+ sv.mu.Unlock()
94+ return
95+ }
96+ if !sv.suppressNotifyUntil.IsZero() && now.Before(sv.suppressNotifyUntil) {
97+ sv.mu.Unlock()
98+ return
99+ }
100+ sv.mu.Unlock()
101+
84 ratio := clampRatio(float64(position) / float64(totalSize))102 ratio := clampRatio(float64(position) / float64(totalSize))
85 103
86 sv.mu.Lock()104 sv.mu.Lock()
@@ -204,7 +222,19 @@ func (sv *SplitView) ApplyRatio() bool {
204 Float64("ratio", ratio).222 Float64("ratio", ratio).
205 Int("position", position).223 Int("position", position).
206 Msg("ApplyRatio: setting position")224 Msg("ApplyRatio: setting position")
225+
226+ // Avoid treating programmatic SetPosition as a user resize.
227+ // We suppress notify::position briefly; GTK may emit during/after SetPosition.
228+ sv.mu.Lock()
229+ sv.suppressNotifyUntil = time.Now().Add(50 * time.Millisecond)
230+ sv.mu.Unlock()
231+
207 sv.paned.SetPosition(position)232 sv.paned.SetPosition(position)
233+
234+ sv.mu.Lock()
235+ sv.hasAppliedRatio = true
236+ sv.mu.Unlock()
237+
208 return true238 return true
209 }239 }
210 240

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