refactor(wayland): route window access through role-neutral accessors
- commit
- 033015d5b9aac99f0a58e1296fbf286ddd5026cc
- author
- brice · · 2026-10-22 10:44 UTC
- parent
- 1912da3
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
17 files · +130 -46
M internal/adapters/wayland/activation.go +3 -3
| @@ -66,7 +66,7 @@ func (a activation) Activate(_ *xdgactivation.ActivationV1, token string, surf * | |||
| 66 | 66 | } | |
| 67 | 67 | var w *window | |
| 68 | 68 | if reason == "" { | |
| 69 | - | if w = s.windows[state.root().windowID()]; w == nil || w.toplevel == nil || !w.mapped { | |
| 69 | + | if w = s.windows[state.root().windowID()]; w == nil || !w.isToplevel() || !w.mapped { | |
| 70 | 70 | reason = "not_toplevel" | |
| 71 | 71 | } | |
| 72 | 72 | } | |
| @@ -116,8 +116,8 @@ func (t *tokenRequest) Commit(r *xdgactivation.ActivationTokenV1) { | |||
| 116 | 116 | ||
| 117 | 117 | // focusClient is the client with the keyboard focus. | |
| 118 | 118 | func (s *Server) focusClient() server.Client { | |
| 119 | - | if w := s.windows[s.seat.focused]; w != nil && w.xdg.resource.Resource.Alive() { | |
| 120 | - | return w.xdg.resource.Client() | |
| 119 | + | if w := s.windows[s.seat.focused]; w != nil && w.alive() { | |
| 120 | + | return w.client() | |
| 121 | 121 | } | |
| 122 | 122 | if l := s.layers[s.seat.focused]; l != nil && l.resource.Resource.Alive() { | |
| 123 | 123 | return l.resource.Client() | |
| @@ -66,7 +66,7 @@ func (a activation) Activate(_ *xdgactivation.ActivationV1, token string, surf * | |||||
| 66 | } | 66 | } | ||
| 67 | var w *window | 67 | var w *window | ||
| 68 | if reason == "" { | 68 | if reason == "" { | ||
| 69 | - | if w = s.windows[state.root().windowID()]; w == nil || w.toplevel == nil || !w.mapped { | 69 | + | if w = s.windows[state.root().windowID()]; w == nil || !w.isToplevel() || !w.mapped { |
| 70 | reason = "not_toplevel" | 70 | reason = "not_toplevel" | ||
| 71 | } | 71 | } | ||
| 72 | } | 72 | } | ||
| @@ -116,8 +116,8 @@ func (t *tokenRequest) Commit(r *xdgactivation.ActivationTokenV1) { | |||||
| 116 | 116 | ||||
| 117 | // focusClient is the client with the keyboard focus. | 117 | // focusClient is the client with the keyboard focus. | ||
| 118 | func (s *Server) focusClient() server.Client { | 118 | func (s *Server) focusClient() server.Client { | ||
| 119 | - | if w := s.windows[s.seat.focused]; w != nil && w.xdg.resource.Resource.Alive() { | 119 | + | if w := s.windows[s.seat.focused]; w != nil && w.alive() { |
| 120 | - | return w.xdg.resource.Client() | 120 | + | return w.client() |
| 121 | } | 121 | } | ||
| 122 | if l := s.layers[s.seat.focused]; l != nil && l.resource.Resource.Alive() { | 122 | if l := s.layers[s.seat.focused]; l != nil && l.resource.Resource.Alive() { | ||
| 123 | return l.resource.Client() | 123 | return l.resource.Client() | ||
M internal/adapters/wayland/constraints.go +8 -8
| @@ -61,11 +61,11 @@ func (h pointerWarp) WarpPointer(r *pointerwarp.WpPointerWarpV1, surf *wayland.S | |||
| 61 | 61 | return | |
| 62 | 62 | } | |
| 63 | 63 | w := s.windows[s.seat.pointerFocus] | |
| 64 | - | if w == nil || !w.mapped || w.xdg.resource.Client() != r.Client() || s.surfaces[surf.Resource] != w.xdg.surface { | |
| 64 | + | if w == nil || !w.mapped || w.client() != r.Client() || s.surfaces[surf.Resource] != w.surf() { | |
| 65 | 65 | return | |
| 66 | 66 | } | |
| 67 | 67 | // Surface-local to window-local (core's, from the geometry origin). | |
| 68 | - | g := w.xdg.geometry | |
| 68 | + | g := w.geometry() | |
| 69 | 69 | s.emit(ports.PointerWarp{ID: w.id, X: x.Float() - float64(g.X), Y: y.Float() - float64(g.Y)}) | |
| 70 | 70 | } | |
| 71 | 71 | ||
| @@ -80,12 +80,12 @@ func (s *Server) relativeMotion(w *window, c ports.PointerMotionTo) bool { | |||
| 80 | 80 | if s.protected() || c.DX == 0 && c.DY == 0 && c.UnaccelDX == 0 && c.UnaccelDY == 0 { | |
| 81 | 81 | return false | |
| 82 | 82 | } | |
| 83 | - | if !w.mapped || !w.xdg.resource.Resource.Alive() { | |
| 83 | + | if !w.mapped || !w.alive() { | |
| 84 | 84 | return false | |
| 85 | 85 | } | |
| 86 | 86 | sent := false | |
| 87 | 87 | usec := uint64(c.Time / time.Microsecond) | |
| 88 | - | for _, rel := range s.relatives[w.xdg.resource.Client()] { | |
| 88 | + | for _, rel := range s.relatives[w.client()] { | |
| 89 | 89 | if rel.Resource.Alive() { | |
| 90 | 90 | rel.SendRelativeMotion(uint32(usec>>32), uint32(usec), server.FixedFromFloat(c.DX), server.FixedFromFloat(c.DY), server.FixedFromFloat(c.UnaccelDX), server.FixedFromFloat(c.UnaccelDY)) | |
| 91 | 91 | sent = true | |
| @@ -272,7 +272,7 @@ func (s *Server) updateConstraint() { | |||
| 272 | 272 | } | |
| 273 | 273 | var want *constraint | |
| 274 | 274 | if w := s.windows[s.seat.pointerFocus]; w != nil && w.mapped && s.seat.pointerFocus == s.seat.focused { | |
| 275 | - | if c := s.constraints[w.xdg.surface]; c != nil && !c.defunct && (c.active || c.contains(w)) { | |
| 275 | + | if c := s.constraints[w.surf()]; c != nil && !c.defunct && (c.active || c.contains(w)) { | |
| 276 | 276 | want = c | |
| 277 | 277 | } | |
| 278 | 278 | } | |
| @@ -340,10 +340,10 @@ func (s *Server) emitConstraint(c *constraint) { | |||
| 340 | 340 | // activates only there, so it never warps the pointer. | |
| 341 | 341 | func (c *constraint) contains(w *window) bool { | |
| 342 | 342 | r := c.region | |
| 343 | - | x, y := w.surfacePoint(w.xdg.server.seat.pointerX, w.xdg.server.seat.pointerY) | |
| 343 | + | x, y := w.surfacePoint(c.surface.server.seat.pointerX, c.surface.server.seat.pointerY) | |
| 344 | 344 | all, rects := c.surface.effectiveInput() | |
| 345 | 345 | if !all { | |
| 346 | - | localX, localY := x-float64(w.xdg.geometry.X), y-float64(w.xdg.geometry.Y) | |
| 346 | + | localX, localY := x-float64(w.geometry().X), y-float64(w.geometry().Y) | |
| 347 | 347 | inside := false | |
| 348 | 348 | for _, input := range rects { | |
| 349 | 349 | if localX >= float64(input.X) && localX < float64(input.X+input.W) && localY >= float64(input.Y) && localY < float64(input.Y+input.H) { | |
| @@ -363,5 +363,5 @@ func (c *constraint) contains(w *window) bool { | |||
| 363 | 363 | ||
| 364 | 364 | // locked reports whether the window's pointer is locked. | |
| 365 | 365 | func (s *Server) locked(w *window) bool { | |
| 366 | - | return !s.protected() && s.constraint != nil && s.constraint.lock != nil && s.constraint.surface == w.xdg.surface | |
| 366 | + | return !s.protected() && s.constraint != nil && s.constraint.lock != nil && s.constraint.surface == w.surf() | |
| 367 | 367 | } | |
| @@ -61,11 +61,11 @@ func (h pointerWarp) WarpPointer(r *pointerwarp.WpPointerWarpV1, surf *wayland.S | |||||
| 61 | return | 61 | return | ||
| 62 | } | 62 | } | ||
| 63 | w := s.windows[s.seat.pointerFocus] | 63 | w := s.windows[s.seat.pointerFocus] | ||
| 64 | - | if w == nil || !w.mapped || w.xdg.resource.Client() != r.Client() || s.surfaces[surf.Resource] != w.xdg.surface { | 64 | + | if w == nil || !w.mapped || w.client() != r.Client() || s.surfaces[surf.Resource] != w.surf() { |
| 65 | return | 65 | return | ||
| 66 | } | 66 | } | ||
| 67 | // Surface-local to window-local (core's, from the geometry origin). | 67 | // Surface-local to window-local (core's, from the geometry origin). | ||
| 68 | - | g := w.xdg.geometry | 68 | + | g := w.geometry() |
| 69 | s.emit(ports.PointerWarp{ID: w.id, X: x.Float() - float64(g.X), Y: y.Float() - float64(g.Y)}) | 69 | s.emit(ports.PointerWarp{ID: w.id, X: x.Float() - float64(g.X), Y: y.Float() - float64(g.Y)}) | ||
| 70 | } | 70 | } | ||
| 71 | 71 | ||||
| @@ -80,12 +80,12 @@ func (s *Server) relativeMotion(w *window, c ports.PointerMotionTo) bool { | |||||
| 80 | if s.protected() || c.DX == 0 && c.DY == 0 && c.UnaccelDX == 0 && c.UnaccelDY == 0 { | 80 | if s.protected() || c.DX == 0 && c.DY == 0 && c.UnaccelDX == 0 && c.UnaccelDY == 0 { | ||
| 81 | return false | 81 | return false | ||
| 82 | } | 82 | } | ||
| 83 | - | if !w.mapped || !w.xdg.resource.Resource.Alive() { | 83 | + | if !w.mapped || !w.alive() { |
| 84 | return false | 84 | return false | ||
| 85 | } | 85 | } | ||
| 86 | sent := false | 86 | sent := false | ||
| 87 | usec := uint64(c.Time / time.Microsecond) | 87 | usec := uint64(c.Time / time.Microsecond) | ||
| 88 | - | for _, rel := range s.relatives[w.xdg.resource.Client()] { | 88 | + | for _, rel := range s.relatives[w.client()] { |
| 89 | if rel.Resource.Alive() { | 89 | if rel.Resource.Alive() { | ||
| 90 | rel.SendRelativeMotion(uint32(usec>>32), uint32(usec), server.FixedFromFloat(c.DX), server.FixedFromFloat(c.DY), server.FixedFromFloat(c.UnaccelDX), server.FixedFromFloat(c.UnaccelDY)) | 90 | rel.SendRelativeMotion(uint32(usec>>32), uint32(usec), server.FixedFromFloat(c.DX), server.FixedFromFloat(c.DY), server.FixedFromFloat(c.UnaccelDX), server.FixedFromFloat(c.UnaccelDY)) | ||
| 91 | sent = true | 91 | sent = true | ||
| @@ -272,7 +272,7 @@ func (s *Server) updateConstraint() { | |||||
| 272 | } | 272 | } | ||
| 273 | var want *constraint | 273 | var want *constraint | ||
| 274 | if w := s.windows[s.seat.pointerFocus]; w != nil && w.mapped && s.seat.pointerFocus == s.seat.focused { | 274 | if w := s.windows[s.seat.pointerFocus]; w != nil && w.mapped && s.seat.pointerFocus == s.seat.focused { | ||
| 275 | - | if c := s.constraints[w.xdg.surface]; c != nil && !c.defunct && (c.active || c.contains(w)) { | 275 | + | if c := s.constraints[w.surf()]; c != nil && !c.defunct && (c.active || c.contains(w)) { |
| 276 | want = c | 276 | want = c | ||
| 277 | } | 277 | } | ||
| 278 | } | 278 | } | ||
| @@ -340,10 +340,10 @@ func (s *Server) emitConstraint(c *constraint) { | |||||
| 340 | // activates only there, so it never warps the pointer. | 340 | // activates only there, so it never warps the pointer. | ||
| 341 | func (c *constraint) contains(w *window) bool { | 341 | func (c *constraint) contains(w *window) bool { | ||
| 342 | r := c.region | 342 | r := c.region | ||
| 343 | - | x, y := w.surfacePoint(w.xdg.server.seat.pointerX, w.xdg.server.seat.pointerY) | 343 | + | x, y := w.surfacePoint(c.surface.server.seat.pointerX, c.surface.server.seat.pointerY) |
| 344 | all, rects := c.surface.effectiveInput() | 344 | all, rects := c.surface.effectiveInput() | ||
| 345 | if !all { | 345 | if !all { | ||
| 346 | - | localX, localY := x-float64(w.xdg.geometry.X), y-float64(w.xdg.geometry.Y) | 346 | + | localX, localY := x-float64(w.geometry().X), y-float64(w.geometry().Y) |
| 347 | inside := false | 347 | inside := false | ||
| 348 | for _, input := range rects { | 348 | for _, input := range rects { | ||
| 349 | if localX >= float64(input.X) && localX < float64(input.X+input.W) && localY >= float64(input.Y) && localY < float64(input.Y+input.H) { | 349 | if localX >= float64(input.X) && localX < float64(input.X+input.W) && localY >= float64(input.Y) && localY < float64(input.Y+input.H) { | ||
| @@ -363,5 +363,5 @@ func (c *constraint) contains(w *window) bool { | |||||
| 363 | 363 | ||||
| 364 | // locked reports whether the window's pointer is locked. | 364 | // locked reports whether the window's pointer is locked. | ||
| 365 | func (s *Server) locked(w *window) bool { | 365 | func (s *Server) locked(w *window) bool { | ||
| 366 | - | return !s.protected() && s.constraint != nil && s.constraint.lock != nil && s.constraint.surface == w.xdg.surface | 366 | + | return !s.protected() && s.constraint != nil && s.constraint.lock != nil && s.constraint.surface == w.surf() |
| 367 | } | 367 | } | ||
M internal/adapters/wayland/decoration.go +1 -1
| @@ -80,7 +80,7 @@ func (d *decoration) UnsetMode(r *xdgdecoration.ZxdgToplevelDecorationV1) | |||
| 80 | 80 | func (d *decoration) send(r *xdgdecoration.ZxdgToplevelDecorationV1) { | |
| 81 | 81 | r.SendConfigure(uint32(xdgdecoration.ZxdgToplevelDecorationV1ModeServerSide)) | |
| 82 | 82 | for _, w := range d.s.windows { | |
| 83 | - | if w.toplevel == d.toplevel && w.hasLast && w.toplevel.Resource.Alive() && w.xdg.resource.Resource.Alive() { | |
| 83 | + | if w.toplevel == d.toplevel && w.hasLast && w.toplevelAlive() && w.alive() { | |
| 84 | 84 | w.sendConfigure() | |
| 85 | 85 | return | |
| 86 | 86 | } | |
| @@ -80,7 +80,7 @@ func (d *decoration) UnsetMode(r *xdgdecoration.ZxdgToplevelDecorationV1) | |||||
| 80 | func (d *decoration) send(r *xdgdecoration.ZxdgToplevelDecorationV1) { | 80 | func (d *decoration) send(r *xdgdecoration.ZxdgToplevelDecorationV1) { | ||
| 81 | r.SendConfigure(uint32(xdgdecoration.ZxdgToplevelDecorationV1ModeServerSide)) | 81 | r.SendConfigure(uint32(xdgdecoration.ZxdgToplevelDecorationV1ModeServerSide)) | ||
| 82 | for _, w := range d.s.windows { | 82 | for _, w := range d.s.windows { | ||
| 83 | - | if w.toplevel == d.toplevel && w.hasLast && w.toplevel.Resource.Alive() && w.xdg.resource.Resource.Alive() { | 83 | + | if w.toplevel == d.toplevel && w.hasLast && w.toplevelAlive() && w.alive() { |
| 84 | w.sendConfigure() | 84 | w.sendConfigure() | ||
| 85 | return | 85 | return | ||
| 86 | } | 86 | } | ||
M internal/adapters/wayland/dialog.go +1 -1
| @@ -76,7 +76,7 @@ func (w *window) setModal(modal bool) { | |||
| 76 | 76 | return | |
| 77 | 77 | } | |
| 78 | 78 | w.modal = modal | |
| 79 | - | if w.mapped { | |
| 79 | + | if w.mapped && w.xdg != nil { | |
| 80 | 80 | w.xdg.server.emit(ports.WindowModal{ID: w.id, Modal: modal}) | |
| 81 | 81 | } | |
| 82 | 82 | } | |
| @@ -76,7 +76,7 @@ func (w *window) setModal(modal bool) { | |||||
| 76 | return | 76 | return | ||
| 77 | } | 77 | } | ||
| 78 | w.modal = modal | 78 | w.modal = modal | ||
| 79 | - | if w.mapped { | 79 | + | if w.mapped && w.xdg != nil { |
| 80 | w.xdg.server.emit(ports.WindowModal{ID: w.id, Modal: modal}) | 80 | w.xdg.server.emit(ports.WindowModal{ID: w.id, Modal: modal}) | ||
| 81 | } | 81 | } | ||
| 82 | } | 82 | } | ||
M internal/adapters/wayland/extforeigntoplevel.go +1 -1
| @@ -72,7 +72,7 @@ func (*extToplevelList) Destroy(*ext.ExtForeignToplevelListV1) {} | |||
| 72 | 72 | func (s *Server) mappedToplevels() []ports.WindowID { | |
| 73 | 73 | ids := make([]ports.WindowID, 0, len(s.windows)) | |
| 74 | 74 | for id, w := range s.windows { | |
| 75 | - | if w.toplevel != nil && w.mapped { | |
| 75 | + | if w.isToplevel() && w.mapped { | |
| 76 | 76 | ids = append(ids, id) | |
| 77 | 77 | } | |
| 78 | 78 | } | |
| @@ -72,7 +72,7 @@ func (*extToplevelList) Destroy(*ext.ExtForeignToplevelListV1) {} | |||||
| 72 | func (s *Server) mappedToplevels() []ports.WindowID { | 72 | func (s *Server) mappedToplevels() []ports.WindowID { | ||
| 73 | ids := make([]ports.WindowID, 0, len(s.windows)) | 73 | ids := make([]ports.WindowID, 0, len(s.windows)) | ||
| 74 | for id, w := range s.windows { | 74 | for id, w := range s.windows { | ||
| 75 | - | if w.toplevel != nil && w.mapped { | 75 | + | if w.isToplevel() && w.mapped { |
| 76 | ids = append(ids, id) | 76 | ids = append(ids, id) | ||
| 77 | } | 77 | } | ||
| 78 | } | 78 | } | ||
M internal/adapters/wayland/foreigntoplevel.go +6 -6
| @@ -44,7 +44,7 @@ func registerForeignToplevel(d *server.Display, s *Server) error { | |||
| 44 | 44 | r.OnDestroy = func() { s.toplevelManagers = removeItem(s.toplevelManagers, m) } | |
| 45 | 45 | ids := make([]ports.WindowID, 0, len(s.windows)) | |
| 46 | 46 | for id, w := range s.windows { | |
| 47 | - | if w.toplevel != nil && w.mapped { | |
| 47 | + | if w.isToplevel() && w.mapped { | |
| 48 | 48 | ids = append(ids, id) | |
| 49 | 49 | } | |
| 50 | 50 | } | |
| @@ -186,7 +186,7 @@ func toplevelState(w *window, version int32) []byte { | |||
| 186 | 186 | ||
| 187 | 187 | // toplevelChanged updates every manager after w mapped or changed. | |
| 188 | 188 | func (s *Server) toplevelChanged(w *window) { | |
| 189 | - | if w.toplevel == nil || !w.mapped { | |
| 189 | + | if !w.isToplevel() || !w.mapped { | |
| 190 | 190 | return | |
| 191 | 191 | } | |
| 192 | 192 | for _, m := range s.toplevelManagers { | |
| @@ -220,7 +220,7 @@ func (s *Server) refreshToplevels() { | |||
| 220 | 220 | for _, l := range s.extToplevelLists { | |
| 221 | 221 | for id, h := range l.handles { | |
| 222 | 222 | w := s.windows[id] | |
| 223 | - | if h.closed || w == nil || w.toplevel == nil || !w.mapped { | |
| 223 | + | if h.closed || w == nil || !w.isToplevel() || !w.mapped { | |
| 224 | 224 | l.closed(id) | |
| 225 | 225 | } | |
| 226 | 226 | } | |
| @@ -231,7 +231,7 @@ func (s *Server) refreshToplevels() { | |||
| 231 | 231 | for _, m := range s.toplevelManagers { | |
| 232 | 232 | for id, h := range m.handles { | |
| 233 | 233 | w := s.windows[id] | |
| 234 | - | if h.req.closed || w == nil || w.toplevel == nil || !w.mapped { | |
| 234 | + | if h.req.closed || w == nil || !w.isToplevel() || !w.mapped { | |
| 235 | 235 | m.closed(id) | |
| 236 | 236 | } | |
| 237 | 237 | } | |
| @@ -253,7 +253,7 @@ func (t *toplevelRequests) window() *window { | |||
| 253 | 253 | if t.s.protected() || t.closed { | |
| 254 | 254 | return nil | |
| 255 | 255 | } | |
| 256 | - | if w := t.s.windows[t.id]; w != nil && w.toplevel != nil && w.mapped && w.toplevel.Resource.Alive() { | |
| 256 | + | if w := t.s.windows[t.id]; w != nil && w.toplevelAlive() && w.mapped { | |
| 257 | 257 | return w | |
| 258 | 258 | } | |
| 259 | 259 | return nil | |
| @@ -274,7 +274,7 @@ func (t *toplevelRequests) Activate(*wlr.ZwlrForeignToplevelHandleV1, *wayland.S | |||
| 274 | 274 | } | |
| 275 | 275 | func (t *toplevelRequests) Close(*wlr.ZwlrForeignToplevelHandleV1) { | |
| 276 | 276 | if w := t.window(); w != nil { | |
| 277 | - | w.toplevel.SendClose() | |
| 277 | + | w.sendClose() | |
| 278 | 278 | } | |
| 279 | 279 | } | |
| 280 | 280 | func (t *toplevelRequests) SetRectangle(r *wlr.ZwlrForeignToplevelHandleV1, _ *wayland.Surface, _, _, w, h int32) { | |
| @@ -44,7 +44,7 @@ func registerForeignToplevel(d *server.Display, s *Server) error { | |||||
| 44 | r.OnDestroy = func() { s.toplevelManagers = removeItem(s.toplevelManagers, m) } | 44 | r.OnDestroy = func() { s.toplevelManagers = removeItem(s.toplevelManagers, m) } | ||
| 45 | ids := make([]ports.WindowID, 0, len(s.windows)) | 45 | ids := make([]ports.WindowID, 0, len(s.windows)) | ||
| 46 | for id, w := range s.windows { | 46 | for id, w := range s.windows { | ||
| 47 | - | if w.toplevel != nil && w.mapped { | 47 | + | if w.isToplevel() && w.mapped { |
| 48 | ids = append(ids, id) | 48 | ids = append(ids, id) | ||
| 49 | } | 49 | } | ||
| 50 | } | 50 | } | ||
| @@ -186,7 +186,7 @@ func toplevelState(w *window, version int32) []byte { | |||||
| 186 | 186 | ||||
| 187 | // toplevelChanged updates every manager after w mapped or changed. | 187 | // toplevelChanged updates every manager after w mapped or changed. | ||
| 188 | func (s *Server) toplevelChanged(w *window) { | 188 | func (s *Server) toplevelChanged(w *window) { | ||
| 189 | - | if w.toplevel == nil || !w.mapped { | 189 | + | if !w.isToplevel() || !w.mapped { |
| 190 | return | 190 | return | ||
| 191 | } | 191 | } | ||
| 192 | for _, m := range s.toplevelManagers { | 192 | for _, m := range s.toplevelManagers { | ||
| @@ -220,7 +220,7 @@ func (s *Server) refreshToplevels() { | |||||
| 220 | for _, l := range s.extToplevelLists { | 220 | for _, l := range s.extToplevelLists { | ||
| 221 | for id, h := range l.handles { | 221 | for id, h := range l.handles { | ||
| 222 | w := s.windows[id] | 222 | w := s.windows[id] | ||
| 223 | - | if h.closed || w == nil || w.toplevel == nil || !w.mapped { | 223 | + | if h.closed || w == nil || !w.isToplevel() || !w.mapped { |
| 224 | l.closed(id) | 224 | l.closed(id) | ||
| 225 | } | 225 | } | ||
| 226 | } | 226 | } | ||
| @@ -231,7 +231,7 @@ func (s *Server) refreshToplevels() { | |||||
| 231 | for _, m := range s.toplevelManagers { | 231 | for _, m := range s.toplevelManagers { | ||
| 232 | for id, h := range m.handles { | 232 | for id, h := range m.handles { | ||
| 233 | w := s.windows[id] | 233 | w := s.windows[id] | ||
| 234 | - | if h.req.closed || w == nil || w.toplevel == nil || !w.mapped { | 234 | + | if h.req.closed || w == nil || !w.isToplevel() || !w.mapped { |
| 235 | m.closed(id) | 235 | m.closed(id) | ||
| 236 | } | 236 | } | ||
| 237 | } | 237 | } | ||
| @@ -253,7 +253,7 @@ func (t *toplevelRequests) window() *window { | |||||
| 253 | if t.s.protected() || t.closed { | 253 | if t.s.protected() || t.closed { | ||
| 254 | return nil | 254 | return nil | ||
| 255 | } | 255 | } | ||
| 256 | - | if w := t.s.windows[t.id]; w != nil && w.toplevel != nil && w.mapped && w.toplevel.Resource.Alive() { | 256 | + | if w := t.s.windows[t.id]; w != nil && w.toplevelAlive() && w.mapped { |
| 257 | return w | 257 | return w | ||
| 258 | } | 258 | } | ||
| 259 | return nil | 259 | return nil | ||
| @@ -274,7 +274,7 @@ func (t *toplevelRequests) Activate(*wlr.ZwlrForeignToplevelHandleV1, *wayland.S | |||||
| 274 | } | 274 | } | ||
| 275 | func (t *toplevelRequests) Close(*wlr.ZwlrForeignToplevelHandleV1) { | 275 | func (t *toplevelRequests) Close(*wlr.ZwlrForeignToplevelHandleV1) { | ||
| 276 | if w := t.window(); w != nil { | 276 | if w := t.window(); w != nil { | ||
| 277 | - | w.toplevel.SendClose() | 277 | + | w.sendClose() |
| 278 | } | 278 | } | ||
| 279 | } | 279 | } | ||
| 280 | func (t *toplevelRequests) SetRectangle(r *wlr.ZwlrForeignToplevelHandleV1, _ *wayland.Surface, _, _, w, h int32) { | 280 | func (t *toplevelRequests) SetRectangle(r *wlr.ZwlrForeignToplevelHandleV1, _ *wayland.Surface, _, _, w, h int32) { | ||
M internal/adapters/wayland/frames.go +1 -1
| @@ -183,7 +183,7 @@ func (s *Server) pacePass(flipped map[string]bool, reports []ports.OutputPresent | |||
| 183 | 183 | func toplevelRoot(surf *surface) *surface { | |
| 184 | 184 | surf = surf.root() | |
| 185 | 185 | for surf.xdg != nil && surf.xdg.window != nil && surf.xdg.window.popup != nil && surf.xdg.window.popup.parent != nil { | |
| 186 | - | surf = surf.xdg.window.popup.parent.xdg.surface.root() | |
| 186 | + | surf = surf.xdg.window.popup.parent.surf().root() | |
| 187 | 187 | } | |
| 188 | 188 | return surf | |
| 189 | 189 | } | |
| @@ -183,7 +183,7 @@ func (s *Server) pacePass(flipped map[string]bool, reports []ports.OutputPresent | |||||
| 183 | func toplevelRoot(surf *surface) *surface { | 183 | func toplevelRoot(surf *surface) *surface { | ||
| 184 | surf = surf.root() | 184 | surf = surf.root() | ||
| 185 | for surf.xdg != nil && surf.xdg.window != nil && surf.xdg.window.popup != nil && surf.xdg.window.popup.parent != nil { | 185 | for surf.xdg != nil && surf.xdg.window != nil && surf.xdg.window.popup != nil && surf.xdg.window.popup.parent != nil { | ||
| 186 | - | surf = surf.xdg.window.popup.parent.xdg.surface.root() | 186 | + | surf = surf.xdg.window.popup.parent.surf().root() |
| 187 | } | 187 | } | ||
| 188 | return surf | 188 | return surf | ||
| 189 | } | 189 | } | ||
M internal/adapters/wayland/globals.go +6 -1
| @@ -131,8 +131,13 @@ func (c compositor) CreateSurface(r *wayland.Compositor, id uint32) { | |||
| 131 | 131 | state.identity = c.server.nextSurface | |
| 132 | 132 | state.wl = w | |
| 133 | 133 | c.server.surfaces[w.Resource] = state | |
| 134 | + | c.server.surfaceByIdentity[state.identity] = state | |
| 134 | 135 | state.sendScale() | |
| 135 | - | w.OnDestroy = func() { delete(c.server.surfaces, w.Resource); state.Destroy(w) } | |
| 136 | + | w.OnDestroy = func() { | |
| 137 | + | delete(c.server.surfaces, w.Resource) | |
| 138 | + | delete(c.server.surfaceByIdentity, state.identity) | |
| 139 | + | state.Destroy(w) | |
| 140 | + | } | |
| 136 | 141 | } | |
| 137 | 142 | } | |
| 138 | 143 | func (c compositor) CreateRegion(r *wayland.Compositor, id uint32) { | |
| @@ -131,8 +131,13 @@ func (c compositor) CreateSurface(r *wayland.Compositor, id uint32) { | |||||
| 131 | state.identity = c.server.nextSurface | 131 | state.identity = c.server.nextSurface | ||
| 132 | state.wl = w | 132 | state.wl = w | ||
| 133 | c.server.surfaces[w.Resource] = state | 133 | c.server.surfaces[w.Resource] = state | ||
| 134 | + | c.server.surfaceByIdentity[state.identity] = state | |||
| 134 | state.sendScale() | 135 | state.sendScale() | ||
| 135 | - | w.OnDestroy = func() { delete(c.server.surfaces, w.Resource); state.Destroy(w) } | 136 | + | w.OnDestroy = func() { |
| 137 | + | delete(c.server.surfaces, w.Resource) | |||
| 138 | + | delete(c.server.surfaceByIdentity, state.identity) | |||
| 139 | + | state.Destroy(w) | |||
| 140 | + | } | |||
| 136 | } | 141 | } | ||
| 137 | } | 142 | } | ||
| 138 | func (c compositor) CreateRegion(r *wayland.Compositor, id uint32) { | 143 | func (c compositor) CreateRegion(r *wayland.Compositor, id uint32) { | ||
M internal/adapters/wayland/imagecopy.go +1 -1
| @@ -351,7 +351,7 @@ func (c *captureTarget) geometry() (o *output, rect image.Rectangle, hidden, ok | |||
| 351 | 351 | case srcWindow: | |
| 352 | 352 | // Core's state gives the size; before it, the last configure. | |
| 353 | 353 | w := c.s.windows[src.window] | |
| 354 | - | if w == nil || !w.mapped || w.toplevel == nil || w.gen != src.gen { | |
| 354 | + | if w == nil || !w.mapped || !w.isToplevel() || w.gen != src.gen { | |
| 355 | 355 | return nil, image.Rectangle{}, false, false | |
| 356 | 356 | } | |
| 357 | 357 | name, size := w.last.Output, ports.Rect{W: w.last.Width, H: w.last.Height} | |
| @@ -351,7 +351,7 @@ func (c *captureTarget) geometry() (o *output, rect image.Rectangle, hidden, ok | |||||
| 351 | case srcWindow: | 351 | case srcWindow: | ||
| 352 | // Core's state gives the size; before it, the last configure. | 352 | // Core's state gives the size; before it, the last configure. | ||
| 353 | w := c.s.windows[src.window] | 353 | w := c.s.windows[src.window] | ||
| 354 | - | if w == nil || !w.mapped || w.toplevel == nil || w.gen != src.gen { | 354 | + | if w == nil || !w.mapped || !w.isToplevel() || w.gen != src.gen { |
| 355 | return nil, image.Rectangle{}, false, false | 355 | return nil, image.Rectangle{}, false, false | ||
| 356 | } | 356 | } | ||
| 357 | name, size := w.last.Output, ports.Rect{W: w.last.Width, H: w.last.Height} | 357 | name, size := w.last.Output, ports.Rect{W: w.last.Width, H: w.last.Height} | ||
M internal/adapters/wayland/popup.go +2 -2
| @@ -31,7 +31,7 @@ func (s *Server) newPopup(x *xdgSurface, r *xdgshell.Surface, id uint32, parentX | |||
| 31 | 31 | var parent *window | |
| 32 | 32 | if parentXDG != nil { | |
| 33 | 33 | for _, w := range s.windows { | |
| 34 | - | if w.xdg.resource != nil && w.xdg.resource.Resource == parentXDG.Resource { | |
| 34 | + | if w.xdg != nil && w.xdg.resource != nil && w.xdg.resource.Resource == parentXDG.Resource { | |
| 35 | 35 | parent = w | |
| 36 | 36 | } | |
| 37 | 37 | } | |
| @@ -166,7 +166,7 @@ func (p *popup) configure(c ports.ConfigurePopup) { | |||
| 166 | 166 | func (s *Server) topGrab(client server.Client, parent *window) bool { | |
| 167 | 167 | var top *window | |
| 168 | 168 | for _, w := range s.windows { | |
| 169 | - | if w.popup != nil && w.popup.grab && !w.popup.done && w.xdg.resource.Client() == client && (top == nil || w.id > top.id) { | |
| 169 | + | if w.popup != nil && w.popup.grab && !w.popup.done && w.client() == client && (top == nil || w.id > top.id) { | |
| 170 | 170 | top = w | |
| 171 | 171 | } | |
| 172 | 172 | } | |
| @@ -31,7 +31,7 @@ func (s *Server) newPopup(x *xdgSurface, r *xdgshell.Surface, id uint32, parentX | |||||
| 31 | var parent *window | 31 | var parent *window | ||
| 32 | if parentXDG != nil { | 32 | if parentXDG != nil { | ||
| 33 | for _, w := range s.windows { | 33 | for _, w := range s.windows { | ||
| 34 | - | if w.xdg.resource != nil && w.xdg.resource.Resource == parentXDG.Resource { | 34 | + | if w.xdg != nil && w.xdg.resource != nil && w.xdg.resource.Resource == parentXDG.Resource { |
| 35 | parent = w | 35 | parent = w | ||
| 36 | } | 36 | } | ||
| 37 | } | 37 | } | ||
| @@ -166,7 +166,7 @@ func (p *popup) configure(c ports.ConfigurePopup) { | |||||
| 166 | func (s *Server) topGrab(client server.Client, parent *window) bool { | 166 | func (s *Server) topGrab(client server.Client, parent *window) bool { | ||
| 167 | var top *window | 167 | var top *window | ||
| 168 | for _, w := range s.windows { | 168 | for _, w := range s.windows { | ||
| 169 | - | if w.popup != nil && w.popup.grab && !w.popup.done && w.xdg.resource.Client() == client && (top == nil || w.id > top.id) { | 169 | + | if w.popup != nil && w.popup.grab && !w.popup.done && w.client() == client && (top == nil || w.id > top.id) { |
| 170 | top = w | 170 | top = w | ||
| 171 | } | 171 | } | ||
| 172 | } | 172 | } | ||
M internal/adapters/wayland/scale.go +1 -1
| @@ -21,7 +21,7 @@ func (s *Server) outputOfSurface(surf *surface) *output { | |||
| 21 | 21 | surf = surf.root() | |
| 22 | 22 | // Popups are on their parent's output. | |
| 23 | 23 | for surf.xdg != nil && surf.xdg.window != nil && surf.xdg.window.popup != nil && surf.xdg.window.popup.parent != nil { | |
| 24 | - | surf = surf.xdg.window.popup.parent.xdg.surface.root() | |
| 24 | + | surf = surf.xdg.window.popup.parent.surf().root() | |
| 25 | 25 | } | |
| 26 | 26 | name := "" | |
| 27 | 27 | switch { | |
| @@ -21,7 +21,7 @@ func (s *Server) outputOfSurface(surf *surface) *output { | |||||
| 21 | surf = surf.root() | 21 | surf = surf.root() | ||
| 22 | // Popups are on their parent's output. | 22 | // Popups are on their parent's output. | ||
| 23 | for surf.xdg != nil && surf.xdg.window != nil && surf.xdg.window.popup != nil && surf.xdg.window.popup.parent != nil { | 23 | for surf.xdg != nil && surf.xdg.window != nil && surf.xdg.window.popup != nil && surf.xdg.window.popup.parent != nil { | ||
| 24 | - | surf = surf.xdg.window.popup.parent.xdg.surface.root() | 24 | + | surf = surf.xdg.window.popup.parent.surf().root() |
| 25 | } | 25 | } | ||
| 26 | name := "" | 26 | name := "" | ||
| 27 | switch { | 27 | switch { | ||
M internal/adapters/wayland/screencast.go +1 -1
| @@ -146,7 +146,7 @@ func (s *Server) openCast(cmd ports.CastCommand) { | |||
| 146 | 146 | gone := ports.CaptureReasonOutputGone | |
| 147 | 147 | if cmd.Window != 0 { | |
| 148 | 148 | gone = ports.CaptureReasonWindowGone | |
| 149 | - | if w := s.windows[cmd.Window]; w != nil && w.mapped && w.toplevel != nil { | |
| 149 | + | if w := s.windows[cmd.Window]; w != nil && w.mapped && w.isToplevel() { | |
| 150 | 150 | src = &captureSource{kind: srcWindow, window: cmd.Window, gen: w.gen} | |
| 151 | 151 | open.Window = cmd.Window | |
| 152 | 152 | } | |
| @@ -146,7 +146,7 @@ func (s *Server) openCast(cmd ports.CastCommand) { | |||||
| 146 | gone := ports.CaptureReasonOutputGone | 146 | gone := ports.CaptureReasonOutputGone | ||
| 147 | if cmd.Window != 0 { | 147 | if cmd.Window != 0 { | ||
| 148 | gone = ports.CaptureReasonWindowGone | 148 | gone = ports.CaptureReasonWindowGone | ||
| 149 | - | if w := s.windows[cmd.Window]; w != nil && w.mapped && w.toplevel != nil { | 149 | + | if w := s.windows[cmd.Window]; w != nil && w.mapped && w.isToplevel() { |
| 150 | src = &captureSource{kind: srcWindow, window: cmd.Window, gen: w.gen} | 150 | src = &captureSource{kind: srcWindow, window: cmd.Window, gen: w.gen} | ||
| 151 | open.Window = cmd.Window | 151 | open.Window = cmd.Window | ||
| 152 | } | 152 | } | ||
M internal/adapters/wayland/seat.go +8 -8
| @@ -276,10 +276,10 @@ func (s *Server) setModifiers(c ports.SetModifiers) { | |||
| 276 | 276 | } | |
| 277 | 277 | ||
| 278 | 278 | func (s *Server) windowKeyboards(w *window) []*wayland.Keyboard { | |
| 279 | - | if w == nil || !w.mapped || !w.xdg.resource.Resource.Alive() { | |
| 279 | + | if w == nil || !w.mapped || !w.alive() { | |
| 280 | 280 | return nil | |
| 281 | 281 | } | |
| 282 | - | return s.clientKeyboards(w.xdg.resource.Client()) | |
| 282 | + | return s.clientKeyboards(w.client()) | |
| 283 | 283 | } | |
| 284 | 284 | ||
| 285 | 285 | // clientKeyboards returns c's wl_keyboards without allocating. The list holds | |
| @@ -301,7 +301,7 @@ func (s *Server) focusTarget(id ports.WindowID) (*wayland.Surface, []*wayland.Ke | |||
| 301 | 301 | return l.surface.wl, s.clientKeyboards(l.surface.wl.Client()) | |
| 302 | 302 | } | |
| 303 | 303 | if w := s.windows[id]; w != nil && w.mapped { | |
| 304 | - | if surf := w.xdg.surfaceResource(); surf != nil { | |
| 304 | + | if surf := w.surfaceResource(); surf != nil { | |
| 305 | 305 | return surf, s.windowKeyboards(w) | |
| 306 | 306 | } | |
| 307 | 307 | } | |
| @@ -319,8 +319,8 @@ func (s *Server) pointerTarget(id ports.WindowID) (server.Client, []*wayland.Poi | |||
| 319 | 319 | if l := s.lockSurfaces[id]; l != nil && s.lockInputTarget(id) { | |
| 320 | 320 | return l.resource.Client(), s.clientPointers(l.resource.Client()), true | |
| 321 | 321 | } | |
| 322 | - | if w := s.windows[id]; w != nil && w.mapped && w.xdg.resource.Resource.Alive() { | |
| 323 | - | return w.xdg.resource.Client(), s.windowPointers(w), true | |
| 322 | + | if w := s.windows[id]; w != nil && w.mapped && w.alive() { | |
| 323 | + | return w.client(), s.windowPointers(w), true | |
| 324 | 324 | } | |
| 325 | 325 | if l := s.layers[id]; l != nil && l.mapped && l.resource.Resource.Alive() { | |
| 326 | 326 | return l.resource.Client(), s.layerPointers(l), true | |
| @@ -335,7 +335,7 @@ func (s *Server) pointerSurface(id ports.WindowID, x, y float64) (*wayland.Surfa | |||
| 335 | 335 | return l.surface.wl, s.clientPointers(l.surface.wl.Client()), x, y | |
| 336 | 336 | } | |
| 337 | 337 | if w := s.windows[id]; w != nil { | |
| 338 | - | if surf := w.xdg.surfaceResource(); surf != nil && surf.Resource.Alive() { | |
| 338 | + | if surf := w.surfaceResource(); surf != nil && surf.Resource.Alive() { | |
| 339 | 339 | x, y := w.surfacePoint(x, y) | |
| 340 | 340 | return surf, s.windowPointers(w), x, y | |
| 341 | 341 | } | |
| @@ -543,10 +543,10 @@ func pointerFrame(p *wayland.Pointer) { | |||
| 543 | 543 | } | |
| 544 | 544 | } | |
| 545 | 545 | func (s *Server) windowPointers(w *window) []*wayland.Pointer { | |
| 546 | - | if w == nil || !w.mapped || !w.xdg.resource.Resource.Alive() { | |
| 546 | + | if w == nil || !w.mapped || !w.alive() { | |
| 547 | 547 | return nil | |
| 548 | 548 | } | |
| 549 | - | return s.clientPointers(w.xdg.resource.Client()) | |
| 549 | + | return s.clientPointers(w.client()) | |
| 550 | 550 | } | |
| 551 | 551 | ||
| 552 | 552 | func (s *Server) layerPointers(l *layerSurface) []*wayland.Pointer { | |
| @@ -276,10 +276,10 @@ func (s *Server) setModifiers(c ports.SetModifiers) { | |||||
| 276 | } | 276 | } | ||
| 277 | 277 | ||||
| 278 | func (s *Server) windowKeyboards(w *window) []*wayland.Keyboard { | 278 | func (s *Server) windowKeyboards(w *window) []*wayland.Keyboard { | ||
| 279 | - | if w == nil || !w.mapped || !w.xdg.resource.Resource.Alive() { | 279 | + | if w == nil || !w.mapped || !w.alive() { |
| 280 | return nil | 280 | return nil | ||
| 281 | } | 281 | } | ||
| 282 | - | return s.clientKeyboards(w.xdg.resource.Client()) | 282 | + | return s.clientKeyboards(w.client()) |
| 283 | } | 283 | } | ||
| 284 | 284 | ||||
| 285 | // clientKeyboards returns c's wl_keyboards without allocating. The list holds | 285 | // clientKeyboards returns c's wl_keyboards without allocating. The list holds | ||
| @@ -301,7 +301,7 @@ func (s *Server) focusTarget(id ports.WindowID) (*wayland.Surface, []*wayland.Ke | |||||
| 301 | return l.surface.wl, s.clientKeyboards(l.surface.wl.Client()) | 301 | return l.surface.wl, s.clientKeyboards(l.surface.wl.Client()) | ||
| 302 | } | 302 | } | ||
| 303 | if w := s.windows[id]; w != nil && w.mapped { | 303 | if w := s.windows[id]; w != nil && w.mapped { | ||
| 304 | - | if surf := w.xdg.surfaceResource(); surf != nil { | 304 | + | if surf := w.surfaceResource(); surf != nil { |
| 305 | return surf, s.windowKeyboards(w) | 305 | return surf, s.windowKeyboards(w) | ||
| 306 | } | 306 | } | ||
| 307 | } | 307 | } | ||
| @@ -319,8 +319,8 @@ func (s *Server) pointerTarget(id ports.WindowID) (server.Client, []*wayland.Poi | |||||
| 319 | if l := s.lockSurfaces[id]; l != nil && s.lockInputTarget(id) { | 319 | if l := s.lockSurfaces[id]; l != nil && s.lockInputTarget(id) { | ||
| 320 | return l.resource.Client(), s.clientPointers(l.resource.Client()), true | 320 | return l.resource.Client(), s.clientPointers(l.resource.Client()), true | ||
| 321 | } | 321 | } | ||
| 322 | - | if w := s.windows[id]; w != nil && w.mapped && w.xdg.resource.Resource.Alive() { | 322 | + | if w := s.windows[id]; w != nil && w.mapped && w.alive() { |
| 323 | - | return w.xdg.resource.Client(), s.windowPointers(w), true | 323 | + | return w.client(), s.windowPointers(w), true |
| 324 | } | 324 | } | ||
| 325 | if l := s.layers[id]; l != nil && l.mapped && l.resource.Resource.Alive() { | 325 | if l := s.layers[id]; l != nil && l.mapped && l.resource.Resource.Alive() { | ||
| 326 | return l.resource.Client(), s.layerPointers(l), true | 326 | return l.resource.Client(), s.layerPointers(l), true | ||
| @@ -335,7 +335,7 @@ func (s *Server) pointerSurface(id ports.WindowID, x, y float64) (*wayland.Surfa | |||||
| 335 | return l.surface.wl, s.clientPointers(l.surface.wl.Client()), x, y | 335 | return l.surface.wl, s.clientPointers(l.surface.wl.Client()), x, y | ||
| 336 | } | 336 | } | ||
| 337 | if w := s.windows[id]; w != nil { | 337 | if w := s.windows[id]; w != nil { | ||
| 338 | - | if surf := w.xdg.surfaceResource(); surf != nil && surf.Resource.Alive() { | 338 | + | if surf := w.surfaceResource(); surf != nil && surf.Resource.Alive() { |
| 339 | x, y := w.surfacePoint(x, y) | 339 | x, y := w.surfacePoint(x, y) | ||
| 340 | return surf, s.windowPointers(w), x, y | 340 | return surf, s.windowPointers(w), x, y | ||
| 341 | } | 341 | } | ||
| @@ -543,10 +543,10 @@ func pointerFrame(p *wayland.Pointer) { | |||||
| 543 | } | 543 | } | ||
| 544 | } | 544 | } | ||
| 545 | func (s *Server) windowPointers(w *window) []*wayland.Pointer { | 545 | func (s *Server) windowPointers(w *window) []*wayland.Pointer { | ||
| 546 | - | if w == nil || !w.mapped || !w.xdg.resource.Resource.Alive() { | 546 | + | if w == nil || !w.mapped || !w.alive() { |
| 547 | return nil | 547 | return nil | ||
| 548 | } | 548 | } | ||
| 549 | - | return s.clientPointers(w.xdg.resource.Client()) | 549 | + | return s.clientPointers(w.client()) |
| 550 | } | 550 | } | ||
| 551 | 551 | ||||
| 552 | func (s *Server) layerPointers(l *layerSurface) []*wayland.Pointer { | 552 | func (s *Server) layerPointers(l *layerSurface) []*wayland.Pointer { | ||
M internal/adapters/wayland/server.go +13 -9
| @@ -215,8 +215,11 @@ type Server struct { | |||
| 215 | 215 | // foreignExports are the live xdg-foreign handles (foreign.go). | |
| 216 | 216 | foreignExports map[string]*foreignExport | |
| 217 | 217 | surfaces map[*server.Resource]*surface | |
| 218 | - | buffers map[*server.Resource]clientBuffer | |
| 219 | - | dmabuf *dmabufGlobal | |
| 218 | + | // surfaceByIdentity finds a surface by its identity (xwayland_shell_v1 | |
| 219 | + | // pairing); kept with surfaces. | |
| 220 | + | surfaceByIdentity map[uint64]*surface | |
| 221 | + | buffers map[*server.Resource]clientBuffer | |
| 222 | + | dmabuf *dmabufGlobal | |
| 220 | 223 | // hdrOutputs records confirmed DRM modesets; absent outputs are SDR. | |
| 221 | 224 | hdrOutputs map[string]ports.OutputHDR | |
| 222 | 225 | colorID uint64 | |
| @@ -367,6 +370,7 @@ func New(opts Options, ch Channels, log zerowrap.Logger) (*Server, error) { | |||
| 367 | 370 | logDamage: opts.LogDamage, | |
| 368 | 371 | channels: ch, | |
| 369 | 372 | surfaces: make(map[*server.Resource]*surface), | |
| 373 | + | surfaceByIdentity: make(map[uint64]*surface), | |
| 370 | 374 | buffers: make(map[*server.Resource]clientBuffer), | |
| 371 | 375 | windows: make(map[ports.WindowID]*window), | |
| 372 | 376 | layers: make(map[ports.WindowID]*layerSurface), | |
| @@ -778,7 +782,7 @@ func (s *Server) apply(cmd ports.ClientCommand) { | |||
| 778 | 782 | } | |
| 779 | 783 | case ports.ConfigureWindow: | |
| 780 | 784 | w := s.windows[c.ID] | |
| 781 | - | if w == nil || w.toplevel == nil || !w.toplevel.Resource.Alive() || !w.xdg.resource.Resource.Alive() { | |
| 785 | + | if w == nil || !w.toplevelAlive() || !w.alive() { | |
| 782 | 786 | s.log.Debug().Uint64("id", uint64(c.ID)).Msg("configure missing window") | |
| 783 | 787 | return | |
| 784 | 788 | } | |
| @@ -789,16 +793,16 @@ func (s *Server) apply(cmd ports.ClientCommand) { | |||
| 789 | 793 | scanoutChanged := !w.hasLast || w.last.Fullscreen != c.Fullscreen || w.last.Output != c.Output || w.last.Visible != c.Visible | |
| 790 | 794 | w.last, w.hasLast = c, true | |
| 791 | 795 | if visibilityChanged { | |
| 792 | - | s.relocateCallbacks(w.xdg.surface) | |
| 796 | + | s.relocateCallbacks(w.surf()) | |
| 793 | 797 | s.dropFeedbacks(time.Now()) | |
| 794 | 798 | s.wakePacer() // reconsider FIFO barriers at the new period | |
| 795 | 799 | } | |
| 796 | 800 | w.sendConfigure() | |
| 797 | 801 | s.toplevelChanged(w) | |
| 798 | - | if scanoutChanged && w.xdg.surface != nil { | |
| 799 | - | s.dmabuf.resendSurface(w.xdg.surface) | |
| 802 | + | if scanoutChanged && w.surf() != nil { | |
| 803 | + | s.dmabuf.resendSurface(w.surf()) | |
| 800 | 804 | } | |
| 801 | - | if surf := w.xdg.surface; surf != nil && c.Output != "" { | |
| 805 | + | if surf := w.surf(); surf != nil && c.Output != "" { | |
| 802 | 806 | surf.sendTreeScale() | |
| 803 | 807 | } | |
| 804 | 808 | if scanoutChanged { | |
| @@ -819,10 +823,10 @@ func (s *Server) apply(cmd ports.ClientCommand) { | |||
| 819 | 823 | s.setShortcutsInhibit(c) | |
| 820 | 824 | case ports.CloseWindow: | |
| 821 | 825 | w := s.windows[c.ID] | |
| 822 | - | if w == nil || w.toplevel == nil || !w.toplevel.Resource.Alive() { | |
| 826 | + | if w == nil || !w.toplevelAlive() { | |
| 823 | 827 | s.log.Debug().Uint64("id", uint64(c.ID)).Msg("close missing window") | |
| 824 | 828 | return | |
| 825 | 829 | } | |
| 826 | - | w.toplevel.SendClose() | |
| 830 | + | w.sendClose() | |
| 827 | 831 | } | |
| 828 | 832 | } | |
| @@ -215,8 +215,11 @@ type Server struct { | |||||
| 215 | // foreignExports are the live xdg-foreign handles (foreign.go). | 215 | // foreignExports are the live xdg-foreign handles (foreign.go). | ||
| 216 | foreignExports map[string]*foreignExport | 216 | foreignExports map[string]*foreignExport | ||
| 217 | surfaces map[*server.Resource]*surface | 217 | surfaces map[*server.Resource]*surface | ||
| 218 | - | buffers map[*server.Resource]clientBuffer | 218 | + | // surfaceByIdentity finds a surface by its identity (xwayland_shell_v1 |
| 219 | - | dmabuf *dmabufGlobal | 219 | + | // pairing); kept with surfaces. |
| 220 | + | surfaceByIdentity map[uint64]*surface | |||
| 221 | + | buffers map[*server.Resource]clientBuffer | |||
| 222 | + | dmabuf *dmabufGlobal | |||
| 220 | // hdrOutputs records confirmed DRM modesets; absent outputs are SDR. | 223 | // hdrOutputs records confirmed DRM modesets; absent outputs are SDR. | ||
| 221 | hdrOutputs map[string]ports.OutputHDR | 224 | hdrOutputs map[string]ports.OutputHDR | ||
| 222 | colorID uint64 | 225 | colorID uint64 | ||
| @@ -367,6 +370,7 @@ func New(opts Options, ch Channels, log zerowrap.Logger) (*Server, error) { | |||||
| 367 | logDamage: opts.LogDamage, | 370 | logDamage: opts.LogDamage, | ||
| 368 | channels: ch, | 371 | channels: ch, | ||
| 369 | surfaces: make(map[*server.Resource]*surface), | 372 | surfaces: make(map[*server.Resource]*surface), | ||
| 373 | + | surfaceByIdentity: make(map[uint64]*surface), | |||
| 370 | buffers: make(map[*server.Resource]clientBuffer), | 374 | buffers: make(map[*server.Resource]clientBuffer), | ||
| 371 | windows: make(map[ports.WindowID]*window), | 375 | windows: make(map[ports.WindowID]*window), | ||
| 372 | layers: make(map[ports.WindowID]*layerSurface), | 376 | layers: make(map[ports.WindowID]*layerSurface), | ||
| @@ -778,7 +782,7 @@ func (s *Server) apply(cmd ports.ClientCommand) { | |||||
| 778 | } | 782 | } | ||
| 779 | case ports.ConfigureWindow: | 783 | case ports.ConfigureWindow: | ||
| 780 | w := s.windows[c.ID] | 784 | w := s.windows[c.ID] | ||
| 781 | - | if w == nil || w.toplevel == nil || !w.toplevel.Resource.Alive() || !w.xdg.resource.Resource.Alive() { | 785 | + | if w == nil || !w.toplevelAlive() || !w.alive() { |
| 782 | s.log.Debug().Uint64("id", uint64(c.ID)).Msg("configure missing window") | 786 | s.log.Debug().Uint64("id", uint64(c.ID)).Msg("configure missing window") | ||
| 783 | return | 787 | return | ||
| 784 | } | 788 | } | ||
| @@ -789,16 +793,16 @@ func (s *Server) apply(cmd ports.ClientCommand) { | |||||
| 789 | scanoutChanged := !w.hasLast || w.last.Fullscreen != c.Fullscreen || w.last.Output != c.Output || w.last.Visible != c.Visible | 793 | scanoutChanged := !w.hasLast || w.last.Fullscreen != c.Fullscreen || w.last.Output != c.Output || w.last.Visible != c.Visible | ||
| 790 | w.last, w.hasLast = c, true | 794 | w.last, w.hasLast = c, true | ||
| 791 | if visibilityChanged { | 795 | if visibilityChanged { | ||
| 792 | - | s.relocateCallbacks(w.xdg.surface) | 796 | + | s.relocateCallbacks(w.surf()) |
| 793 | s.dropFeedbacks(time.Now()) | 797 | s.dropFeedbacks(time.Now()) | ||
| 794 | s.wakePacer() // reconsider FIFO barriers at the new period | 798 | s.wakePacer() // reconsider FIFO barriers at the new period | ||
| 795 | } | 799 | } | ||
| 796 | w.sendConfigure() | 800 | w.sendConfigure() | ||
| 797 | s.toplevelChanged(w) | 801 | s.toplevelChanged(w) | ||
| 798 | - | if scanoutChanged && w.xdg.surface != nil { | 802 | + | if scanoutChanged && w.surf() != nil { |
| 799 | - | s.dmabuf.resendSurface(w.xdg.surface) | 803 | + | s.dmabuf.resendSurface(w.surf()) |
| 800 | } | 804 | } | ||
| 801 | - | if surf := w.xdg.surface; surf != nil && c.Output != "" { | 805 | + | if surf := w.surf(); surf != nil && c.Output != "" { |
| 802 | surf.sendTreeScale() | 806 | surf.sendTreeScale() | ||
| 803 | } | 807 | } | ||
| 804 | if scanoutChanged { | 808 | if scanoutChanged { | ||
| @@ -819,10 +823,10 @@ func (s *Server) apply(cmd ports.ClientCommand) { | |||||
| 819 | s.setShortcutsInhibit(c) | 823 | s.setShortcutsInhibit(c) | ||
| 820 | case ports.CloseWindow: | 824 | case ports.CloseWindow: | ||
| 821 | w := s.windows[c.ID] | 825 | w := s.windows[c.ID] | ||
| 822 | - | if w == nil || w.toplevel == nil || !w.toplevel.Resource.Alive() { | 826 | + | if w == nil || !w.toplevelAlive() { |
| 823 | s.log.Debug().Uint64("id", uint64(c.ID)).Msg("close missing window") | 827 | s.log.Debug().Uint64("id", uint64(c.ID)).Msg("close missing window") | ||
| 824 | return | 828 | return | ||
| 825 | } | 829 | } | ||
| 826 | - | w.toplevel.SendClose() | 830 | + | w.sendClose() |
| 827 | } | 831 | } | ||
| 828 | } | 832 | } | ||
M internal/adapters/wayland/surface.go +4 -0
| @@ -28,6 +28,10 @@ const ( | |||
| 28 | 28 | roleSessionLock | |
| 29 | 29 | // roleDragIcon is the icon of a data drag (dnd.go). | |
| 30 | 30 | roleDragIcon | |
| 31 | + | // roleX11 is the surface of an X11 window paired through | |
| 32 | + | // xwayland_shell_v1. | |
| 33 | + | //lint:ignore U1000 used by the X11 window role (xwm) | |
| 34 | + | roleX11 | |
| 31 | 35 | ) | |
| 32 | 36 | ||
| 33 | 37 | type surface struct { | |
| @@ -28,6 +28,10 @@ const ( | |||||
| 28 | roleSessionLock | 28 | roleSessionLock | ||
| 29 | // roleDragIcon is the icon of a data drag (dnd.go). | 29 | // roleDragIcon is the icon of a data drag (dnd.go). | ||
| 30 | roleDragIcon | 30 | roleDragIcon | ||
| 31 | + | // roleX11 is the surface of an X11 window paired through | |||
| 32 | + | // xwayland_shell_v1. | |||
| 33 | + | //lint:ignore U1000 used by the X11 window role (xwm) | |||
| 34 | + | roleX11 | |||
| 31 | ) | 35 | ) | ||
| 32 | 36 | ||||
| 33 | type surface struct { | 37 | type surface struct { | ||
A internal/adapters/wayland/window.go +71 -0
| @@ -0,0 +1,71 @@ | |||
| 1 | + | package wayland | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "github.com/bnema/go-wayland-bindings/server/wayland" | |
| 5 | + | "github.com/bnema/neferwl/internal/ports" | |
| 6 | + | "github.com/bnema/purego-libwayland/server" | |
| 7 | + | ) | |
| 8 | + | ||
| 9 | + | // Role-independent accessors of a window. Code outside xdg.go goes through | |
| 10 | + | // them instead of dereferencing w.xdg, which is nil for windows of another | |
| 11 | + | // role. | |
| 12 | + | ||
| 13 | + | // isToplevel reports whether w is a toplevel (not a popup). | |
| 14 | + | func (w *window) isToplevel() bool { return w.toplevel != nil } | |
| 15 | + | ||
| 16 | + | // surf is the window's surface, nil when it has none. | |
| 17 | + | func (w *window) surf() *surface { | |
| 18 | + | if w.xdg != nil { | |
| 19 | + | return w.xdg.surface | |
| 20 | + | } | |
| 21 | + | return nil | |
| 22 | + | } | |
| 23 | + | ||
| 24 | + | // alive reports whether the window's role object is alive. | |
| 25 | + | func (w *window) alive() bool { | |
| 26 | + | return w.xdg != nil && w.xdg.resource.Resource.Alive() | |
| 27 | + | } | |
| 28 | + | ||
| 29 | + | // client is the window's client; the zero Client when it has no role object. | |
| 30 | + | func (w *window) client() server.Client { | |
| 31 | + | if w.xdg != nil { | |
| 32 | + | return w.xdg.resource.Client() | |
| 33 | + | } | |
| 34 | + | return server.Client{} | |
| 35 | + | } | |
| 36 | + | ||
| 37 | + | // geometry is the committed window geometry; empty means the whole surface. | |
| 38 | + | func (w *window) geometry() ports.Rect { | |
| 39 | + | if w.xdg != nil { | |
| 40 | + | return w.xdg.geometry | |
| 41 | + | } | |
| 42 | + | return ports.Rect{} | |
| 43 | + | } | |
| 44 | + | ||
| 45 | + | // sendConfigure sends w.last to the client. | |
| 46 | + | func (w *window) sendConfigure() { | |
| 47 | + | if w.xdg != nil { | |
| 48 | + | w.sendXDGConfigure() | |
| 49 | + | } | |
| 50 | + | } | |
| 51 | + | ||
| 52 | + | // sendClose asks the client to close the window. | |
| 53 | + | func (w *window) sendClose() { | |
| 54 | + | if w.toplevel != nil { | |
| 55 | + | w.toplevel.SendClose() | |
| 56 | + | } | |
| 57 | + | } | |
| 58 | + | ||
| 59 | + | // toplevelAlive reports whether the window is a toplevel whose protocol | |
| 60 | + | // object is alive. | |
| 61 | + | func (w *window) toplevelAlive() bool { | |
| 62 | + | return w.toplevel != nil && w.toplevel.Resource.Alive() | |
| 63 | + | } | |
| 64 | + | ||
| 65 | + | // surfaceResource is the window's wl_surface, nil when it has none or it died. | |
| 66 | + | func (w *window) surfaceResource() *wayland.Surface { | |
| 67 | + | if w.xdg != nil { | |
| 68 | + | return w.xdg.surfaceResource() | |
| 69 | + | } | |
| 70 | + | return nil | |
| 71 | + | } | |
| @@ -0,0 +1,71 @@ | |||||
| 1 | + | package wayland | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "github.com/bnema/go-wayland-bindings/server/wayland" | |||
| 5 | + | "github.com/bnema/neferwl/internal/ports" | |||
| 6 | + | "github.com/bnema/purego-libwayland/server" | |||
| 7 | + | ) | |||
| 8 | + | ||||
| 9 | + | // Role-independent accessors of a window. Code outside xdg.go goes through | |||
| 10 | + | // them instead of dereferencing w.xdg, which is nil for windows of another | |||
| 11 | + | // role. | |||
| 12 | + | ||||
| 13 | + | // isToplevel reports whether w is a toplevel (not a popup). | |||
| 14 | + | func (w *window) isToplevel() bool { return w.toplevel != nil } | |||
| 15 | + | ||||
| 16 | + | // surf is the window's surface, nil when it has none. | |||
| 17 | + | func (w *window) surf() *surface { | |||
| 18 | + | if w.xdg != nil { | |||
| 19 | + | return w.xdg.surface | |||
| 20 | + | } | |||
| 21 | + | return nil | |||
| 22 | + | } | |||
| 23 | + | ||||
| 24 | + | // alive reports whether the window's role object is alive. | |||
| 25 | + | func (w *window) alive() bool { | |||
| 26 | + | return w.xdg != nil && w.xdg.resource.Resource.Alive() | |||
| 27 | + | } | |||
| 28 | + | ||||
| 29 | + | // client is the window's client; the zero Client when it has no role object. | |||
| 30 | + | func (w *window) client() server.Client { | |||
| 31 | + | if w.xdg != nil { | |||
| 32 | + | return w.xdg.resource.Client() | |||
| 33 | + | } | |||
| 34 | + | return server.Client{} | |||
| 35 | + | } | |||
| 36 | + | ||||
| 37 | + | // geometry is the committed window geometry; empty means the whole surface. | |||
| 38 | + | func (w *window) geometry() ports.Rect { | |||
| 39 | + | if w.xdg != nil { | |||
| 40 | + | return w.xdg.geometry | |||
| 41 | + | } | |||
| 42 | + | return ports.Rect{} | |||
| 43 | + | } | |||
| 44 | + | ||||
| 45 | + | // sendConfigure sends w.last to the client. | |||
| 46 | + | func (w *window) sendConfigure() { | |||
| 47 | + | if w.xdg != nil { | |||
| 48 | + | w.sendXDGConfigure() | |||
| 49 | + | } | |||
| 50 | + | } | |||
| 51 | + | ||||
| 52 | + | // sendClose asks the client to close the window. | |||
| 53 | + | func (w *window) sendClose() { | |||
| 54 | + | if w.toplevel != nil { | |||
| 55 | + | w.toplevel.SendClose() | |||
| 56 | + | } | |||
| 57 | + | } | |||
| 58 | + | ||||
| 59 | + | // toplevelAlive reports whether the window is a toplevel whose protocol | |||
| 60 | + | // object is alive. | |||
| 61 | + | func (w *window) toplevelAlive() bool { | |||
| 62 | + | return w.toplevel != nil && w.toplevel.Resource.Alive() | |||
| 63 | + | } | |||
| 64 | + | ||||
| 65 | + | // surfaceResource is the window's wl_surface, nil when it has none or it died. | |||
| 66 | + | func (w *window) surfaceResource() *wayland.Surface { | |||
| 67 | + | if w.xdg != nil { | |||
| 68 | + | return w.xdg.surfaceResource() | |||
| 69 | + | } | |||
| 70 | + | return nil | |||
| 71 | + | } | |||
M internal/adapters/wayland/xdg.go +2 -2
| @@ -151,8 +151,8 @@ type window struct { | |||
| 151 | 151 | hasLast bool | |
| 152 | 152 | } | |
| 153 | 153 | ||
| 154 | - | // sendConfigure sends w.last as xdg_toplevel + xdg_surface configure. | |
| 155 | - | func (w *window) sendConfigure() { | |
| 154 | + | // sendXDGConfigure sends w.last as xdg_toplevel + xdg_surface configure. | |
| 155 | + | func (w *window) sendXDGConfigure() { | |
| 156 | 156 | c := w.last | |
| 157 | 157 | w.toplevel.SendConfigure(int32(c.Width), int32(c.Height), toplevelStates(c, w.toplevel.Version())) | |
| 158 | 158 | s := w.xdg.server | |
| @@ -151,8 +151,8 @@ type window struct { | |||||
| 151 | hasLast bool | 151 | hasLast bool | ||
| 152 | } | 152 | } | ||
| 153 | 153 | ||||
| 154 | - | // sendConfigure sends w.last as xdg_toplevel + xdg_surface configure. | 154 | + | // sendXDGConfigure sends w.last as xdg_toplevel + xdg_surface configure. |
| 155 | - | func (w *window) sendConfigure() { | 155 | + | func (w *window) sendXDGConfigure() { |
| 156 | c := w.last | 156 | c := w.last | ||
| 157 | w.toplevel.SendConfigure(int32(c.Width), int32(c.Height), toplevelStates(c, w.toplevel.Version())) | 157 | w.toplevel.SendConfigure(int32(c.Width), int32(c.Height), toplevelStates(c, w.toplevel.Version())) | ||
| 158 | s := w.xdg.server | 158 | s := w.xdg.server | ||