Wayland环境下如何接收指针事件并透传至下层客户端?
Wayland录屏光标高亮方案:无需libinput的纯客户端实现
针对你的需求,最优方案是结合Wayland官方的屏幕录制扩展与全屏透明overlay层,完全绕开直接处理输入事件的问题,自然实现事件透传与光标状态监听:
核心思路
利用wp_screen_cast_v1扩展(Wayland Protocols稳定扩展)从compositor获取光标位置、点击状态等元数据,同时创建无输入区域的全屏overlay层负责绘制高亮效果。这样overlay层不接收任何输入事件,所有操作直接透传至下层应用,而光标状态由compositor主动推送,无需额外权限。
具体实现步骤
1. 初始化屏幕录制流,获取光标元数据
- 从Wayland display获取
wp_screen_cast_manager_v1对象,创建wp_screen_cast_stream_v1用于屏幕录制。 - 设置流的
cursor_mode为WP_SCREEN_CAST_STREAM_V1_CURSOR_MODE_METADATA:wp_screen_cast_stream_v1_set_cursor_mode(stream, WP_SCREEN_CAST_STREAM_V1_CURSOR_MODE_METADATA); - 注册以下事件回调:
cursor_position:接收光标实时坐标,用于更新高亮圆圈位置。cursor_button:接收鼠标按键的按下/释放状态,用于切换高亮颜色(比如点击时改为红色,松开后恢复半透明)。
2. 创建全屏透明overlay层
- 使用
zwlr_layer_surface_v1创建全屏层,配置参数如下:- 设置
layer为ZWLR_LAYER_SURFACE_V1_LAYER_OVERLAY(确保层在所有窗口之上)。 anchor设为所有四边(ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT),实现全屏覆盖。exclusive_zone设为-1,告知compositor该层不占用布局空间,不影响下层窗口。
- 设置
- 清空输入区域与不透明区域,确保事件透传与层透明:
wl_surface_set_input_region(surface, nullptr); wl_surface_set_opaque_region(surface, nullptr); - 提交surface完成初始化:
zwlr_layer_surface_v1_commit(layer_surface);
3. 绘制光标高亮效果
- 收到
cursor_position事件时,计算高亮圆圈的绘制坐标(以光标为中心),调用wl_surface_damage标记需要更新的区域。 - 收到
cursor_button事件时,切换高亮圆圈的颜色(比如按下时使用不透明度更高的红色,释放后恢复半透明蓝色)。 - 每次状态更新后调用
wl_surface_commit提交绘制,compositor会自动刷新overlay层。
替代方案(无法使用录屏扩展时)
如果因环境限制无法使用wp_screen_cast_v1,可以尝试以下方法:
- 使用
wl_seat获取wl_pointer对象,注册motion与button事件回调。 - 为overlay层设置全屏输入区域,但在事件回调中调用
wl_pointer_set_input_region临时清空输入区域,让compositor将事件透传至下层应用,之后再恢复输入区域以继续接收后续事件。这种方法依赖compositor的事件处理逻辑,兼容性可能较差,不推荐作为首选。
内容的提问来源于stack exchange,提问作者mgunyho
相关产品推荐
相关产品推荐

