螺纹输入冒险

2021-01-22 14:25:01

过来吧,在本文中,我们将讨论Mutter如何在本机后端中获得输入线程。

Mutter并非总是一个独立的合成器工具包,过去它曾经依赖于Clutter和Cogl库来获得工具包通常带来的所有好处:能够在屏幕上画图并能够接收输入。

在Wayland的崛起中,对外部工具箱的依赖促使许多设计决策围绕输入管理进行,通常涉及在工具箱中添加支持以及必要的挂钩,以便Mutter可以使用或修改行为。双方不可避免地参与其中。

后来,Mutter合并了自己的Clutter和Cogl副本,但最初的API障碍基本上保持不变。随着时间的流逝,并且仍在持续进行中,我们一直在对Mutter进行重构,以便所有与您操作系统的底层对话的代码都一起存储在src /后端中,从而使这些代码脱离了Clutter和Cogl。

但是,就输入而言,Clutter API障碍在大多数情况下仍然存在,它仍然受到X11设计的严重影响,并且在最初设计时就被大量使用。一些例子,没有特殊的恶名或秩序:

我们仍然以紧凑的方式转发输入轴,这要求查询输入设备以将event-> motion.axes [3]位置解码为CLUTTER_INPUT_AXIS_PRESSURE。节省空间的特性直接来自XIEvent和XIQueryDevice。

指针约束是通过挂钩可以施加最终指针位置的函数来完成的。

由于CLUTTER_TOUCH_CANCEL的语义略有不同,因此wl_touch.cancel的发出对libinput事件处理产生了奇怪的影响。

完善这些交互,使后端代码保持更独立,这是所涉及工作的重要组成部分。

主线程上下文已经是一个繁忙的地方,在最坏的情况下(并且已大大简化),我们:

全部在一帧的过程中。输入线程将退出该过程的第一步。为了使它无缝运行,线程需要一定程度的独立性,它需要产生ClutterEvents并知道在没有任何外部代理的情况下指针将最终到达何处。例如:

输入线程接管所有这些。主线程当然会有一些参与(例如指定有效的障碍或约束或虚拟输入),但是这些同步点要么稀缺,要么已经隐式异步。

输入线程的主要目标是为主线程提供ClutterEvent,而实际上它们是在无关的线程中产生的。为此,从它们派生的所有信息必须独立于输入线程状态。因此,将ClutterInputDevice和ClutterInputDeviceTool(代表输入设备和绘图板工具)变形为不可变的对象,其下的所有更改(例如,配置)都在输入线程内部进行处理,并在发出的事件中抽象化。

使线程始终准备好分派libinput听起来可能只是为您提供新框架所涉及的复杂性的一小部分,但这确实带来了一些好处:

Libinput事件始终总是尽快分派,因此这将减少日志中的“客户端错误:事件处理滞后XXms”消息。

输入处理不会因主线程中的其他操作而停顿,这意味着更少的尴尬情况使我们无法及时处理事件(例如,至少在合成器端重复执行了一个键释放停止键)。

使用输入线程单独绘制光标逻辑位置,更新光标平面位置以反映下一帧的最新位置,只需要向输入线程询问即可。

通常,输入代码的组织比较整齐,其中较少的细节泄漏到后端域之外。

代码总是走到更好的地方,合并的工作并没有实现所有可能实现的目标。以下是您不希望看到的固定问题:

主线程仍然负责KMS,并更新光标平面缓冲区和位置。这意味着即使主线程停止运行,指针光标仍将冻结,尽管下面有输入线程处理事件。将来,还会有另一个单独的线程来处理原子KMS操作,因此输入和KMS线程可以在它们之间进行交谈并绕过任何主线程停顿。

如果您需要在硬锁定时切换到另一个TTY,则主线程仍会涉及Ctrl + Alt + Fn的处理。对于开发人员来说,使其完全在输入线程中进行处理将是一件小事,也许是将来的工作。

拥有几乎不受任何其他事物阻碍的输入处理能力是处理1000Hz鼠标和其他高频输入设备的先决条件。 但是,针对这些行为的节流行为没有改变,短期内应该会有更好的行为。 到目前为止,我们一直在努力使Mutter尽快运行并尽可能地解除锁定。 这是迈向更高级别设计的第一步,该设计在内部可以防止失速情况。