系统UI
系统UI是UI的一部分,负责在设备上启动和停止任何应用程序。它负责管理应用程序窗口,并以特定方式将它们组合在一起。例如,以全屏显示应用程序或同时允许显示来自不同应用程序的多个窗口。
在桌面系统中,系统UI类似于微软Windows的Shell或KDE的Plasmashell加上KWin合成器。
系统UI有以下任务
任务 | 描述 |
---|---|
合成 | 管理多个应用程序的表面,称为窗口。 根据所需设计,将这些窗口排列在一个或多个物理屏幕上。 处理窗口装饰、过渡效果和其他系统级用户体验。 |
通信接口 | 作为应用程序与其自身之间交换信息的通道,例如切换语言。 |
输入处理 | 根据用户当前焦点在输入事件之间切换。 提供系统输入服务,如为触摸系统启动虚拟键盘。 |
管理系统级应用程序和服务 | 通过在用户交互时启动应用程序和在关键情况下(例如低内存)停止它们来管理应用程序的生命周期。 通过显示诸如帧率、当前使用的CPU数量和内存资源之类的统计信息来提供一个中心UI,以监视UI性能和所有已启动的应用程序。 |
管理空闲时间并显示主屏幕 | 在启动后向用户显示默认视图。 显示基本数据,如当前时间。 显示由几个选定应用程序组成的视图。 |
实现系统UI
系统UI的主要功能是能够管理多个应用程序和窗口。因此,基于Linux的系统是推荐的开发环境,其中启用了多进程模式。在其他操作系统上,您可以使用单进程模式。有关单进程和多进程模式之间的区别的更多信息,请参阅单进程与多进程模式和Wayland和Qt。
窗口管理
系统UI的中心角色是处理应用程序窗口。在客户端,您需要使用ApplicationManagerWindow。在系统UI一侧,您需要实现WindowManager::windowAdded的处理程序。每当客户端窗口变得可见时,都会发出WindowManager::windowAdded信号。该信号有一个参数,WindowObject,它代表客户端ApplicationManagerWindow在系统UI一侧的表现。
为了区分客户端窗口,您应该使用窗口属性。例如,您可以将一个type
属性附加到客户端窗口中,告诉系统UI它是顶级窗口、弹出窗口还是其他类型的窗口。客户端和服务器端窗口表示都可以访问这些属性。通常,它们始终保持同步;但是底层的Wayland协议是完全异步的。
要将WindowObject包含在系统UI的渲染树中,将WindowObject设置为WindowItem的window
属性。WindowItem充当窗口对象的容器Item。因此,WindowItem决定了客户端窗口在系统UI中的位置、可见性等。
一个简单的系统UI示例是为“Hello World!”系统UI示例编写的。
Item { width: 800 height: 600 // Show application names and icons Column { spacing: 20 Repeater { model: ApplicationManager Column { id: delegate required property bool isRunning required property var icon required property var application required property string name Image { source: delegate.icon MouseArea { anchors.fill: parent onClicked: delegate.isRunning ? delegate.application.stop() : delegate.application.start() } } Text { font.pixelSize: 20 text: delegate.name } } } } // Show windows Column { anchors.right: parent.right Repeater { model: WindowManager WindowItem { required property var model width: 600 height: 200 window: model.window } } } }
通知
如果您想要显示通知或弹出窗口,应用程序或客户端可以通过ApplicationInterface::createNotification()创建这些窗口。然后,通过NotificationManager在系统UI上提供这些窗口。
下面的代码片段是桌面系统UI示例的一部分,该示例说明了如何显示弹出窗口。
// System UI for a notification Text { z: 9999 font.pixelSize: 46 anchors.centerIn: parent text: NotificationManager.count > 0 ? NotificationManager.get(0).summary : "" }
意图
系统UI和其他应用程序可以通过IntentObject和IntentServer QML类型发送和接收意图。Intent代表系统UI上的单个意图定义;IntentServer是系统UI端表示意图子系统的单例。
有关实现意图支持的更多详细信息,请参阅意图系统UI和应用程序示例。
生命周期
ApplicationManager提供API来启动和停止应用程序。但是,推荐的方法是使用ApplicationObject::start()和ApplicationObject::stop()。可选地,您也可以在start()函数中传递一个documentUrl
。然后,当您多次调用start()
时,每次使用不同的documentUrl()
,您就不会重新启动应用程序;而是只触发应用程序或客户端侧的ApplicationInterface::openDocument()。调用ApplicationObject::stop()会在应用程序侧触发ApplicationInterface::quit()。应用程序应进行所有必要的清理,并确认它可以终止,使用ApplicationInterface::acknowledgeQuit()。
您可以实现针对IPC机制(如窗口属性、Intents或专有IPC)的特定要求的其他生命周期管理功能。
有关更多信息,请参阅桌面系统UI示例。
监控
为了监控您的应用,您可以使用MonitorModel以间隔从各种来源获取数据并存储这些值的历,史。您可以利用这些数据进行分析,例如绘制其过往值随时间变化的图表。更多信息请见应用程序进程信息展示示例。
包管理器
ApplicationManager提供了ApplicationModel中所有可用应用的列表。除了随系统UI捆绑的应用程序以及系统应用外,ApplicationManager还提供了一种在运行时安装新应用的途径。这些应用由PackageManager单例维护。
要开始安装,请使用PackageManager::startPackageInstallation。一旦从应用包中提取所有元数据,将发射PackageManager::taskRequestingInstallationAcknowledge信号。该信号可以用来提供更多关于包的信息,例如名称、大小或权限。使用PackageManager::acknowledgePackageInstallation来确认此安装。安装完成后,您可以按照生命周期描述的方式启动新应用。要删除已安装的应用程序,请使用PackageManager::removePackage。
更多信息请见包安装。
编写系统UI的最佳实践
以下是一些编写系统UI时要考虑的关键实践
- 始终尽快在目标上测试您编写的系统UI及其应用。 这尤其重要,因为您的目标硬件与异步Wayland协议的结合可能会在对系统某些部分的定时上产生一些限制。例如,当应用程序启动后,窗口属性何时可供系统UI使用。最好尽早确定这些限制。为了能够在System UI以及应用程序(或Wayland客户端)上运行流畅的用户界面,硬件加速对于两者都是必要的。这种流畅性是通过特定于硬件的纹理共享机制实现的。现在,这些机制是特定于硬件的,并且与您的开发机器相比,目标平台可能使用的是不同的机制。尽早在目标硬件上测试可以帮助及早发现共享机制中存在的问题或其他图形密集型元素(如着色效果或3D引擎集成)的副作用。
- 允许系统UI停止占用太多内存或CPU的应用程序。 设计系统使系统UI能够在不必要时停止应用程序,尤其当内存或CPU等硬件资源较低时。这提供了更好的可伸缩性。
- 总是使用两个不同的插件文件夹。 一个文件夹用于系统UI特定或受权限的应用程序。另一个文件夹用于包含基础元素的其他应用程序,例如您的UI样式或您不同窗口类型的Items。
关于根元素的一些说明
- 如果系统UI的根元素是一个Item,应用程序管理器将为此创建一个QQuickWindow并将其Item设置为根Item。
- 如果系统UI的根元素是一个窗口或被窗口包裹的项,则窗口将最初显示,无论其
visible
属性值如何。
相关信息
© 2024 Qt公司。本文档中的贡献包含各自所有者的版权。本提供的文档根据自由软件开发基金会发布的GNU自由文档许可证第1.3版许可。Qt及其相关标志是Qt公司在芬兰和其他国家/地区的商标。所有其他商标均为各自所有者的财产。