GTK4 中的数据传输

桌面应用程序之间用户发起数据传输的传统方法是剪贴板或拖放。GTK+ 从一开始就支持这些方法,但在 GTK3 之前,我们用于这种数据传输的 API 是对相应的 X11 API 的简单伪装:选择、属性和原子。这并不奇怪,因为整个 GDK API 都是以 X11 为模型的。不幸的是,该实现包括诸如增量传输和字符串格式转换之类的弊端。

对于 GTK4,我们正在抛弃这些东西,因为我们正在将 GDK 中的内容移动得更接近 Wayland API。数据传输是迫切需要这种现代化的领域之一。值得庆幸的是,它现在几乎完成了,因此值得看看发生了哪些变化,以及未来事物将如何运作。

概念

如果您的应用程序想要发送的数据不是字符串,它可能是一些对象,例如 GFile、GdkTexture 或 GdkRGBA。接收端的应用程序可能不使用 GTK 或 GLib,因此不会知道这些类型。即使它知道,也没有办法将对象从一个进程完整地传递到另一个进程。

核心上,数据传输的工作原理是,发送应用程序发送一个文件描述符,目标应用程序从该文件描述符读取字节流。剪贴板和 DND 的协议使用诸如 text/uri-list、image/png 或 application/x-color 之类的 MIME 类型来标识字节流的格式。

发送对象涉及协商双方都支持的数据格式,将源端的对象序列化为该格式的字节流,传输数据,并在目标端反序列化对象。

本地情况

在进入具体的 API 之前,值得停下来考虑一下另一种常见的数据传输情况:在单个应用程序内部。使用相同的剪贴板和 DND 机制将数据从应用程序的一侧发送到另一侧是很常见的。由于在这种情况下我们没有跨越进程边界,因此我们可以避免字节流以及相关的序列化和反序列化开销,而只需传递对该对象的引用即可传输数据。

API

我们在上一节中提到的对象由 GType(例如 G_TYPE_FILE 或 GDK_TYPE_TEXTURE)描述,而正如所提到的,Wayland 和 X11 协议中的数据交换格式由 MIME 类型描述。

我们引入的第一个用于处理这些类型的 API 是 GdkContentFormats 对象。它可以包含格式列表,这些格式可以是 GType 或 MIME 类型。我们使用 GdkContentFormats 对象来描述应用程序可以提供数据采用的格式,以及应用程序可以接收数据的格式。

您可能想知道为什么我们在同一个对象中混合使用 GType 和 MIME 类型。答案是我们希望使用相同的 API 来处理跨进程和本地情况。虽然我们需要为跨进程情况匹配 MIME 类型,但我们需要本地情况的 GType。

转换

我们仍然需要一种方法来关联 GType 和 MIME 类型,以便我们可以相互转换。这由 GdkContentSerializer 和 GdkContentDeserializer API 处理。这些本质上是转换函数的注册表:GdkContentSerializer 知道如何将 GType 转换为 MIME 类型,而 GdkContentDeserializer 处理相反的方向。

GDK 具有用于常见类型的预定义转换,但该系统可以通过使用 gdk_content_register_serializer 和 gdk_content_register_deserializer 来扩展。

内容

现在我们知道如何描述格式以及在它们之间进行转换,但为了将所有这些整合在一起,我们仍然需要一个方便的 API,该 API 在一侧接收对象,并在另一侧提供字节流。为此,我们添加了 GdkContentProvider API。

GdkContentProvider 允许您将对象与输入端的格式描述结合使用,并在输出端提供异步写入器 API,该 API 可以连接到我们想要在其上发送数据的文件描述符。

典型的内容提供程序是这样创建的

gdk_content_provider_new_for_value (gvalue)
gdk_content_provider_new_for_bytes (gbytes, mimetype)

它接收的 GValue 包含对象及其类型的信息,因此如果我们提供对象作为 GBytes(本质上只是一段内存),则不需要额外的类型信息,我们需要单独提供类型信息。

剪贴板

GTK3 有一个 GtkClipboard 对象,它为复制/粘贴操作提供实现。在 GTK 中拥有此对象并不理想,因为它需要在 GTK 支持的平台上进行不同的实现。因此,GTK4 将该对象移动到 GDK,并因此将其重命名为 GdkClipboard。它也已被移植到上面描述的新数据传输 API。要在 GTK4 中将数据放入剪贴板,请使用“set” API 之一

gdk_clipboard_set_content()
gdk_clipboard_set_value()
gdk_clipboard_set_text()

最终,所有这些函数都会将 GdkContentProvider 与剪贴板关联起来。

要在 GTK4 中从剪贴板读取数据,请使用异步“read”API 之一

