【Wayland】QtWayland框架分析

news2025/1/11 11:00:54

QtWayland框架分析

QtWayland概念介绍

QtWayland是Qt官方基于Wayland开发的一款Toolbox,根据其官网介绍

The QtWayland module consists of two parts:
Wayland platform plugin:
Enables Qt applications to be run as Wayland clients.
QtWaylandCompositor API:
Enables the creation of Wayland compositors using Qt and QtQuick.

可以将QtWayland的功能归纳为两点:

  1. 基于Qt/QtQuick,使用QtWayland可以写出一套 Compositor(Wayland Compositor)
  2. Qt应用可以作为Wayland的Client端运行。
  • 下图摘自Qt官网,对于Qt与Wayland关系的介绍。
    在这里插入图片描述 如何运行QtWayland?
  • Qtwayland是基于Qt编译的,可以参考QtWayland官网提供的编译手顺。并且QtWayland在其源码中,提供了一些Compositor的例子,在运行例子前只需要设置 如“QT_WAYLAND_HARDWARE_INTEGRATION”,“XDG_RUNTIME_DIR ”等环境变量即可(这里不在详细描述)

QtWayland源码分析

本文基于QtWayland 6.4的源码,对其模块框架及Compositor启动流程进行分析。

模块框架

请添加图片描述

  • ClientApi:Qtwayland提供给Client端使用的API。这些Api大部分是对于Wayland协议的封装。这样做的好处,是将Wayland协议与Client端进行了隔离。
  • ServerApi:QtWayland提供给你Server端(即Compositor)使用的API。这些API也是对Wayland协议的封装。你可以基于这些API,写出一个Compositor。
  • Plugins:插件模块。从Shell角度考虑,存在多种Shell,比如xdg-shell、ivi-shell、wl-shell、fullscreen-shell,Plugins实现了多种Shell(Client端),Qt应用只需要在启动前设定 Shell有关的环境变量,在启动Qt应用时就会根据环境变量使用不同的Shell。除了Shell外,还包括HardWareIntegration,这是Server端和Client端使用的Buffer,也是根据设定的 环境变量进行加载。
  • Platform:除了QtWayland,QtBase中实现了一个叫 eglfs的platform使用的渲染方式。
  • Common:协议文件、Scanner(根据协议文件生成源代码的工具。)

Compositor启动(Server)

  • QWaylandCompositor是启动的入口
// src\compositor\compositor_api\qwaylandcompositor.h
class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandCompositor : public QWaylandObject
{
    Q_OBJECT
    // 对应类 QWaylandCompositorPrivate 
    Q_DECLARE_PRIVATE(QWaylandCompositor)
    // ...
public:
    QWaylandCompositor(QObject *parent = nullptr);
    ~QWaylandCompositor() override;
}

// src\compositor\compositor_api\qwaylandcompositor_p.h
class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandCompositorPrivate : public QObjectPrivate, public QtWaylandServer::wl_compositor, public QtWaylandServer::wl_subcompositor
{
public:
    QWaylandCompositorPrivate(QWaylandCompositor *compositor);
    ~QWaylandCompositorPrivate() override; 
}
  • 创建QWaylandCompositor,调用其构造函数
// new QWaylandCompositor(),因为它提供默认参数,所以可以不传参数
QWaylandCompositor::QWaylandCompositor(QObject *parent)
    : QWaylandObject(*new QWaylandCompositorPrivate(this), parent)
{
}
// new QWaylandCompositorPrivate
QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *compositor)
{
    // ...
    // 创建Display(全局Display)
    if (!display) {
        display = wl_display_create();
        ownsDisplay = true;
    }
   // ...
}
  • 到这步,创建了全局的Display对象。上面的代码中可以看到 wl_compositor 这个对象。
  • 写Compositor(Server)时,创建QWaylandCompositor后,需要调用其create方式,进行Server端的初始化。
/*
 * Initializes the QWaylandCompositor.
 * If you override this function in your subclass, be sure to call the base class implementation.
 */
void QWaylandCompositor::create()
{
    Q_D(QWaylandCompositor);
    // d 是QWaylandCompositorPrivate
    // 大部分初始化是在 QWaylandCompositorPrivate::init中实现
    d->preInit();
    d->init();
}

