feat(wayland): add wl_subcompositor so foot maps
- commit
- 812b032bd3f7fdf13aa8deb807bde395c7c7e993
- author
- brice · · 2026-09-23 12:20 UTC
- parent
- e9aeb28
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +37 -2
M internal/adapters/wayland/globals.go +35 -0
| @@ -12,6 +12,11 @@ func registerGlobals(d *server.Display, o Options, s *Server) error { | |||
| 12 | 12 | func() error { | |
| 13 | 13 | return wayland.NewCompositorGlobal(d, 6, func(c server.Client, v, id uint32) { wayland.NewCompositor(c, int32(v), id, compositor{s}) }) | |
| 14 | 14 | }, | |
| 15 | + | func() error { | |
| 16 | + | return wayland.NewSubcompositorGlobal(d, 1, func(c server.Client, v, id uint32) { | |
| 17 | + | wayland.NewSubcompositor(c, int32(v), id, subcompositor{s}) | |
| 18 | + | }) | |
| 19 | + | }, | |
| 15 | 20 | func() error { | |
| 16 | 21 | return wayland.NewShmGlobal(d, 1, func(c server.Client, v, id uint32) { | |
| 17 | 22 | r, e := wayland.NewShm(c, int32(v), id, shm{}) | |
| @@ -77,6 +82,36 @@ func (compositor) CreateRegion(r *wayland.Compositor, id uint32) { | |||
| 77 | 82 | } | |
| 78 | 83 | func (compositor) Release(*wayland.Compositor) {} | |
| 79 | 84 | ||
| 85 | + | type subcompositor struct{ server *Server } | |
| 86 | + | ||
| 87 | + | func (subcompositor) Destroy(*wayland.Subcompositor) {} | |
| 88 | + | func (c subcompositor) GetSubsurface(r *wayland.Subcompositor, id uint32, w, parent *wayland.Surface) { | |
| 89 | + | if w == nil || parent == nil { | |
| 90 | + | return | |
| 91 | + | } | |
| 92 | + | state := c.server.surfaces[w.Resource] | |
| 93 | + | if state == nil { | |
| 94 | + | return | |
| 95 | + | } | |
| 96 | + | if state.role != nil { | |
| 97 | + | r.PostError(uint32(wayland.SubcompositorErrorBadSurface), "surface already has role") | |
| 98 | + | return | |
| 99 | + | } | |
| 100 | + | if sub, err := wayland.NewSubsurface(r.Client(), 1, id, subsurface{state}); err == nil { | |
| 101 | + | state.role = func(bool) {} | |
| 102 | + | sub.OnDestroy = func() { state.role = nil } | |
| 103 | + | } | |
| 104 | + | } | |
| 105 | + | ||
| 106 | + | type subsurface struct{ surface *surface } | |
| 107 | + | ||
| 108 | + | func (subsurface) Destroy(*wayland.Subsurface) {} | |
| 109 | + | func (subsurface) SetPosition(*wayland.Subsurface, int32, int32) {} | |
| 110 | + | func (subsurface) PlaceAbove(*wayland.Subsurface, *wayland.Surface) {} | |
| 111 | + | func (subsurface) PlaceBelow(*wayland.Subsurface, *wayland.Surface) {} | |
| 112 | + | func (subsurface) SetSync(*wayland.Subsurface) {} | |
| 113 | + | func (subsurface) SetDesync(*wayland.Subsurface) {} | |
| 114 | + | ||
| 80 | 115 | type region struct{} | |
| 81 | 116 | ||
| 82 | 117 | func (region) Destroy(*wayland.Region) {} | |
| @@ -12,6 +12,11 @@ func registerGlobals(d *server.Display, o Options, s *Server) error { | |||||
| 12 | func() error { | 12 | func() error { | ||
| 13 | return wayland.NewCompositorGlobal(d, 6, func(c server.Client, v, id uint32) { wayland.NewCompositor(c, int32(v), id, compositor{s}) }) | 13 | return wayland.NewCompositorGlobal(d, 6, func(c server.Client, v, id uint32) { wayland.NewCompositor(c, int32(v), id, compositor{s}) }) | ||
| 14 | }, | 14 | }, | ||
| 15 | + | func() error { | |||
| 16 | + | return wayland.NewSubcompositorGlobal(d, 1, func(c server.Client, v, id uint32) { | |||
| 17 | + | wayland.NewSubcompositor(c, int32(v), id, subcompositor{s}) | |||
| 18 | + | }) | |||
| 19 | + | }, | |||
| 15 | func() error { | 20 | func() error { | ||
| 16 | return wayland.NewShmGlobal(d, 1, func(c server.Client, v, id uint32) { | 21 | return wayland.NewShmGlobal(d, 1, func(c server.Client, v, id uint32) { | ||
| 17 | r, e := wayland.NewShm(c, int32(v), id, shm{}) | 22 | r, e := wayland.NewShm(c, int32(v), id, shm{}) | ||
| @@ -77,6 +82,36 @@ func (compositor) CreateRegion(r *wayland.Compositor, id uint32) { | |||||
| 77 | } | 82 | } | ||
| 78 | func (compositor) Release(*wayland.Compositor) {} | 83 | func (compositor) Release(*wayland.Compositor) {} | ||
| 79 | 84 | ||||
| 85 | + | type subcompositor struct{ server *Server } | |||
| 86 | + | ||||
| 87 | + | func (subcompositor) Destroy(*wayland.Subcompositor) {} | |||
| 88 | + | func (c subcompositor) GetSubsurface(r *wayland.Subcompositor, id uint32, w, parent *wayland.Surface) { | |||
| 89 | + | if w == nil || parent == nil { | |||
| 90 | + | return | |||
| 91 | + | } | |||
| 92 | + | state := c.server.surfaces[w.Resource] | |||
| 93 | + | if state == nil { | |||
| 94 | + | return | |||
| 95 | + | } | |||
| 96 | + | if state.role != nil { | |||
| 97 | + | r.PostError(uint32(wayland.SubcompositorErrorBadSurface), "surface already has role") | |||
| 98 | + | return | |||
| 99 | + | } | |||
| 100 | + | if sub, err := wayland.NewSubsurface(r.Client(), 1, id, subsurface{state}); err == nil { | |||
| 101 | + | state.role = func(bool) {} | |||
| 102 | + | sub.OnDestroy = func() { state.role = nil } | |||
| 103 | + | } | |||
| 104 | + | } | |||
| 105 | + | ||||
| 106 | + | type subsurface struct{ surface *surface } | |||
| 107 | + | ||||
| 108 | + | func (subsurface) Destroy(*wayland.Subsurface) {} | |||
| 109 | + | func (subsurface) SetPosition(*wayland.Subsurface, int32, int32) {} | |||
| 110 | + | func (subsurface) PlaceAbove(*wayland.Subsurface, *wayland.Surface) {} | |||
| 111 | + | func (subsurface) PlaceBelow(*wayland.Subsurface, *wayland.Surface) {} | |||
| 112 | + | func (subsurface) SetSync(*wayland.Subsurface) {} | |||
| 113 | + | func (subsurface) SetDesync(*wayland.Subsurface) {} | |||
| 114 | + | ||||
| 80 | type region struct{} | 115 | type region struct{} | ||
| 81 | 116 | ||||
| 82 | func (region) Destroy(*wayland.Region) {} | 117 | func (region) Destroy(*wayland.Region) {} | ||
M internal/adapters/wayland/server_test.go +2 -2
| @@ -284,8 +284,8 @@ func TestFootWindow(t *testing.T) { | |||
| 284 | 284 | t.Fatalf("app ID: %q", w.AppID) | |
| 285 | 285 | } | |
| 286 | 286 | case err := <-done: | |
| 287 | - | t.Skipf("foot unavailable: %v: %s", err, output.String()) | |
| 287 | + | t.Fatalf("foot exited: %v: %s", err, output.String()) | |
| 288 | 288 | case <-time.After(10 * time.Second): | |
| 289 | - | t.Skipf("foot did not map: %s", output.String()) | |
| 289 | + | t.Fatalf("foot did not map: %s", output.String()) | |
| 290 | 290 | } | |
| 291 | 291 | } | |
| @@ -284,8 +284,8 @@ func TestFootWindow(t *testing.T) { | |||||
| 284 | t.Fatalf("app ID: %q", w.AppID) | 284 | t.Fatalf("app ID: %q", w.AppID) | ||
| 285 | } | 285 | } | ||
| 286 | case err := <-done: | 286 | case err := <-done: | ||
| 287 | - | t.Skipf("foot unavailable: %v: %s", err, output.String()) | 287 | + | t.Fatalf("foot exited: %v: %s", err, output.String()) |
| 288 | case <-time.After(10 * time.Second): | 288 | case <-time.After(10 * time.Second): | ||
| 289 | - | t.Skipf("foot did not map: %s", output.String()) | 289 | + | t.Fatalf("foot did not map: %s", output.String()) |
| 290 | } | 290 | } | ||
| 291 | } | 291 | } | ||