GTK 4.11.1

这是新开发周期的第一个 GTK 快照。最近很多事情都到位了,所以值得花一些时间来了解一下新内容以及您在 4.12 中可以看到的内容。

列表视图改进

GtkListView、GtkColumnView 和 GtkGridView 小部件系列是 GTK 4 中的重大新增功能之一。它们旨在取代 GtkTreeView,但到目前为止,这显然仍然有点理想化。

在 GTK 4.10 中,我们终于迈出了将 GtkFileChooser 从树视图移植过来的重要一步,这表明列表视图已准备好投入使用。下一个 GTK 4 版本将带来许多缺失的功能

  • 最后,修复了长期存在的滚动错误
  • 更好的键盘导航,具有可自定义的 Tab 键行为
  • 焦点控制
  • 程序化滚动
  • 章节,也许

其中一些已经在 4.11.1 中可用。我们甚至设法将滚动修复反向移植到 4.10.1。

更好的纹理

纹理在 GTK 的 GL 渲染器中经常使用,用于图标和图像、字形以及中间的离屏渲染。大多数时候,我们不必考虑它们,它们只是工作。但是,如果纹理是您的应用程序的主要内容,例如在图像查看器中,您需要对其进行更多控制,并且重要的是,极端情况可以正常工作。

在 GTK 4.10 中,我们引入了 GskTextureScale 节点,该节点使应用程序可以控制在放大或缩小纹理时应用的过滤。这使应用程序可以请求使用具有 GSK_SCALING_FILTER_TRILINEAR 的 mipmap。GTK 4.12 将在有利时自动使用 mipmap。

我们最近探索的一个极端情况是纹理切片。每当纹理大于 GL 堆栈支持的大小时,GSK 会将其分解为较小的切片,并为每个切片使用单独的 GL 纹理。现代 GPU 支持巨大的纹理(在我的系统上,最大纹理大小为 16384),这意味着切片支持在实践中很少经过测试,也没有被我们的单元测试很好地覆盖。

我们添加了对人为限制纹理大小的支持(使用 GSK_MAX_TEXTURE_SIZE 环境变量),并立即发现我们的纹理切片支持需要一些改进。它将在 4.12 中运行得更好。

分数缩放

它在 4 月 1 日发布,但这不是玩笑。

我们已将对实验性 wp_fractional_scale_manager_v1 协议的支持添加到 Wayland 后端,并使用 wp_viewporter 协议告知合成器有关缓冲区正在使用的缩放比例。很高兴这很容易适应我们的渲染堆栈,但不要期望奇迹发生。它在 cairo 渲染器中运行良好(如您在视频中看到的),但我们仍然认为它在 GL 和 Vulkan 渲染器中是实验性的。

要尝试使用 GL 渲染器的分数缩放,请设置

GDK_DEBUG=gl-fractional

在环境中。

总结

GTK 4.11 中有很多新事物值得探索。请尝试它们,并通过 gitlabDiscourse 告诉我们您的想法。

GTK 内部的更新

一些核心 GTK 开发人员最近聚在一起几天,进行一些有重点的工作并讨论当前和未来的计划。

很难在一篇博客文章中总结三天的讨论,但这里有一些重点。

图标主题

GtkIconTheme 代码已经存在很长时间了。它实现了图标主题规范,并且来自我们随桌面发布大型图标集并期望主题将其切换出来的时代。这并不是今天制作或使用图标的真正方式。

我们需要一个更好的解决方案,用于从设计师在工作表中制作图标集到开发人员将单个图标复制到他们的应用程序中的工作流程。

在 GTK 内部,这将需要某种形式的“资产管理器”来维护从图标名称到图像/文件/资源的映射。

语言

虽然我们无法摆脱为我们所有的语言绑定提供带有 gobject-introspection 元数据的 C 接口,但使用比 C 更具表现力的语言和更强大的编译器可能会更好。