void QWaylandCompositorPrivate::init()
{
    // 设置Server端Socket名字
    // Socket用来跟Client端进行协议通讯
    if (socket_name.isEmpty()) {
        const int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name"));
        if (socketArg != -1 && socketArg + 1 < arguments.size())
            socket_name = arguments.at(socketArg + 1).toLocal8Bit();
    }
    // 这里初始化了wl_compositor/wl_subcompositor协议
    // 这里会调用到wl_global_create,将全局对象发布到display上
    wl_compositor::init(display, 4);
    wl_subcompositor::init(display, 1);
    // 初始化shm
    wl_display_init_shm(display);
	// 创建Server端Socket
	// Socket用于跟Client端通信
    if (!socket_name.isEmpty()) {
        if (wl_display_add_socket(display, socket_name.constData()))
            qFatal("Fatal: Failed to open server socket: \"%s\". XDG_RUNTIME_DIR is: \"%s\"\n", socket_name.constData(), getenv("XDG_RUNTIME_DIR"));
    } else {
        const char *autoSocketName = wl_display_add_socket_auto(display);
        if (!autoSocketName)
            qFatal("Fatal: Failed to open default server socket. XDG_RUNTIME_DIR is: \"%s\"\n", getenv("XDG_RUNTIME_DIR"));
        socket_name = autoSocketName;
        emit q->socketNameChanged(socket_name);
    }
    // 拿到loop
    loop = wl_display_get_event_loop(display);
    int fd = wl_event_loop_get_fd(loop);
	// 通过Qt的QSocketNotifier 监听fd,当有读事件时触发回调processWaylandEvents
    QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, q);
    QObject::connect(sockNot, SIGNAL(activated(QSocketDescriptor)), q, SLOT(processWaylandEvents()));

    QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
    QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents()));

}
  • 上述部分,完成了全局Display创建、Socket创建、wl_compositor这个重要协议的初始化,监听Socket的事件并绑定事件处理函数。Compositor端初始化的主要工作到这里完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/21446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

地理空间技术改变世界的未来

摘要: 地理空间技术是一项重大的科学发现&#xff0c;它将人类的可能性推向了一个全新的水平。那么什么是地理空间技术呢&#xff1f;事实上&#xff0c;它与普通的空间数据不同&#xff0c;地理空间技术的创新使我们能够确定物体或人在地球上的确切位置。人们将地理空间技术应…

网络安全系列-四十: suricata 的运行模型Running mode讲解

1. 什么是Running mode 1.1. 基本概念 Sruciata由线程、线程模块、队列组成。 数据包在线程间传递通过队列实现,线程由多个线程模块组成,每个线程模块实现一种功能一个数据包可以由多个线程处理,数据包将通过队列传递到下一个线程。包每次由一个线程处理,但是引擎可以同时…

docker (网卡设置、namespace、网络互通)

1 查看网卡信息 查看网卡的三种命令 ip a lo&#xff1a; 表示本地网络 127.0.0.1eth0&#xff1a; 连接网卡的网络docker0&#xff1a; docker的网卡 ip link show ls /sys/class/net 以文件的形式查看 2 网卡的操作 网卡中增加IP ip addr add 192.168.100.120/24 dev et…

springboot+jsp大学图书借阅管理系统idea maven

本论文是以构建图书借阅为目标&#xff0c;使用 jsp制作&#xff0c;由前台用户借阅图书、后台管理员添加图书两大部分组成。着重论述了系统设计分析&#xff0c;系统的实现&#xff08;用户注册模块&#xff0c;用户登录&#xff0c;用户浏览图书模块&#xff0c;图书借阅模块…

代码复杂度分析

