QtWayland

repository·dev·Indexed 41 days ago

https://github.com/qt/qtwayland

A module that enables Qt applications to act as Wayland clients and provides the QtWaylandCompositor API for developers to build custom Wayland compositors using Qt and QtQuick. It includes tools for managing displays, surfaces, outputs, and input seats via classes like QWaylandCompositor, QWaylandOutput, QWaylandPointer, and QWaylandSeat.

Tokens
9.7K
Snippets
20
Records
38
Agent score
97%

What's inside QtWayland

  1. Understand Qt internal protocol extension stability

    dev

    The protocol extensions located in the src/extensions/ directory are considered internal implementation details of Qt and are subject to change, removal, or renaming.

    However, since Qt 5.4, Qt guarantees backwards compatibility for these protocols through a specific versioning strategy: if a client detects a global from one of these extensions, it can safely bind to it. The existing events and requests within that protocol will maintain the same number of arguments across different compositor versions. This ensures compatibility even in environments where multiple Qt versions coexist (e.g., a statically linked application running against a system-installed Qt compositor).

  2. How Qt internal protocol versioning works

    dev

    To maintain stability, Qt internal protocol extensions use versioned names (for example, zqt_key_v1).

    If a breaking change to a protocol is required, the protocol is not modified in place; instead, it is renamed by incrementing its version number. This allows older clients to continue using the previous version while newer clients can opt into the updated version. Any unversioned protocols currently in the directory are considered legacy and will be transitioned to versioned names if compatibility breaks.

  3. Overview of the QtWayland module

    dev

    The QtWayland module provides two primary capabilities:

    1. Wayland platform plugin: Allows Qt applications to run as Wayland clients.
    2. QtWaylandCompositor API: Provides the tools to build your own Wayland compositors using Qt and QtQuick.

    To build this module, you must have the following external dependencies installed:

    • xkbcommon
    • wayland
  4. Understand the minimal C++ compositor example

    dev

    This example demonstrates the fundamental requirements for implementing a C++ based Wayland compositor using QtWayland.

    Key Characteristics:

    • No Input Handling: To maintain simplicity, this example does not implement input event delivery (it does not handle finding the correct window or mapping coordinates).
    • IVI-Application Shell: It utilizes the IVI-application shell protocol. Instead of standard window management, it positions windows based on their ivi_id.

    This serves as a baseline for developers looking to build custom compositors where specific window positioning logic (like IVI/In-Vehicle Infotainment) is required.

  5. How IVI-shell works with ivi-application and ivi-controller

    dev

    The IVI-shell plugin implements the GENIVI API for In-Vehicle Infotainment by mapping it to the Wayland-Ivi-Extension. It utilizes two distinct protocols:

    1. ivi-application (provided by Weston): Used by clients to create and destroy surfaces using unique IDs.
    2. ivi-controller (provided by GENIVI's wayland-ivi-extension): Used by controllers (like an HMI Controller) to manage properties such as visibility, position, and size for surfaces identified by unique IDs.

    In an IVI use case, a Unique ID is required to both create and control an ivi-surface and an ivi-layer.

  6. Manage input devices with QWaylandSeat

    dev

    In a Qt Wayland Compositor, QWaylandSeat represents a group of input devices (keyboard, pointer, touch) that share a common set of input events. It is used to manage input focus and dispatch hardware or synthetic input events to Wayland clients.

    Key Capabilities

    You can define the capabilities of a seat using CapabilityFlags:

    • Pointer (0x01)
    • Keyboard (0x02)
    • Touch (0x04)
    • DefaultCapabilities (Pointer | Keyboard | Touch)

    Input Focus Management

    • Keyboard Focus: Use setKeyboardFocus(QWaylandSurface *surface) to direct keyboard input to a specific surface. Use keyboardFocus() to retrieve the current focused surface.
    • Mouse Focus: Use setMouseFocus(QWaylandView *view) to set the current mouse focus. Use mouseFocus() to retrieve it.

    Event Dispatching

    QWaylandSeat provides methods to manually inject input events into the Wayland protocol:

    • Mouse: sendMouseMoveEvent, sendMousePressEvent, sendMouseReleaseEvent, and sendMouseWheelEvent.
    • Keyboard: sendKeyPressEvent, sendKeyReleaseEvent, or sendKeyEvent (for Qt key codes).
    • Touch: sendTouchPointPressed, sendTouchPointMoved, sendTouchPointReleased, and sendTouchFrameEvent.

    QML Integration

    The class is available in QML as WaylandSeat (version 1.0).

    // Example: Creating a seat with specific capabilities
    QWaylandSeat *seat = new QWaylandSeat(compositor, QWaylandSeat::Keyboard | QWaylandSeat::Pointer);
    
    // Example: Sending a mouse move event to a view
    seat->sendMouseMoveEvent(view, QPointF(100.0, 100.0));
    
    // Example: Setting keyboard focus to a surface
    seat->setKeyboardFocus(surface);
  7. Use QWaylandSurface to manage Wayland surfaces

    dev

    In a Qt Wayland Compositor, QWaylandSurface represents a Wayland surface provided by a client. It acts as the container for buffers, roles, and input regions. Developers use it to track surface properties like size, scale, and orientation, and to manage how the surface is presented via QWaylandView objects.

    Key responsibilities include:

    • Role Management: Assigning a QWaylandSurfaceRole to define how the surface should be treated (e.g., as a top-level window or a sub-surface).
    • Buffer Tracking: Monitoring bufferSize, bufferScale, and hasContent to know when new pixel data is available.
    • Input Handling: Using inputRegionContains(position) to determine if a specific coordinate falls within the surface's interactive area.
    • Lifecycle: Managing the surface via initialize() and destroy() methods.
    // Example: Checking surface content and size
    if (surface->hasContent()) {
        QSize size = surface->bufferSize();
        int scale = surface->bufferScale();
        // Process the surface content...
    }
  8. Test a Qt-based compositor on X11

    dev

    When testing a compositor on X11, QWidget applications typically use shared memory, but OpenGL and Qt Quick applications require specific methods to send graphics memory buffers.

    For NVIDIA users, you must use driver version 364.12 or newer, and Qt must be configured with -opengl es2.

    To run a compositor with EGL integration on X11, use the following command:

    QT_XCB_GL_INTEGRATION=xcb_egl QT_WAYLAND_CLIENT_BUFFER_INTEGRATION=wayland-egl ./minimal-qml

    If you need to manually set the client-side buffer integration for a client, run it with the -platform flag:

    ./client -platform wayland-egl
  9. Use custom Wayland shell integrations

    dev

    For non-desktop or embedded platforms, you may need to use custom Wayland shell extensions instead of the standard xdg_shell or wl_shell. These are provided via shell integration plugins.

    The shell integration is determined by the QT_WAYLAND_SHELL_INTEGRATION environment variable. If not specified, the system attempts to use shells in this order: xdg-shell $\rightarrow$ xdg-shell-v6 $\rightarrow$ wl-shell $\rightarrow$ ivi-shell.

    Available Shell Integrations:

    • ivi-shell
    • wl-shell (deprecated)
    • xdg-shell
    • fullscreen-shell-v1

    Example: Running an application with ivi-shell

    QT_WAYLAND_SHELL_INTEGRATION=ivi-shell ./hellowindow -platform wayland
  10. Set unique IDs for IVI surfaces and layers using QT_IVI_SURFACE_ID

    dev

    Since Qt does not provide a direct API for setting the unique IDs required by the ivi-application and ivi-controller protocols, you must use the QT_IVI_SURFACE_ID environment variable.

    ID Generation Rules

    • Manual Setting: Set QT_IVI_SURFACE_ID to define the base ID. This value is used for both the ivi-surface and the ivi-layer.
    • Automatic Increment: If an application requires more than two surfaces, the ivi-surface IDs will be incremented automatically.
    • Internal Generation: If QT_IVI_SURFACE_ID is not set, the IDs for ivi-surface and ivi-layer will be generated internally by the system.

    ID Bit Structure

    The QT_IVI_SURFACE_ID is a 32-bit value composed of a process ID and a surface ID:

    • Bits 0 to 22: Process ID.
    • Bits 23 to 32: Surface ID within that process.

    Example: If the process ID is 0x765 and there are two surfaces:

    • The ivi-layer ID is 0x765.
    • The first ivi-surface ID is 0x765.
    • The second ivi-surface ID is 0x00400765.
    # Example of setting the environment variable before running the application
    export QT_IVI_SURFACE_ID=0x765
    ./your_ivi_application
  11. Configure client buffer integrations

    dev

    QtWaylandCompositor can load client buffer integrations as plugins to handle graphics memory buffers. By default, the wayland-egl plugin is used. If you need to use a different integration (such as for specific hardware), set the QT_WAYLAND_CLIENT_BUFFER_INTEGRATION environment variable.

    Warning: If a non-standard integration is used instead of wayland-egl, Weston clients may not work.

    Available integrations:

    • wayland-egl (default)
    • linux-dmabuf-v1
    • brcm
  12. Use QWaylandSeat for manual input injection

    dev

    If you are building a custom compositor, you can use QWaylandSeat to translate host input events (like those from a mouse or keyboard) into Wayland protocol events for clients.

    Mouse Events

    • void sendMouseMoveEvent(QWaylandView *surface, const QPointF &localPos, const QPointF &outputSpacePos = QPointF())
    • void sendMousePressEvent(Qt::MouseButton button)
    • void sendMouseReleaseEvent(Qt::MouseButton button)
    • void sendMouseWheelEvent(Qt::Orientation orientation, int delta)

    Keyboard Events

    • void sendKeyPressEvent(uint code)
    • void sendKeyReleaseEvent(uint code)
    • void sendKeyEvent(int qtKey, bool pressed): Uses Qt key codes.
    • void sendUnicodeKeyPressEvent(uint unicode) (Available since version 6.7)
    • void sendUnicodeKeyReleaseEvent(uint unicode) (Available since version 6.7)

    Touch Events

    • uint sendTouchPointPressed(QWaylandSurface *surface, int id, const QPointF &position)
    • uint sendTouchPointMoved(QWaylandSurface *surface, int id, const QPointF &position)
    • uint sendTouchPointReleased(QWaylandSurface *surface, int id, const QPointF &position)
    • void sendTouchFrameEvent(QWaylandClient *client)
    • void sendTouchCancelEvent(QWaylandClient *client)