花式合成器
Fancy Compositor 是一个示例,演示了如何用纯 QML 编写一个花哨的 Wayland 合成器。
简介
Fancy Compositor 是一个小型桌面风格的 Wayland 合成器示例,它展示了 Qt Wayland CompositorQML API 的强大功能和易用性。
Fancy Compositor 示例与Minimal QML 示例类似,它是一个完整的 Wayland 合成器,仅使用 QML 代码实现。
初始化合成器
与Minimal QML 示例一样,Fancy Compositor 支持 Qt 所支持的主要外壳扩展。
// 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 的子模块,它会自动添加到支持的接口列表中,并由服务器广播给客户端。
当连接的客户端创建了一个表面并将其绑定到其中一个外壳扩展时,就会发出相应的信号。然后,它会调用我们自定义的WaylandOutput 类中的一个方法,将ShellSurface 附加到ListModel 中。
function handleShellSurface(shellSurface) { shellSurfaces.append({shellSurface: shellSurface}); }
该模型将作为Repeater 的源代码,在合成器的WaylandOutput 中创建ShellSurfaceItems 。这将在Qt Quick 场景中添加表面视图。由于它是ShellSurfaceItem ,它还为合成器的用户提供了某些交互选项,具体取决于使用的是哪种外壳扩展。
Repeater { model: output.shellSurfaces // Chrome displays a shell surface on the screen (See Chrome.qml) Chrome { shellSurface: modelData onDestroyAnimationFinished: output.shellSurfaces.remove(index) } }
键盘
除了基本的窗口系统功能外,Fancy 合成器还支持在进程中运行的可选屏幕键盘。它使用 Qt Virtual Keyboard模块,并在该模块可用时启用。
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 Virtual Keyboard模块的硬性依赖。如果加载失败,合成器将继续正常运行,但不支持屏幕键盘。
最后,我们需要一种方式让合成器将文本输入信息传递给客户端。这可以通过text-input
扩展实现。Fancy Compositor 示例同时支持text_input_unstable_v2
协议和 Qt 的qt_text_input_method_unstable_v1
协议。
qt_text_input_method_unstable_v1
扩展通过实例化QtTextInputMethodManager 作为WaylandCompositor 的子节点添加到合成器中,而TextInputManager 则添加text_input_unstable_v2
。
当qt_text_input_method_unstable_v1
可用时,较新的 Qt 应用程序会选择它,而其他客户端可以使用text_input_unstable_v2
。
过渡
除了基本功能外,Fancy Compositor 示例还演示了状态之间的动画转换。
首先是激活过渡。这仅在XdgShell 上支持,因为这是唯一具有activated 状态的 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 。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.