1.复杂度分析原则 1.1 最大循环原则 只看高阶部分 public class SumNum {public static void main(String[] args) {System.out.println(sum2(4));}/*** 1-n 的累加* param n* return*/public static int sum1(int n){int sum 0;// 执行1次for (int i0;i<n;i){//这是三个…

轻量应用云服务器如何部署SpringBoot项目(jar包形式)?

这篇文章将介绍如何在腾讯云的轻量应用服务器上部署我们的java项目&#xff0c;本次演示的是java项目是使用springboot开发的单体项目&#xff0c;项目开发完成之后需要打包成jar&#xff0c;然后上传至云服务器&#xff0c;安装运行数据库文件之后&#xff0c;使用java -jar 的…

企业经营欺诈评分模型的开发与划定

近两周&#xff0c;番茄风控上线的课程中&#xff0c;涉及的财税票贷产品课程干货满满。 今天我们跟大家讲讲在模型中最干货的内容&#xff0c;也就是在税票贷产品中最干货的欺诈模型的开发与使用&#xff0c;本文会基于税票中票&#xff08;也就是发票&#xff09;相关的数据进…

双缝函数的编程

摘要 在傅立叶光学中&#xff0c;光学元件通常可以建模为传递函数&#xff0c;该函数对输入场的振幅和相位进行调制。VirtualLab Fusion提供了可编程功能&#xff0c;用户可以在其中定义元件的函数体现。 此示例提供了具有自定义缝隙宽度的双缝函数的代码段。 狭缝在y方向上是无…

CUDA 编程基础

1. GPU与CPU并行计算框架2. CUDA编程模型3 CUDA程序1. GPU与CPU并行计算框架 GPU并不是一个独立运行的计算平台&#xff0c;而需要与CPU协同工作&#xff0c;可以看成是CPU的协处理器&#xff0c;因此当我们在说GPU并行计算时&#xff0c;其实是指的基于CPUGPU的异构计算架构。…

学习日记(XML 文件解析、检索、工厂设计模式、装饰设计模式)

文章目录学习日记&#xff08;XML 文件解析、检索、工厂设计模式、装饰设计模式&#xff09;一、XML 概述1. 概念2. XML 的创建及语法规则3. XML 文档约束方式二、XML 文件的解析技术1. 使用 Dom4j 解析 XML 文件2. XML 解析案例三、XML 文件的数据检索技术&#xff1a;XPath四…

Nacos 注册中心、配置文件中心的常用配置(springcloud)

Nacos Discovery Starter 更多的配置项 1.服务端地址 spring.cloud.nacos.discovery.server-addr 无 Nacos Server 启动监听的 ip 地址和端口2.服务名 spring.cloud.nacos.discovery.s ervice ${spring.application.name} 给当前的服务命名3.服务分组spring.cloud.nacos.disc…

Nuttx系统学习笔记(三)——使用Nuttx操作STM32F429外设

在上一篇&#xff0c;我们已经学会了如何将Nuttx进行烧录&#xff0c;以及学会了如何部署这个操作系统&#xff0c;接下来我们就要使用这个操作系统来实现我们对嵌入式设备的控制&#xff0c;当然也是从点灯开始的。这个基于Posix架构的操作系统使用起来是跟FreeRTOS那些操作系…

【微信开发第五章】SpringBoot实现微信分享

前言 在进行微信公众号业务开发的时候&#xff0c;有些时候需要用到微信分享&#xff0c;以卡片的形式分享出去&#xff0c;例如订单信息&#xff0c;用户信息。该篇文章每一步都有记录&#xff0c;力争理解的同时各位小伙伴也能够实现功能 效果图如下&#xff1a; 文章目录前…

centos 7.9 部署 harbor 镜像仓库实践

centos 7.9 harbor 部署镜像仓库 文章目录centos 7.9 harbor 部署镜像仓库1. 安装 docker1.1 配置 docker2. 安装 docker-compose3. 下载 harbor4. 定制配置文件 harbor.yml5. 配置证书5.1 生成证书颁发机构证书5.2 生成服务器证书5.3 向 Harbor 和 Docker 提供证书6. 部署 har…

【软件测试】一线大厂的测试开发基本技能,我不再想庸庸碌碌......

目录&#xff1a;导读一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结能在一线大厂工作是大多数人的目标&#xff0c;不仅薪酬高&#xf…

[Git] 系列四Push Pull —— Git 远程仓库和高级操作

[Git] 系列四Push & Pull —— Git 远程仓库和高级操作 Author: Xin Pan Date: 2022.11.06 git fetch git fetch 完成了仅有的但是很重要的两步: 从远程仓库下载本地仓库中缺失的提交记录更新远程分支指针(如 o/main) git fetch 并不会改变你本地仓库的状态。它不会更…

Github 注册

Github 注册 https://github.com/ 1. 简介 初始 Github 注册 填写注册信息 一开始注册github发现了这个问题&#xff0c;多试几次。或者换个浏览器&#xff0c;或者对octocaptcha做一个域名映射。 140.82.112.4 http://octocaptcha.com填写验证码 当注册成功后&#xff0…

【小专题】正交试验法设计测试用例

正交试验法设计测试用例 正交试验法设计工具&#xff1a; 1、正交设计助手 2、AllPairs 3、python&#xff08;本质是使用AllPairs&#xff09; 先看一个案例&#xff1a; 假设一个web系统&#xff0c;需要做兼容性测试&#xff0c;该系统兼容不同操作系统、数据库和web服…

【ESP8266与ESP12E 电机拓展板握手】

【ESP8266与ESP12E 电机拓展板握手】 1. 前言2. 材料3. 工作原理3.1 板载功能3.2 引脚接口定义图3.3 产品技术规格4. 方案4.1 普通马达接线图4.2 42步进电机接线图5. 相关代码5.1 直流电机的管理代码5.2 步进电机管理代码6. 应用7. 来源1. 前言 ESP12E Motor Shield 是一块扩展…

代码改成多线程,竟有 这些问题

文章目录CPU 使用率飙高事务问题导致服务挂掉CPU 使用率飙高 每条数据都有些业务逻辑&#xff0c;如果单线程导入所有的数据&#xff0c;导入效率会非常低。于是改成了多线程导入。 如果 excel 中有大量的数据&#xff0c;很可能会出现 CPU 使用率飙高的问题。 我们都知道&am…