gdk_clipboard_read_async()
gdk_clipboard_read_value_async()
gdk_clipboard_read_text_async()

拖放

GTK3 拖放 API 涉及侦听 GtkWidget 上的多个信号,并为拖动源和目标调用一些特殊的设置函数。它很灵活,但通常被认为是令人困惑的,我们在这里不会详细描述它。

在 GTK4 中,拖放 API 已围绕内容提供程序和事件控制器的概念进行重组。要启动拖放操作,您可以创建一个 GtkDragSource 事件控制器来响应拖动手势(您也可以通过仅调用 gdk_drag_begin 来启动“一次性”拖放操作),并为要传输的数据提供一个 GdkContentProvider。要接收拖放操作,您可以创建一个 GtkDropTarget 事件控制器,并在它发出 ::drop-done 信号时调用异步读取方法

gdk_drop_read_value_async()
gdk_drop_read_text_async()

Guadec 上的 GTK BoF

像每年一样,我们在塞萨洛尼基的 Guadec 上举办了 GTK BoF。今年,我们的参与人数相当多 - 每个人都对 GTK4 计划感兴趣。

但由于 Emmanuele 早上很忙,我们首先讨论了一些其他主题。

GLib

我们从会议室收集了一些关于有用的 GLib 添加的建议。

  • 用于 OS 信息的 API(基本上是 /etc/os-release 中的数据)。这似乎没有争议;Robert 将会实现它
  • 一个有序的 map。这在许多地方通过将哈希表与列表或数组组合在一起进行临时实现。似乎达成了一致意见,即在 GLib 中提供此功能是值得的,前提是有人进行 API 提案的工作

关于有序 map 的讨论也触及了通用容器接口;Philipp 描述了如何做到这一点,请参阅此处的详细信息。

仍然是关于容器的话题,Alex 描述了传输注释的问题。我们讨论了各种想法,但可能没有完美的解决方案。

Matthias 指出,Pango 中仍然存在一些 Unicode 数据。我们简要讨论了拥有一个商定的、可映射的 Unicode 数据二进制格式是多么好,以便每个人都可以共享它。除此之外,将最后的数据移动到 GLib 没有争议。

暗黑模式

由于“暗黑模式”BoF 加入了我们,我们接下来转为讨论暗黑模式。在第二天的供应商主题 BoF 中对该主题进行了更多讨论;GTK 的讨论重点是如何实现暗黑模式的技术细节。

有多种选择

  • 向主题索引文件添加额外元数据,以将主题标记为暗黑
  • 添加一个“暗黑主题名称”设置,并将暗黑主题和浅色主题视为独立的
  • 保留现有的向主题名称附加“-dark”以查找主题的暗黑变体的约定

保留现有约定的务实解决方案似乎得到了会议室的支持。Matthias 开始探索一些应用程序支持 API 此处

GTK

最终,我们转为讨论 GTK4 的状态和进展。高级摘要是,GTK4 仍然需要完成一些功能

  • 一个可伸缩的列表视图,可以循环利用行小部件。这包括更广泛地在更多地方使用列表模型。为了使其完整,它还应包括使用这些技术的网格视图。Benjamin 正在从事这项工作
  • 动画的基础设施和 API。这将类似于 CSS 中动画的工作方式,并且部分工作不仅要移植我们现有的 CSS 动画支持,还要将堆栈切换动画、显示器、进度条和微调器移植到新框架。Emmanuele 正在从事这项工作。
  • 完成菜单/弹出窗口的重构。 有些人尝试了新的弹出窗口菜单栏。反馈是,我们应该回到嵌套子菜单,至少对于菜单栏来说是这样,并推进删除菜单,因为菜单的一些特殊之处(例如保持向上的三角形、滚动)很难保持工作(或保持良好工作)。 Matthias 将在 Guadec 之后重新开始处理这个问题。
  • 快捷键 – 用事件控制器替换助记符、加速键和按键绑定。 有一个相当完整的分支,其中包含代码和 API,一些人已经在这方面工作了; 如果能帮助审查和测试它,将不胜感激。
  • 新的拖放 API 需要完成。

好消息是,这个列表相当短,并且大多数项目都有名字。坏消息是,每个项目的工作量都相当大。 因此,在我们合并所有这些项目之前,承诺 4.0 版本的紧凑时间表并不是一个好主意。因此,以下是暂定的,但(我们希望)在某种程度上是现实的

  • 今年年底之前再发布一个 GTK 3.9x 快照
  • 在 2020 年春季与 GNOME 3.36 大约同时发布功能完整的 3.99 版本
  • 在 2020 年秋季与 GNOME 3.38 大约同时发布 4.0 版本

