Fancy Compositor
Fancy Compositor 是一个示例,演示了如何使用纯 QML 编写一个花哨的 Wayland 合成器。
简介
Fancy Compositor 是一个小型桌面风格的 Wayland 合成器示例,旨在展示 Qt Wayland Compositor QML 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 ,因此根据所使用的shell扩展不同,它还为合成器的用户提供了某些交互选项。
Repeater {
model: output.shellSurfaces
// Chrome displays a shell surface on the screen (See Chrome.qml)
Chrome {
shellSurface: modelData
onDestroyAnimationFinished: output.shellSurfaces.remove(index)
}
}键盘
除了基本的窗口系统功能外,Fancy Compositor 还支持一个可选的、在同一进程中运行的屏幕键盘。该功能使用 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 协议。
通过将QtTextInputMethodManager 作为WaylandCompositor 的子类进行实例化,将qt_text_input_method_unstable_v1 扩展添加到合成器中,同时TextInputManager 会添加text_input_unstable_v2 。
较新的 Qt 应用程序会在qt_text_input_method_unstable_v1 可用时自动选用它,而其他客户端则可以使用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 提供的丰富功能可供您自由运用。
© 2026 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.