当然,我们不能也不会用不同的语言重写所有 GTK。尝试替换较小的部分会很好。允许用不同的语言编写新代码也可能会引入新的贡献者。

输入

我们讨论了滚动速度问题,并决定在关于我们认为正确解决方案的问题中写一个解释性评论

  • 分别处理滚轮和触摸板滚动
  • 将来自控制中心/合成器的配置注入 libinput
  • gtk 通过事件获取

我们讨论的另一个主要的输入问题是“异步事件处理”及其问题。出现这种情况的两个主要案例是 webkit,其具有 ui<>web 进程通信,以及 IBus。在这两种情况下,我们认为实际上没有兴趣将未处理的事件重新注入到 GTK 捕获/冒泡传播中。相反,此类剩余事件应仅“本地”处理(在 IBus 的情况下,向条目添加/删除字符,或移动光标)。

平台库

使用 GTK4,我们有意地改变了将所有内容都放在 GTK 本身中的做法,而是引入了“平台库”(如 libadwaita)的概念,以承载更多特定于平台的窗口小部件。

总的来说,我们对这种结果感到满意,并且我们希望继续这种方法。也许可以将一些比窗口小部件更像是管道的东西移回 GTK 本身。

GTK5?

我们需要打开一个 .90 分支来执行会破坏我们现在已弃用的 API(例如文件选择器,以及更通用的选择器对话框/小部件拆分)的操作。我们中的一些人一直渴望开始这项工作。但是,在 4.x 中仍然有很多工作要做(例如 GtkListView 修复)。

考虑到计划在 4.12 中实现的颜色管理工作,建议在 4.12 之后打开一个 4.90 开发分支。这将使其在今年年底,并在 4.0 发布 3 年后,这似乎是合理的。

结束

在最后一天,我们很高兴在我们的地方接待了文档和跟踪团队。

一个房间里的三个黑客马拉松!

我们要感谢 GNOME 基金会支持我们的会议。❤️

文件选择器的网格

在上一篇文章中,我们讨论了弃用树视图和单元格渲染器等。所有这些弃用都会给使用这些 API 的应用程序和库带来大量工作,那么我们为什么要这样做呢?

原因之一是为了启用新功能。例如文件选择器的网格视图。我们只用了 18 年!您可以在 Bugzilla 中查看原始的功能请求。现在这很容易实现,因为 GtkListView 和 GtkGridView 可以使用相同的数据模型。

这是带有新的视图切换的文件选择器

这是网格视图本身
从合并请求的喜欢数量来看,这是一个受欢迎的功能。我们希望您喜欢它。❤️

如果您想支持这项工作,请考虑向支持 GTK 开发的 GNOME 基金会捐款。您可以通过点击此处进行捐赠。

关于弃用

如果您关注 GTK 的 git 存储库,您可能会注意到最近几周发生了变化。

我们有一个名为 gtk/deprecations 的目录,该目录用于存放实现已弃用的 API 的源文件,这些 API 将在下一个主要版本中删除。在 4.0 版本中,我们清空了该目录,并且它一直处于空状态。但最近,它又开始重新积累文件。

这是一个很好的机会来提醒大家我们在 GTK 中如何使用弃用。但首先,让我们来看看细节。

细节,第一部分:单元格渲染器

在 GTK 4 中,我们引入了一系列新的基于列表模型的列表和小部件:GtkListView、GtkColumnView、GtkGridView。还有一个使用列表模型的新组合框实现,名为 GtkDropDown。总的来说,这些旨在为你在 GTK 3 中使用单元格渲染器所能做的一切提供替代方案。

最终目标是移除单元格渲染器,因为它们是一个独立的渲染和布局系统,往往会干扰 GTK 的 CSS 和布局机制,使一切变得更加复杂。

但我们并没有完全在 4.0 版本中完成,主要是因为我们在 GTK 本身中仍然大量使用树视图。首先是文件选择器。由于文件选择器将在 4.10 版本中移植为使用 GtkColumnView,现在是时候弃用单元格渲染器机制以及所有使用它们的窗口小部件了。