不可避免地,我们还讨论了其他一些希望拥有的东西。 这些都不在 GTK4 的路线图上; 但如果有人出现来完成这项工作,它们可能会发生

  • 一个“小部件存储库”或“hig”库,以便不会用过于具体或实验性的小部件来超载 GTK
  • 一个“UI 设计器”小部件。 这也可以存在于一个单独的库中
  • 更好地支持拆分标题栏和状态转换

我们还讨论了 GTK 本身之外的事情,这些事情会阻止应用程序移植到 GTK4。 这包括常用的库,例如 GtkSourceView、vte 和 webkitgtk,所有这些库都需要 GTK4 端口,然后依赖它们的应用程序才能被移植。 其中一些工作已经在进行中; 但在这方面提供任何帮助,我们将不胜感激!

GTK4 移植的另一个潜在障碍是平台支持。 GL 渲染器在 Linux 上运行良好; Vulkan 渲染器需要一些修复。 在 Windows 上,我们目前使用 Cairo 回退,这可能足以满足 4.0 的需求。 或者,我们可以合并 现有工作,将 GL 渲染器与 ANGLE 一起使用。 在 OS X 上情况不太乐观,我们没有可用的后端; 如果您想在这方面帮助我们,首先是将 GDK 后端适应 GDK 中的更改。

黑客时间

下午,房间从讨论转变为黑客马拉松,在人们的笔记本电脑上可以看到各种与 GTK 相关的工作正在进行中:加速 GtkBuilder 模板加载、嵌套弹出菜单、一个半成品 GtkSourceView 端口。

您将有望很快在 GTK master 中看到这些(和其他)内容。

GTK 3.96.0

本周,我们发布了 GTK 3.96.0。 同样,自从上次发布以来已经有一段时间了,因此值得总结一下此版本中的新功能。 这里的内容实在太多了,无法全部涵盖,因此这篇文章仅突出显示最重要的更改。

此版本是我们迈向 GTK 4 的另一个里程碑。 尽管仍有一些未完成的事情,但此版本比我们希望通过 GTK 4 实现的目标更接近。

GSK

GSK 已经进行了一些错误修复和新测试,使用新的调试工具 gtk4-node-editor 可以更容易地完成这些测试。 它可以加载和显示序列化的渲染节点树,例如从 GTK 检查器保存的那个,并比较不同渲染器的输出。

3D 转换支持已提升到我们可以进行动画转换的水平,如下面的立方体旋转所示。

GDK

向 Wayland 风格的 API 发展的趋势仍在继续,更多的 X11 专用 API 被移动到 X11 后端或直接删除。 子表面和全局坐标的使用已大大减少,但这项工作仍未完成。

拖放的重构也已继续进行,引入了 GdkDragGdkDrop 对象。 此重构的 GTK 部分仍未完成。

事件已得到简化,现在仅用于输入。 其他事件已被 GdkSurface 上的信号和属性取代。 具体来说,公开事件已被 ::render 信号取代,配置事件已被 ::size-changed 信号取代。 映射事件已被 :mapped 属性取代,gdk_event_handler_set() 已被 ::event 信号取代。

Wayland 后端已获得对 GtkSettings 的设置门户的支持,并使用 text-input-unstable-v3 协议来实现其输入法支持。

GTK

小部件

对于自定义小部件,一个重大变化是引入了 GtkLayoutManager,这是一个新的委托对象,负责接管大小分配。 布局管理器可以选择使用布局子项来保存布局属性。 这取代了 GTK 容器(例如 GtkBoxGtkGrid)中与布局相关的子属性。

有许多布局管理器可用

  • GtkBinLayout,用于简单的单子容器
  • GtkBoxLayout,用于线性排列的子项
  • GtkGridLayout,用于排列在网格中的子项
  • GtkFixedLayout,用于自由定位和转换的子项
  • GtkCustomLayout,作为一种将传统 measuresize_allocate vfunc 转换为布局管理器的快速方法

未来将出现更多布局管理器实现。 最突出的是,基于约束的布局管理器正在开发中。

GtkAssistantGtkStackGtkNotebook 已公开
其子项可访问的页面对象。页面对象
也通过列表模型公开。 这些容器的非布局相关的子属性已转换为这些页面对象上的常规属性。

由于所有现有的子属性都已转换为常规属性、移动到布局属性或移动到此类页面对象,因此已从 GtkContainer 中删除对子属性的支持。

核心 GtkEntry 功能已移至新的 GtkText 小部件中,该小部件还实现了扩展的 GtkEditable 接口。 GTK 中的所有现有条目子类都已转换为包装 GtkText 小部件的 GtkEditable 实现。 这还包括一个新的 GtkPasswordEntry

其他更改

