派生自Kylin Wayland Window Compositor的又一个wlroots系wayland合成器
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 27 天前 | ||
| 2 个月前 | ||
| 24 天前 | ||
| 24 天前 | ||
| 24 天前 | ||
| 2 个月前 | ||
| 24 天前 | ||
| 1 个月前 | ||
| 1 年前 | ||
| 26 天前 | ||
| 24 天前 | ||
| 2 个月前 | ||
| 1 年前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 1 年前 | ||
| 1 个月前 | ||
| 24 天前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 26 天前 | ||
| 26 天前 | ||
| 3 年前 |

GXDE Wayland合成器
派生自Kylin Wayland Window Compositor的又一个wlroots系wayland合成器
查看文档 »
查看往期版本
·
报告Bug
·
请求新功能
关于本项目
GXDE Wayland 合成器(亦称 gxde-wlcom)是基于 wlroots 开发的 Wayland 合成器,其原始代码派生自 kylin-wayland-compositor。(以下简称 kywc)
本仓库由 GXDE OS 团队fork,并在原项目基础上针对 GXDE OS 进行适配与优化,当前作为 GXDE OS Wayland 会话的默认合成器进行开发与维护。
该项目以开源协议 GPL-3.0-or-later 发布,项目中引用或包含的来自其他开源项目的文件及代码片段,均遵照其原始许可证要求进行使用。
优点
- 依赖少,未引入Qt或者GTK等图形框架(内部的QML文件vendor自
deepin-kwin,仅用作移植参考,实际构建.deb包时通过-Dexamples=false参数跳过) - 按需设计应用与合成器之间的协议,目前协议支持情况请参阅「PROTOCOLS」。
- 特效支持,支持常用的窗口动效。
- 完整的中文输入支持,支持
input-method v2和text-input v1/v2/v3。 - 快捷键和触摸手势支持,支持键盘快捷键,触摸板和触摸屏手势设置。
- 输入设备支持,支持鼠标、键盘、触摸板、触摸屏、数位板。
- 多语言国际化支持。
- 多后端支持,支持
x11/wayland嵌套运行,支持drm和fbdev显示后端。
GXDE做出的修改
- 修改构建,解决依赖问题。
- 移植DDE Shell/deepin-chameleon主题「云璃」的默认窗体外观。
- 移植
dde-shell协议,并扩展wlr-layer-shell排布逻辑,为deepin-menu等沿用X11思路的菜单守护进程在Wayland下提供菜单定位支持。 - Cherry pick了上游Wlroots的一些更新。
- 自动安装
gxde-wlcom会话与startgxde_wlcom启动脚本至系统。 - 修复了原版Wlcom(截至我们Fork时的版本)在GXDE OS上
layer-shell表面无法吸附至屏幕顶端的问题。 - 提供了新接口允许设置GXDE主题。
- 提供了新接口允许控制GTK标题栏上最小化/最大化/关闭按钮的可见性。(默认为全部可见)
- 提供了一个接口,允许用户强制裁剪所有CSD(客户端自行装饰的)窗口,使其拥有圆角。用户亦可允许合成器跳过对
layer-shell表面(这些表面通常包含GXDE顶栏、Dock、GXDE控制中心等)圆角的裁剪。强制裁剪圆角为不稳定功能。 - 为原来Wlcom的一些功能做了一些alias, 供GXDE控制中心使用(详见这里)。
- 参考
deepin-kwin移植了Deepin风格的多任务视图。 - 修正了
wl_seat晚于剪贴板相关全局对象广播的问题。dde-clipboard-daemon一类基于KWayland的客户端会在data-control管理器一被广播就拿seat创建data device,此前会因此启动即崩溃。 - 新增剪贴板持久化:源程序退出后,合成器会接管其剪贴板内容,使截图工具一类「复制完就退出」的程序仍能被正常粘贴(构建参数
-Dclipboard_persist=false可关闭)。 - 新增全屏截图到剪贴板:按下
PrintScreen截取全屏;也可通过top.gxde.Wlcom.Screenshot接口调用(详见这里)。
依赖项
运行时需要使用的库或程序:
- wayland, libinput, xkbcommon
- libseat, libdrm, libsystemd, librsvg-2.0
- cairo, pango, pangocairo, pixman-1, glib-2.0, gio-2.0
- gbm, json-c, libudev
- xwayland, xcb (可选)
编译时需要的库或程序:
- ninja-build, libdrm-dev, libxkbcommon-dev, libpixman-1-dev, libgbm-dev, libudev-dev, libseat-dev, libinput-dev, libdisplay-info-dev, hwdata, libegl-dev, libgles2-mesa-dev, libxcb1-dev, libxcb-composite0-dev, libxcb-icccm4-dev, libxcb-render0-dev, libxcb-res0-dev, libxcb-ewmh-dev, libxcb-errors-dev, xwayland
Wlroots问题
无须担心Wlroots,meson会自动从https://github.com/GXDE-OS/open-kylin-wlroots.git (我们对Open Kylin版Wlroots的fork) 拉取Open Kylin打过自己补丁的Wlroots,锁定合适的版本并作为子项目构建并静态链接。
为何作为子项目编译?Open Kylin对Wlroots做了大量扩展与修改,并且二进制/devel包名仍然是wlroots:
| 项目 | GXDE自带的Wlroots (25.4) | Open Kylin版本 (0.7.14-ok17) | 是否冲突 |
|---|---|---|---|
.so二进制 |
libwlroots-0.19.so |
libwlroots-0.17.so |
侥幸不冲突,但凡有一天这俩版本一旦跟上就会冲突 |
| 头文件 | /usr/include/wlr |
/usr/include/wlr |
是,若安装dev包将会覆盖 |
为避免与系统上现有包冲突起见,我们这么做了。
treeland-protocols 0.5.9 与 personalization 协议
理论上现在不用担心这个了,GXWM已经做到了对两个版本的自适应支持
这一节关系到整个桌面能否启动,改动protocols/treeland-personalization-manager-v1.xml前请务必读完。
上游在treeland-protocols 0.5.9(提交8576b9c,2026-06-16)中删除了get_wallpaper_context请求和treeland_personalization_wallpaper_context_v1接口,理由是该功能已迁移至xdg-desktop-portal。问题在于这次删除没有bump版本号——manager接口前后都是version="2",接口名也没变,提交信息自己写的就是Influence: Broken change。
Wayland的opcode是按XML中的出现顺序排的,少一个请求,后面全部错位一格:
| 客户端发出 | opcode | 布局不一致的服务端会执行 |
|---|---|---|
0.5.9客户端的get_cursor_context |
1 | 0.5.8服务端的get_wallpaper_context |
0.5.8客户端的get_appearance_context |
4 | 0.5.9服务端的destroy |
由于两种布局同名、同版本,服务端在bind时拿不到任何信号去区分对面是哪一种,无法同时兼容。一旦对不上,所有DTK程序(libdtkgui/libdtk6gui,也就是几乎全部GXDE程序)会在启动时被合成器以wl_display error杀掉,桌面直接起不来。
因此本仓库vendor的XML必须与系统上DTK编译时所用的那一份保持wire一致,而不是跟着上游master走。当前仓库内的版本对应 0.5.8(含wallpaper context)。
何时需要切换
真正的引爆点不是apt upgrade treeland-protocols——XML只是编译期输入,升级协议包本身不改变任何已编译好的客户端。引爆点是libdtkgui/libdtk6gui等被按0.5.9重新编译的那一刻。
不过下面的自动探测已经把这件事接管了,正常情况下不需要改代码、不需要重新编译、也不需要人工切换,只要重新登录一次即可:布局是在wl_global_create时定死的,运行中的合成器不会中途重新探测,所以DTK升级后当前会话里新启动的DTK程序仍会挂,注销重登后自动探测就会看到新的DTK并切到0.5.9。
只有两种情况仍需人工介入:
- DTK5与DTK6不同步(只重编了其中一个)——见下文,需要补完编译或手动指定优先保谁。
- 有人把
protocols/同步到了上游——这是唯一会让开关失效的操作。好在它编译期就会失败(wallpaper实现引用的生成符号消失,直接报incomplete type等一串错误),产不出二进制,所以不构成隐患。
判断依据(任选其一):
# 1. 看系统协议包版本
dpkg -l treeland-protocols
# 2. 直接看DTK是否还引用wallpaper context,这一条才是决定性的(也是合成器自动探测所用的判据)
strings -a /usr/lib/x86_64-linux-gnu/libdtk6gui.so.* | grep -c treeland_personalization_wallpaper_context
# >0 : DTK仍按0.5.8编译,需要0.5.8布局
# 0 : DTK已按0.5.9编译,需要0.5.9布局
运行时开关(无需重新编译)
合成器把两种布局都编译在了同一个二进制里,启动时选一个:0.5.8布局用的是wayland-scanner生成的方法表,0.5.9布局则在运行时从同一张表里挑出{0,2,3,4,5}(跳过get_wallpaper_context)拼出来,因此两条路径同源、不会各自漂移。前提是vendor的XML保持0.5.8超集——真正切到0.5.9后这个开关连同wallpaper实现一起删掉即可。
这个前提有代码守卫:启动时会核对vendor的XML里第1号请求是不是get_wallpaper_context,不是就打ERROR说明开关已失效、并原样服务vendor的表。它针对的是「请求还在但位置变了」这种能编译通过、却会静默错开全部opcode的改动;至于整个请求被删掉的情况编译期就过不去,轮不到它管。
默认行为是自动探测:启动时扫描已安装的libdtk*gui(Qt5与Qt6两套都查,含multiarch路径),看它们是否还引用treeland_personalization_wallpaper_context_v1。这比看协议包版本准,因为XML只是编译期输入。探测不到DTK时(构建chroot、精简安装)退回去看/usr/share/treeland-protocols,再不行默认0.5.8。
理论上不需要强制设定,但如果非得要,设环境变量即可,改startgxde_wlcom里一行然后重新登录:
export GXDE_WLCOM_PERSONALIZATION=058 # 或 059;亦接受 0.5.8 / 0.5.9
确认当前选了哪个(该行是INFO级,默认WARN不显示,需-V或KYWC_LOG_LEVEL=INFO):
grep Personalization ~/.log/gxde-wlcom.log | tail -1
# (Treeland Shim) Personalization: probed 4 DTK libraries, wallpaper context referenced -> using the 0.5.8 layout
# (Treeland Shim) Personalization: layout forced to 0.5.9 by GXDE_WLCOM_PERSONALIZATION
若探测发现DTK5与DTK6不一致(一个已按0.5.9重编、另一个还没有),会打一条ERROR并选择0.5.8。这种混合状态下没有任何一种选择能让两边都活,只能把落后的那个包补编译完,或用环境变量指定优先保谁。
总开关:完全不广播该协议
上面的开关是在两种布局之间二选一,而这个是直接不广播treeland_personalization_manager_v1这个global:
export GXWM_DONOT_BROADCAST_TLPM=TRUE # 亦接受 ON / YES / 1,大小写不敏感
默认关闭(即默认正常广播)。取值不在上述列表内的一律视为关闭,包括导出了但为空的情况,所以=FALSE、=0或export GXWM_DONOT_BROADCAST_TLPM=都是照常广播,不会误伤。
万一哪天上游又来一次不bump版本号的破坏性改动,而上面的布局开关也救不了场,用它可以让桌面先能登录进去。客户端拿不到这个global就会回退到自己的默认外观——窗口模糊、自定义圆角、客户端指定的标题栏这些会失效,但比登进桌面panel不显示强。
该开关的日志是WARN级(默认可见,无需-V)
grep Personalization ~/.log/gxde-wlcom.log | tail -1
# [WARN]: (Treeland Shim) Personalization: global not advertised, disabled by GXWM_DONOT_BROADCAST_TLPM
彻底移除兼容代码
日常切换用上面的开关就够了,本节是等GXDE彻底转向0.5.9之后清理死代码的做法(此后合成器不再能服务0.5.8客户端)。
个人觉得没必要移除,全程用开关就够了。
按顺序撤销这两个提交即可,无需其他改动:
git revert 773f0364 # feat: Treeland personal manager version autoswitch
git revert 17585154 # fix: DTK program crashes due to lacking wallpaper support ...
ninja -C build
顺序不能反。 773f0364的运行时开关引用了get_wallpaper_context/manager_get_wallpaper_context等符号,先撤17585154会留下一堆悬空引用。
这个流程已实测过:两步revert无冲突,编译通过,撤销后protocols/treeland-personalization-manager-v1.xml回到1010e86f(与上游master逐字节相同),与0.5.9包wire完全一致(54项)。注意773f0364同时包含本章节的README内容,撤销它也会一并删掉这些说明——如果之后还需要留档,记得把仍然适用的部分捡回来。
若日后rebase/squash导致hash失效,等价的手工步骤是:
- 用系统上的新版覆盖vendor的XML:
cp /usr/share/treeland-protocols/treeland-personalization-manager-v1.xml protocols/ - 删除
src/view/treeland_personalization.c中的运行时开关:enum personalization_layout、manager里的layout/interface_059/requests_059、manager_implementation_059与manager_impl_059、layout_derive_059、file_contains、dtk_lib_patterns、layout_from_env、layout_detect、layout_is_059,以及treeland_personalization_manager_create里的探测段落;personalization_manager_bind与wl_global_create改回直接使用生成的treeland_personalization_manager_v1_interface和manager_impl。 - 删除同一文件中的wallpaper context实现:
wallpaper_*系列函数、wallpaper_impl、manager_get_wallpaper_context、manager_impl中的.get_wallpaper_context、personalization_context里的wallpaper子结构、manager里的wallpaper_contexts与wallpaper_metadata及其初始化/释放。文件里另有BLEND_MODE_WALLPAPER相关的两处,属于window context的blend mode,与本节无关,不要删。 ninja -C build,编译期若有遗漏会直接报错。
不要git revert b9dafa79。 那个提交引入的是整套personalization支持(window/cursor/font/appearance四类context),撤销它会连窗口圆角、模糊、标题栏控制一起丢掉。撤销后合成器不再广播该global,客户端会自行回退、不会崩溃,但功能全部消失,属于因噎废食。
顺带一提,b9dafa79当初vendor的XML本身就是0.5.9布局(与上游master逐字节相同),只是当时系统上的DTK还是按0.5.8编译的,才导致了错位。所以撤销17585154实际上就是把该文件还原回b9dafa79时的状态。
改动XML后必须做的校验
描述文字随便改,但wire布局(接口、请求/事件顺序、参数类型、type="destructor"、since、version)必须与目标版本完全一致。改完请比对:
python3 - <<'EOF' protocols/treeland-personalization-manager-v1.xml /usr/share/treeland-protocols/treeland-personalization-manager-v1.xml
import sys, xml.etree.ElementTree as ET
def wire(p):
out = []
for i in ET.parse(p).getroot().findall('interface'):
out.append(('IFACE', i.get('name'), i.get('version')))
for kind in ('request', 'event'):
for op, m in enumerate(i.findall(kind)):
args = [(a.get('type'), a.get('interface')) for a in m.findall('arg')]
out.append((kind, i.get('name'), op, m.get('name'), m.get('type'), m.get('since'), args))
return out
a, b = wire(sys.argv[1]), wire(sys.argv[2])
print("WIRE IDENTICAL" if a == b else "WIRE MISMATCH:\n" + "\n".join(
f" ours={x}\n upst={y}" for x, y in zip(a, b) if x != y))
EOF
再嵌套跑一遍确认真机行为,这一步能在污染真实会话之前抓到问题:
WAYLAND_DISPLAY=wayland-0 ./build/gxde-wlcom # 对外暴露 wayland-1
WAYLAND_DISPLAY=wayland-1 gxde-terminal # 任一DTK程序,能起来即为正常
同样的比对建议对protocols/下其余treeland协议一并执行——它们目前与系统包一致。
开始上手
编译
(EMACS Flymake/clang用户请看) 初始化Flymake/clang
$ meson setup build
$ ln -sf build/compile_commands.json compile_commands.json
然后重新打开emacs。
手动编译 (命令行)
编译选项见meson_options.txt,简单的编译指令如下:
$ meson setup build -Dbuildtype=debugoptimized
$ ninja -C build
$ meson install -C build --skip-subprojects
手动编辑 (构建脚本)
构建脚本位于./build-deb, 这是个shell脚本,用于在调试时生成安装包,便于在调试机器上轻松部署与卸载。
首先先修改脚本权限:
$ chmod a+x ./build-deb
然后以下上参数帮助:
用法: ./build-deb <选项>
选项:
-b, --binary 仅构建二进制包(默认行为)
-d, --install-deps 先安装构建依赖(读 debian/control),再构建
-c, --clean 仅清理构建产物后退出
-h, --help 打印帮助信息
初次编译建议执行:
$ ./build-deb -d # 安装依赖并构建
以后就可以不用安装依赖了:
$ ./build-deb # 直接构建
构建完成后清理中间产物:
$ ./build-deb -c
使用
注意: 默认情况下,日志打印到文件
$HOME/.log/kylin-wlcom.log。
基础使用
程序参数如下:
Usage: kylin-wlcom [options] [command]
-h, --help Show help message and quit.\n
-d, --debug Enables full logging, including debug information.\n
-D, --debug <options> noxwayland or logtostdout.\n
-s, --session <process> Run session on startup\n
-v, --version Show the version number and quit.\n
-V, --verbose Enables more verbose logging.\n
通过-D参数可以方便运行时调试, 支持参数如下:
-Dnoxwayland 关闭xwayland支持
-Dlogtostdout 将日志打印到stdout
-Dloginmtime 使用monotonic time输出日志
在GXDE上建立kywc会话
请参阅「./docs/gxde/gxde-wlcom-session.md」,了解如何在GXDE上建立kywc会话。
现在GXDE Wlcom会在安装.deb包时自动安装会话文件,不再需要手动安装,相关的.desktop文件与启动脚本可以在本repo的data/下找到。
GXDE版本的特殊功能
多任务视图
按Meta+S打开或关闭多任务视图。当前实现提供:
- 根据
com.deepin.wrap.gnome.desktop.background的picture-uri设置显示桌面及工作区壁纸预览; - 带抗锯齿圆角和3px活动高亮线的工作区预览;
- 显示普通及最小化窗口的实时缩略图;
- 关闭窗口、切换窗口置顶状态;
- 添加、删除、切换工作区;
- 将窗口拖入其他工作区,释放后保持多任务视图开启;
- 拖拽工作区预览以重新排序工作区。
Deepin KWin的原始实现和资源保存在
src/vendor/dkwin/multitask/upstream/,Wlcom适配层位于
src/vendor/dkwin/multitask/wlcom_multitask.c。
GXDE菜单中的「多任务视图」启动器也可直接使用,无需修改桌面文件。
gxde-wlcom会在用户会话总线上提供com.deepin.wm,并将
/com/deepin/wm上的PerformAction(1)直接连接到同一个原生多任务视图
开关。接口契约与验证方法见
multitasking-launcher-interface.md。
显示桌面
Wayland会话中,gxde-wlcom直接持有com.deepin.wm,并兼容
GetIsShowDesktop()和SetShowDesktop(bool)。接口与Meta+D共用
view_manager_show_desktop()状态机,因此只恢复由本次“显示桌面”操作
最小化的窗口。X11会话仍由原来的deepin-wm处理;本包不安装或替换
deepin-daemon的desktop-toggle。
切换窗口
可以通过Alt + Tab或者Alt + Shift + Tab唤起窗口切换器,其外观模仿Deepin KWin。
设置GTK主题
在用户会话总线,我们提供了top.gxde.Wlcom.Theme接口,可以通过其SetGTK方法,设置已安装的主题。
GNOME与UKUI的主题设置会同步更改,更改应该立即可见。
以下是使用示例,您需要把主题名称换为本机真实存在的主题。
busctl --user call \
top.gxde.Wlcom.Theme \
/top/gxde/Wlcom/Theme \
top.gxde.Wlcom.Theme \
SetGTK s "主题名称"
该方法接收一个字符串参数并返回boolean。返回true代表所有可用设置项均已成功写入。
设置GTK窗口按钮的可见性
top.gxde.Wlcom.WindowBtn接口用于设置GTK窗口的最小化、最大化和关闭按钮是否显示。使用三个boolean参数对应这三个按钮是否显示。
以下是例子 --
设置最小化/最大化/关闭按钮都需要显示:
busctl --user call \
top.gxde.Wlcom.WindowBtn \
/top/gxde/Wlcom/WindowBtn \
top.gxde.Wlcom.WindowBtn \
SetGtkDecorationButtons bbb true true true
查询当前设置:
busctl --user call \
top.gxde.Wlcom.WindowBtn \
/top/gxde/Wlcom/WindowBtn \
top.gxde.Wlcom.WindowBtn \
GetGtkDecorationButtons
强制裁剪圆角 (不稳定)
强制裁剪圆角与Wlcom所支持的窗口圆角不同,在强制裁剪圆角下,所有CSD(客户端自行装饰的)窗口都会被强制裁剪圆角,圆角大小取决于Wlcom设置的窗口圆角大小(即数值与普通「启用窗口圆角」功能共享)
在用户会话总线,我们提供了top.gxde.Wlcom.WindowCorner接口,用于管理两个持久化的DBus配置:
ForceRoundCorner:强制裁剪窗口圆角。ForceRoundCornerExcludeLayerShell:启用强制裁剪时,不裁剪wlr-layer-shell表面(例如顶栏、Dock、GXDE控制中心等的窗体)。仅在ForceRoundCorner启用时生效。
启用强制圆角裁切
busctl --user call \
top.gxde.Wlcom.WindowCorner \
/top/gxde/Wlcom/WindowCorner \
top.gxde.Wlcom.WindowCorner \
SetForceRoundCorner b true
将上述命令中的true改为false即可关闭相应配置。可通过以下方法查询
当前值:
busctl --user call \
top.gxde.Wlcom.WindowCorner \
/top/gxde/Wlcom/WindowCorner \
top.gxde.Wlcom.WindowCorner \
启用强制裁剪,但排除wlr-layer-shell表面:
busctl --user call \
top.gxde.Wlcom.WindowCorner \
/top/gxde/Wlcom/WindowCorner \
top.gxde.Wlcom.WindowCorner \
SetForceRoundCornerExcludeLayerShell b true
注意事项
配置修改后立即生效,并写入~/.config/gxde-wlcom/config.json的theme对象,对应的key分别为force_round_corner和force_round_corner_exclude_layer_shell。
多语言支持
在po目录中,LINGUAS文件中加入支持的语言,POTFILES.in加入需要翻译的源文件。
然后运行以下命令,更新pot文件:
$ meson compile gxde-wlcom-pot
里程碑
参与开发
请参阅「CONTRIBUTING」文件,了解贡献所需的信息。
对于MR,请将代码PR至gxde/testing分支,测试稳定后将由管理员合并至gxde/zhuangzhuang分支并bump。
GXDE Wlcom的贡献者们
(注:不知道为何很多原版KYWC的贡献者没有显示,您可以在此处找到原版KYWC贡献者的信息)
许可证
该项目使用开源协议GPL-3.0-or-later,详见「COPYING」。
项目中来源于其他开源项目的文件或代码片段遵守原开源协议要求。
请参阅./LICENSES/文件夹下的许可。
对于每一个源码,也请查看其顶部标明的SPDX-License-Identifier。
致谢
感谢以下代码与模板提供参考:
- Treeland: https://github.com/linuxdeepin/treeland
- Treeland Protocols: https://github.com/linuxdeepin/treeland-protocols
- Open Kylin Wlcom: https://gitee.com/openkylin/kylin-wayland-compositor
- Open Kylin Wlroots: https://gitee.com/openkylin/wlroots
- Deepin KWin: https://github.com/linuxdeepin/deepin-kwin
- Wlroots: https://gitlab.freedesktop.org/wlroots/wlroots
- Sway: https://github.com/swaywm
- Wayfire: https://github.com/wayfire
- LabWC: https://github.com/labwc
- Best Readme Template: https://github.com/othneildrew/Best-README-Template