这是一个大量的代码,超过 75,000 行。

细节,第二部分:对话框

在 GTK 4 中,我们删除了 gtk_main() 和 gtk_dialog_run(),因为最好避免递归主循环。同样,我们没有完成,无法删除 GtkDialog 本身,因为它被用作我们所有复杂对话框的基类。

GTK 4.10 为我们的“选择器”对话框引入了替代 API。新的 API 遵循 gio 异步模式。这是一个示例

GtkFileDialog * gtk_file_dialog_new (void);

void            gtk_file_dialog_open (GtkFileDialog *self,
                                      GtkWindow *parent,
                                      GFile *current_file,
                                      GCancellable *cancellable,
                                      GAsyncReadyCallback callback,
                                      gpointer user_data);

GFile *        gtk_file_dialog_open_finish (GtkFileDialog *self,
                                            GAsyncResult *result,
                                            GError **error);

这在 C 语言中看起来可能有点笨拙,但它可以很好地转换为具有 Promise 和异常概念的语言

try {
  const file = await dialog.open(parent, ...);
  
  ...
} catch (e) {
  ...
};

要了解有关新 API 的更多信息,你可以查看它们的在线文档:GtkColorDialogGtkFontDialogGtkFileDialogGtkAlertDialog

有了这些替代方案,我们可以弃用选择器接口、它们的窗口小部件实现以及它们的基类 GtkDialog。

无需惊慌

GTK 中的弃用是对下一个主要版本中将出现的 API 兼容性破坏性变更的早期展望。但是最终的 GTK 5 版本还很遥远。我们甚至还没有制定它的计划。

完全没有必要急于进行“弃用清理”。你只需要在想要移植到 GTK 5(它还不存在)时删除所有弃用的用法。

不过,你仍然可以做一些事情。我们在 4.10 中引入弃用是为了让我们的用户有时间适应,并为我们的想法提供反馈。如果你想这样做,你可以在 gitlab 中提交问题,在 discourse 中开始讨论,或者在 matrix 上找到我们。

与此同时…

弃用警告可能会很烦人,但幸运的是,有简单的方法可以关闭它们。对于偶尔调用已弃用的函数,最好将其包装在 G_GNUC_BEGIN/END_IGNORE_DEPRECATIONS 中

G_GNUC_BEGIN_IGNORE_DEPRECATIONS
gtk_dialog_add_button (dialog, "Apply", GTK_RESPONSE_APPLY);
G_GNUC_END_IGNORE_DEPRECATIONS

如果你确定你永远不想看到任何弃用警告,你也可以直接将 -Wno-deprecated-declarations 传递给 gcc。

GTK 字体选择器内部

我之前写过关于 GTK 中字体处理的文章:之前。这篇文章将重点介绍如何在你的应用程序中使用更高级的字体(和字体选择器)功能。

查找字体

文件选择器最突出的最终用户功能当然是你可以使用搜索条目按名称搜索字体

一个更隐藏的功能是你可以按各种标准过滤列表。一个标准是只显示等宽字体,另一个是只显示涵盖特定语言的字体

这里需要注意的一个小细节是,GTK 会自动更改预览文本以匹配你正在过滤的语言。

少即是多

字体选择器返回一个 PangoFontDescription,其中包含所选字体的完整详细信息:字体系列、样式、大小等。如果你的应用程序只需要字体系列,那么让用户选择样式和大小却被忽略是很令人困惑的。

如果你的应用程序是这种情况,你可以使用 gtk_font_chooser_set_level() 和 GtkFontChooserLevel 标志来告知 GTK 你需要的字体详细信息

