Merge pull request 'feat(surface): expose the wl_surface proxy for extension requests' (#1) from feat/surface-wl-proxy into main
Reviewed-on: https://git.bnema.dev/bnema/neferclient/pulls/1
2 files · +30 -0
M surface.go +15 -0
| @@ -162,6 +162,21 @@ func (f *frameCallback) Dispatch(ev *wl.Event) { | |||
| 162 | 162 | // ID returns the surface's identifier used in Handler callbacks. | |
| 163 | 163 | func (s *Surface) ID() SurfaceID { return s.id } | |
| 164 | 164 | ||
| 165 | + | // WLSurface returns the wl_surface proxy, for requests of protocol extensions | |
| 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 | + | } | |
| 179 | + | ||
| 165 | 180 | // Size returns the current logical size and scale (1 until announced). Before | |
| 166 | 181 | // the first configure the size is the requested one (zero for lock surfaces). | |
| 167 | 182 | func (s *Surface) Size() (w, h int32, scale float64) { return s.width, s.height, s.scale } | |
| @@ -162,6 +162,21 @@ func (f *frameCallback) Dispatch(ev *wl.Event) { | |||||
| 162 | // ID returns the surface's identifier used in Handler callbacks. | 162 | // ID returns the surface's identifier used in Handler callbacks. | ||
| 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 | |||
| 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 | + | } | |||
| 179 | + | ||||
| 165 | // 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 | ||
| 166 | // 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). | ||
| 167 | func (s *Surface) Size() (w, h int32, scale float64) { return s.width, s.height, s.scale } | 182 | func (s *Surface) Size() (w, h int32, scale float64) { return s.width, s.height, s.scale } | ||
M surface_wire_test.go +15 -0
| @@ -126,6 +126,21 @@ func TestSetInputRegionCommitsOnlyOnceMapped(t *testing.T) { | |||
| 126 | 126 | require.Error(t, ls.SetInputRegion(nil), "lock surfaces take all input") | |
| 127 | 127 | } | |
| 128 | 128 | ||
| 129 | + | // WLSurface is the surface's own wl_surface, on the connection's context, so | |
| 130 | + | // an extension bound with Conn.Bind can pass it as a request argument. | |
| 131 | + | func TestWLSurfaceIsTheSurfaceProxy(t *testing.T) { | |
| 132 | + | c, _ := connectWire(t, surfaceGlobals, surfaceOutputs) | |
| 133 | + | s, err := c.NewToplevel("wl", 64, 48) | |
| 134 | + | require.NoError(t, err) | |
| 135 | + | p := s.WLSurface() | |
| 136 | + | require.NotNil(t, p) | |
| 137 | + | require.Equal(t, s.SurfaceObjectID(), p.ID()) | |
| 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") | |
| 142 | + | } | |
| 143 | + | ||
| 129 | 144 | // GO-007: one lock surface per output. | |
| 130 | 145 | func TestLockRefusesSecondSurfacePerOutput(t *testing.T) { | |
| 131 | 146 | c, _ := connectWire(t, surfaceGlobals, surfaceOutputs) | |
| @@ -126,6 +126,21 @@ func TestSetInputRegionCommitsOnlyOnceMapped(t *testing.T) { | |||||
| 126 | require.Error(t, ls.SetInputRegion(nil), "lock surfaces take all input") | 126 | require.Error(t, ls.SetInputRegion(nil), "lock surfaces take all input") | ||
| 127 | } | 127 | } | ||
| 128 | 128 | ||||
| 129 | + | // WLSurface is the surface's own wl_surface, on the connection's context, so | |||
| 130 | + | // an extension bound with Conn.Bind can pass it as a request argument. | |||
| 131 | + | func TestWLSurfaceIsTheSurfaceProxy(t *testing.T) { | |||
| 132 | + | c, _ := connectWire(t, surfaceGlobals, surfaceOutputs) | |||
| 133 | + | s, err := c.NewToplevel("wl", 64, 48) | |||
| 134 | + | require.NoError(t, err) | |||
| 135 | + | p := s.WLSurface() | |||
| 136 | + | require.NotNil(t, p) | |||
| 137 | + | require.Equal(t, s.SurfaceObjectID(), p.ID()) | |||
| 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") | |||
| 142 | + | } | |||
| 143 | + | ||||
| 129 | // GO-007: one lock surface per output. | 144 | // GO-007: one lock surface per output. | ||
| 130 | func TestLockRefusesSecondSurfacePerOutput(t *testing.T) { | 145 | func TestLockRefusesSecondSurfacePerOutput(t *testing.T) { | ||
| 131 | c, _ := connectWire(t, surfaceGlobals, surfaceOutputs) | 146 | c, _ := connectWire(t, surfaceGlobals, surfaceOutputs) | ||