KDE 不仅要好用,还必须好看。
缘由
对于大部分 KDE 用户,是不太可能将所有的工作都扔给 Qt 系应用程序去干的;我们还是不得不少量接触 Gtk 应用。大部分人应该都注意到过,一些应用,特别是大量 Gtk3 应用,在 KDE 下是不能正确显示阴影的,有些甚至不能拖动边框改变大小;对于 Steam 和开了自定义标题栏的 VSCode 这类无装饰窗口来说也是如此。
开始之前
请注意以下几点:
- 本文只针对 KDE plasma 桌面,其它的桌面环境基本不可能用本文中的方法解决问题。
- 本文要求使用微风(Breeze)窗口装饰,因为几乎只有它支持对特定窗口修改装饰设置。
- 本文描述的设置项名称全部采用简体中文。
- 你的混成器必须开着,因为没有它就不会绘制阴影。
- 目前没有提供视频教程的计划。
部分原理阐述来自于 farseerfc。
基础知识
阴影如何绘制
很显然,最初的 X11 是没有“窗口装饰”这种 fancy 的东西的,更别提“阴影”了;X11 核心协议从未规定过这些东西。但是 X11 核心协议有两个功能:子窗口和 reparent。
子窗口,顾名思义,是将一个窗口作为另一个窗口的“孩子”,移动父窗口时会同样地移动子窗口,而所有的“顶级窗口”其实都是 X11 root window 的孩子;而 reparent,就是令窗口“重新认亲”。
所以,绝大部分 WM(窗口管理器)实现窗口装饰的方法,差不多就是查询 X11 root window 的所有孩子,分别为它们创建一个“装饰”窗口,并让它们 reparent 为新建的装饰窗口的孩子;这样便实现了窗口装饰。
接下来就是阴影的问题了。阴影该由谁绘制并无固定的要求,但是历史做法是由装饰绘制阴影。KDE 延续了这种做法,阴影是装饰提供的,也就是说,没有装饰,除非应用自己绘制阴影,否则是不会有阴影的。
问题如何产生
由于 Gnome 所默认基于的 Wayland 没有子窗口和 reparenting 这些技术,所以窗口装饰无法使用传统方式实现。于是,Gtk3 的 App 开始自己绘制装饰,并声明自己是 CSD App,不希望获得一个“额外的”窗口装饰,同时期待着桌面环境能给他一个不由装饰提供的阴影。
Gnome 决心抛弃 SSD 的逻辑,所以开始直接给所有的窗口添加阴影,而非使用装饰来实现;但是 KDE 仍使用传统方式,由装饰来提供阴影,这导致了使用 CSD 的应用均无法获得阴影,别的无装饰窗口也是如此(比如 Steam)。
解决问题
问题的关键点在于,KDE 下没有窗口装饰的窗口就没有阴影。所以解决问题的基本方向,就是给窗口加上窗口装饰。KDE 的窗口规则可以做到这一点,本文使用优秀的 RSS 阅读器 FeedReader
作为例子。
打开 FeedReader
,你会发现它在 KDE 下既没有阴影,也无法通过拖动窗口边缘来调整大小。
设法为它加上窗口装饰
进入系统设置
下的窗口管理
分类,打开窗口规则
选项,点击右侧的新建
按钮新建一个配置,并将匹配
选项卡下相关条目如图填写(对于 FeedReader):
你也可以单击检测窗口属性
按钮之后再点击目标窗口内容来自动填写这一页。
将外观和修正
选项卡下无标题栏和边框
这一项如图填写:
保存配置后,你应该发现窗口装饰被强行加上了。
去掉多余的标题栏
虽然有了阴影,但是两个标题栏显然是不行的。这也是 KDE 会默认不给 CSD 应用添加窗口装饰的主要原因。我们需要设法在不去掉窗口装饰的前提下去掉标题栏。
好在微风
窗口装饰给我们提供了相关的选项。
前往系统设置
下的应用程序风格
分类,打开窗口装饰
配置,并确认你正在使用微风
窗口装饰。点击配置微风
按钮,并在特定窗口优先规则
选项卡下添加一个新的规则。同样,你可以使用检测窗口属性
按钮来自动填写匹配。勾选边框大小
并选择无边框
,勾选隐藏窗口标题栏
,保存配置。
原则上,你会的到一个非常令人满意的效果。下面是采用上面的方法之后的 FeedReader 界面:
不仅阴影正确渲染,而且可以通过拖动窗口边缘来更改窗口大小了(我的阴影比较淡,外加背景颜色较深,可能比较难观察出来;但是对比第一张图可以看出明显的效果:阴影渲染已经和别的应用程序无异了)。
小结
本文所述方法几乎可以解决任何无装饰窗口在 KDE 下没有阴影的问题,包括一些 Gtk3 应用、Steam、开了自定义标题栏的 VSCode 等。确保你的混成器是开启的,因为 KDE 依赖它绘制阴影和动画。