fix(surface): return nil from WLSurface after Close and document waiting on Bind handlers
- commit
- 14ed328fa8312517615170bee4e58531242ba528
- author
- brice · · 2026-10-02 04:15 UTC
- committer
- brice · · 2026-10-02 08:25 UTC
- parent
- 1b50de6
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +16 -4
M surface.go +13 -4
| @@ -163,10 +163,19 @@ func (f *frameCallback) Dispatch(ev *wl.Event) { | |||
| 163 | 163 | func (s *Surface) ID() SurfaceID { return s.id } | |
| 164 | 164 | ||
| 165 | 165 | // WLSurface returns the wl_surface proxy, for requests of protocol extensions | |
| 166 | - | // bound with [Conn.Bind] that take a surface argument. It is valid until | |
| 167 | - | // [Surface.Close]. The Surface owns it: do not destroy it, attach buffers or | |
| 168 | - | // commit it. Owner goroutine only. | |
| 169 | - | func (s *Surface) WLSurface() *wayland.Surface { return s.surf } | |
| 166 | + | // bound with [Conn.Bind] that take a surface argument, or nil after | |
| 167 | + | // [Surface.Close]. The Surface owns it: use it only as a request argument; do | |
| 168 | + | // not call its methods or add handlers. Owner goroutine only. | |
| 169 | + | // | |
| 170 | + | // Handlers of objects bound with [Conn.Bind] run on the reader goroutine. To | |
| 171 | + | // wait for their answer, keep calling [Conn.Dispatch] on [Conn.Wake]: the | |
| 172 | + | // reader stops reading while the event queue is full. | |
| 173 | + | func (s *Surface) WLSurface() *wayland.Surface { | |
| 174 | + | if s.closed { | |
| 175 | + | return nil | |
| 176 | + | } | |
| 177 | + | return s.surf | |
| 178 | + | } | |
| 170 | 179 | ||
| 171 | 180 | // Size returns the current logical size and scale (1 until announced). Before | |
| 172 | 181 | // the first configure the size is the requested one (zero for lock surfaces). | |
| @@ -163,10 +163,19 @@ func (f *frameCallback) Dispatch(ev *wl.Event) { | |||||
| 163 | func (s *Surface) ID() SurfaceID { return s.id } | 163 | func (s *Surface) ID() SurfaceID { return s.id } | ||
| 164 | 164 | ||||
| 165 | // WLSurface returns the wl_surface proxy, for requests of protocol extensions | 165 | // WLSurface returns the wl_surface proxy, for requests of protocol extensions | ||
| 166 | - | // bound with [Conn.Bind] that take a surface argument. It is valid until | 166 | + | // bound with [Conn.Bind] that take a surface argument, or nil after |
| 167 | - | // [Surface.Close]. The Surface owns it: do not destroy it, attach buffers or | 167 | + | // [Surface.Close]. The Surface owns it: use it only as a request argument; do |
| 168 | - | // commit it. Owner goroutine only. | 168 | + | // not call its methods or add handlers. Owner goroutine only. |
| 169 | - | func (s *Surface) WLSurface() *wayland.Surface { return s.surf } | 169 | + | // |
| 170 | + | // Handlers of objects bound with [Conn.Bind] run on the reader goroutine. To | |||
| 171 | + | // wait for their answer, keep calling [Conn.Dispatch] on [Conn.Wake]: the | |||
| 172 | + | // reader stops reading while the event queue is full. | |||
| 173 | + | func (s *Surface) WLSurface() *wayland.Surface { | |||
| 174 | + | if s.closed { | |||
| 175 | + | return nil | |||
| 176 | + | } | |||
| 177 | + | return s.surf | |||
| 178 | + | } | |||
| 170 | 179 | ||||
| 171 | // Size returns the current logical size and scale (1 until announced). Before | 180 | // Size returns the current logical size and scale (1 until announced). Before | ||
| 172 | // the first configure the size is the requested one (zero for lock surfaces). | 181 | // the first configure the size is the requested one (zero for lock surfaces). | ||
M surface_wire_test.go +3 -0
| @@ -136,6 +136,9 @@ func TestWLSurfaceIsTheSurfaceProxy(t *testing.T) { | |||
| 136 | 136 | require.NotNil(t, p) | |
| 137 | 137 | require.Equal(t, s.SurfaceObjectID(), p.ID()) | |
| 138 | 138 | require.Same(t, c.Context(), p.Context()) | |
| 139 | + | ||
| 140 | + | s.Close() | |
| 141 | + | require.Nil(t, s.WLSurface(), "a destroyed proxy's id can be reused") | |
| 139 | 142 | } | |
| 140 | 143 | ||
| 141 | 144 | // GO-007: one lock surface per output. | |
| @@ -136,6 +136,9 @@ func TestWLSurfaceIsTheSurfaceProxy(t *testing.T) { | |||||
| 136 | require.NotNil(t, p) | 136 | require.NotNil(t, p) | ||
| 137 | require.Equal(t, s.SurfaceObjectID(), p.ID()) | 137 | require.Equal(t, s.SurfaceObjectID(), p.ID()) | ||
| 138 | require.Same(t, c.Context(), p.Context()) | 138 | require.Same(t, c.Context(), p.Context()) | ||
| 139 | + | ||||
| 140 | + | s.Close() | |||
| 141 | + | require.Nil(t, s.WLSurface(), "a destroyed proxy's id can be reused") | |||
| 139 | } | 142 | } | ||
| 140 | 143 | ||||
| 141 | // GO-007: one lock surface per output. | 144 | // GO-007: one lock surface per output. | ||