QtWayland启动流程分析
QtWayland版本:6.4.0
 QtWayland的服务端(CompositorServer)入口点是QWaylandCompositor这个类,可以参考官网提供的example,其路径为:examples\wayland\minimal-cpp
下面基于minimal-cpp这个例子,进行分析。
启动流程分析
- examples\wayland\minimal-cpp\main.cpp
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QGuiApplication>
#include "window.h"
#include "compositor.h"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    Window window;
    window.resize(800,600);
    // 这里启动了Compositor Server
    Compositor compositor(&window);
    window.show();
    return app.exec();
}
上面的代码中,使用QGuiApplication 创建了一个App实例,并使用Window类(其父类为QOpenGLWindow),创建了一个WIndow对象。这里重点关注的是Compositor类,通过创建Compositor类实际上启动了 QtWayland Compositor Server。
- examples\wayland\minimal-cpp\compositor.h
class Compositor : public QWaylandCompositor
{
    //省略
}
Compositor::Compositor(Window *window)
    : m_window(window)
{
    window->setCompositor(this);
    connect(window, &Window::glReady, this, [this] { create(); });
}
Compositor::~Compositor()
{
}
void Compositor::create()
{
    QWaylandOutput *output = new QWaylandOutput(this, m_window);
    QWaylandOutputMode mode(m_window->size(), 60000);
    output->addMode(mode, true);
    QWaylandCompositor::create();
    output->setCurrentMode(mode);
    m_iviApplication = new QWaylandIviApplication(this);
    connect(m_iviApplication, &QWaylandIviApplication::iviSurfaceCreated, this, &Compositor::onIviSurfaceCreated);
}
分析一下上面Compositor类的代码
 Compositor的父类是QWaylandCompositor,因此创建Compositor时会调用父类的构造函数。
QWaylandCompositor(QObject *parent = nullptr);
QWaylandCompositor::QWaylandCompositor(QObject *parent)
    : QWaylandObject(*new QWaylandCompositorPrivate(this), parent)
{
}
上面的代码创建了QWaylandCompositorPrivate这个类。我们看一下这个类的定义。
// 父类有
// QtWaylandServer::wl_compositor
// QtWaylandServer::wl_subcompositor
// QObjectPrivate
class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandCompositorPrivate : public QObjectPrivate, public QtWaylandServer::wl_compositor, public QtWaylandServer::wl_subcompositor
{
}
QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *compositor)
{
    if (QGuiApplication::platformNativeInterface())
        display = static_cast<wl_display*>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("server_wl_display"));
    if (!display) {
    	// 创建了全局Display对象
        display = wl_display_create();
        ownsDisplay = true;
    }
   // 省略
}
QWaylandCompositorPrivate这个类的父类比较多,主要包括 QtWaylandServer::wl_compositor和QtWaylandServer::wl_subcompositor这两个,这两个类是QtWayland根据 Wayland.xml 这个协议生成的,利用这两个类可以初始化wl_compositor和wl_subcompositor两个协议对象。在QWaylandCompositorPrivate的构造函数中调用了wl_display_create,通过该函数创建了全局的Display对象。
- 让我们回到上面代码中Compositor这个类的构造函数中。
Compositor::Compositor(Window *window)
    : m_window(window)
{
    window->setCompositor(this);
    connect(window, &Window::glReady, this, [this] { create(); });
父类的构造函数执行后,会执行当前类的构造函数。上面代码中,只关注connect这段。该段代码将 Window::glReady这个信息和Compositor类的create函数绑定。glReady这个信号会在WIndow(父类为QOpenGLWindow)自身初始化中,被调用。本文只关住 create这个函数。
- examples\wayland\minimal-cpp\compositor.cpp
void Compositor::create()
{
    QWaylandOutput *output = new QWaylandOutput(this, m_window);
    QWaylandOutputMode mode(m_window->size(), 60000);
    output->addMode(mode, true);
    QWaylandCompositor::create();
    output->setCurrentMode(mode);
    // 省略
}
- 上面的代码中创建了QWaylandOutput,这个类最终会初始化wl_output这个Wayland协议。代码中调用了QWaylandCompositor::create()
- src\compositor\compositor_api\qwaylandcompositor.cpp
/*!
 * 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->preInit();
    d->init();
}
void QWaylandCompositorPrivate::preInit()
{
    Q_Q(QWaylandCompositor);
    if (preInitialized)
        return;
    if (seats.empty())
        seats.append(q->createSeat());
    preInitialized = true;
}
void QWaylandCompositorPrivate::init()
{
    Q_Q(QWaylandCompositor);
    QStringList arguments = QCoreApplication::instance()->arguments();
	 
	 // 设置Socket名字
    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_compoisotor和wl_subcompositor这两个协议
    wl_compositor::init(display, 4);
    wl_subcompositor::init(display, 1);
    // 省略
    // 初始化shm
    wl_display_init_shm(display);
	
	// 创建socket,socket用于Compositor server与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,并使用QSocketNotifier,监听fd产生可读的event,当有可读的event时,调用processWaylandEvents这个函数
    loop = wl_display_get_event_loop(display);
    int fd = wl_event_loop_get_fd(loop);
    QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, q);
    QObject::connect(sockNot, SIGNAL(activated(QSocketDescriptor)), q, SLOT(processWaylandEvents()));
    // 省略
    // 标记已经初始化了
    initialized = true;
}
void QWaylandCompositor::processWaylandEvents()
{
    Q_D(QWaylandCompositor);
    int ret = wl_event_loop_dispatch(d->loop, 0);
    if (ret)
        fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret);
}
- 上面的代码,创建了CompositorServer与Client端通信使用的sockect,并且监听了event loop的fd,当fd可读时触发绑定的事件函数。到这里Compoositor server端主要的启动流程便完事了。
- 启动时序图:
  










![[Linux]----守护进程](https://img-blog.csdnimg.cn/e8603c06422645efb3d67a8b3a283dc5.png)