GTK 小部件可以使用射影线性变换来转换其子项
变换。 此功能在 CSS 中可用,并且
作为 gtk_widget_allocateGskTransform 参数。 GtkFixed
第一个公开此功能的容器。 有关更多示例,
请参阅 GtkRevealer 的摆动转换、旋转转换
GtkStack 或 gtk4-demo 中的固定布局示例。

已引入许多列表模型,供内部使用
并作为公共 API:GtkMapListModelGtkSliceListModelGtkSortListModelGtkSelectionModelGtkSingleSelection。 当我们引入基于列表模型的 GtkListView 时,它们将得到更广泛的应用。

GtkBuilder 可以内联指定对象值属性,而不是通过 ID 引用它们,并且 gtk4-builder-tool 的 simplify 命令已获得一个选项,可以自动将 GTK 3 UI 定义文件转换为 GTK 4。

即将推出

有关 GTK 4 即将推出的更多信息,请在 Discourse、IRC 上找到我们,或在此处查看 这里

GTK 4 中的条目

最近在 GTK master 中完成的较大重构之一是重新设计条目层次结构。 这篇文章总结了已更改的内容,以及我们为什么认为这种方式更好。

GTK 3 中的条目

让我们首先看看 GTK 3 中的情况。

GtkEntry 是这里的基础类。 它实现了 GtkEditable 接口。 GtkSpinButtonGtkEntry 的子类。 多年来,添加了更多内容。 GtkEntry 获得了对条目完成、嵌入图标和显示进度的支持。 我们添加了另一个子类 GtkSearchEntry

这种方法的一些问题立即显现出来。 gtkentry.c 的代码超过 11100 行。 不仅很难在此大型代码库中添加更多功能,而且也很难对其进行子类化——这是创建您自己的条目的唯一方法,因为所有单行文本编辑功能都在 GtkEntry 中。

GtkEditable 接口非常旧——它在 GTK 2 之前就存在了。 不幸的是,它作为一个接口并没有真正成功——GtkEntry 是唯一的实现,并且它以一种令人困惑的方式在内部使用接口函数。

GTK 4 中的条目

现在让我们看看 GTK master 中的情况。

我们做的第一件事是将 GtkEntry 的核心文本编辑功能移到一个名为 GtkText 的新部件中。这基本上是一个没有所有额外功能的输入框,比如图标、补全和进度。

我们通过向 GtkEditable 接口添加一些更常用的功能(如 width-chars 和 max-width-chars)使其更有用,并使 GtkText 实现它。我们还添加了辅助 API,以便轻松地将 GtkEditable 实现委托给另一个对象。

“复杂”的输入框部件(GtkEntry、GtkSpinButton、GtkSearchEntry)现在都是组合部件,它们包含一个 GtkText 子部件,并将其 GtkEditable 实现委托给这个子部件。

最后,我们添加了一个新的 GtkPasswordEntry 部件,它接管了 GtkEntry 过去拥有的相应功能,例如显示大写锁定警告

或者允许用户查看内容。

为什么这样更好?

这次重构的主要目标之一是使在 GTK 之外创建自定义输入框部件更容易。

过去,这需要子类化 GtkEntry,并浏览一个复杂的 vfunc 迷宫来覆盖。现在,您只需添加一个 GtkText 部件,将其 GtkEditable 实现委托给它,就可以轻松获得一个功能齐全的输入框部件。

而且您可以灵活地在 GtkText 组件周围添加各种花哨的东西。例如,我们在 gtk4-demo 中添加了一个带标签的输入框,现在可以很容易地在 GTK 之外实现。

从 GTK 3 移植时,这会影响您吗?

在将代码移植到这种新的输入框样式时,有几个需要注意的潜在陷阱。

GtkSearchEntry 和 GtkSpinButton 不再派生自 GtkEntry。如果您看到有关将这些类之一强制转换为 GtkEntry 的运行时警告,您很可能需要切换到使用 GtkEditable API。

GtkEntry 和其他复杂的输入框部件不再可聚焦 – 焦点会转移到包含的 GtkText。但 gtk_widget_grab_focus() 仍然有效,并将焦点移动到正确的位置。您不太可能受到此影响。

大写锁定警告功能已从 GtkEntry 中删除。如果您将 GtkEntry 的 visibility==FALSE 用于密码,则只需切换到 GtkPasswordEntry。

如果您将 GtkEntry 用于基本的编辑功能,并且不需要任何额外的输入框功能,则应考虑使用 GtkText。

主题更改,再次回顾

快速更新上周关于主题更改的帖子

我们发布了 3.24.4 版本,以修复 3.24.3 中的一些疏忽。此版本包含新主题,我们将在下一个版本中推送。

我们还制作了另一个 NewAdwaita tar 包,其中包含根据上周收到的一些建议进行的改进。

