Skip to content

feat(wayland-cursor): 客户端自己的鼠标指针 —— fork 的第六个也是最后一个成员 - #306

Merged
Sunrisepeak merged 2 commits into
mainfrom
feat/wayland-cursor
Aug 30, 2026
Merged

feat(wayland-cursor): 客户端自己的鼠标指针 —— fork 的第六个也是最后一个成员#306
Sunrisepeak merged 2 commits into
mainfrom
feat/wayland-cursor

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

Wayland 没有服务端光标:客户端要指针,就得自己加载主题、把图像变成 wl_buffer、附到交给 wl_pointer.set_cursor 的 surface 上。没有这个库,每个应用都得自己解析 XCursor 文件格式。

⚠ 不要和 compat.xcursor 搞混:那是 X11 的 libXcursor.so.1,要和 X 服务器说话。

配套 fork PR:mcpplibs/wayland#2(已合)。至此 fork 建齐了上游发布的每一个库,没有第七个。

又一处编译期宿主路径,同样置空

xcursor.c:493 写死 "~/.icons:/usr/share/icons:/usr/share/pixmaps:…" —— 重定位之后指的是宿主的主题。而 xcursor_library_path() 先读 getenv("XCURSOR_PATH") 且设置了就原样返回(xcursor.c:515),所以这是兜底不是唯一入口,和 LIBINPUT_QUIRKS_DIR / XKB_CONFIG_ROOT 完全对称。

fork CI 里 grep 二进制确认路径真没被编进去 —— 这条只能这么查,因为值错了的失败方式是在恰好有 /usr/share/icons 的机器上静默正常工作

一份 tarball 六个条目,tag 仍未动

wayland-1.26.0-mcpp3.tar.gz 作为 release 资产,六个描述符在同一个提交里换指向。旧资产原样保留,没有任何窗口里 main 是坏的。

GLOBAL/CN  b95537b21b0df211…  1032352 bytes   逐字节一致

测试成员:第一版段错误了

我以为传 null wl_shm 只会跑到主题解析器。实际 wayland-cursor.c:410shm_pool_create(shm, …) 直达 wl_shm_create_pool无保护解引用,exit 139。

wl_shm 只能来自合成器的 registry,所以这个库的 buffer 那半属于有合成器的程序 —— 正如打开 /dev/input/event* 不属于 tests/examples/libinput

改成断言仍然承载打包风险的部分:

  • 模块导出全部六个名字
  • 两个公共结构能当值用 —— 不是不透明句柄。导出成不透明会在这里编过、在调用者第一个 image->hotspot_x 上炸,所以测试碰字段而不只是命名类型
  • 真的链了 client(wl_shm_create_pool)—— 这正是 §3 的主题加载器需要活 wl_shm 的原因
  • wl_cursor_frame 系列 —— 纯粹是 images 数组上的算术,无需 shm,是本测试唯一能跑的真实行为
13 项断言全过
wayland      2 passed; 0 failed     ← 新 tarball 上无退化
wayland-egl  1 passed; 0 failed

Wayland 没有服务端光标:客户端要指针,就得自己加载主题、把图像变成 wl_buffer、
附到交给 wl_pointer.set_cursor 的 surface 上。没有这个库,每个应用都得自己解析
XCursor 文件格式。

不要和 compat.xcursor 搞混:那是 X11 的 libXcursor.so.1,要和 X 服务器说话。

至此 fork 建齐了上游发布的每一个库,没有第七个。

## 又一处编译期宿主路径,同样置空

xcursor.c:493 写死 "~/.icons:/usr/share/icons:/usr/share/pixmaps:..." ——
重定位之后指的是宿主的主题。而 xcursor_library_path() 先读
getenv("XCURSOR_PATH") 且设置了就原样返回(xcursor.c:515),所以这是兜底不是
唯一入口,和 LIBINPUT_QUIRKS_DIR / XKB_CONFIG_ROOT 完全对称。

fork CI 里 grep 二进制确认路径真没被编进去——这条只能这么查,因为值错了的失败
方式是在恰好有 /usr/share/icons 的机器上静默正常工作。

## 一份 tarball 六个条目,tag 仍未动

发 wayland-1.26.0-mcpp3.tar.gz 作为 release 资产,六个描述符同一个提交里换指向。
旧资产原样保留,没有任何窗口里 main 是坏的。两镜像逐字节一致:
    GLOBAL/CN b95537b21b0df211...  1032352 bytes

## 测试成员:第一版段错误了

我以为传 null wl_shm 只会跑到主题解析器。实际 wayland-cursor.c:410 的
shm_pool_create(shm, ...) 直达 wl_shm_create_pool 并无保护解引用,exit 139。

wl_shm 只能来自合成器的 registry,所以这个库的 buffer 那半属于有合成器的程序,
正如打开 /dev/input/event* 不属于 tests/examples/libinput。

改成断言仍然承载打包风险的部分:模块导出全部六个名字、两个**公共结构**能当值用
(不是不透明句柄——导出成不透明会在这里编过、在调用者第一个 image->hotspot_x 上
炸)、以及真的链了 client。外加 wl_cursor_frame 系列——纯粹是 images 数组上的
算术,无需 shm,是本测试唯一能跑的真实行为。

13 项断言全过;wayland(2 passed)与 wayland-egl(1 passed)在新 tarball 上无退化。
llvm 那条腿抓到的,gcc 腿结构上看不见:

    ld.lld: error: undefined symbol: wl_proxy_get_version
    >>>   wayland-cursor.o:(wl_shm_create_pool(wl_shm*, int, int))

wl_shm_create_pool 是 wayland-scanner 的 static inline 协议包装,取它的地址
**强制本 TU 实例化一份**,而那份会调 wl_proxy_marshal_flags 等 libwayland-client
私有符号。GNU ld 经 libwayland-cursor 的传递 DT_NEEDED 解析得到,lld 故意不——
而 lld 是对的:命名了某个符号的程序应当链接定义它的库。

wl_display_connect 是普通导出函数,引用它证明同一件事而不实例化任何东西。
和 wayland-egl 测试同一形状,那个因此两条腿都绿。

同时把收尾备注写进文档:

§12.5 libwayland-cursor 与第七个发现变量 XCURSOR_PATH
§13.1 wlroots 只卡 hwdata + libdisplay-info——从它自己的 meson 逐条读出。
      并纠正本文档早前两处:cairo **不是** wlroots 的缺口(只在 examples/,
      required: false);libdisplay-info 体量虽小但是整个 wlroots 的闸门
§13.2 桌面侧仍缺的七项,含规模
§13.3 发现变量总表:七格六有,第七格(光标主题)机制已就位缺提供方
§13.4 本轮被自己的测试抓住的三处——都是从假设写断言而不是从源码

版本 v1.1 -> v1.2
@Sunrisepeak
Sunrisepeak merged commit 1b55da3 into main Aug 30, 2026
11 checks passed
@Sunrisepeak
Sunrisepeak deleted the feat/wayland-cursor branch August 30, 2026 13:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant