fix(core): move the selected window, not the fullscreen one, from the overview
Under a pinned fullscreen window, Focused reports the covering window, so a move-to-workspace bind on a card behind it moved the fullscreen window. The fullscreen is left first, as when choosing that card.
- commit
- adeb0406bb5e921605af8b6f4b4963b2a378414d
- author
- brice · · 2026-10-02 15:32 UTC
- parent
- 2cae17f
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +45 -0
M internal/core/overview.go +4 -0
| @@ -208,6 +208,10 @@ func (m *Monitor) overviewMoveTo(a Action) { | |||
| 208 | 208 | if m.card() != 0 || id == 0 || !ok || m.Workspaces[i] == cur { | |
| 209 | 209 | return | |
| 210 | 210 | } | |
| 211 | + | if cur.pinned() && id != cur.cover() { | |
| 212 | + | // Focused reports the covering window while it covers. | |
| 213 | + | cur.leaveFullscreen() | |
| 214 | + | } | |
| 211 | 215 | cur.FocusID(id) | |
| 212 | 216 | m.MoveToWorkspace(i, column) | |
| 213 | 217 | // The row that received the window keeps it focused on close. | |
| @@ -208,6 +208,10 @@ func (m *Monitor) overviewMoveTo(a Action) { | |||||
| 208 | if m.card() != 0 || id == 0 || !ok || m.Workspaces[i] == cur { | 208 | if m.card() != 0 || id == 0 || !ok || m.Workspaces[i] == cur { | ||
| 209 | return | 209 | return | ||
| 210 | } | 210 | } | ||
| 211 | + | if cur.pinned() && id != cur.cover() { | |||
| 212 | + | // Focused reports the covering window while it covers. | |||
| 213 | + | cur.leaveFullscreen() | |||
| 214 | + | } | |||
| 211 | cur.FocusID(id) | 215 | cur.FocusID(id) | ||
| 212 | m.MoveToWorkspace(i, column) | 216 | m.MoveToWorkspace(i, column) | ||
| 213 | // The row that received the window keeps it focused on close. | 217 | // The row that received the window keeps it focused on close. | ||
M internal/core/overview_cover_test.go +41 -0
| @@ -158,6 +158,47 @@ func TestOverviewCoverPickStashCard(t *testing.T) { | |||
| 158 | 158 | } | |
| 159 | 159 | } | |
| 160 | 160 | ||
| 161 | + | // Window binds act on the selected card: a window behind the fullscreen | |
| 162 | + | // one moves or closes, not the fullscreen window. | |
| 163 | + | func TestOverviewCoverActsOnSelection(t *testing.T) { | |
| 164 | + | for _, tc := range pinnedCases { | |
| 165 | + | t.Run(tc.name, func(t *testing.T) { | |
| 166 | + | m := coverMonitor(tc.overflow, tc.float) | |
| 167 | + | m.ToggleOverview() | |
| 168 | + | if e := m.Apply(ActionCloseWindow); e.Close != 2 { | |
| 169 | + | t.Fatalf("front close %d", e.Close) | |
| 170 | + | } | |
| 171 | + | m.OverviewMove(-1, 0) | |
| 172 | + | if e := m.Apply(ActionCloseWindow); e.Close != 1 { | |
| 173 | + | t.Fatalf("behind close %d", e.Close) | |
| 174 | + | } | |
| 175 | + | w := m.Current() | |
| 176 | + | m.Apply(ActionMoveWindowToWorkspaceDown) | |
| 177 | + | if got, _ := m.find(1); got == w || !w.has(2) { | |
| 178 | + | t.Fatalf("moved the wrong window: %v", windows(m)) | |
| 179 | + | } | |
| 180 | + | }) | |
| 181 | + | } | |
| 182 | + | } | |
| 183 | + | ||
| 184 | + | // A fullscreen tile whose column is also maximized hands the maximized | |
| 185 | + | // state to the column picked behind it, as a maximized row does. | |
| 186 | + | func TestOverviewCoverMaximizedPick(t *testing.T) { | |
| 187 | + | m := newMonitor("", "") | |
| 188 | + | m.SetOutput(300, 200) | |
| 189 | + | m.SetOverflow(OverflowFixed) | |
| 190 | + | m.AddWindow(1) | |
| 191 | + | m.AddWindow(2) | |
| 192 | + | w := m.Current() | |
| 193 | + | w.ToggleFullWidth() | |
| 194 | + | m.ToggleFullscreen() | |
| 195 | + | m.ToggleOverview() | |
| 196 | + | m.OverviewPick(1) | |
| 197 | + | if f, _ := m.Focused(); f != 1 || w.fullscreen != 0 || !w.Columns[0].FullWidth || w.Columns[1].FullWidth { | |
| 198 | + | t.Fatalf("focused %d, fullscreen %d, columns %+v", f, w.fullscreen, w.Columns) | |
| 199 | + | } | |
| 200 | + | } | |
| 201 | + | ||
| 161 | 202 | // A fixed fullscreen tile among several columns is the front card, the | |
| 162 | 203 | // other columns behind it, as for a maximized column. | |
| 163 | 204 | func TestOverviewCoverTileAmongColumns(t *testing.T) { | |
| @@ -158,6 +158,47 @@ func TestOverviewCoverPickStashCard(t *testing.T) { | |||||
| 158 | } | 158 | } | ||
| 159 | } | 159 | } | ||
| 160 | 160 | ||||
| 161 | + | // Window binds act on the selected card: a window behind the fullscreen | |||
| 162 | + | // one moves or closes, not the fullscreen window. | |||
| 163 | + | func TestOverviewCoverActsOnSelection(t *testing.T) { | |||
| 164 | + | for _, tc := range pinnedCases { | |||
| 165 | + | t.Run(tc.name, func(t *testing.T) { | |||
| 166 | + | m := coverMonitor(tc.overflow, tc.float) | |||
| 167 | + | m.ToggleOverview() | |||
| 168 | + | if e := m.Apply(ActionCloseWindow); e.Close != 2 { | |||
| 169 | + | t.Fatalf("front close %d", e.Close) | |||
| 170 | + | } | |||
| 171 | + | m.OverviewMove(-1, 0) | |||
| 172 | + | if e := m.Apply(ActionCloseWindow); e.Close != 1 { | |||
| 173 | + | t.Fatalf("behind close %d", e.Close) | |||
| 174 | + | } | |||
| 175 | + | w := m.Current() | |||
| 176 | + | m.Apply(ActionMoveWindowToWorkspaceDown) | |||
| 177 | + | if got, _ := m.find(1); got == w || !w.has(2) { | |||
| 178 | + | t.Fatalf("moved the wrong window: %v", windows(m)) | |||
| 179 | + | } | |||
| 180 | + | }) | |||
| 181 | + | } | |||
| 182 | + | } | |||
| 183 | + | ||||
| 184 | + | // A fullscreen tile whose column is also maximized hands the maximized | |||
| 185 | + | // state to the column picked behind it, as a maximized row does. | |||
| 186 | + | func TestOverviewCoverMaximizedPick(t *testing.T) { | |||
| 187 | + | m := newMonitor("", "") | |||
| 188 | + | m.SetOutput(300, 200) | |||
| 189 | + | m.SetOverflow(OverflowFixed) | |||
| 190 | + | m.AddWindow(1) | |||
| 191 | + | m.AddWindow(2) | |||
| 192 | + | w := m.Current() | |||
| 193 | + | w.ToggleFullWidth() | |||
| 194 | + | m.ToggleFullscreen() | |||
| 195 | + | m.ToggleOverview() | |||
| 196 | + | m.OverviewPick(1) | |||
| 197 | + | if f, _ := m.Focused(); f != 1 || w.fullscreen != 0 || !w.Columns[0].FullWidth || w.Columns[1].FullWidth { | |||
| 198 | + | t.Fatalf("focused %d, fullscreen %d, columns %+v", f, w.fullscreen, w.Columns) | |||
| 199 | + | } | |||
| 200 | + | } | |||
| 201 | + | ||||
| 161 | // A fixed fullscreen tile among several columns is the front card, the | 202 | // A fixed fullscreen tile among several columns is the front card, the | ||
| 162 | // other columns behind it, as for a maximized column. | 203 | // other columns behind it, as for a maximized column. | ||
| 163 | func TestOverviewCoverTileAmongColumns(t *testing.T) { | 204 | func TestOverviewCoverTileAmongColumns(t *testing.T) { | ||