typedef enum {
  GTK_FONT_CHOOSER_LEVEL_FAMILY     = 0,
  GTK_FONT_CHOOSER_LEVEL_STYLE      = 1 << 0, 
  GTK_FONT_CHOOSER_LEVEL_SIZE       = 1 << 1,
  GTK_FONT_CHOOSER_LEVEL_VARIATIONS = 1 << 2,
  GTK_FONT_CHOOSER_LEVEL_FEATURES   = 1 << 3
} GtkFontChooserLevel;

例如,在

gtk_font_chooser_set_level (chooser, 
                            GTK_FONT_CHOOSER_LEVEL_FAMILY);

之后,字体选择器看起来像这样

简单得多!

进入深渊

现代字体是很复杂的野兽,表面下隐藏着很多东西。如果告诉它,GTK 字体选择器可以使许多这些字体功能可用。

首先,有字体变体。这些让你连续变化字体的特征(只要这些特征作为变体轴暴露出来)。

 

典型的变体轴是字体的粗细、宽度和倾斜度,但可能还有其他轴(例如本例中的光学大小)。

所选变体是字体选择器返回的 PangoFontDescription 的一部分,应用程序无需执行任何额外的工作来应用它们。只需像往常一样使用字体描述。

要在 GTK 文件选择器中启用字体变体支持,请使用 GTK_FONT_CHOOSER_LEVEL_VARIATIONS 标志

level = level | GTK_FONT_CHOOSER_LEVEL_VARIATIONS;
gtk_font_chooser_set_level (chooser, level);

更多功能

字体不仅包含字形轮廓,还包含许多其他数据,这些数据可以在渲染这些字形时以各种方式应用。这包括传统的字距调整和连字数据,还包括可选的字形形状或位置变体,甚至是调色板。通过使用 OpenType 功能,用户可以启用其中的许多功能。

这是一个用于字形形状变体的 OpenType 功能的示例


从左到右切换时在此处打开的功能称为 ss12。值得庆幸的是,字体还提供了更有意义的名称“单层 g”。

此示例显示了 frac 功能对分数显示的效果。

在 GTK 字体选择器中,OpenType 功能与变体显示在同一页面上。如你所见,它们可能有很多

请注意,Pango 将 OpenType 功能与字体本身分开处理。它们不是字体描述的一部分,但必须使用 PangoAttributes 或通过 Pango markup 应用于文本。

要应用来自 GTK 字体选择器的所选字体功能,请调用 gtk_font_chooser_get_font_features() 并将返回的字符串传递给 pango_attr_font_features_new()。

要在 GTK 文件选择器中启用 OpenType 功能支持,请使用 GTK_FONT_CHOOSER_LEVEL_FEATURES 标志

level = level | GTK_FONT_CHOOSER_LEVEL_FEATURES;
gtk_font_chooser_set_level (chooser, level);

总结

总而言之,你可以使用 GtkFontChooser 的 level 属性来影响你向应用程序用户提供的字体选择粒度。如果你在其中包含字体功能,请不要忘记使用 PangoAttributes 或标记应用所选功能。

所有这一切都得益于 harfbuzz 为我们提供了一个跨平台的 API 来访问字体及其所有功能。否则,这是不可能的。值得指出的是,这是通过直接访问 harfbuzz 对象来完成的,而不是将所有 harfbuzz API 都包装在 Pango 中。

 

 

GTK 4.4

GTK 4.4.0 现在可以在通常的地方下载。以下是其中一些主要工作。

NGL 渲染器和 GL 支持

NGL 渲染器继续得到改进。这包括速度提升、变换渲染的修复、避免使用巨大的中间纹理以及正确处理部分彩色字体。在驱动程序开发人员的一些帮助下,NGL 现在可以与 Mali 驱动程序正确配合使用。我们计划在下一个周期中删除原始的 GL 渲染器。

在 GSK 之外,我们的 OpenGL 设置代码已经过清理和简化。我们越来越依赖 EGL,现在需要 EGL 1.4。在 X11 上,我们使用 EGL,如果需要,则回退到 GLX。在 Windows 上,我们默认使用 WGL。

