花哨的合成器
花哨的合成器是一个示例,展示了如何使用纯 QML 编写一个花哨的 Wayland 合成器。
简介
花哨的合成器是一个小的桌面风格 Wayland 合成器示例,展示了 Qt Wayland Compositor QML API 的强大和易用性。
花哨的合成器示例类似于 最小 QML 示例,因为它是一个完整的 Wayland 合成器,仅使用 QML 代码实现。
初始化合成器
与 最小 QML 示例一样,花哨的合成器支持 Qt 支持的常用 shell 扩展。
// Shell surface extension. Needed to provide a window concept for Wayland clients. // I.e. requests and events for maximization, minimization, resizing, closing etc. XdgShell { onToplevelCreated: (toplevel, xdgSurface) => screen.handleShellSurface(xdgSurface) } // Minimalistic shell extension. Mainly used for embedded applications. IviApplication { onIviSurfaceCreated: (iviSurface) => screen.handleShellSurface(iviSurface) } // Deprecated shell extension, still used by some clients WlShell { onWlShellSurfaceCreated: (shellSurface) => screen.handleShellSurface(shellSurface) }
这些扩展作为 WaylandCompositor 的子项而被实例化,并自动将它们添加到从服务器广播给客户端的受支持接口列表。
当连接的客户端创建一个表面并将其绑定到某个 shell 扩展时,就会发出相应的信号。这会调用我们自定义的 WaylandOutput 类中的一个方法,该方法将 ShellSurface 添加到一个 ListModel 中。
function handleShellSurface(shellSurface) { shellSurfaces.append({shellSurface: shellSurface}); }
这个模型被用作 Repeater 的源,在合成器的 WaylandOutput 中创建 ShellSurfaceItems。这向 Qt Quick 场景添加了表面的视图。由于它是一个 ShellSurfaceItem,它也向合成器的用户提供了某些交互选项,具体取决于正在使用的哪个 shell 扩展。
Repeater { model: output.shellSurfaces // Chrome displays a shell surface on the screen (See Chrome.qml) Chrome { shellSurface: modelData onDestroyAnimationFinished: output.shellSurfaces.remove(index) } }
键盘
除了基本的窗口系统功能外,花哨的合成器还支持可选的运行在进程中的屏幕键盘。它使用 Qt 虚拟键盘 模块,如果该模块可用,则将启用。
import QtQuick import QtQuick.VirtualKeyboard InputPanel { visible: active y: active ? parent.height - height : parent.height anchors.left: parent.left anchors.right: parent.right }
代码很简单。我们在输出的底部实例化一个 InputPanel,并确保仅在其当前活动时才可见。
Loader { anchors.fill: parent source: "Keyboard.qml" }
然后使用一个 Loader 元素将键盘添加到 WaylandOutput。在这里使用 Loader 以避免对 Qt 虚拟键盘 模块的硬依赖。如果加载失败,那么合成器将继续正常操作,但将不支持屏幕键盘。
最后,我们需要一种方式让合成器将文本输入传达给其客户端。这通过一个text-input
扩展来实现。Fancy Compositor 示例支持text_input_unstable_v2
协议以及 Qt 的qt_text_input_method_unstable_v1
协议。
通过将qt_text_input_method_unstable_v1
扩展作为WaylandCompositor
的子对象实例化,将其添加到合成器中,并通过TextInputManager
添加text_input_unstable_v2
。
较新的 Qt 应用将选择可用的qt_text_input_method_unstable_v1
,而其他客户端则可以使用text_input_unstable_v2
。
过渡
除了基本功能外,Fancy Compositor 示例还演示了状态之间的动画过渡。
其中第一个是激活过渡。这仅在XdgShell上受支持,因为这是唯一具有激活状态的 Shell 扩展。
Connections { target: shellSurface.toplevel !== undefined ? shellSurface.toplevel : null // some signals are not available on wl_shell, so let's ignore them ignoreUnknownSignals: true function onActivatedChanged() { // xdg_shell only if (shellSurface.toplevel.activated) { receivedFocusAnimation.start(); } } } SequentialAnimation { id: receivedFocusAnimation ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } NumberAnimation { target: scaleTransform; property: "xScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } } ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } NumberAnimation { target: scaleTransform; property: "xScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } } }
当客户端窗口在XdgShell协议下激活时,我们触发动画,使窗口“弹出”200毫秒。
Fancy Compositor 还支持销毁动画。这会在窗口关闭并销毁表面时触发,无论是客户端优雅地关闭其窗口,还是它崩溃。
onSurfaceDestroyed: { bufferLocked = true; destroyAnimation.start(); } SequentialAnimation { id: destroyAnimation ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } NumberAnimation { target: chrome; property: "opacity"; to: chrome.isChild ? 0 : 1; duration: 150 } } NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } ScriptAction { script: destroyAnimationFinished() } }
为了确保动画持续时间内有内容存在,我们首先锁定缓冲区。这意味着客户端渲染的最后一帧将保留在内存中,直到我们完成它。
同样,我们在项目的缩放比例上触发动画。相关的动画模仿关闭CRT屏幕,向用户提供视觉提示,表示窗口正在关闭,而不仅仅是从空气中消失。
可以采用任何类型的动画效果来进行这种状态变化,Qt Quick 提供了完整的工具。
© 2024 Qt 公司有限公司。本文档的贡献包含在此处的是其各自所有者的版权。本文档提供的文档根据自由软件基金会发布的条款和使用GNU自由文档许可证版本1.3进行许可。Qt以及相应的标志是芬兰和/或世界其他国家的Qt公司商标。所有其他商标均为其各自所有者的财产。