一台 11 寸的二合一设备装了基于 wlroots 的合成器,外接键盘用起来很顺手,拔掉键盘那一刻问题立刻暴露出来:屏幕上没有可用的软键盘。前后试过三条路——桌面环境自带的虚拟键盘组件、基于输入法框架的方案、以及调 shell 命令模拟按键的老套路——结果要么拖进来一堆图形库依赖,要么点了输入框毫无反应。最后落到 wvkbd 上才安静下来:一份几千行的 C 代码,编译期四个 pkg-config 依赖,常驻内存十几 MB 量级,启动几乎是瞬时的。它就是那种“少而精”的 Wayland 触屏键盘,没有花哨的联想、没有主题商店,只做一件事——在屏幕上画出一块按键区,把触摸翻译成按键事件交给合成器。这篇就按我实际折腾的顺序,把这个 Wayland 触屏键盘从协议背景、编译安装、参数调优、布局改写,到“键盘死活不弹”的排查链路完整讲一遍。如果你手里有一台触屏设备、一块平板、或者一个自制的掌机外壳,正卡在“Wayland 下没有趁手软键盘”这一步,下面这些内容可以直接拿去照着做。
1. 为什么 Wayland 桌面上的软键盘总是“要么太重、要么不弹”
在动手编译之前,值得先把这件事的底层原因说清楚,因为它直接决定了后面遇到问题该怎么定位。很多人第一次在 Wayland 上找软键盘,都是先搜到一堆老教程,照着装上、配好、重启,然后发现点了输入框什么都不发生。这不是配置写错了,而是找错了技术路线。
1.1 X11 时代的老办法在 Wayland 上失灵的根本原因
X11 时代的软键盘方案大致分两类。第一类是靠全局注入按键事件,程序自己往焦点窗口里塞 X 事件,典型的做法是调用外部命令模拟键盘输入;第二类是直接监听全局按键、绘制窗口、抢焦点,用“伪窗口 + 模拟事件”的组合拳。这两类方案有个共同前提:任何程序都能看到全局输入状态,也能向任意窗口注入事件。这个前提在 X11 下成立,在 Wayland 下直接被推翻。
Wayland 的设计里,客户端之间是隔离的,一个程序既看不到别的窗口在干什么,也不能随随便便往别人的输入队列里塞东西。想发按键,必须走合成器提供的一条正式通道;想在屏幕上悬浮一块面板,必须走另一条正式通道。老办法不是“配置麻烦”,而是协议层面就不允许。所以你会看到一种很有迷惑性的现象:软键盘进程明明在跑,日志也没报错,窗口就是不出现,或者出现了但打字没反应——因为它拿不到该拿的权限,也不知道该往哪儿放窗口。
理解了这一点,后面所有排查都会变得有方向感:wvkbd 能不能工作,本质上是它需要的两条协议,你的合成器到底实现了没有、实现了多少。
1.2 wvkbd 只吃两条协议:layer-shell 与 virtual-keyboard
wvkbd 的设计极度克制,它把依赖压缩到了两条协议上。第一条是wlr-layer-shell,用来把键盘画成一层贴在屏幕边缘的面板,而不是普通窗口——这解决了“键盘要浮在所有窗口之上、又不抢焦点”的问题;第二条是virtual-keyboard-unstable-v1,这是向合成器提交按键事件的正式通道,也是它能把触摸变成真实按键的根本原因。
这两条协议的分工非常清晰,缺一不可,而且缺失时的症状完全不同,这一点我后面在排查章节会详细展开。这里先给个速查表,方便你对号入座:
| 缺失的协议 | 典型症状 | 判断依据 |
|---|---|---|
| wlr-layer-shell | 键盘窗口完全不出现,进程却正常运行 | 合成器日志里看不到 layer surface 创建记录 |
| virtual-keyboard-unstable-v1 | 键盘正常显示、按键有高亮反馈,但字符进不了输入框 | 触摸有反应、光标不动,输入框内容无变化 |
| 两者都缺 | 进程启动即退出或立刻静默 | 启动时输出协议绑定失败的提示 |
值得强调的是,wvkbd 属于“老派”的虚拟键盘实现,它并不走输入法框架那条路。输入法框架那套是给中文、日文这类需要候选词和组字的场景准备的,走的是另一条协议族,链路更长、组件更多,好处是能处理复杂文本输入,代价是“点一下只为了打个密码”这件事会变得很重。wvkbd 走的是更直接的按键注入,好处是延迟极低、依赖极少,代价是不做候选词联想。如果你需要拼音输入,通常的做法是让 wvkbd 负责弹出和基础按键,复杂文本交给输入法框架,两者配合而不是互相替代——这个组合方式我在第 3 章会讲怎么落。
1.3 把“少而精”拆开看:到底少在哪里
“少而精”这种说法很容易变成营销词,所以我把实际的量化对比列出来。以下数值来自我在同一台设备上对不同方案的粗略观测,只能作为量级参考,不是精确基准:
| 维度 | wvkbd | 桌面环境自带软键盘组件 | 完整输入法框架 |
|---|---|---|---|
| 编译期依赖数量 | 4 个左右 pkg-config 包 | 十余个,含大型图形工具包 | 数十个 |
| 常驻内存 | 十几 MB 量级 | 数十到上百 MB | 上百 MB |
| 冷启动到可按键 | 通常一秒以内 | 数秒 | 数秒以上 |
| 是否支持自定义键位 | 纯文本布局文件,改完即用 | 通常需要插件或主题机制 | 一般不支持 |
| 中文候选词 | 不支持 | 视组件而定 | 支持 |
“少”带来的直接好处不只是省内存。更关键的是可预测:依赖少意味着升级系统时不容易被连带打断,布局是纯文本意味着你可以随时改一个键位而不用等上游发版,代码量小意味着出问题时你能真的读得懂源码去定位。我在一台长期挂在墙上的触屏面板上跑这套组合,连续运行几周没有出现过键盘进程崩溃或者内存缓慢增长的情况,这种稳定性在“少而精”的方案里反而更常见。
“精”则体现在它把精力集中在触摸交互上:按键有按下高亮、支持长按重复、支持滑动切换、支持横竖屏两套高度,这些都是触屏场景真正需要的东西,而不是把桌面键盘的键位表原样搬过来。
2. 拿到源码之后的第一件事:看清它要什么、编出什么
很多人编译开源项目失败,不是命令打错,而是没搞清楚“这个项目期望的运行环境是什么”。wvkbd 的编译过程其实很短,但有几个点如果不提前确认,会在 make 阶段报一堆看不懂的错。
2.1 依赖盘点:四个包与一个容易漏的字体环节
编译期需要的东西并不多,核心是这几类:Wayland 客户端库、协议描述文件集合、二维绘图库、文本排版库,以及键盘布局与键位映射相关的库。用发行版的包管理器安装时,通常对应的名字是wayland、wayland-protocols、cairo、pango、libxkbcommon这几套的开发包。不同发行版命名略有差异,但凡是带-devel或-dev后缀的那几个基本不会错。
这里有一个特别容易踩的坑:确认 pkg-config 能真正找到它们。装完包不等于能被找到,尤其在自定义前缀或者多版本共存的系统上。验证方式很直接,逐个查一遍:
pkg-config --exists wayland-client && echo wayland-ok pkg-config --exists wayland-protocols && echo protocols-ok pkg-config --exists cairo && echo cairo-ok pkg-config --exists pango && echo pango-ok pkg-config --exists xkbcommon && echo xkbcommon-ok哪一行没打印出来,就说明哪个包要么没装,要么装在了 pkg-config 默认搜索路径之外。后一种情况需要设置PKG_CONFIG_PATH指向对应的pkgconfig目录,而不是去改 Makefile。
第二个容易漏的是字体。wvkbd 的按键文字是靠文本排版库渲染的,如果你在极简系统上跑,很可能只装了基础字体甚至没装任何常用字体,结果就是键盘能画出来,但按键上是一片空白。这种情况特别容易被误判成“渲染错误”,实际上是字体缺失。装一套常见的无衬线字体(比如任何带常规字重的字体包)就能解决,这也顺带解释了为什么有人用-fn参数指定字体后突然就正常了。
2.2 make 之后多出来的几个可执行文件到底是什么
在源码目录里执行 make,编译完成后你会发现产物不止一个,而是几个名字相似的可执行文件,通常带mobintl、comp之类的后缀。第一次看会有点困惑:这是编译出了好几个不同的程序吗?
不是。它们本质上是同一份程序,只是内嵌了不同的默认键盘布局。也就是说,直接用某个带后缀的可执行文件启动,等价于用主程序加上一个指定布局的参数启动。这个设计的好处是简单——你不用记参数,直接调对应的名字就行;坏处是容易让人误以为它们是不同工具,从而在文档里看到参数时对不上号。
我个人的习惯是统一用主程序 + 显式布局参数的方式启动,理由有两个:一是启动命令自解释,别人看你的配置文件一眼就知道用的是哪套布局;二是后面你要切布局时只改一个参数,不用去记哪个文件名对应哪套键位。判断哪个后缀对应哪套布局,最省事的办法就是依次跑起来看一眼按键排布,或者直接打开对应的布局文本文件对照键位。
2.3 安装位置与 PREFIX 选择
安装这一步没有太多技巧,但有一个选择值得说清楚:要不要用默认前缀装到系统目录。如果你只是自己用、并且系统是你一个人的,装到默认位置最省事,后续写自启动配置时路径也短。但如果你习惯把自编译软件和包管理器管理的文件严格分开,那就指定一个自定义前缀,把可执行文件、布局文件、协议描述都收在同一个目录树下,将来升级或者删除时直接删目录,干净利落。
这里有个细节:布局文件的位置决定了程序能不能找到它。如果你改动了布局文件又不想重新安装,最稳妥的做法是在启动时显式指定布局文件的完整路径,而不是依赖默认搜索路径。这一点在调试阶段尤其重要,否则你会陷入“明明改了文件却没生效”的困惑——很可能你改的是源码目录里的那份,而程序读的是安装目录里的那份。这种问题排查起来很浪费时间,养成显式指定路径的习惯能直接绕过。
3. 把键盘调到“能用”:尺寸、配色、输出与显隐控制
编译装好只是第一步。默认参数下的键盘能不能用,取决于你的屏幕尺寸和握持姿势——在一台 11 寸设备上,默认高度可能刚好,在 7 寸小屏上就可能高到把输入框全挡住。这一章讲的全是实测出来的调参经验。
3.1 高度是最容易调错的参数:横屏与竖屏的分工
高度参数有两个,分别对应横屏和竖屏。这里最容易犯的错误是只设了一个,然后在转动屏幕后发现键盘高度完全不对——要么高得离谱挡住半个界面,要么矮到手指根本按不准。
调这个参数的正确姿势是按比例而不是按像素绝对值去思考。先量出你屏幕的物理宽度(竖屏时是高度方向),然后取一个大约占屏幕短边 30% 到 40% 的值作为初始高度,再实际按几下感受一下。手指的触控目标在物理尺寸上最好不要小于 8 毫米见方,对应到像素上大约是:屏幕 PPI 乘以 0.32。举个例子,一块 250 PPI 左右的屏幕,单个按键的舒适边长就在 80 像素上下,一套 10 键宽的布局,宽度方向需要 800 像素,再叠加边距,键盘总高度自然就落在 300 到 400 像素这个区间。
我一般会把两个方向的参数都显式写进启动命令,即使当前只用其中一个。原因是设备一旦被转屏,合成器不会替你重算高度,两个值都写全了才不会出现“转了屏键盘变得不能用”的尴尬。
用有序列表把调参步骤列一下,方便你照着做:
- 先不加任何高度参数启动一次,观察默认高度下能露出多少内容区,判断是偏高还是偏矮。
- 按上文的物理尺寸估算给出一个初值,写进启动命令。
- 打开一个带多行输入框的界面(比如聊天输入或者记事本),实际打字一轮,重点看两件事:手指按边缘按键时会不会误触,以及键盘上方是否还留有足够的内容可视区。
- 如果误触明显,增大高度;如果内容区被挤压到无法阅读,减小高度。
- 把最终确定的值连同横屏值一起写死到启动配置里,不要靠运行时临时传参。
注意:调整高度时不要一次跨度太大。人的手感适应性很强,一次改 20% 以上反而会让你判断不出哪个更合适。每次微调 5% 到 10%,改两三轮基本就能定下来。
3.2 字体与配色:小屏上可读性优先
wvkbd 允许指定字体和前景、背景、按键按下时的配色。这三项看起来是“外观选项”,实际上直接影响可用性。
先说字体。小屏上按键文字过大会互相挤压,被截断成半个字符,看起来像是渲染 bug;过小则在阳光下完全看不清。比较稳妥的做法是选一个字形简洁的无衬线字体,并且优先保证行高适配按键高度,而不是单纯追求字号大。如果发现文字被裁切,第一反应应该是调字体而不是调键盘高度——很多时候只是行高超出了按键格子的内边距。
再说配色。默认配色在室内看没问题,但在强光环境下对比度往往不够。我的经验是把背景压深、文字提亮,拉开足够对比度;按下态用明显的色相变化而不是单纯加亮,因为单纯加亮在小屏上很难分辨。同时要注意一个容易被忽略的点:深色键盘在夜间使用时,屏幕局部亮度集中,容易造成注意力被键盘吸走,适当降低背景亮度或者调整整体透明度会更舒服,前提是你的合成器支持对 layer 面板做透明度控制。
配色参数写在启动命令里意味着改一次要重启一次键盘进程。调试阶段我建议先在一份临时命令行里反复试,试到满意了再落到配置文件,不要直接改配置文件然后反复重启合成器。
3.3 多屏环境下用输出绑定把键盘钉在正确的屏幕上
多显示器是软键盘最容易出问题的地方。默认情况下,layer 面板往往出现在合成器认为的“当前输出”上,而你的触摸屏可能是另一块。表现出来的现象就很有意思:手指在触屏上按,键盘却在旁边那块显示器底部闪着。
解决方式是显式指定键盘要绑定到哪个输出。输出的名字可以通过合成器提供的查询命令拿到(不同合成器命令不一样,一般在状态栏配置或者输出管理工具里能看到,形如几个字母加连字符的短名)。绑定之后,键盘就固定出现在那块屏幕上,无论焦点如何变化。
这里有个实测出来的经验:如果你的触摸屏是竖屏旋转过的,输出的逻辑尺寸和物理尺寸可能不一致,此时键盘的实际绘制区域可能超出可见范围,看起来像是被裁掉了一截。遇到这种情况不要急着调高度参数,先确认输出当前的变换状态,很多时候把变换修正过来,键盘就自动正常了。这个坑我在一台旋转装的面板上踩过,花了半小时以为是布局文件写错了。
3.4 隐藏启动与运行时显隐的几种做法
大多数场景下,键盘不需要全程显示——看视频、浏览网页时一直占着底部空间很浪费。所以“默认隐藏、需要时呼出”是更合理的用法。wvkbd 支持以隐藏状态启动,这给了我们做开关控制的基础。
至于运行时怎么切换显示状态,不同版本的支持方式不完全一样,我建议你先看本地安装版本自带的帮助输出,再决定用信号还是用参数控制。常见的几种做法:
- 通过发送信号让运行中的实例切换显示状态,配合合成器的快捷键绑定,实现一键呼出/收起。
- 用脚本先检查进程是否存在,不存在则以隐藏状态启动,存在则发信号切换。
- 干脆常驻显示,但通过降低高度和调整位置降低存在感。
我自己的做法是第二种,写成一个十几行的判断脚本,绑到合成器的一个快捷键上。这样平时键盘不占地方,需要打字时按一下组合键就出来,打完再按一下收回。脚本的逻辑核心就是“进程在不在”这个判断,不需要任何额外依赖。
#!/bin/sh # 简化示意:进程存在则切换,不存在则以隐藏态启动 if pgrep -x "wvkbd-mobintl" > /dev/null 2>&1; then pkill -USR1 -x "wvkbd-mobintl" else wvkbd-mobintl --hidden & fi注意:信号编号和实际行为请以你本地版本为准,不同版本可能有差异。上线前先用一次手动测试确认“发信号确实切换了状态”,再写进快捷键绑定,避免出现“按了没反应还不知道为什么”的情况。
4. 改布局文件:从默认键位到自己的键位表
wvkbd 最让我满意的设计是布局完全由文本文件描述。这意味着加一个 Esc 键、换一个 Enter 形态、把方向键挪到顺手的位置,都不需要动源码,也不需要等上游更新。但布局文件的写法有一定门槛,改错一个字符就可能整块区域画不出来,所以这一章重点讲“怎么改才不出错”。
4.1 布局文件的组织方式与键名规则
打开一个布局文件,你会看到它是一行行文本,每一行代表键盘上的一“行”按键,行内的每个条目代表一个按键。条目里一般包含两部分信息:这个按键上显示什么字,以及它实际发出什么键。有些条目还会附带宽度比例,用来做“空格键比其他键宽三倍”这种排版。
理解这套结构的关键在于区分显示文本和键值符号。显示文本决定用户看到什么,键值符号决定系统收到什么。这两者可以不一样——比如你可以让按键显示一个箭头图标,但实际发出的是方向键的键值。初学者常犯的错误是把这两者混为一谈,导致按键看起来对、按下去却是另一个字符。
键值符号的命名遵循键盘映射领域的通用约定,常见的有单个字母、功能键名、修饰键名,以及方向键名。改布局的时候建议从现有文件里复制粘贴再修改,而不是凭记忆手写,因为命名上的大小写和拼写细节很容易记错,而错了之后程序往往不会报错,只是那个键变成无效。
另外要注意修饰键的语义。布局文件里可以定义“按下这个键时,下一个按键带上修饰”的行为,这在触屏上非常重要,因为没有物理 Ctrl。常见做法是把 Ctrl 和 Alt 放在最下一行两侧,用起来像粘滞键。
4.2 三个我必改的位置:Esc、Enter 与方向键
拿到一套新布局,我基本上第一时间会改三个地方,这三个改动带来的手感提升最明显。
第一是 Esc 和 Ctrl 的位置。默认布局往往为了照顾移动端输入法习惯,把这两个键藏进次级页或者干脆省掉。但一旦你用它连远程终端、或者在编辑器里操作,没有 Esc 会非常难受。我的做法是把 Esc 固定在左上角第一个位置,Ctrl 固定在左下角,两个键都用粘滞语义,这样单手也能完成组合键。
第二是 Enter 的形态。默认布局里 Enter 常常是一个窄键,需要精确点按。触屏上这个体验很差,尤其是快速发消息的时候。把它加宽、并放在右手拇指的自然落点上,误触率会明显下降。同时要确认它发出的是回车还是换行——在聊天软件里这两者行为不同,选错了会出现“按了没反应”的错觉。
第三是方向键的排布。手机上常见的做法是塞进次级页,但如果你经常用这套键盘操作终端或者做表格,把方向键做成一块紧凑的四向区域放在右下角会更实用。代价是占用了原本属于符号键的空间,所以这个改动要根据你的主要用途来权衡。
为了让你更直观地判断该改哪里,我把自己常用的改动整理成了一张对照表:
| 改动项 | 默认情况 | 我的改法 | 收益 |
|---|---|---|---|
| Esc | 常被省略或藏在次级页 | 固定左上角,粘滞语义 | 终端操作不中断 |
| Ctrl | 常缺失 | 固定左下角,粘滞语义 | 单手可完成组合键 |
| Enter | 较窄,位置偏中 | 加宽,置于右手拇指落点 | 减少误触 |
| 方向键 | 常进次级页 | 右下角紧凑四向区 | 终端与表格效率提升 |
| 空格 | 常规宽度 | 宽度加倍,居中偏下 | 长按拖动手势更稳 |
4.3 改完之后怎么验证没写坏
布局文件改错时的失败模式很隐蔽:程序可能照常启动,界面照常画出,只是某一块区域变成空白,或者某个键按下去没反应。如果不去验证,很可能带着一个坏键用很久。
我的验证流程是三步。第一步看渲染:启动后扫一眼整块键盘,确认每一行按键都在自己该在的位置、文字没有被明显裁切、没有出现空白格子。空白格子往往意味着该条目的键值符号拼写有误。第二步逐键点击:打开一个纯文本编辑器,把每个按键都点一遍,确认输出的字符和预期一致。这一步听起来笨,但它是唯一能发现“显示对了、发出错了”这类问题的方法。第三步测组合:把粘滞修饰键和字母键组合起来试一次,确认组合确实生效,而不是只发了一个修饰键。
还有一个容易被忽略的验证点:长按行为。删格键、退格键这类按键在长按时应该连续触发,如果布局里把它的语义写成了普通字符键,长按就不会重复,删一段文字会变成一件极其痛苦的事情。这一点在第二步逐键点击时顺便就能测出来。
5. 键盘不出现时,我是怎么一层层把问题逼出来的
前面几章都是顺利路径。真实情况是,绝大多数人第一次跑 wvkbd 都不会一次成功,而且失败现象高度相似——什么都不发生。这一章把我遇到过的问题按“排查顺序”整理出来,每一步都带上判断依据,你可以照着链路走一遍。
5.1 第一步先确认协议在不在:合成器支持性排查
排查永远从最底层开始。键盘进程能不能真正干活,取决于合成器是否提供了它需要的两条协议。判断方法不需要读源码,用最直接的手段:在终端里前台启动键盘进程,观察它的标准输出。协议绑定失败通常会有提示,哪怕很简短。
如果前台启动完全没有输出、进程也不退出,但屏幕上什么都没有,那大概率是 layer 面板创建被拒。这时要去看合成器的日志,确认它是否支持 layer 协议,以及有没有相关报错。有些合成器版本较老或者编译时裁掉了这部分功能,这种情况下再怎么改参数都没用,只能换合成器版本或者换方案。
如果键盘能画出来、按键有按下高亮,但输入框里什么字都不进,那问题落在第二条协议上。这时候可以做一个非常干脆的判断实验:打开一个最简单的输入界面,点进去让光标闪起来,再点键盘上的字母键。光标连位置都不动,说明按键事件根本没进到客户端;如果光标动了但字符没出现,那是另一个层面的问题,通常和键位映射有关。
注意:不要靠“看起来有没有反应”来判断,一定要用光标位置这种客观指标。按键高亮只是本地绘制效果,它亮了不代表事件发出去了。
5.2 出现了但被挡住或位置错乱:图层与独占区的问题
键盘确实出现了,但是被状态栏挡住、或者跑到屏幕中间、或者只露出半个——这类问题都出在图层和占位设置上。
layer 面板在屏幕上的层级是分档的,软键盘一般应该放在最上面那一档,否则某些全屏窗口会盖住它。如果发现键盘在切换窗口后“消失”,第一反应应该是层级不够,而不是进程挂了。验证方法很简单:把当前窗口最小化或者切到空白工作区,看键盘是否重新出现——重新出现就确认是层级问题。
位置错乱的另一个常见原因是合成器给面板预留的独占区没算对。有些合成器会因为面板的存在而缩小可用窗口区域,有些则不会。当你发现开了键盘之后窗口内容被挤压、或者反过来键盘盖住了窗口内容时,需要去查合成器关于面板占位的配置项,而不是调键盘自己的位置参数。这个分工要记牢:键盘管自己画多大、画在哪块屏;占不占位、占多少,是合成器的职责。
还有一个非常容易被误判的情况:屏幕旋转过之后,键盘画出来的尺寸没变但屏幕的有效区域变了,于是看起来像是“键盘太宽溢出屏幕”。这时候去调键盘宽度是徒劳的,正确做法是检查输出变换设置,以及是否有横竖屏两套参数而只填了一套。
5.3 按键有反馈但字不进去:焦点与键位映射
这一类问题最折磨人,因为所有表象都是“正常的”:键盘显示正常,按下有高亮,甚至能听到合成器的按键提示音,就是输入框没反应。
我遇到的几种原因,按可能性从高到低排:
- 焦点没有真的在输入框上。触屏上点输入框这一步很容易没点准,尤其是小尺寸输入框。判断方法是点完之后看有没有光标闪烁或者边框高亮变化。没有的话,先解决焦点问题,键盘是无辜的。
- 键位映射没建立成功。虚拟键盘需要向合成器提交一份键位映射表,如果这一步失败,后续所有按键都会落在无效键码上。这种现象的典型特征是“所有键都无效”,而不是个别键无效。区分“个别无效”和“全部无效”非常重要,前者是布局文件问题,后者是链路问题。
- 和输入法框架抢了通道。如果你同时启用了输入法框架并且它自带了虚拟键盘模块,两套东西可能互相干扰。判断方法很直接:临时停掉其中一个,看问题是否消失。这类冲突在混合使用时出现概率不低,我在一台设备上就遇到过两套软键盘交替弹出的情况,最后是通过明确分工解决的——日常简单输入用 wvkbd,需要候选词时再切输入法。
- 按键被重复处理。个别情况下一次触摸会触发两次按下事件,表现为输入一个字符出现两个。这个通常和合成器对触摸事件的处理有关,排查时可以换一个简单的点击测试界面观察。
5.4 长按重复与多点触控的边界情况
长按重复的体验在触屏上很关键。删格键长按要能连续删、方向键长按要能连续移动,否则操作效率会低到无法接受。如果发现长按只触发一次,先确认布局里那个键的语义是否支持重复(4.3 节讲过验证方法),再确认合成器有没有对触摸长按做额外处理。
多点触控的边界问题更微妙。软键盘本身对多指同时按下通常只处理其中一个,这意味着你没法像物理键盘那样同时按两个字母。组合键必须靠粘滞修饰键来实现,这也解释了为什么修饰键的设计在这类键盘上这么重要。如果你发现按住一个键再按另一个键时行为诡异(比如第一个键卡住不放),那基本可以确定是触摸事件没有被正确释放,检查方法是逐个手指抬起,看高亮是否随之消失。
6. 日常使用中的小工具链与真实体验
把键盘跑起来只是开始,能不能长期用得舒服,取决于它怎么被集成进你的日常流程。这一章讲几个我实际在用的做法,以及长时间使用后的真实感受。
6.1 自启动写在合成器配置里,而不是系统服务里
我一开始图省事,把键盘写成了开机自启的系统服务。结果很快就发现问题:服务启动时机和合成器就绪时机不一定对齐,有时候键盘先起来,找不到可用的 Wayland 会话,直接退出;有时候运气好起来了,但绑定到了错误的输出上。这种“时好时坏”的状态最难排查,因为每次重启现象都不一样。
改成写在合成器自己的配置里之后就稳定了。合成器配置里的启动项天然是在会话就绪之后执行的,环境变量、输出信息、协议支持全都是现成的,键盘一起来就在正确的环境里。这个改动看起来只是换了个位置,实际解决的问题是“启动顺序依赖”——这个坑在集成任何 Wayland 客户端程序时都值得记一下。
配置里我建议同时把输出绑定和隐藏启动都写进去,一次性把初始状态定好,避免后续还要手动调整。
6.2 一个开关脚本解决“平时不需要键盘”的问题
3.4 节给过脚本雏形,这里说说实际用下来需要注意的细节。
第一是进程名匹配要精确。如果你的布局用的是带后缀的可执行文件,脚本里的匹配串也必须跟着改,否则会出现“判断不到进程、每次都启动新的”这种问题,结果就是屏幕上叠了好几个键盘实例,看起来像鬼影。
第二是给切换留一点延迟。快速连按快捷键时,切换信号可能在键盘完成上一次状态转换之前就到达,导致状态错乱(该显示的没显示,该隐藏的反而出来了)。实际操作中我养成了一秒内不连按的习惯,问题就消失了。
第三是异常退出后的状态清理。如果键盘进程因为某种原因挂了,脚本再次执行时会重新拉起一个新的,这是符合预期的。但如果挂的时候正处在显示状态,会留下一个看不见但占着的 layer 面板。解决办法是在脚本里加一步判断,在拉起新实例之前确保旧实例已经彻底退出。
6.3 功耗与响应:长时间挂着到底值不值
这是我最关心的实际问题,因为设备是电池供电的。
从功耗角度看,wvkbd 没有后台轮询、没有定时重绘,只有触摸事件才触发绘制,隐藏状态下基本不消耗 CPU。我在一台设备上对比过“整天挂着显示”和“按需呼出”两种用法,续航差异很小,属于可以忽略的量级。真正耗电的是屏幕本身——深色键盘在 OLED 屏上反而比亮色更省,这也是我在 3.2 节推荐深色背景的原因之一。
响应方面,从触摸到字符出现基本感觉不到延迟,这一点比基于完整输入法框架的方案有明显优势。原因是链路短:触摸事件直接转成按键事件提交给合成器,中间没有组字、候选、上屏这些环节。代价是中文输入需要额外配合,这个取舍要提前想清楚——如果你的主要输入是中文长文本,wvkbd 作为唯一方案会很别扭;如果主要是输入命令、密码、短消息、表单,它就是最顺手的那个。
最后提一句维护成本。这套东西我从编译到日常使用,前后改过两次布局、调整过一次高度,之后就再没动过。系统升级也没有出现过因为依赖变动而挂掉的情况——依赖少的方案在这个维度上确实省心。唯一需要留意的上游变化是协议本身,不过那属于比较长周期的事情,日常使用基本感知不到。
我个人在实际操作中的体会是:选软键盘这件事,不要一上来就找功能最全的。先明确你到底需要什么——是中文长文本,还是命令与表单;是一次输入几十个字,还是频繁短促的确认操作。答案不同,方案就差得很远。wvkbd 在“频繁短促输入 + 需要随时呼出 + 希望改键就改键”这个组合下几乎是无敌的,而在“长时间写作”这个场景下它只是配角。想清楚定位,再决定把它放在工具箱的哪个位置,比反复折腾配置有效得多。