我们的 GL 支持可以与最新的 NVidia 驱动程序配合使用。

主题

包含的主题已重新组织和重命名。我们现在提供的三个主题称为 Default、Default-dark、Default-hc 和 Default-hc-dark。Adwaita 主题正在迁移到 libadwaita。

在较小的主题改进中,包括新的错误下划线(现在是点状而不是波浪线)以及对半透明文本选择的支持。

输入

输入处理在本周期中得到了积极开发。我们匹配了内置输入法的行为与 IBus 的行为,用于显示和处理组合序列和死键。作为其中的一部分,我们现在支持多个死键和死键组合,这些组合不会产生单个 Unicode 字符(例如 ẅ)。

我们现在完全支持 32 位键码,因此使用 Unicode 键码(例如用于组合标记)是可行的。

表情符号

我们的表情符号数据已更新到 CLDR 39,我们正在寻找按语言和地区(例如 it-ch)翻译的表情符号数据。

调试

检查器现在默认启用,因此调试 GTK 应用程序应该会更容易一些。

Windows

除了之前提到的 WGL 改进之外,我们现在在 Windows 上使用 GL 进行媒体播放。4.4 版本末期的一个重大变化是,我们现在对平板电脑和其他输入设备使用 WinPointer API,取代了过时的 wintab API。Windows 上的 DND 支持也得到了改进,并且本地 DND 协议已被删除。

数据统计

GTK 4.4 是 5 个月开发的成果,共有 71 位开发者提交了 838 个独立的提交;总共添加了 88133 行代码,删除了 63094 行代码。

变更集最多的开发者
Matthias Clasen 456 54.4%
Benjamin Otte 82 9.8%
Emmanuele Bassi 48 5.7%
Alexander Mikhaylenko 35 4.2%
Chun-wei Fan 30 3.6%
Christian Hergert 18 2.1%
Luca Bacci 17 2.0%
Carlos Garnacho 10 1.2%
Bilal Elmoussaoui 10 1.2%
Florian Müllner 7 0.8%
Yuri Chornoivan 6 0.7%
Maximiliano Sandoval R 6 0.7%
Marc-André Lureau 5 0.6%
Marco Trevisan (Treviño) 5 0.6%
Pawan Chitrakar 5 0.6%
Piotr Drąg 4 0.5%
Timm Bäder 4 0.5%
Xavier Claessens 4 0.5%
Zhi 4 0.5%
Sebastian Cherek 4 0.5%

GTK 4 中的文本输入

为了总结最近关于输入主题的一系列文章,让我们来谈谈 GTK 4 中的文本编辑。

简单情况:快捷键

也许您只需要将一些键作为编辑命令来处理,例如 Ctrl-z 来撤消。在这种情况下,您可以使用带有操作的快捷键,并在您的 widget class_init 中设置所有内容。

/* install an undo action */ 
gtk_widget_class_install_action (widget_class,
                                  "text.undo", NULL,
                                  my_undo_func);

/* bind Ctrl-z to the undo action */
 gtk_widget_class_add_binding_action (widget_class,
                                      GDK_KEY_z, GDK_CONTROL_MASK,
                                      "text.undo", NULL);

复杂情况:文本编辑器

当您需要完整的文本编辑功能时,最好的方法是重用 GTK 中为此目的提供的现成 widget 之一:输入框之一,或者如果您需要一个成熟的文本编辑器,则使用 GtkTextView。

如果现有输入框都不符合您的用例,您也可以将您自己的 GtkEditable 实现包装在 GtkText widget 周围,并免费获得文本编辑 widget 的所有困难部分。GTK 文档 解释了如何做到这一点。

中间地带

但是,如果您不想要一个输入框,但仍然需要让用户方便地输入单个 Unicode 字符(如 ñ 或 Å)呢?我让您来提出一个用例(虽然我脑海中有一个)。