试用一下,并告诉我们您的想法!

GTK 3 中的主题更改

Adwaita 一直是默认的 GTK+ 主题,已经很长一段时间了(在所有平台上)。它很好地为我们服务,但 Adwaita 一段时间没有进行重大更新,并且人们希望对其进行刷新。

更新 Adwaita 是一项挑战,因为大多数 GTK 应用程序都使用稳定的 3.x 系列,其中一些应用程序为其自己的自定义部件包含与 Adwaita 兼容的主题。鉴于此发布系列的稳定性,我们不希望给应用程序带来主题兼容性问题。同时,3.x 是当今使用的主要 GTK 版本,我们希望确保 GTK 应用程序不会感觉过时或老旧。

试验

已经考虑和讨论了许多解决此问题的方法。其中,提出了一个试用有限的主题更改的初步计划,并有可能将其包含在未来的 GTK 3 版本中。

我们希望,由于主题更改的有限性,它们不应该给应用程序带来问题。但是,我们不想仅仅把希望寄托在希望上。因此,接下来的三周被指定为测试和咨询期,如果一切顺利,我们希望将该主题合并到 GTK 3.24.4 版本中。

应该强调的是,这些更改仅限于 Adwaita 本身。自 GTK 3.22 以来,GTK 的 CSS 选择器和类没有更改,Adwaita 的更改不会影响其他 GTK 主题。

Adwaita 更新的主题与 GTK 3.24.3 版本并行提供为单独的 tar 包,可以在此处下载。邀请 GTK 应用程序开发人员试用 3.24.3 以及新版本的 Adwaita,并报告他们遇到的任何问题。GTK 团队和 Adwaita 作者也将进行自己的测试。有关如何以各种方式测试新主题的详细信息此处

我们希望在 GTK 的稳定性承诺与提供最新应用程序的愿望之间取得平衡。要做到这一点需要微妙的平衡,我们渴望在此过程中与 GTK 用户互动!

主题更改

本文的其余部分总结了对主题所做的更改。这有望证明这些更改的有限程度。它还将帮助开发人员知道在测试时要注意什么。

颜色

许多 Adwaita 颜色都进行了非常细微的调整。新颜色比以前的版本更鲜艳,因此使 Adwaita 更具活力和活力。新颜色也是更广泛调色板的一部分,该调色板用于应用程序图标。这些颜色也可以用于自定义应用程序样式。

颜色变化是微妙的,因此新旧版本之间的任何兼容性问题都不应该很严重。蓝色仍然是蓝色(只是稍微不同的色调!)。红色仍然是红色。在视觉上,主题的深色和浅色版本基本保持相同。

Adwaita 的深色变体,显示了旧版本(左)和新版本(右)之间细微的颜色变化。

请注意,在深色主题中,按钮的红色已略微调低。

标题栏和按钮

在更新的 Adwaita 版本中,大多数部件都没有进行特别更改。但是,标题栏和按钮是两个有特定于部件的更改的地方。在这两种情况下,都努力使其更轻巧和优雅。

按钮的实心边框已替换为阴影。它们的背景也更平坦,它们的拐角更圆。它们的形状也发生了非常细微的变化。

标题栏已更新以补充按钮更改。这主要是通过使它们的背景变暗来完成的,以便为按钮提供足够的对比度。标题栏的聚焦和未聚焦状态之间的对比度也增加了。这使用户更容易识别聚焦的窗口。

乍一看,这些变化是一些最重要的变化,但是它们是通过一些非常小的代码更改来实现的。

GNOME 日历应用程序中的标题栏(旧版本在顶部,新版本在底部)

开关

除了标题栏和按钮外,唯一要更改的部件是开关。当 GTK 首次引入开关时,它们在桌面上是一个相当新的概念。因此,它们包含明确的“ON”和“OFF”标签,以便传达开关的工作方式。此后,开关部件已变得无处不在,并且用户已经熟悉不包含标签的开关。

最新的 Adwaita 更改使该主题与其他平台保持一致,并通过删除标签并引入更圆润的形状,使开关在外观上更紧凑和现代化。

其他地方,没有变化

除了上述更改之外,Adwaita 中的其他内容几乎没有变化。绝大多数部件保持不变,尽管颜色略有变化。通常,UI 布局不应更改,用户应该对这些更改感到满意。

找出不同之处(旧版本的 Adwaita 在左侧,新版本在右侧)

结论

请试用新主题。我们希望您喜欢它!

