IVI 合成器

IVI Compositor 是一个演示如何使用IviApplication 扩展的示例。

简介

本示例演示了如何在 Wayland 显示服务器(也称为 Wayland 合成器)中使用IviApplication shell 扩展。

有关使用 Qt 创建一个 Qt Wayland Compositor基本原理,请参阅Minimal QML 示例

协议

IviApplication 是一个shell 扩展,专门用于制作车载信息娱乐系统。

它是一个简约的协议,只提供以下功能:

  1. 客户端可以用一个IVI-id 标识自己。
  2. 服务器可要求客户端调整自身大小。
识别码

在典型的IviApplication 设置中,会预先定义一组可以连接到服务器的应用程序。由于在设计系统时已经知道这些应用程序,因此可以为它们分配硬编码的标识号。如果客户端和服务器事先就这些编号达成一致,就可以在 ID 编号中加入语义。

例如,如果客户端将自己定位为导航应用程序,服务器就能识别出来,并为其窗口分配屏幕上居中的大块区域。另一方面,如果一个应用程序将自己标识为时钟,那么它可能会被分配到屏幕边缘较小的区域。

默认情况下,Qt 应用程序会将其系统 PID("进程 ID")作为IVI-id 发布。客户端可以在连接服务器之前,通过在其环境中设置QT_IVI_SURFACE_ID 来覆盖这一点。

示例

Qt Wayland Compositor 可同时支持多个 shell 扩展,但IVICompositor 示例仅支持IviApplication 协议。这意味着客户端也必须支持该 shell 扩展才能连接到服务器。

示例中的合成器窗口横向分为两个:左侧区域指定用于id 为 "1337 "的专用应用程序,右侧区域用于所有其他应用程序。

创建布局

窗口布局是在WaylandOutput 中创建的。这通常对应于合成器可用的物理屏幕。如果只创建一个WaylandOutput ,如IVICompositor 示例,它通常对应主屏幕。

WaylandOutput {
    sizeFollowsWindow: true
    window: Window {
        width: 1024
        height: 768
        visible: true
        Rectangle {
            id: leftArea
            width: parent.width / 2
            height: parent.height
            anchors.left: parent.left
            color: "cornflowerblue"
            Text {
                anchors.centerIn: parent
                text: "Ivi surface with id 1337"
            }
        }
        Rectangle {
            id: rightArea
            width: parent.width / 2
            height: parent.height
            anchors.right: parent.right
            color: "burlywood"
            Text {
                anchors.centerIn: parent
                text: "Other surfaces"
            }
        }
    }
}

代码会为屏幕创建一个WaylandOutput ,并在其上创建一个窗口,作为所有合成器内容的顶层容器。在该窗口内,它将创建两个矩形,作为应用程序连接时的容器。

连接客户端

如果没有进行其他配置,Qt 应用程序将使用与其进程 ID 相同的IVI-id进行连接。例如,如果我们使用-platform wayland 运行另一个 Qt 示例应用程序,只要其 ID 与 "1337 "不同,它就会被委派到布局的右侧。

但是,如果我们在启动示例之前将QT_IVI_SURFACE_ID 环境变量设置为 "1337",它就会被委派到布局的左侧。

当客户端连接到IVIApplication 接口时,它将发出iviSurfaceCreated 信号。应用程序表面的定位就是在这里处理的。

IviApplication {
    onIviSurfaceCreated: (iviSurface) =>  {
        var surfaceArea = iviSurface.iviId === 1337 ? leftArea : rightArea;
        var item = chromeComponent.createObject(surfaceArea, { "shellSurface": iviSurface } );
        item.handleResized();
    }
}

iviSurfaceCreated 信号会接收一个IviSurface 参数,该参数可用于访问客户端的 ID。然后,合成器会为曲面创建一个ShellSurfaceItem (由chromeComponent 定义)。ShellSurfaceItem 是用于将外壳曲面放置到Qt Quick 场景中的类,您将在所有Qt Wayland Compositor 示例中看到相同的模式。

IVICompositor 示例的特别之处在于它会检查进入的外壳表面的iviId 属性,并根据该属性决定ShellSurfaceItem 的父对象。如果 ID 等于 "1337",它的父级将是leftArea ;如果 ID 不等于 "1337",它的父级将是rightArea

ShellSurfaceItem 的实现会在大小发生变化时通知客户端,从而处理大小调整(如果合成器在桌面式窗口系统中运行,窗口大小发生调整,就会出现这种情况)。

onWidthChanged: handleResized()
onHeightChanged: handleResized()
function handleResized() {
    if (width > 0 && height > 0)
        shellSurface.sendConfigure(Qt.size(width, height));
}

sendConfigure() 方法在IviSurface 中定义,它将向客户端发送一个事件。客户端将收到一个包含新大小的调整大小事件,以便转发其内容。

如果多个应用程序连接到布局中的同一区域,它们将按照正常的Qt Quick 排序规则堆叠。目前还没有关闭应用程序或管理状态的内置机制,但可以通过普通的Qt Quick 代码轻松添加。

示例项目 @ code.qt.io

© 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.