detached ec21f32

perf(overview): skip separator allocation for rounded outline

commit
ec21f3234eec62047f4cd53d14e21a5b02c00735
author
brice · · 2026-10-21 14:36 UTC
parent
de11a8d
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
2/2
3 files · +23 -5
M internal/adapters/vulkan/damage_delta_test.go +4 -1
@@ -444,7 +444,10 @@ func TestDamageSelectionOutlineDelta(t *testing.T) {
444444 a := &ports.SelectionOutline{Rect: ports.Rect{X: 10, Y: 10, W: 40, H: 30}, Width: 2, Radius: 10, Active: true}
445445 b := *a
446446 b.Rect.X = 60
447- for _, pair := range [][2]*ports.SelectionOutline{{nil, a}, {a, nil}, {a, &b}, {a, a}} {
447+ wider, rounder := *a, *a
448+ wider.Width++
449+ rounder.Radius++
450+ for _, pair := range [][2]*ports.SelectionOutline{{nil, a}, {a, nil}, {a, &b}, {a, &wider}, {a, &rounder}, {a, a}} {
448451 old, cur := deltaScene(1), deltaScene(2)
449452 old.Outline, cur.Outline = pair[0], pair[1]
450453 area, ok := sceneDelta(old, cur, func(r ports.Rect) image.Rectangle { return image.Rect(r.X, r.Y, r.X+r.W, r.Y+r.H) }, 500000)
@@ -444,7 +444,10 @@ func TestDamageSelectionOutlineDelta(t *testing.T) {
444 a := &ports.SelectionOutline{Rect: ports.Rect{X: 10, Y: 10, W: 40, H: 30}, Width: 2, Radius: 10, Active: true}444 a := &ports.SelectionOutline{Rect: ports.Rect{X: 10, Y: 10, W: 40, H: 30}, Width: 2, Radius: 10, Active: true}
445 b := *a445 b := *a
446 b.Rect.X = 60446 b.Rect.X = 60
447- for _, pair := range [][2]*ports.SelectionOutline{{nil, a}, {a, nil}, {a, &b}, {a, a}} {447+ wider, rounder := *a, *a
448+ wider.Width++
449+ rounder.Radius++
450+ for _, pair := range [][2]*ports.SelectionOutline{{nil, a}, {a, nil}, {a, &b}, {a, &wider}, {a, &rounder}, {a, a}} {
448 old, cur := deltaScene(1), deltaScene(2)451 old, cur := deltaScene(1), deltaScene(2)
449 old.Outline, cur.Outline = pair[0], pair[1]452 old.Outline, cur.Outline = pair[0], pair[1]
450 area, ok := sceneDelta(old, cur, func(r ports.Rect) image.Rectangle { return image.Rect(r.X, r.Y, r.X+r.W, r.Y+r.H) }, 500000)453 area, ok := sceneDelta(old, cur, func(r ports.Rect) image.Rectangle { return image.Rect(r.X, r.Y, r.X+r.W, r.Y+r.H) }, 500000)
M internal/core/overview.go +4 -4
@@ -1338,7 +1338,6 @@ func overviewOutline(dst []ports.Separator, layout []Placement, b, gap, radius i
13381338 if sel < 0 {
13391339 return dst, nil
13401340 }
1341- dst = slices.Grow(dst, outlineLines)
13421341 r := layout[sel].Rect
13431342 edges := [4]Rect{
13441343 {X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: b},
@@ -1355,10 +1354,11 @@ func overviewOutline(dst []ports.Separator, layout []Placement, b, gap, radius i
13551354 }
13561355 }
13571356 }
1357+ if radius := windowRadius(layout[sel], gap, radius); !cut && radius > 0 {
1358+ return dst, &ports.SelectionOutline{Rect: Rect{X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: r.H + 2*b}, Width: b, Radius: radius + b, Active: true}
1359+ }
1360+ dst = slices.Grow(dst, outlineLines)
13581361 if !cut {
1359- if radius := windowRadius(layout[sel], gap, radius); radius > 0 {
1360- return dst, &ports.SelectionOutline{Rect: Rect{X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: r.H + 2*b}, Width: b, Radius: radius + b, Active: true}
1361- }
13621362 for _, e := range edges {
13631363 dst = append(dst, ports.Separator{Rect: e, Active: true})
13641364 }
@@ -1338,7 +1338,6 @@ func overviewOutline(dst []ports.Separator, layout []Placement, b, gap, radius i
1338 if sel < 0 {1338 if sel < 0 {
1339 return dst, nil1339 return dst, nil
1340 }1340 }
1341- dst = slices.Grow(dst, outlineLines)
1342 r := layout[sel].Rect1341 r := layout[sel].Rect
1343 edges := [4]Rect{1342 edges := [4]Rect{
1344 {X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: b},1343 {X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: b},
@@ -1355,10 +1354,11 @@ func overviewOutline(dst []ports.Separator, layout []Placement, b, gap, radius i
1355 }1354 }
1356 }1355 }
1357 }1356 }
1357+ if radius := windowRadius(layout[sel], gap, radius); !cut && radius > 0 {
1358+ return dst, &ports.SelectionOutline{Rect: Rect{X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: r.H + 2*b}, Width: b, Radius: radius + b, Active: true}
1359+ }
1360+ dst = slices.Grow(dst, outlineLines)
1358 if !cut {1361 if !cut {
1359- if radius := windowRadius(layout[sel], gap, radius); radius > 0 {
1360- return dst, &ports.SelectionOutline{Rect: Rect{X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: r.H + 2*b}, Width: b, Radius: radius + b, Active: true}
1361- }
1362 for _, e := range edges {1362 for _, e := range edges {
1363 dst = append(dst, ports.Separator{Rect: e, Active: true})1363 dst = append(dst, ports.Separator{Rect: e, Active: true})
1364 }1364 }
M internal/core/overview_cascade_test.go +15 -0
@@ -1215,6 +1215,21 @@ func TestOverviewOutlinePileAllocations(t *testing.T) {
12151215 }
12161216 }
12171217
1218+func TestOverviewOutlineRoundedAllocations(t *testing.T) {
1219+ ps := []Placement{{Rect: Rect{X: 20, Y: 20, W: 100, H: 80}, Preview: 0.5, Focused: true, Floating: true}}
1220+ // Keep the returned outline alive so its one snapshot allocation is counted.
1221+ var outline *ports.SelectionOutline
1222+ n := testing.AllocsPerRun(50, func() {
1223+ _, outline = overviewOutline(nil, ps, 2, 0, 12)
1224+ })
1225+ if outline == nil {
1226+ t.Fatal("setup: no rounded outline")
1227+ }
1228+ if n != 1 {
1229+ t.Fatalf("rounded overviewOutline allocs = %v, want 1 (outline only)", n)
1230+ }
1231+}
1232+
12181233 func TestSubtractRects(t *testing.T) {
12191234 h := Rect{X: 0, Y: 10, W: 100, H: 2}
12201235 v := Rect{X: 10, Y: 0, W: 2, H: 100}
@@ -1215,6 +1215,21 @@ func TestOverviewOutlinePileAllocations(t *testing.T) {
1215 }1215 }
1216 }1216 }
1217 1217
1218+func TestOverviewOutlineRoundedAllocations(t *testing.T) {
1219+ ps := []Placement{{Rect: Rect{X: 20, Y: 20, W: 100, H: 80}, Preview: 0.5, Focused: true, Floating: true}}
1220+ // Keep the returned outline alive so its one snapshot allocation is counted.
1221+ var outline *ports.SelectionOutline
1222+ n := testing.AllocsPerRun(50, func() {
1223+ _, outline = overviewOutline(nil, ps, 2, 0, 12)
1224+ })
1225+ if outline == nil {
1226+ t.Fatal("setup: no rounded outline")
1227+ }
1228+ if n != 1 {
1229+ t.Fatalf("rounded overviewOutline allocs = %v, want 1 (outline only)", n)
1230+ }
1231+}
1232+
1218 func TestSubtractRects(t *testing.T) {1233 func TestSubtractRects(t *testing.T) {
1219 h := Rect{X: 0, Y: 10, W: 100, H: 2}1234 h := Rect{X: 0, Y: 10, W: 100, H: 2}
1220 v := Rect{X: 10, Y: 0, W: 2, H: 100}1235 v := Rect{X: 10, Y: 0, W: 2, H: 100}

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 24

Tags 10

↑↓ moveenter openesc close