Not all wayland compositors advertise the global registry events
in the same order. In particular, river and sway differ in that
sway advertises the data_device_manager before the seat, and river
does it after. This commit updates our code to correctly bind
the data_device so that we can work with the clipboard regardless
of the registry event order.
Special thanks to Isaac Freund (river maintainer) for helping me
find the root of this problem. You can see Isaac's extremely helpful
and detailed analysis here:
https://github.com/riverwm/river/issues/554#issuecomment-1059750874
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
---
app/os_wayland.go | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/app/os_wayland.go b/app/os_wayland.go
index 6fe5bb1e..ea2a4332 100644
--- a/app/os_wayland.go
+++ b/app/os_wayland.go
@@ -628,15 +628,7 @@ func gio_onRegistryGlobal(data unsafe.Pointer, reg *C.struct_wl_registry, name C
}
callbackStore(unsafe.Pointer(s), d.seat)
C.wl_seat_add_listener(s, &C.gio_seat_listener, unsafe.Pointer(s))
- if d.dataDeviceManager == nil {
- break
- }
- d.seat.dataDev = C.wl_data_device_manager_get_data_device(d.dataDeviceManager, s)
- if d.seat.dataDev == nil {
- break
- }
- callbackStore(unsafe.Pointer(d.seat.dataDev), d.seat)
- C.wl_data_device_add_listener(d.seat.dataDev, &C.gio_data_device_listener, unsafe.Pointer(d.seat.dataDev))
+ d.bindDataDevice()
case "wl_shm":
d.shm = (*C.struct_wl_shm)(C.wl_registry_bind(reg, name, &C.wl_shm_interface, 1))
case "xdg_wm_base":
@@ -648,6 +640,7 @@ func gio_onRegistryGlobal(data unsafe.Pointer, reg *C.struct_wl_registry, name C
d.imm = (*C.struct_zwp_text_input_manager_v3)(C.wl_registry_bind(reg, name, &C.zwp_text_input_manager_v3_interface, 1))*/
case "wl_data_device_manager":
d.dataDeviceManager = (*C.struct_wl_data_device_manager)(C.wl_registry_bind(reg, name, &C.wl_data_device_manager_interface, 3))
+ d.bindDataDevice()
}
}
@@ -1303,6 +1296,19 @@ func (w *window) loop() error {
return nil
}
+// bindDataDevice initializes the dataDev field if and only if both
+// the seat and dataDeviceManager fields are initialized.
+func (d *wlDisplay) bindDataDevice() {
+ if d.seat != nil && d.dataDeviceManager != nil {
+ d.seat.dataDev = C.wl_data_device_manager_get_data_device(d.dataDeviceManager, d.seat.seat)
+ if d.seat.dataDev == nil {
+ return
+ }
+ callbackStore(unsafe.Pointer(d.seat.dataDev), d.seat)
+ C.wl_data_device_add_listener(d.seat.dataDev, &C.gio_data_device_listener, unsafe.Pointer(d.seat.dataDev))
+ }
+}
+
func (d *wlDisplay) dispatch(p *poller) error {
dispfd := C.wl_display_get_fd(d.disp)
// Poll for events and notifications.
--
2.36.1