您可以做的一件事是直接使用 GtkIMContext,让它为您处理按键事件。它的工作方式是将按键事件控制器附加到您的 widget,并将输入法上下文连接到它

controller = gtk_event_controller_key_new ();
gtk_widget_add_controller (widget, controller);

im_context = gtk_im_multicontext_new ();
gtk_event_controller_key_set_im_context (controller, im_context);

现在,到达您 widget 的按键事件将被传递到输入法上下文中。将处理程序连接到其 ::commit 信号以接收已完成的输入

static void
commit_cb (GtkIMContext *context,
           const char   *str,
           DemoWidget   *demo)
{
  pango_layout_set_text (demo->layout, str, -1);
  pango_layout_set_attributes (demo->layout, NULL);
  gtk_widget_queue_draw (GTK_WIDGET (demo));
}

...

g_signal_connect (im_context, "commit",
                  G_CALLBACK (commit_cb), demo);

您可以将类似的处理程序连接到 ::preedit-changed 信号,以在预编辑期间提供用户反馈,就像 GtkEntry 一样。

单字符输入的完整示例可以在此处找到。

关于输入的更多信息

我之前写过关于输入的文章(这里这里),最近,Carlos 和我在 Guadec 上做了关于输入相关主题的演讲(幻灯片)。在这些文章中,我解释了死键的工作原理,以及如何键入

<dead_acute> A

以产生 Á 字符。

但是输入充满了惊喜,我刚刚了解到一种替代死键的方法,值得在这里介绍。

背景

首先让我们回顾一下当您将 <dead_acute> A 序列发送到 GTK 时会发生什么。

我们收到第一个按键事件,并注意到它是一个死键,因此我们将其存储在我们所谓的预编辑中,并等待下一个事件。当下一个键到达并且它代表一个字母(更准确地说,是 Unicode 类别 Ll、Lu、Lt、Lm 或 Lo 之一)时,我们查找与 dead_acute 匹配的 Unicode 组合标记,即 U+301 COMBINING ACUTE ACCENT,然后我们反转序列。所以提交的文本是

A <combining acute>

我们必须反转顺序的原因是,组合标记位于基本字符之后,而死键位于之前。

这可以工作,但对于编写多重音符字符来说有点不直观。您必须从上到下考虑您想要应用的重音,因为它们是倒退应用的。例如,要创建一个顶部带有尖音符的 Â,您键入

<dead_acute> <dead_circumflex> A

然后它会被反转并最终变为

A <combinining circumflex> <combining acute>

更好的方法

对我来说,按这个顺序指定重音感觉自然得多

  1. 给我一个 A
  2. 然后在上面放一个 ^
  3. 然后在上面放一个 ´

好消息是:我们可以做到这一点!键盘布局可以使用任何 Unicode 字符作为 keysym,因此我们可以直接使用组合标记,而无需绕道死键。

例如,“英语(美国,国际,AltGr Unicode 组合)”布局包含用于组合标记的键。使用此布局的一个小障碍是它默认情况下不会显示在 GNOME 设置键盘面板中。您必须运行

gsettings set org.gnome.desktop.input-sources show-all-sources true

使其显示出来。

此布局中的组合标记放置在“第三级”中。要使用它们,您需要设置一个“第三级选择器”键。在键盘面板中,这称为“替代字符键”。一个常见的选择是右 Alt 键。

完成所有这些准备工作后,您现在可以键入 A Alt+^ Alt+’ 来获得一个顶部带有 ´ 的 Â 。太棒了!

图形 API 探险

许多人正在致力于将桌面虚拟化 UI 移植到 GTK4。这通常涉及 virgl,而 GTK3 的解决方案是使用 GtkGLArea。

对于 GTK4,渲染无论如何都在 GL 中进行,因此只需将您的内容包装在 GdkTexture 中并将其交给 GTK 即可,可以通过将其用作带有 GtkPicture 的可绘制对象,或者使用您自己的 snapshot() 实现中的 GskTextureNode。

