refactor(wayland): use go-wayland-bindings for protocol bindings (#1)
Replaces the hand-written Wayland bindings with go-wayland-bindings. Reviewed-on: https://git.bnema.dev/bnema/nefercap/pulls/1
- commit
- 298ec90558ea8441d81bfeaf6842027dc479e51d
- author
- brice · · 2026-10-02 10:30 UTC
- committer
- bnema · · 2026-10-02 10:30 UTC
- parent
- 7e79979
- signature
- unsigned
8 files · +30 -15
M go.mod +1 -0
| @@ -3,6 +3,7 @@ module github.com/bnema/nefercap | |||
| 3 | 3 | go 1.27 | |
| 4 | 4 | ||
| 5 | 5 | require ( | |
| 6 | + | github.com/bnema/go-wayland-bindings v0.1.0 | |
| 6 | 7 | github.com/bnema/nefergui v0.3.0 | |
| 7 | 8 | github.com/bnema/purego-libwayland v0.8.0 | |
| 8 | 9 | github.com/bnema/wlturbo v0.5.0 | |
| @@ -3,6 +3,7 @@ module github.com/bnema/nefercap | |||||
| 3 | go 1.27 | 3 | go 1.27 | ||
| 4 | 4 | ||||
| 5 | require ( | 5 | require ( | ||
| 6 | + | github.com/bnema/go-wayland-bindings v0.1.0 | |||
| 6 | github.com/bnema/nefergui v0.3.0 | 7 | github.com/bnema/nefergui v0.3.0 | ||
| 7 | github.com/bnema/purego-libwayland v0.8.0 | 8 | github.com/bnema/purego-libwayland v0.8.0 | ||
| 8 | github.com/bnema/wlturbo v0.5.0 | 9 | github.com/bnema/wlturbo v0.5.0 | ||
M go.sum +2 -0 generated file: collapsed
M internal/adapters/wayland/copycapture.go +2 -2
| @@ -5,8 +5,8 @@ import ( | |||
| 5 | 5 | "fmt" | |
| 6 | 6 | "time" | |
| 7 | 7 | ||
| 8 | - | "github.com/bnema/wlturbo/protocol/imagecapturesource" | |
| 9 | - | "github.com/bnema/wlturbo/protocol/imagecopycapture" | |
| 8 | + | imagecapturesource "github.com/bnema/go-wayland-bindings/client/extimagecapturesource" | |
| 9 | + | imagecopycapture "github.com/bnema/go-wayland-bindings/client/extimagecopycapture" | |
| 10 | 10 | ||
| 11 | 11 | "github.com/bnema/nefercap/internal/ports" | |
| 12 | 12 | ) | |
| @@ -5,8 +5,8 @@ import ( | |||||
| 5 | "fmt" | 5 | "fmt" | ||
| 6 | "time" | 6 | "time" | ||
| 7 | 7 | ||||
| 8 | - | "github.com/bnema/wlturbo/protocol/imagecapturesource" | 8 | + | imagecapturesource "github.com/bnema/go-wayland-bindings/client/extimagecapturesource" |
| 9 | - | "github.com/bnema/wlturbo/protocol/imagecopycapture" | 9 | + | imagecopycapture "github.com/bnema/go-wayland-bindings/client/extimagecopycapture" |
| 10 | 10 | ||||
| 11 | "github.com/bnema/nefercap/internal/ports" | 11 | "github.com/bnema/nefercap/internal/ports" | ||
| 12 | ) | 12 | ) | ||
M internal/adapters/wayland/extensions.go +15 -6
| @@ -4,13 +4,13 @@ import ( | |||
| 4 | 4 | "context" | |
| 5 | 5 | "errors" | |
| 6 | 6 | "fmt" | |
| 7 | + | "reflect" | |
| 7 | 8 | "sync" | |
| 8 | 9 | "time" | |
| 9 | 10 | ||
| 11 | + | imagecapturesource "github.com/bnema/go-wayland-bindings/client/extimagecapturesource" | |
| 12 | + | "github.com/bnema/go-wayland-bindings/client/xdgoutput" | |
| 10 | 13 | "github.com/bnema/wlturbo" | |
| 11 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 12 | - | "github.com/bnema/wlturbo/protocol/imagecapturesource" | |
| 13 | - | "github.com/bnema/wlturbo/protocol/xdgoutput" | |
| 14 | 14 | ||
| 15 | 15 | "github.com/bnema/nefercap/internal/ports" | |
| 16 | 16 | ) | |
| @@ -490,12 +490,15 @@ func (l *layerProxy) hand() (state layerState, reason uint32, violation bool) { | |||
| 490 | 490 | // thread-safe, non-blocking work such as cancelling a context. It never sees | |
| 491 | 491 | // the token. The attachment object is never destroyed after a success: that | |
| 492 | 492 | // would not release the exclusion, and closing the connection ends it. | |
| 493 | - | func AuthorizeLayer(ctx context.Context, display *wlturbo.Display, surface *core.Surface, token string, onDetached func(error)) error { | |
| 493 | + | // | |
| 494 | + | // surface is the layer's wl_surface proxy, whichever bindings created it; it | |
| 495 | + | // must belong to display, and nothing else may dispatch display meanwhile. | |
| 496 | + | func AuthorizeLayer(ctx context.Context, display *wlturbo.Display, surface wlturbo.Proxy, token string, onDetached func(error)) error { | |
| 494 | 497 | return authorizeLayer(ctx, display, surface, token, onDetached, DefaultAttachTimeout) | |
| 495 | 498 | } | |
| 496 | 499 | ||
| 497 | - | func authorizeLayer(ctx context.Context, display *wlturbo.Display, surface *core.Surface, token string, onDetached func(error), timeout time.Duration) error { | |
| 498 | - | if display == nil || surface == nil || surface.Context() != display.Context() { | |
| 500 | + | func authorizeLayer(ctx context.Context, display *wlturbo.Display, surface wlturbo.Proxy, token string, onDetached func(error), timeout time.Duration) error { | |
| 501 | + | if display == nil || surface == nil || nilPointer(surface) || surface.Context() != display.Context() { | |
| 499 | 502 | return errors.New("wayland: authorize layer: surface does not belong to display") | |
| 500 | 503 | } | |
| 501 | 504 | if !validToken(token) { | |
| @@ -552,6 +555,12 @@ func authorizeLayer(ctx context.Context, display *wlturbo.Display, surface *core | |||
| 552 | 555 | return nil | |
| 553 | 556 | } | |
| 554 | 557 | ||
| 558 | + | // nilPointer reports a typed nil proxy, which is a non-nil interface. | |
| 559 | + | func nilPointer(p wlturbo.Proxy) bool { | |
| 560 | + | v := reflect.ValueOf(p) | |
| 561 | + | return v.Kind() == reflect.Pointer && v.IsNil() | |
| 562 | + | } | |
| 563 | + | ||
| 555 | 564 | // validToken accepts exactly the compositor's token format. | |
| 556 | 565 | func validToken(token string) bool { | |
| 557 | 566 | if len(token) != tokenLen { | |
| @@ -4,13 +4,13 @@ import ( | |||||
| 4 | "context" | 4 | "context" | ||
| 5 | "errors" | 5 | "errors" | ||
| 6 | "fmt" | 6 | "fmt" | ||
| 7 | + | "reflect" | |||
| 7 | "sync" | 8 | "sync" | ||
| 8 | "time" | 9 | "time" | ||
| 9 | 10 | ||||
| 11 | + | imagecapturesource "github.com/bnema/go-wayland-bindings/client/extimagecapturesource" | |||
| 12 | + | "github.com/bnema/go-wayland-bindings/client/xdgoutput" | |||
| 10 | "github.com/bnema/wlturbo" | 13 | "github.com/bnema/wlturbo" | ||
| 11 | - | "github.com/bnema/wlturbo/protocol/core" | |||
| 12 | - | "github.com/bnema/wlturbo/protocol/imagecapturesource" | |||
| 13 | - | "github.com/bnema/wlturbo/protocol/xdgoutput" | |||
| 14 | 14 | ||||
| 15 | "github.com/bnema/nefercap/internal/ports" | 15 | "github.com/bnema/nefercap/internal/ports" | ||
| 16 | ) | 16 | ) | ||
| @@ -490,12 +490,15 @@ func (l *layerProxy) hand() (state layerState, reason uint32, violation bool) { | |||||
| 490 | // thread-safe, non-blocking work such as cancelling a context. It never sees | 490 | // thread-safe, non-blocking work such as cancelling a context. It never sees | ||
| 491 | // the token. The attachment object is never destroyed after a success: that | 491 | // the token. The attachment object is never destroyed after a success: that | ||
| 492 | // would not release the exclusion, and closing the connection ends it. | 492 | // would not release the exclusion, and closing the connection ends it. | ||
| 493 | - | func AuthorizeLayer(ctx context.Context, display *wlturbo.Display, surface *core.Surface, token string, onDetached func(error)) error { | 493 | + | // |
| 494 | + | // surface is the layer's wl_surface proxy, whichever bindings created it; it | |||
| 495 | + | // must belong to display, and nothing else may dispatch display meanwhile. | |||
| 496 | + | func AuthorizeLayer(ctx context.Context, display *wlturbo.Display, surface wlturbo.Proxy, token string, onDetached func(error)) error { | |||
| 494 | return authorizeLayer(ctx, display, surface, token, onDetached, DefaultAttachTimeout) | 497 | return authorizeLayer(ctx, display, surface, token, onDetached, DefaultAttachTimeout) | ||
| 495 | } | 498 | } | ||
| 496 | 499 | ||||
| 497 | - | func authorizeLayer(ctx context.Context, display *wlturbo.Display, surface *core.Surface, token string, onDetached func(error), timeout time.Duration) error { | 500 | + | func authorizeLayer(ctx context.Context, display *wlturbo.Display, surface wlturbo.Proxy, token string, onDetached func(error), timeout time.Duration) error { |
| 498 | - | if display == nil || surface == nil || surface.Context() != display.Context() { | 501 | + | if display == nil || surface == nil || nilPointer(surface) || surface.Context() != display.Context() { |
| 499 | return errors.New("wayland: authorize layer: surface does not belong to display") | 502 | return errors.New("wayland: authorize layer: surface does not belong to display") | ||
| 500 | } | 503 | } | ||
| 501 | if !validToken(token) { | 504 | if !validToken(token) { | ||
| @@ -552,6 +555,12 @@ func authorizeLayer(ctx context.Context, display *wlturbo.Display, surface *core | |||||
| 552 | return nil | 555 | return nil | ||
| 553 | } | 556 | } | ||
| 554 | 557 | ||||
| 558 | + | // nilPointer reports a typed nil proxy, which is a non-nil interface. | |||
| 559 | + | func nilPointer(p wlturbo.Proxy) bool { | |||
| 560 | + | v := reflect.ValueOf(p) | |||
| 561 | + | return v.Kind() == reflect.Pointer && v.IsNil() | |||
| 562 | + | } | |||
| 563 | + | ||||
| 555 | // validToken accepts exactly the compositor's token format. | 564 | // validToken accepts exactly the compositor's token format. | ||
| 556 | func validToken(token string) bool { | 565 | func validToken(token string) bool { | ||
| 557 | if len(token) != tokenLen { | 566 | if len(token) != tokenLen { | ||
M internal/adapters/wayland/extensions_test.go +4 -1
| @@ -9,8 +9,8 @@ import ( | |||
| 9 | 9 | "testing" | |
| 10 | 10 | "time" | |
| 11 | 11 | ||
| 12 | + | core "github.com/bnema/go-wayland-bindings/client/wayland" | |
| 12 | 13 | "github.com/bnema/wlturbo" | |
| 13 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 14 | 14 | "github.com/stretchr/testify/require" | |
| 15 | 15 | ||
| 16 | 16 | "github.com/bnema/nefercap/internal/adapters/wayland/testserver" | |
| @@ -225,6 +225,9 @@ func TestAuthorizeLayerRejectsBadInput(t *testing.T) { | |||
| 225 | 225 | require.Error(t, AuthorizeLayer(context.Background(), nil, nil, testserver.Token, nil)) | |
| 226 | 226 | _, srv := newSource(t, extConfig()) | |
| 227 | 227 | display, surface := hudConnection(t, srv) | |
| 228 | + | require.Error(t, AuthorizeLayer(context.Background(), display, (*core.Surface)(nil), testserver.Token, nil), "typed nil surface") | |
| 229 | + | _, other := hudConnection(t, srv) | |
| 230 | + | require.Error(t, AuthorizeLayer(context.Background(), display, other, testserver.Token, nil), "surface of another connection") | |
| 228 | 231 | for _, tok := range []string{"", "has space", testserver.Token[:63], testserver.Token + "0", testserver.Token[:63] + "G", testserver.Token[:63] + "A"} { | |
| 229 | 232 | require.Error(t, AuthorizeLayer(context.Background(), display, surface, tok, nil), "%q", tok) | |
| 230 | 233 | } | |
| @@ -9,8 +9,8 @@ import ( | |||||
| 9 | "testing" | 9 | "testing" | ||
| 10 | "time" | 10 | "time" | ||
| 11 | 11 | ||||
| 12 | + | core "github.com/bnema/go-wayland-bindings/client/wayland" | |||
| 12 | "github.com/bnema/wlturbo" | 13 | "github.com/bnema/wlturbo" | ||
| 13 | - | "github.com/bnema/wlturbo/protocol/core" | |||
| 14 | "github.com/stretchr/testify/require" | 14 | "github.com/stretchr/testify/require" | ||
| 15 | 15 | ||||
| 16 | "github.com/bnema/nefercap/internal/adapters/wayland/testserver" | 16 | "github.com/bnema/nefercap/internal/adapters/wayland/testserver" | ||
| @@ -225,6 +225,9 @@ func TestAuthorizeLayerRejectsBadInput(t *testing.T) { | |||||
| 225 | require.Error(t, AuthorizeLayer(context.Background(), nil, nil, testserver.Token, nil)) | 225 | require.Error(t, AuthorizeLayer(context.Background(), nil, nil, testserver.Token, nil)) | ||
| 226 | _, srv := newSource(t, extConfig()) | 226 | _, srv := newSource(t, extConfig()) | ||
| 227 | display, surface := hudConnection(t, srv) | 227 | display, surface := hudConnection(t, srv) | ||
| 228 | + | require.Error(t, AuthorizeLayer(context.Background(), display, (*core.Surface)(nil), testserver.Token, nil), "typed nil surface") | |||
| 229 | + | _, other := hudConnection(t, srv) | |||
| 230 | + | require.Error(t, AuthorizeLayer(context.Background(), display, other, testserver.Token, nil), "surface of another connection") | |||
| 228 | for _, tok := range []string{"", "has space", testserver.Token[:63], testserver.Token + "0", testserver.Token[:63] + "G", testserver.Token[:63] + "A"} { | 231 | for _, tok := range []string{"", "has space", testserver.Token[:63], testserver.Token + "0", testserver.Token[:63] + "G", testserver.Token[:63] + "A"} { | ||
| 229 | require.Error(t, AuthorizeLayer(context.Background(), display, surface, tok, nil), "%q", tok) | 232 | require.Error(t, AuthorizeLayer(context.Background(), display, surface, tok, nil), "%q", tok) | ||
| 230 | } | 233 | } | ||
M internal/adapters/wayland/shm.go +1 -1
| @@ -4,8 +4,8 @@ import ( | |||
| 4 | 4 | "errors" | |
| 5 | 5 | "fmt" | |
| 6 | 6 | ||
| 7 | + | core "github.com/bnema/go-wayland-bindings/client/wayland" | |
| 7 | 8 | "github.com/bnema/wlturbo" | |
| 8 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 9 | 9 | "golang.org/x/sys/unix" | |
| 10 | 10 | ||
| 11 | 11 | "github.com/bnema/nefercap/internal/ports" | |
| @@ -4,8 +4,8 @@ import ( | |||||
| 4 | "errors" | 4 | "errors" | ||
| 5 | "fmt" | 5 | "fmt" | ||
| 6 | 6 | ||||
| 7 | + | core "github.com/bnema/go-wayland-bindings/client/wayland" | |||
| 7 | "github.com/bnema/wlturbo" | 8 | "github.com/bnema/wlturbo" | ||
| 8 | - | "github.com/bnema/wlturbo/protocol/core" | |||
| 9 | "golang.org/x/sys/unix" | 9 | "golang.org/x/sys/unix" | ||
| 10 | 10 | ||||
| 11 | "github.com/bnema/nefercap/internal/ports" | 11 | "github.com/bnema/nefercap/internal/ports" | ||
M internal/adapters/wayland/source.go +4 -4
| @@ -18,11 +18,11 @@ import ( | |||
| 18 | 18 | "sync/atomic" | |
| 19 | 19 | "time" | |
| 20 | 20 | ||
| 21 | + | imagecapturesource "github.com/bnema/go-wayland-bindings/client/extimagecapturesource" | |
| 22 | + | imagecopycapture "github.com/bnema/go-wayland-bindings/client/extimagecopycapture" | |
| 23 | + | core "github.com/bnema/go-wayland-bindings/client/wayland" | |
| 24 | + | "github.com/bnema/go-wayland-bindings/client/xdgoutput" | |
| 21 | 25 | "github.com/bnema/wlturbo" | |
| 22 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 23 | - | "github.com/bnema/wlturbo/protocol/imagecapturesource" | |
| 24 | - | "github.com/bnema/wlturbo/protocol/imagecopycapture" | |
| 25 | - | "github.com/bnema/wlturbo/protocol/xdgoutput" | |
| 26 | 26 | "github.com/bnema/zerowrap" | |
| 27 | 27 | ||
| 28 | 28 | "github.com/bnema/nefercap/internal/logging" | |
| @@ -18,11 +18,11 @@ import ( | |||||
| 18 | "sync/atomic" | 18 | "sync/atomic" | ||
| 19 | "time" | 19 | "time" | ||
| 20 | 20 | ||||
| 21 | + | imagecapturesource "github.com/bnema/go-wayland-bindings/client/extimagecapturesource" | |||
| 22 | + | imagecopycapture "github.com/bnema/go-wayland-bindings/client/extimagecopycapture" | |||
| 23 | + | core "github.com/bnema/go-wayland-bindings/client/wayland" | |||
| 24 | + | "github.com/bnema/go-wayland-bindings/client/xdgoutput" | |||
| 21 | "github.com/bnema/wlturbo" | 25 | "github.com/bnema/wlturbo" | ||
| 22 | - | "github.com/bnema/wlturbo/protocol/core" | |||
| 23 | - | "github.com/bnema/wlturbo/protocol/imagecapturesource" | |||
| 24 | - | "github.com/bnema/wlturbo/protocol/imagecopycapture" | |||
| 25 | - | "github.com/bnema/wlturbo/protocol/xdgoutput" | |||
| 26 | "github.com/bnema/zerowrap" | 26 | "github.com/bnema/zerowrap" | ||
| 27 | 27 | ||||
| 28 | "github.com/bnema/nefercap/internal/logging" | 28 | "github.com/bnema/nefercap/internal/logging" | ||
M internal/adapters/wayland/workspaces.go +1 -1
| @@ -8,7 +8,7 @@ import ( | |||
| 8 | 8 | "unicode" | |
| 9 | 9 | "unicode/utf8" | |
| 10 | 10 | ||
| 11 | - | extworkspace "github.com/bnema/wlturbo/protocol/workspace" | |
| 11 | + | "github.com/bnema/go-wayland-bindings/client/extworkspace" | |
| 12 | 12 | ||
| 13 | 13 | "github.com/bnema/nefercap/internal/ports" | |
| 14 | 14 | ) | |
| @@ -8,7 +8,7 @@ import ( | |||||
| 8 | "unicode" | 8 | "unicode" | ||
| 9 | "unicode/utf8" | 9 | "unicode/utf8" | ||
| 10 | 10 | ||||
| 11 | - | extworkspace "github.com/bnema/wlturbo/protocol/workspace" | 11 | + | "github.com/bnema/go-wayland-bindings/client/extworkspace" |
| 12 | 12 | ||||
| 13 | "github.com/bnema/nefercap/internal/ports" | 13 | "github.com/bnema/nefercap/internal/ports" | ||
| 14 | ) | 14 | ) | ||