detached 62026dc

fix(overview): inset only the focused maximized cascade column

Only the focused maximized column has cards behind it. A click records the
clicked window in the maximize history, and a test covers clicks on the peek
strips.
commit
62026dce6ac7e1f10ab1d587bebbfe669c8511ac
author
brice · · 2026-10-07 14:05 UTC
parent
079b695
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +28 -6
M docs/config.md +1 -1
@@ -196,7 +196,7 @@ Left/right focus follows column order across band boundaries. Up/down visits sta
196196
197197 Three-finger vertical swipes scroll bands; horizontal swipes switch workspaces. Scroll and fixed workspaces retain their existing gesture axes. A switch keeps the source workspace's axis throughout its transition; the destination's axes apply to the next gesture. The `focus-workspace-prev/next` commands switch to the previous or next workspace, whether the transition is vertical or horizontal. Four-finger and stash gestures keep their existing behaviour.
198198
199-In the [overview](#overview), the selected band is centred at the usual overview zoom, whatever the band count. The other bands of the workspace sit above and below it, dimmed, and may run off screen. Neighbor workspaces sit left and right, fully dimmed, with their selected row level with the centred band. The stash pile stays left of the band, inside the workspace's slot. A maximized column shows the columns it hides as dimmed cards behind it, peeking out on their side of the band; selecting one (left/right, Return or a click) moves the maximization to it, and Escape gives it back.
199+In the [overview](#overview), the selected band is centred at the usual overview zoom, whatever the band count. The other bands of the workspace sit above and below it, dimmed, and may run off screen. Neighbor workspaces sit left and right, fully dimmed, with their selected row level with the centred band. The stash pile stays left of the band, inside the workspace's slot. A maximized column shows the columns it hides as dimmed cards behind it, peeking out on their side of the band: the nearest one on each side, then the next ones stacked at the band's edge. Selecting a card (left/right, Return or a click on a visible card) moves the maximization to it, and Escape gives it back.
200200
201201 In the overview, up/down move to the previous or next band and stop at the first and last; with a stash card selected they browse the pile. Left/right move along the band; past its first column they enter the stash, or go to the previous workspace when there is none; past its last column they go to the next workspace (with the overview closed, focus crosses into the next band instead). Covering floats fan left and right of the band: left/right traverse them before entering the stash or changing workspace, and up/down do nothing on a float. `h`/`j`/`k`/`l` and the focus binds follow the arrows; `focus-workspace-prev/next` always change workspace, except over a selected stash card, where they browse the pile. Three-finger swipes follow the fingers: vertical moves one band (or one stash card) and horizontal one workspace per gesture, even over a stash card. A vertical wheel or continuous scroll changes workspace, except over a selected stash card, where it browses the pile; a horizontal one moves along the band.
202202
@@ -196,7 +196,7 @@ Left/right focus follows column order across band boundaries. Up/down visits sta
196 196
197 Three-finger vertical swipes scroll bands; horizontal swipes switch workspaces. Scroll and fixed workspaces retain their existing gesture axes. A switch keeps the source workspace's axis throughout its transition; the destination's axes apply to the next gesture. The `focus-workspace-prev/next` commands switch to the previous or next workspace, whether the transition is vertical or horizontal. Four-finger and stash gestures keep their existing behaviour.197 Three-finger vertical swipes scroll bands; horizontal swipes switch workspaces. Scroll and fixed workspaces retain their existing gesture axes. A switch keeps the source workspace's axis throughout its transition; the destination's axes apply to the next gesture. The `focus-workspace-prev/next` commands switch to the previous or next workspace, whether the transition is vertical or horizontal. Four-finger and stash gestures keep their existing behaviour.
198 198
199-In the [overview](#overview), the selected band is centred at the usual overview zoom, whatever the band count. The other bands of the workspace sit above and below it, dimmed, and may run off screen. Neighbor workspaces sit left and right, fully dimmed, with their selected row level with the centred band. The stash pile stays left of the band, inside the workspace's slot. A maximized column shows the columns it hides as dimmed cards behind it, peeking out on their side of the band; selecting one (left/right, Return or a click) moves the maximization to it, and Escape gives it back.199+In the [overview](#overview), the selected band is centred at the usual overview zoom, whatever the band count. The other bands of the workspace sit above and below it, dimmed, and may run off screen. Neighbor workspaces sit left and right, fully dimmed, with their selected row level with the centred band. The stash pile stays left of the band, inside the workspace's slot. A maximized column shows the columns it hides as dimmed cards behind it, peeking out on their side of the band: the nearest one on each side, then the next ones stacked at the band's edge. Selecting a card (left/right, Return or a click on a visible card) moves the maximization to it, and Escape gives it back.
200 200
201 In the overview, up/down move to the previous or next band and stop at the first and last; with a stash card selected they browse the pile. Left/right move along the band; past its first column they enter the stash, or go to the previous workspace when there is none; past its last column they go to the next workspace (with the overview closed, focus crosses into the next band instead). Covering floats fan left and right of the band: left/right traverse them before entering the stash or changing workspace, and up/down do nothing on a float. `h`/`j`/`k`/`l` and the focus binds follow the arrows; `focus-workspace-prev/next` always change workspace, except over a selected stash card, where they browse the pile. Three-finger swipes follow the fingers: vertical moves one band (or one stash card) and horizontal one workspace per gesture, even over a stash card. A vertical wheel or continuous scroll changes workspace, except over a selected stash card, where it browses the pile; a horizontal one moves along the band.201 In the overview, up/down move to the previous or next band and stop at the first and last; with a stash card selected they browse the pile. Left/right move along the band; past its first column they enter the stash, or go to the previous workspace when there is none; past its last column they go to the next workspace (with the overview closed, focus crosses into the next band instead). Covering floats fan left and right of the band: left/right traverse them before entering the stash or changing workspace, and up/down do nothing on a float. `h`/`j`/`k`/`l` and the focus binds follow the arrows; `focus-workspace-prev/next` always change workspace, except over a selected stash card, where they browse the pile. Three-finger swipes follow the fingers: vertical moves one band (or one stash card) and horizontal one workspace per gesture, even over a stash card. A vertical wheel or continuous scroll changes workspace, except over a selected stash card, where it browses the pile; a horizontal one moves along the band.
202 202
M internal/core/overview.go +11 -5
@@ -596,16 +596,18 @@ func (m *Monitor) OverviewPick(id WindowID) {
596596 } else if item, ok := w.itemOf(id); ok {
597597 m.setFront(w, item)
598598 if i := w.columnOf(id); i >= 0 {
599- if item.kind == stackColumns && !w.overviewMaximized() {
600- w.selectOverviewColumn(i)
601- }
602- m.ov.selected = id
599+ // The clicked window first: a maximization moving to its
600+ // column records it in the maximize history.
603601 for j, v := range w.Columns[i].Windows {
604602 if v == id {
605603 w.Columns[i].Focus = j
606604 break
607605 }
608606 }
607+ if item.kind == stackColumns && !w.overviewMaximized() {
608+ w.selectOverviewColumn(i)
609+ }
610+ m.ov.selected = id
609611 }
610612 }
611613 m.closeOverview()
@@ -996,7 +998,11 @@ func (w *Workspace) previewTilesInto(tiles []Placement) ([]Placement, int, Rect)
996998 r.Y = g + w.band(i)*w.Usable.H
997999 r.W = w.cellWidth()
9981000 if c.FullWidth {
999- in := w.bandCardsInset(i)
1001+ in := 0
1002+ if i == w.Focus {
1003+ // Only the focused column has cards behind it.
1004+ in = w.bandCardsInset(i)
1005+ }
10001006 r.X, r.W = g+in, max(w.Usable.W-2*g-2*in, 0)
10011007 }
10021008 } else if w.Overflow == OverflowFixed {
@@ -596,16 +596,18 @@ func (m *Monitor) OverviewPick(id WindowID) {
596 } else if item, ok := w.itemOf(id); ok {596 } else if item, ok := w.itemOf(id); ok {
597 m.setFront(w, item)597 m.setFront(w, item)
598 if i := w.columnOf(id); i >= 0 {598 if i := w.columnOf(id); i >= 0 {
599- if item.kind == stackColumns && !w.overviewMaximized() {599+ // The clicked window first: a maximization moving to its
600- w.selectOverviewColumn(i)600+ // column records it in the maximize history.
601- }
602- m.ov.selected = id
603 for j, v := range w.Columns[i].Windows {601 for j, v := range w.Columns[i].Windows {
604 if v == id {602 if v == id {
605 w.Columns[i].Focus = j603 w.Columns[i].Focus = j
606 break604 break
607 }605 }
608 }606 }
607+ if item.kind == stackColumns && !w.overviewMaximized() {
608+ w.selectOverviewColumn(i)
609+ }
610+ m.ov.selected = id
609 }611 }
610 }612 }
611 m.closeOverview()613 m.closeOverview()
@@ -996,7 +998,11 @@ func (w *Workspace) previewTilesInto(tiles []Placement) ([]Placement, int, Rect)
996 r.Y = g + w.band(i)*w.Usable.H998 r.Y = g + w.band(i)*w.Usable.H
997 r.W = w.cellWidth()999 r.W = w.cellWidth()
998 if c.FullWidth {1000 if c.FullWidth {
999- in := w.bandCardsInset(i)1001+ in := 0
1002+ if i == w.Focus {
1003+ // Only the focused column has cards behind it.
1004+ in = w.bandCardsInset(i)
1005+ }
1000 r.X, r.W = g+in, max(w.Usable.W-2*g-2*in, 0)1006 r.X, r.W = g+in, max(w.Usable.W-2*g-2*in, 0)
1001 }1007 }
1002 } else if w.Overflow == OverflowFixed {1008 } else if w.Overflow == OverflowFixed {
M internal/core/overview_cascade_test.go +16 -0
@@ -182,6 +182,22 @@ func TestOverviewCascadeMaximizedCardPick(t *testing.T) {
182182 w.FocusID(7)
183183 w.ToggleFullWidth()
184184 m.ToggleOverview()
185+ // Each card's strip right of the maximized column hits it: 8 next to
186+ // it, 9 at the band's edge.
187+ ps := m.Layout()
188+ front, near, far := previewOf(t, ps, 7).Rect, previewOf(t, ps, 8).Rect, previewOf(t, ps, 9).Rect
189+ for _, c := range []struct {
190+ x0, x1 int
191+ want WindowID
192+ }{{front.X + front.W, near.X + near.W, 8}, {near.X + near.W, far.X + far.W, 9}} {
193+ x := (c.x0 + c.x1) / 2
194+ if c.x0 >= c.x1 {
195+ t.Fatalf("no strip for %d: front %v near %v far %v", c.want, front, near, far)
196+ }
197+ if got := overviewIn(ps, float64(x), float64(centreY(far))); got != c.want {
198+ t.Fatalf("strip at x=%d hits %d, want %d", x, got, c.want)
199+ }
200+ }
185201 m.OverviewPick(9)
186202 if m.ov.open || focusedID(m) != 9 || !w.Columns[w.Focus].FullWidth || w.Columns[w.columnOf(7)].FullWidth {
187203 t.Fatalf("pick: open %v, focus %d, maximization not moved", m.ov.open, focusedID(m))
@@ -182,6 +182,22 @@ func TestOverviewCascadeMaximizedCardPick(t *testing.T) {
182 w.FocusID(7)182 w.FocusID(7)
183 w.ToggleFullWidth()183 w.ToggleFullWidth()
184 m.ToggleOverview()184 m.ToggleOverview()
185+ // Each card's strip right of the maximized column hits it: 8 next to
186+ // it, 9 at the band's edge.
187+ ps := m.Layout()
188+ front, near, far := previewOf(t, ps, 7).Rect, previewOf(t, ps, 8).Rect, previewOf(t, ps, 9).Rect
189+ for _, c := range []struct {
190+ x0, x1 int
191+ want WindowID
192+ }{{front.X + front.W, near.X + near.W, 8}, {near.X + near.W, far.X + far.W, 9}} {
193+ x := (c.x0 + c.x1) / 2
194+ if c.x0 >= c.x1 {
195+ t.Fatalf("no strip for %d: front %v near %v far %v", c.want, front, near, far)
196+ }
197+ if got := overviewIn(ps, float64(x), float64(centreY(far))); got != c.want {
198+ t.Fatalf("strip at x=%d hits %d, want %d", x, got, c.want)
199+ }
200+ }
185 m.OverviewPick(9)201 m.OverviewPick(9)
186 if m.ov.open || focusedID(m) != 9 || !w.Columns[w.Focus].FullWidth || w.Columns[w.columnOf(7)].FullWidth {202 if m.ov.open || focusedID(m) != 9 || !w.Columns[w.Focus].FullWidth || w.Columns[w.columnOf(7)].FullWidth {
187 t.Fatalf("pick: open %v, focus %d, maximization not moved", m.ov.open, focusedID(m))203 t.Fatalf("pick: open %v, focus %d, maximization not moved", m.ov.open, focusedID(m))

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 25

Tags 10

↑↓ moveenter openesc close