dmabuf 绕行

这是一个不错的理论,但实践更为复杂 - 内容通常以 dmabuf 对象的形式提供,并且使用 4k 渲染,如果可以,您真的想避免额外的副本。因此,我们不得不研究可用的解决方案,以便在不复制的情况下将 dmabuf 作为纹理导入 GL 中。

这变成了一场对图形 API 迷宫的快速浏览:OpenGL、EGL、GL ES、GLX、DRI……不胜枚举。最后,事实证明您可以使用 EGL 将 dmabuf 包装到 EGLImage 中,并使用 GL_OES_EGL_image 扩展从中创建 GL 纹理。

GLX 到 EGL

这在我们的 Wayland 后端中工作正常,该后端使用 EGL。不幸的是,我们较旧的 X11 后端有一个使用 GLX 的 GL 实现,并且似乎没有办法将 dmabuf 导入到 GLX 上下文中。

因此,我们不得不做一些额外的工作,并使我们的 X11 后端也使用 EGL。值得庆幸的是,Emmanuele 几年前有一个关于此类转换的旧的未完成的分支,经过一些初始的挠头,搞清楚了它为什么不渲染任何东西(在进行 GL 工作时总是这样)后,可以使其工作

解决方案

事实证明,使用 EGL 导入 dmabuf 完全可以在 GTK 之外完成,因此我们不需要为其添加特定于 Linux 的 API。为了避免您自己编写此类代码的麻烦,这里是我提出的代码。

在我们已经决定将 X11 后端移植到 EGL 之后,我了解到导入 dmabuf 的另一种可能性可能是使用 DRI3PixmapFromBuffer 从 dmabuf 创建一个 X11 pixmap,将其转换为 GLXPixmap 并使用 glxBindTexImageEXT 创建纹理。

图形 API 不是太棒了吗! :-)

输入,再探

我上次的更新谈到了 GTK 输入法中 Compose 序列的更好视觉反馈。我当时没有明确提及死键,但从历史上看,X11 对待死键和 Compose 序列的方式完全相同。

死键是某些键盘布局的一个功能,您可以在其中按下一个本身不产生字符的键,而是修改您键入的下一个键。通常,这用于可以与不同基本字符组合的重音。例如,键入 <dead_acute> <a> 以生成 á 或 <dead_acute> <o> 以生成 ó。

传统上,死键是真正“死的”——在最终结果出现之前,你不会得到任何视觉反馈。在上次更新中描述的改进之后,我们现在可以在输入时显示死键了。

这是一个很好的改进。但事实证明,并不是所有人都满意。

组合序列和死键的共享处理有一些影响:其中一个影响是,输入一个不存在的序列,例如 <dead_grave> <x>,将会产生蜂鸣声,并且没有输出。对于你用组合键显式启动的组合序列来说,这是可以接受的,但当你可能只是想输入 `x` 时,这就不是很好了。

那些决定使用组合序列来处理死键的人,预见到了偶尔需要实际输入间隔符的情况,因此添加了诸如 <dead_grave> <space><dead_grave> <dead_grave> 这样的序列来产生一个单独的 ` 字符。

虽然这是一个不错的想法,但这仍然非常不方便,因为你需要输入六次 <dead_grave> 才能产生 `‍`‍`,例如在 Markdown 中输入代码示例时。

在思考了一段时间并比较了其他系统的做法之后,我们做了两个更改,希望能够使死键的使用像键盘上的任何其他键一样方便。

  • <dead key> <key> 序列与我们的任何组合序列不匹配时,提交单独的键
  • 当一个 <dead key> 跟在另一个 <dead key> 之后时,提交第一个,并将第二个视为新组合序列的开始

总之,这样一来,键入 <dead_acute> <a> 会产生 á,键入 <dead_grave> <x> 会产生 `x,而你只需要键入三次 <dead_grave> 即可输入 `‍`‍`:

好多了!