我们感谢您的反馈 - 特别是如果您是 GTK 应用程序开发人员。您可以在 irc 上(在 GimpNet 上的 #gtk+ 频道中)或通过 gtk-devel-list 邮件列表提供反馈,或者在gitlab中提交问题。

来自 Guadec GTK+ BoF 的报告

在 Guadec 的 BoF 日期间,GTK+ 团队进行了一整天的计划会议,我们坐满了房间,包括来自几个下游(不仅仅是 GNOME)的代表。

我们的议程也安排得很满。

GTK+ 3

我们首先回顾了我们之前概述的 GTK+ 3 计划。

除了那里提到的内容外,我们还计划向后移植新的事件控制器,以使移植到 GTK+ 4 更容易。我们还将添加 meson 构建支持以帮助 Windows 构建。

3.24 版本将有效地成为 3.22 分支的延续,并且在发行版中作为稳定更新发布应该是完全安全的。

我们计划在 GNOME 3.30 发布时及时发布 GTK+ 3.24.0。

GTK+ 4 遗留问题

一天的大部分时间都用于讨论 GTK+ 4。我们回顾了路线图上的遗留任务列表

  • 完成 DND:GTK+ 级别的 手势,本地快捷方式
  • 引入 GtkToplevel 并干净地支持弹出窗口
  • 添加转换
  • 创建一个快捷方式事件控制器来替换按键绑定
  • 将 GtkTextView 移植到渲染节点
  • 分析 cairo 后端,确保其性能与 GTK+ 3 相当
  • 移植各种依赖库
    • vte
    • webkit
    • libchamplain
    • gtk-vnc
    • gtk-spice

这些任务中的大多数都有名字,但如果您想帮助完成这些任务中的任何一项,请务必与我们联系!

此列表中明显缺少以前在路线图上的一些内容

  • 基于约束的布局 (emeus)
  • 着色器编译器和应用程序提供的着色器
  • 设计器支持

如果出现合并请求,所有这些仍然可能发生,但我们认为我们不应该阻止它们。它们可以在 GTK+ 4 之外进行开发,并成为 GTK+ 5 的素材。

GTK+ 后端

我们花了一些时间评估 GTK+ master 中 GDK 后端的状态。

Windows 后端状态良好。我们有几个人帮助维护和进行功能开发,meson 使其构建更容易得多,并且我们有 ci 用于它。

Quartz 后端的状态要差得多。它没有保持可构建的状态,没有人为其提供修复或功能开发,并且我们没有 ci。我们提供了一台可以用于 ci 的 macbook,并建议我们可以使用 travis ci 来进行 OS X。

GTK+ 时间线

我们在这方面花费了很长时间,并没有达成 100% 的共识,但如果我们继续在未完成的遗留问题上取得良好进展,那么在 2019 年春季发布 GTK+ 4 似乎是现实的。

当我们发布 GTK+ 3.96 时,我们还将宣布 GTK+ 4.0 的日期。我们希望能够在 GNOME 3.32 之前承诺发布,这样 GNOME 应用程序开发人员可以将他们的 master 分支切换到 GTK+ 4,而无需担心这会破坏 3.32 的其他开发。

应用程序移植

我们现在非常希望收到来自应用程序端口的反馈。但是我们处于一个有点困难的境地,因为在 GtkToplevel 和快捷方式控制器工作完成之前,我们不能合理地声称已经完成了主要的 API 工作。

我们目前对应用程序作者的建议是

  • 如果您有点冒险精神,请在分支上移植到 3.94。在 GTK+ 4 开发的剩余时间内,应该可以在不需要太多工作的情况下保持其正常运行。
  • 如果您不那么冒险,请等到 3.24 发布,使用它来准备您的移植,然后移植到 GTK+ 3.96。
  • 无论哪种方式,请将您的移植提供给用户进行测试,无论是作为常规版本还是带有捆绑 GTK+ 的 Flatpak。

GLib 分流

下午,我们花了一些时间讨论 GLib。我们回顾了一长串大小项目。值得注意的亮点:GProperty 可能会在 2.60 中实现,我们可能很快就可以使用 g_autoptr。

其他想法

我们讨论了许多其他可以而且应该做的事情。

例如,有人建议(并且普遍同意)我们应该将 gsk 合并到 gdk 中,因为它很小,而且内部结构有些交织。还建议在 gtk/ 中创建子目录,例如用于 css 机制。

GTK+ 3.94

今天,我们发布了 GTK+ 3.94.0。同样,自上次发布以来已经有一段时间了,因此值得总结一下此版本中的新功能。这里的内容太多了,无法全部涵盖,因此这篇文章只会重点介绍最重要的更改。

此版本是我们迈向 GTK+ 4 的另一个里程碑。虽然还有一些未完成的事情,但此版本更接近我们希望使用 GTK+ 4 实现的目标。

GSK

Broadway 后端现在有一个 GskRenderer,因此 Broadway 的未来看起来更好。

我们引入了一种新的渲染节点类型 GskOffsetNode,它是一种简化的 GskTransformNode,并接管了在我们在渲染节点树中上下移动时转换内容的工作。通过此更改,我们现在可以缓存多个帧的小部件的渲染节点,并在必要时重新定位它们。

我们还引入了 GskDebugNodes,它接管了节点名称,并让我们简化了一些用于创建渲染节点的 GTK+ api。

当回退到 cairo 进行渲染时,我们现在使用记录表面而不是图像表面,因此我们可以在不同的比例下重放渲染。

一个重要的新操作是 gsk_render_node_diff,用于比较两个渲染节点树(有关详细信息,请参见下文)。

GDK

遵循将 GDK api 与 Wayland 而不是 X 对齐的总体趋势,GdkWindow 被重命名为 GdkSurface。

GdkTexture api 经过了改进,具有新的 GdkMemoryTexture 和 GdkGLTexture 子类,并且引入了一个强大的新抽象 GdkPaintable

GdkPaintable 表示一个可以在任何大小的任何位置绘制的对象,而无需任何类型的布局。这受到了其他地方类似概念的启发,例如 ClutterContent、HTML/CSS 绘制源或 SVG 绘制服务器。为了展示此概念的强大功能,在 gtk4-demo 中添加了一些新的演示

DND 代码继续进行重大重构。它现在使用 3.93 中引入的用于剪贴板处理的相同内容提供程序基础结构,并且它为 DND 操作的源端和目标端提供了单独的对象。这里将会有更多变化。

GTK

小部件

GTK+ 已获得对显示视频的支持,包括 GtkVideo 和 GtkMediaControls 小部件,并且还有一个新的 GtkPicture 小部件,用于从 GtkImage(实际上是关于图标)中分离图像查看。

GtkFontChooser 允许调整 OpenType 功能和字体变体,并且用于颜色表情符号输入的 Ctrl-Shift-e 已被可以通过 GtkEntry::enable-emoji-completion 属性启用的补全所取代。

输入

GtkWidget 中的特定于事件的信号继续消失。此时只剩下 ::event,但它也会消失。相反,我们正在使用事件控制器,并且添加了几个新的控制器来覆盖所有需要的事件

  • GtkEventControllerMotion
  • GtkEventControllerKey
  • GtkGestureStylus

为了使此转换更容易,现在可以在 ui 文件中创建事件控制器。

Wayland 有自己的基于 Wayland 文本协议的平台输入法。

绘图

::draw 信号已被删除,所有小部件都必须实现 ::snapshot。它们现在可以创建自己的 GtkSnapshot 实例以进行中间渲染。裁剪不再在 GTK+ 级别应用 - 如果需要,小部件可以自由地在其分配之外绘制。

小部件失效已更改,它现在通过丢弃失效小部件的缓存渲染节点并重新创建渲染节点树的缺失部分来工作。

为了找到需要重绘的区域,GTK+ 会比较上一帧和当前帧的渲染节点树,并应用一些启发式方法来防止矩形数量增长过大。

GTK+ 检查器可让您跟踪失效,您可以在此处看到它的运行情况

其他更改

GTK+ 不再支持通用的可加载模块。输入法、打印后端和媒体后端已转换为 GIOModules 和扩展点。

平台 im 模块(即 Windows、Wayland、Broadway im 上下文)始终包含在内,并且在其平台上默认启用。

GDK 中的 Vulkan 支持现在可以使用 GDK_VULKAN_DEVICE 环境变量指定的特定设备。使用 GDK_VULKAN_DEVICE=list 可查看所有可用设备。

试用一下

使用 GTK+ 3.94.0,应该可以开始移植应用程序了。文档中有一个初始移植指南。

GTK+ 3 的更新

计划

当我们开始向 GTK+ 4 开发时,我们制定了一个计划,其中表示 GTK+ 3.22 将是 GTK+ 3 的最终稳定分支。 我们已经坚持了一段时间。

它为我们提供了相当好的服务 - GTK+ 3 停止了剧烈的变化,这受到了欢迎,并且我们终于看到应用程序从 GTK+ 2 迁移过来。

现实

但是,GTK+ 4 的成熟需要时间(更多信息将在另一篇文章中介绍),并且一些不错的新功能(例如字体变体支持或 Emoji 完成)在主分支中闲置未使用。 我们还收到了一些移植应用程序对关键 API 的请求。

因此,我们已决定最好改变方向,并通过在 9 月份发布 GTK+ 3.24 版本,允许在 GTK+ 3.x 中加入有限数量的新功能和 API。

现在 git 中有一个 gtk-3-24 分支。GTK+ 3.x 的维护已转移到该分支,我们将不再进行任何进一步的 3.22.x 版本发布。

亮点

此新分支的第一个版本是 GTK+ 3.23.0,可以在此处找到

https://download.gnome.org/sources/gtk+/3.23/gtk+-3.23.0.tar.xz

此版本的亮点包括新的字体选择器功能,

  • 允许设置 OpenType 字体功能
  • 显示 OpenType 字体功能的示例
  • 允许选择 OpenType 字体变体
  • 支持选择的详细程度

新的 Emoji 功能,

  • 支持 Emoji 的完成弹出窗口
  • 删除 Ctrl-Shift-e 快捷键

gdk_window_move_to_rect 作为公共 API,

以及在 FreeBSD 上使用匿名共享内存的 Wayland 后端。

数字学

进行另一个 3.x 循环的副作用是,我们将使 GTK+ 3.24 成为最终的 GTK+ 3,这与 GTK+ 2.24 成为最终的 GTK+ 2 有着令人愉悦的相似之处。

GTK+ 4 中的输入法

GTK 对可加载模块的支持可以追溯到很久以前,这就是为什么 GTK 有很多代码来处理 GTypeModules 和搜索路径等。 后来,Alex 为 GVfs 重新审视了该主题,并提出了扩展点和 GIO 模块的概念,它们实现了这些扩展点。这是一个更好的框架,GTK 4 是我们切换到使用它的绝佳机会。

GTK+ 4 中的更改

因此,我最近花了一些时间在 GTK 中的模块支持上。这里的主要变化如下

  • 我们不再支持通用可加载模块。此功能的少数剩余用户之一是 libcanberra,我们将考虑直接在 GTK+ 中实现“事件声音”功能,而不是依赖于模块来实现。如果您依赖于加载 GTK+ 模块,请来和我们讨论其他实现您正在做的事情的方法。
  • 打印后端现在使用名为“gtk-print-backend”的扩展点定义,该扩展点需要 GtkPrintBackend 类型。现有的打印后端已转换为实现此扩展点的 GIO 模块。由于我们从未支持过树外打印后端,因此这不应影响其他任何人。
  • 输入法也使用扩展点定义,名为“gtk-im-module”,它需要 GtkIMContext 类型。 我们已经放弃了所有非平台 IM 模块,并将平台 IM 模块移到了 GTK+ 本身中,同时也实现了扩展点。

适配现有的输入法

由于我们仍然支持树外 IM 模块,我想用这篇文章的其余部分来简要介绍一下 GTK+ 4 的树外 IM 模块必须是什么样子。

将传统的基于 GTypeModule 的 IM 模块转换为新的扩展点需要几个步骤。下面的示例代码取自 Broadway 输入法。

使用 G_DEFINE_DYNAMIC_TYPE

我们将从模块加载类型,并且 G_DEFINE_DYNAMIC_TYPE 是定义此类类型的正确方法

G_DEFINE_DYNAMIC_TYPE (GtkIMContextBroadway,
                       gtk_im_context_broadway,
                       GTK_TYPE_IM_CONTEXT)

请注意,此宏定义了一个 gtk_im_context_broadway_register_type() 函数,我们将在下一步中使用它。

请注意,除了更常见的 class_init 之外,动态类型还需要一个 class_finalize 函数,它可以是微不足道的

static void
gtk_im_context_broadway_class_finalize
               (GtkIMContextBroadwayClass *class)
{
}

实现 GIO 模块 API

为了用作 GIOModule,模块必须实现三个函数:g_io_module_load()、g_io_module_unload() 和 g_io_module_query()(严格来说,最后一个是可选的,但我们无论如何都要在这里实现它)。

void
g_io_module_load (GIOModule *module)
{
  g_type_module_use (G_TYPE_MODULE (module));
  gtk_im_context_broadway_register_type  
                        (G_TYPE_MODULE (module));
  g_io_extension_point_implement
             (GTK_IM_MODULE_EXTENSION_POINT_NAME,
              GTK_TYPE_IM_CONTEXT_BROADWAY,
              "broadway",
              10);
 }
void
g_io_module_unload (GIOModule *module)
{
}
char **
g_io_module_query (void)
{
  char *eps[] = {
    GTK_IM_MODULE_EXTENSION_POINT_NAME,
    NULL
  };
  return g_strdupv (eps);
}

正确安装您的模块

GTK+ 仍将在 $LIBDIR/gtk-4.0/immodules/ 中查找要加载的输入法,但 GIO 仅查看名称以“lib”开头的共享对象,因此请确保您遵循该约定。

调试

就是这样!

现在 GTK+ 4 应该加载您的输入法,如果您使用 GTK_DEBUG=modules 运行 GTK+ 4 应用程序,您应该在调试输出中看到您的模块。