package clipboard import ( "fmt" "github.com/AvengeMedia/DankMaterialShell/core/internal/proto/ext_data_control" "github.com/AvengeMedia/DankMaterialShell/core/internal/proto/virtual_keyboard" wlclient "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client" ) type session struct { display *wlclient.Display ctx *wlclient.Context registry *wlclient.Registry seat *wlclient.Seat dataControlMgr *ext_data_control.ExtDataControlManagerV1 virtualKeyboardMgr *virtual_keyboard.ZwpVirtualKeyboardManagerV1 } // connectSession opens a short-lived Wayland connection and binds the seat // plus whichever clipboard-related globals the compositor advertises. func connectSession() (*session, error) { display, err := wlclient.Connect("") if err != nil { return nil, fmt.Errorf("wayland connect: %w", err) } s := &session{display: display, ctx: display.Context()} registry, err := display.GetRegistry() if err != nil { display.Destroy() return nil, fmt.Errorf("get registry: %w", err) } s.registry = registry var bindErr error bind := func(name uint32, iface string, version uint32, proxy wlclient.Proxy) { if err := registry.Bind(name, iface, version, proxy); err != nil { bindErr = fmt.Errorf("bind %s: %w", iface, err) } } registry.SetGlobalHandler(func(e wlclient.RegistryGlobalEvent) { switch e.Interface { case ext_data_control.ExtDataControlManagerV1InterfaceName: mgr := ext_data_control.NewExtDataControlManagerV1(s.ctx) bind(e.Name, e.Interface, e.Version, mgr) s.dataControlMgr = mgr case virtual_keyboard.ZwpVirtualKeyboardManagerV1InterfaceName: mgr := virtual_keyboard.NewZwpVirtualKeyboardManagerV1(s.ctx) bind(e.Name, e.Interface, e.Version, mgr) s.virtualKeyboardMgr = mgr case "wl_seat": if s.seat != nil { return } seat := wlclient.NewSeat(s.ctx) bind(e.Name, e.Interface, e.Version, seat) s.seat = seat } }) display.Roundtrip() display.Roundtrip() if bindErr != nil { s.Close() return nil, bindErr } return s, nil } func (s *session) requireDataControl() (*ext_data_control.ExtDataControlManagerV1, error) { switch { case s.dataControlMgr == nil: return nil, fmt.Errorf("compositor does not support ext_data_control_manager_v1") case s.seat == nil: return nil, fmt.Errorf("no seat available") default: return s.dataControlMgr, nil } } func (s *session) Close() { if s.dataControlMgr != nil { s.dataControlMgr.Destroy() } if s.registry != nil { s.registry.Destroy() } s.display.Destroy() }