refactor(drm): drop the unreachable own-separator overlay check
A float's own lines lie inside its rect and only exist with borders on, where the inset check already refuses it. Tests now cover stacking: a window under or over the candidate, popups after it, hidden and touching popups.
- commit
- d6ec785f0ad373545f431515c3482944d34e7c30
- author
- brice · · 2026-10-08 05:12 UTC
- parent
- 892d98e
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +30 -6
M internal/adapters/drm/overlay.go +1 -1
| @@ -141,7 +141,7 @@ func overlayCandidate(s ports.Scene, surfaces map[ports.WindowID]ports.SurfaceCo | |||
| 141 | 141 | return ports.SceneWindow{}, ports.SurfaceContent{}, colorBypass, "border" | |
| 142 | 142 | } | |
| 143 | 143 | for _, sep := range s.Separators { | |
| 144 | - | if sep.Window == pick.ID || sep.Rect.Overlaps(pick.Rect) { | |
| 144 | + | if sep.Rect.Overlaps(pick.Rect) { | |
| 145 | 145 | // The overlay shows the buffer alone; the lines would go | |
| 146 | 146 | // under it. | |
| 147 | 147 | return ports.SceneWindow{}, ports.SurfaceContent{}, colorBypass, "border" | |
| @@ -141,7 +141,7 @@ func overlayCandidate(s ports.Scene, surfaces map[ports.WindowID]ports.SurfaceCo | |||||
| 141 | return ports.SceneWindow{}, ports.SurfaceContent{}, colorBypass, "border" | 141 | return ports.SceneWindow{}, ports.SurfaceContent{}, colorBypass, "border" | ||
| 142 | } | 142 | } | ||
| 143 | for _, sep := range s.Separators { | 143 | for _, sep := range s.Separators { | ||
| 144 | - | if sep.Window == pick.ID || sep.Rect.Overlaps(pick.Rect) { | 144 | + | if sep.Rect.Overlaps(pick.Rect) { |
| 145 | // The overlay shows the buffer alone; the lines would go | 145 | // The overlay shows the buffer alone; the lines would go | ||
| 146 | // under it. | 146 | // under it. | ||
| 147 | return ports.SceneWindow{}, ports.SurfaceContent{}, colorBypass, "border" | 147 | return ports.SceneWindow{}, ports.SurfaceContent{}, colorBypass, "border" | ||
M internal/adapters/drm/overlay_test.go +29 -5
| @@ -233,11 +233,6 @@ func TestOverlayPopupAndBorder(t *testing.T) { | |||
| 233 | 233 | t.Fatalf("border: %q", reason) | |
| 234 | 234 | } | |
| 235 | 235 | s, _ = overlayScene() | |
| 236 | - | s.Separators = []ports.Separator{{Rect: ports.Rect{X: 300, W: 2, H: 2}, Window: 2}} | |
| 237 | - | if _, _, _, reason := overlayCandidate(s, c, false, nil, nil); reason != "border" { | |
| 238 | - | t.Fatalf("own border: %q", reason) | |
| 239 | - | } | |
| 240 | - | s, _ = overlayScene() | |
| 241 | 236 | s.Border.Width = 2 | |
| 242 | 237 | s.Windows[1].Inset = ports.SideLeft | |
| 243 | 238 | if _, _, _, reason := overlayCandidate(s, c, false, nil, nil); reason != "border" { | |
| @@ -269,6 +264,35 @@ func TestOverlayIgnoresWhatDoesNotCoverIt(t *testing.T) { | |||
| 269 | 264 | } | |
| 270 | 265 | } | |
| 271 | 266 | ||
| 267 | + | // Draw order decides: a window listed before the candidate is under it, one | |
| 268 | + | // after is over it; a popup is over it wherever it is listed, unless hidden. | |
| 269 | + | func TestOverlayStackingOrder(t *testing.T) { | |
| 270 | + | under := ports.SceneWindow{ID: 8, Floating: true, Below: true, Rect: ports.Rect{X: 120, W: 20, H: 20}} | |
| 271 | + | over := under | |
| 272 | + | over.Below = false | |
| 273 | + | popup := ports.SceneWindow{ID: 7, Popup: true, Rect: ports.Rect{X: 120, W: 20, H: 20}} | |
| 274 | + | for name, tc := range map[string]struct { | |
| 275 | + | edit func(*ports.Scene) | |
| 276 | + | want string | |
| 277 | + | }{ | |
| 278 | + | "window under": {func(s *ports.Scene) { s.Windows = append([]ports.SceneWindow{under}, s.Windows...) }, ""}, | |
| 279 | + | "window over": {func(s *ports.Scene) { s.Windows = append(s.Windows, over) }, "window_above"}, | |
| 280 | + | "popup after": {func(s *ports.Scene) { s.Windows = append(s.Windows, popup) }, "window_above"}, | |
| 281 | + | "hidden popup": {func(s *ports.Scene) { p := popup; p.Hidden = true; s.Windows = append(s.Windows, p) }, ""}, | |
| 282 | + | "popup touching": {func(s *ports.Scene) { | |
| 283 | + | p := popup | |
| 284 | + | p.Rect.X = 80 | |
| 285 | + | s.Windows = append(s.Windows, p) | |
| 286 | + | }, ""}, | |
| 287 | + | } { | |
| 288 | + | s, c := overlayScene() | |
| 289 | + | tc.edit(&s) | |
| 290 | + | if _, _, _, reason := overlayCandidate(s, c, false, nil, nil); reason != tc.want { | |
| 291 | + | t.Errorf("%s: reason %q, want %q", name, reason, tc.want) | |
| 292 | + | } | |
| 293 | + | } | |
| 294 | + | } | |
| 295 | + | ||
| 272 | 296 | // A cursor commit refused with the overlay on drops the overlay: the | |
| 273 | 297 | // next frame is composed. | |
| 274 | 298 | func TestOverlayCursorConflictDropsOverlay(t *testing.T) { | |
| @@ -233,11 +233,6 @@ func TestOverlayPopupAndBorder(t *testing.T) { | |||||
| 233 | t.Fatalf("border: %q", reason) | 233 | t.Fatalf("border: %q", reason) | ||
| 234 | } | 234 | } | ||
| 235 | s, _ = overlayScene() | 235 | s, _ = overlayScene() | ||
| 236 | - | s.Separators = []ports.Separator{{Rect: ports.Rect{X: 300, W: 2, H: 2}, Window: 2}} | |||
| 237 | - | if _, _, _, reason := overlayCandidate(s, c, false, nil, nil); reason != "border" { | |||
| 238 | - | t.Fatalf("own border: %q", reason) | |||
| 239 | - | } | |||
| 240 | - | s, _ = overlayScene() | |||
| 241 | s.Border.Width = 2 | 236 | s.Border.Width = 2 | ||
| 242 | s.Windows[1].Inset = ports.SideLeft | 237 | s.Windows[1].Inset = ports.SideLeft | ||
| 243 | if _, _, _, reason := overlayCandidate(s, c, false, nil, nil); reason != "border" { | 238 | if _, _, _, reason := overlayCandidate(s, c, false, nil, nil); reason != "border" { | ||
| @@ -269,6 +264,35 @@ func TestOverlayIgnoresWhatDoesNotCoverIt(t *testing.T) { | |||||
| 269 | } | 264 | } | ||
| 270 | } | 265 | } | ||
| 271 | 266 | ||||
| 267 | + | // Draw order decides: a window listed before the candidate is under it, one | |||
| 268 | + | // after is over it; a popup is over it wherever it is listed, unless hidden. | |||
| 269 | + | func TestOverlayStackingOrder(t *testing.T) { | |||
| 270 | + | under := ports.SceneWindow{ID: 8, Floating: true, Below: true, Rect: ports.Rect{X: 120, W: 20, H: 20}} | |||
| 271 | + | over := under | |||
| 272 | + | over.Below = false | |||
| 273 | + | popup := ports.SceneWindow{ID: 7, Popup: true, Rect: ports.Rect{X: 120, W: 20, H: 20}} | |||
| 274 | + | for name, tc := range map[string]struct { | |||
| 275 | + | edit func(*ports.Scene) | |||
| 276 | + | want string | |||
| 277 | + | }{ | |||
| 278 | + | "window under": {func(s *ports.Scene) { s.Windows = append([]ports.SceneWindow{under}, s.Windows...) }, ""}, | |||
| 279 | + | "window over": {func(s *ports.Scene) { s.Windows = append(s.Windows, over) }, "window_above"}, | |||
| 280 | + | "popup after": {func(s *ports.Scene) { s.Windows = append(s.Windows, popup) }, "window_above"}, | |||
| 281 | + | "hidden popup": {func(s *ports.Scene) { p := popup; p.Hidden = true; s.Windows = append(s.Windows, p) }, ""}, | |||
| 282 | + | "popup touching": {func(s *ports.Scene) { | |||
| 283 | + | p := popup | |||
| 284 | + | p.Rect.X = 80 | |||
| 285 | + | s.Windows = append(s.Windows, p) | |||
| 286 | + | }, ""}, | |||
| 287 | + | } { | |||
| 288 | + | s, c := overlayScene() | |||
| 289 | + | tc.edit(&s) | |||
| 290 | + | if _, _, _, reason := overlayCandidate(s, c, false, nil, nil); reason != tc.want { | |||
| 291 | + | t.Errorf("%s: reason %q, want %q", name, reason, tc.want) | |||
| 292 | + | } | |||
| 293 | + | } | |||
| 294 | + | } | |||
| 295 | + | ||||
| 272 | // A cursor commit refused with the overlay on drops the overlay: the | 296 | // A cursor commit refused with the overlay on drops the overlay: the | ||
| 273 | // next frame is composed. | 297 | // next frame is composed. | ||
| 274 | func TestOverlayCursorConflictDropsOverlay(t *testing.T) { | 298 | func TestOverlayCursorConflictDropsOverlay(t *testing.T) { | ||