Wayland 中为何收不到 wl_data_device 的 data_offer 事件?
数据小陈
结论
日志显示,wl_data_device_manager 和 wl_seat 已绑定,客户端也已发送 get_data_device 请求。问题更可能出在客户端没有创建获得键盘焦点的 wl_surface。Wayland 核心剪贴板选择通常与键盘焦点关联,因此仅创建数据设备并注册 listener,不能保证后台客户端收到剪贴板通知。具体行为还取决于合成器及其策略。
日志说明了什么
服务端发送了 wl_seat.name("Hyprland") 和 wl_seat.capabilities(3),但客户端没有为 wl_seat 注册 listener,因此这两项事件被丢弃。它们不同于 data_offer,也不能证明剪贴板选择已传递给客户端。
日志中也没有服务端发送的 wl_data_device.data_offer 或 wl_data_device.selection 事件。data_offer 用于通知客户端有剪贴板或拖放数据提供对象;注册回调本身不会触发该事件。处理剪贴板时还应关注 selection 回调,并在收到新 offer 时处理其 MIME 类型。
建议的排查步骤
- 创建并映射一个
wl_surface,使其获得键盘焦点。当前程序没有创建 surface,因此无法依靠核心wl_data_device接口在后台读取剪贴板。 - 等该 surface 获得焦点后,从另一个客户端设置或更新剪贴板内容,再观察
data_offer和selection回调。回调是否触发取决于当前选择状态和合成器行为。注册 listener 成功并不保证能收到初始剪贴板内容。 - 如果需要在没有焦点时监听剪贴板,检查合成器是否支持相应的数据控制协议。日志列出了
zwlr_data_control_manager_v1和ext_data_control_manager_v1,但这不表示核心wl_data_device支持后台访问。客户端需要实现所选扩展协议,并遵循合成器的访问策略。 - 为区分“没有事件”和“输出没有刷新”,让
fprintf(stderr, ...)与fflush(stdout)使用同一个输出流:
fprintf(stderr, "data_offer received\n");
fflush(stderr);
确认收到 data_offer 后,再通过 offer 查询 MIME 类型,并使用对应的 Wayland 数据传输流程读取内容。
注意事项
这段日志不足以断定 Hyprland 出现故障。它能确认请求已发出,但无法说明服务端发送剪贴板 offer 的条件是否满足。先让客户端获得键盘焦点,并触发一次新的剪贴板选择,再检查核心协议路径;如果要在后台读取,则需单独核对数据控制扩展和合成器策略。
备注:内容仅供参考。
