diff options
Diffstat (limited to 'examples/wayland/custom-shell/compositor')
-rw-r--r-- | examples/wayland/custom-shell/compositor/CMakeLists.txt | 57 | ||||
-rw-r--r-- | examples/wayland/custom-shell/compositor/compositor.pro | 29 | ||||
-rw-r--r-- | examples/wayland/custom-shell/compositor/compositor.qrc | 6 | ||||
-rw-r--r-- | examples/wayland/custom-shell/compositor/exampleshell.cpp | 119 | ||||
-rw-r--r-- | examples/wayland/custom-shell/compositor/exampleshell.h | 88 | ||||
-rw-r--r-- | examples/wayland/custom-shell/compositor/exampleshellintegration.cpp | 29 | ||||
-rw-r--r-- | examples/wayland/custom-shell/compositor/exampleshellintegration.h | 26 | ||||
-rw-r--r-- | examples/wayland/custom-shell/compositor/images/background.png | bin | 0 -> 2275 bytes | |||
-rw-r--r-- | examples/wayland/custom-shell/compositor/main.cpp | 29 | ||||
-rw-r--r-- | examples/wayland/custom-shell/compositor/qml/main.qml | 72 |
10 files changed, 455 insertions, 0 deletions
diff --git a/examples/wayland/custom-shell/compositor/CMakeLists.txt b/examples/wayland/custom-shell/compositor/CMakeLists.txt new file mode 100644 index 000000000..be1d7f623 --- /dev/null +++ b/examples/wayland/custom-shell/compositor/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.14) +project(custom-shell-compositor) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/custom-shell/compositor") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml WaylandCompositor) + +qt_add_executable(custom-shell-compositor + exampleshell.cpp exampleshell.h + exampleshellintegration.cpp exampleshellintegration.h + main.cpp +) + +qt6_generate_wayland_protocol_server_sources(custom-shell-compositor + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../protocol/example-shell.xml +) + +set_target_properties(custom-shell-compositor PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(custom-shell-compositor PUBLIC + Qt::Core + Qt::Gui + Qt::Qml + Qt::WaylandCompositor +) + +# Resources: +set(compositor_resource_files + "images/background.png" + "qml/main.qml" +) + +qt6_add_resources(custom-shell-compositor "compositor" + PREFIX + "/" + FILES + ${compositor_resource_files} +) + +install(TARGETS custom-shell-compositor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/custom-shell/compositor/compositor.pro b/examples/wayland/custom-shell/compositor/compositor.pro new file mode 100644 index 000000000..d64ddac61 --- /dev/null +++ b/examples/wayland/custom-shell/compositor/compositor.pro @@ -0,0 +1,29 @@ +QT += core gui qml + +QT += waylandcompositor + +CONFIG += wayland-scanner +CONFIG += c++11 +SOURCES += \ + main.cpp \ + exampleshell.cpp \ + exampleshellintegration.cpp \ + +HEADERS += \ + exampleshell.h \ + exampleshellintegration.h + +OTHER_FILES = \ + qml/main.qml \ + images/background.jpg + +WAYLANDSERVERSOURCES += \ + ../protocol/example-shell.xml + +RESOURCES += compositor.qrc + +TARGET = custom-shell-compositor + + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/custom-shell/compositor +INSTALLS += target diff --git a/examples/wayland/custom-shell/compositor/compositor.qrc b/examples/wayland/custom-shell/compositor/compositor.qrc new file mode 100644 index 000000000..59c00f5f9 --- /dev/null +++ b/examples/wayland/custom-shell/compositor/compositor.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.png</file> + <file>qml/main.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/custom-shell/compositor/exampleshell.cpp b/examples/wayland/custom-shell/compositor/exampleshell.cpp new file mode 100644 index 000000000..f134a8ba6 --- /dev/null +++ b/examples/wayland/custom-shell/compositor/exampleshell.cpp @@ -0,0 +1,119 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "exampleshell.h" +#include "exampleshellintegration.h" + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandResource> + +ExampleShell::ExampleShell() +{ +} + +ExampleShell::ExampleShell(QWaylandCompositor *compositor) + : QWaylandCompositorExtensionTemplate<ExampleShell>(compositor) +{ + this->compositor = compositor; +} + +//! [initialize] +void ExampleShell::initialize() +{ + QWaylandCompositorExtensionTemplate::initialize(); + + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + if (!compositor) { + qWarning() << "Failed to find QWaylandCompositor when initializing ExampleShell"; + return; + } + + init(compositor->display(), 1); +} +//! [initialize] + +//! [surface_create] +void ExampleShell::example_shell_surface_create(Resource *resource, wl_resource *surfaceResource, uint32_t id) +{ + QWaylandSurface *surface = QWaylandSurface::fromResource(surfaceResource); + + if (!surface->setRole(ExampleShellSurface::role(), resource->handle, QT_EXAMPLE_SHELL_ERROR_ROLE)) + return; + + QWaylandResource shellSurfaceResource(wl_resource_create(resource->client(), &::qt_example_shell_surface_interface, + wl_resource_get_version(resource->handle), id)); + + auto *shellSurface = new ExampleShellSurface(this, surface, shellSurfaceResource); + emit shellSurfaceCreated(shellSurface); +} +//! [surface_create] + +ExampleShellSurface::ExampleShellSurface(ExampleShell *shell, QWaylandSurface *surface, const QWaylandResource &resource) +{ + m_shell = shell; + m_surface = surface; + init(resource.resource()); + setExtensionContainer(surface); + QWaylandCompositorExtension::initialize(); +} + +QWaylandSurfaceRole ExampleShellSurface::s_role("qt_example_shell_surface"); + +/*! + * Returns the surface role for the ExampleShellSurface. + */ +QWaylandSurfaceRole *ExampleShellSurface::role() +{ + return &s_role; +} + +/*! + * Returns the ExampleShellSurface corresponding to the \a resource. + */ +ExampleShellSurface *ExampleShellSurface::fromResource(wl_resource *resource) +{ + auto *res = Resource::fromResource(resource); + return static_cast<ExampleShellSurface *>(res->object()); +} + +QWaylandQuickShellIntegration *ExampleShellSurface::createIntegration(QWaylandQuickShellSurfaceItem *item) +{ + return new ExampleShellIntegration(item); +} + +void ExampleShellSurface::example_shell_surface_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource); + delete this; +} + +void ExampleShellSurface::example_shell_surface_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void ExampleShellSurface::example_shell_surface_set_window_title(Resource *resource, const QString &window_title) +{ + Q_UNUSED(resource); + m_windowTitle = window_title; + emit windowTitleChanged(); +} + +void ExampleShellSurface::example_shell_surface_set_minimized(Resource *resource, uint32_t minimized) +{ + Q_UNUSED(resource); + if (m_minimized != minimized) { + m_minimized = minimized; + emit minimizedChanged(); + } +} + +void ExampleShellSurface::setMinimized(bool newMinimized) +{ + if (m_minimized == newMinimized) + return; + m_minimized = newMinimized; + send_minimize(newMinimized); + emit minimizedChanged(); +} diff --git a/examples/wayland/custom-shell/compositor/exampleshell.h b/examples/wayland/custom-shell/compositor/exampleshell.h new file mode 100644 index 000000000..5dd8b6c98 --- /dev/null +++ b/examples/wayland/custom-shell/compositor/exampleshell.h @@ -0,0 +1,88 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef EXAMPLESHELL_H +#define EXAMPLESHELL_H + +#include <QtWaylandCompositor/QWaylandCompositorExtension> +#include <QtWaylandCompositor/QWaylandQuickExtension> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandResource> +#include <QtCore/QSize> + +#include <QtWaylandCompositor/QWaylandShellSurface> +#include "qwayland-server-example-shell.h" + +class ExampleShellSurface; + +//! [ExampleShell] +class ExampleShell + : public QWaylandCompositorExtensionTemplate<ExampleShell> + , QtWaylandServer::qt_example_shell +//! [ExampleShell] +{ + Q_OBJECT +public: + ExampleShell(); + ExampleShell(QWaylandCompositor *compositor); + + void initialize() override; + + using QtWaylandServer::qt_example_shell::interface; + using QtWaylandServer::qt_example_shell::interfaceName; + +protected: + void example_shell_surface_create(Resource *resource, wl_resource *surfaceResource, uint32_t id) override; + +signals: + void shellSurfaceCreated(ExampleShellSurface *shellSurface); + +private: + QWaylandCompositor *compositor; +}; + +class ExampleShellSurface : + public QWaylandShellSurfaceTemplate<ExampleShellSurface> + , public QtWaylandServer::qt_example_shell_surface +{ + Q_OBJECT + Q_PROPERTY(QString windowTitle READ windowTitle NOTIFY windowTitleChanged) + Q_PROPERTY(bool minimized READ minimized WRITE setMinimized NOTIFY minimizedChanged) +public: + ExampleShellSurface(ExampleShell *shell, QWaylandSurface *surface, const QWaylandResource &resource); + + using QtWaylandServer::qt_example_shell_surface::interface; + using QtWaylandServer::qt_example_shell_surface::interfaceName; + static QWaylandSurfaceRole *role(); + static ExampleShellSurface *fromResource(::wl_resource *resource); + + QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) override; + + QWaylandSurface *surface() const { return m_surface; } + const QString &windowTitle() const { return m_windowTitle; } + bool minimized() const { return m_minimized; } + void setMinimized(bool newMinimized); + +signals: + void windowTitleChanged(); + void minimizedChanged(); + +protected: + void example_shell_surface_destroy_resource(Resource *resource) override; + void example_shell_surface_destroy(Resource *resource) override; + void example_shell_surface_set_window_title(Resource *resource, const QString &window_title) override; + void example_shell_surface_set_minimized(Resource *resource, uint32_t minimized) override; + +private: + static QWaylandSurfaceRole s_role; + QWaylandSurface *m_surface = nullptr; + ExampleShell *m_shell = nullptr; + QString m_windowTitle; + bool m_minimized = false; +}; + +//! [declare_extension] +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(ExampleShell) +//! [declare_extension] + +#endif // EXAMPLESHELL_H diff --git a/examples/wayland/custom-shell/compositor/exampleshellintegration.cpp b/examples/wayland/custom-shell/compositor/exampleshellintegration.cpp new file mode 100644 index 000000000..840927d0f --- /dev/null +++ b/examples/wayland/custom-shell/compositor/exampleshellintegration.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "exampleshellintegration.h" + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> +#include <QtWaylandCompositor/QWaylandSeat> +#include "exampleshell.h" + + +ExampleShellIntegration::ExampleShellIntegration(QWaylandQuickShellSurfaceItem *item) + : QWaylandQuickShellIntegration(item) + , m_item(item) + , m_shellSurface(qobject_cast<ExampleShellSurface *>(item->shellSurface())) +{ + m_item->setSurface(m_shellSurface->surface()); + connect(m_shellSurface, &ExampleShellSurface::destroyed, this, &ExampleShellIntegration::handleExampleShellSurfaceDestroyed); +} + +ExampleShellIntegration::~ExampleShellIntegration() +{ + m_item->setSurface(nullptr); +} + +void ExampleShellIntegration::handleExampleShellSurfaceDestroyed() +{ + m_shellSurface = nullptr; +} diff --git a/examples/wayland/custom-shell/compositor/exampleshellintegration.h b/examples/wayland/custom-shell/compositor/exampleshellintegration.h new file mode 100644 index 000000000..d03826ef0 --- /dev/null +++ b/examples/wayland/custom-shell/compositor/exampleshellintegration.h @@ -0,0 +1,26 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef EXAMPLESHELLINTEGRATION_H +#define EXAMPLESHELLINTEGRATION_H + +#include "exampleshell.h" +#include <QtWaylandCompositor/QWaylandQuickShellIntegration> +#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> + +class ExampleShellIntegration : public QWaylandQuickShellIntegration +{ + Q_OBJECT +public: + ExampleShellIntegration(QWaylandQuickShellSurfaceItem *item); + ~ExampleShellIntegration() override; + +private slots: + void handleExampleShellSurfaceDestroyed(); + +private: + QWaylandQuickShellSurfaceItem *m_item = nullptr; + ExampleShellSurface *m_shellSurface = nullptr; +}; + +#endif // EXAMPLESHELLINTEGRATION_H diff --git a/examples/wayland/custom-shell/compositor/images/background.png b/examples/wayland/custom-shell/compositor/images/background.png Binary files differnew file mode 100644 index 000000000..cf264746f --- /dev/null +++ b/examples/wayland/custom-shell/compositor/images/background.png diff --git a/examples/wayland/custom-shell/compositor/main.cpp b/examples/wayland/custom-shell/compositor/main.cpp new file mode 100644 index 000000000..72f233e8e --- /dev/null +++ b/examples/wayland/custom-shell/compositor/main.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QtCore/QUrl> +#include <QtCore/QDebug> +#include <QtGui/QGuiApplication> +#include <QtQml/QQmlApplicationEngine> + +#include <QtQml/qqml.h> +#include <QtQml/QQmlEngine> + +#include "exampleshell.h" + +static void registerTypes() +{ + qmlRegisterType<ExampleShellQuickExtension>("io.qt.examples", 1, 0, "ExampleShell"); +} + +int main(int argc, char *argv[]) +{ + // ShareOpenGLContexts is needed for using the threaded renderer + // on Nvidia EGLStreams + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); + QGuiApplication app(argc, argv); + registerTypes(); + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); + + return app.exec(); +} diff --git a/examples/wayland/custom-shell/compositor/qml/main.qml b/examples/wayland/custom-shell/compositor/qml/main.qml new file mode 100644 index 000000000..149e0e748 --- /dev/null +++ b/examples/wayland/custom-shell/compositor/qml/main.qml @@ -0,0 +1,72 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWayland.Compositor +import QtQuick.Layouts +import QtQuick.Controls + +import io.qt.examples 1.0 + +WaylandCompositor { + id: comp + + ListModel { id: shellSurfaces } + + + WaylandOutput { + sizeFollowsWindow: true + window: Window { + width: 1024 + height: 768 + visible: true + + ColumnLayout { + anchors.fill: parent + spacing: 0 + Image { + fillMode: Image.Tile + source: "qrc:/images/background.png" + smooth: false + Layout.fillHeight: true + Layout.fillWidth: true + GridLayout { + columns: 3 + Repeater { + model: shellSurfaces + ShellSurfaceItem { + id: chrome + shellSurface: modelData + visible: !shellSurface.minimized + onSurfaceDestroyed: shellSurfaces.remove(index) + } + } + } + } + Row { + id: taskbar + Layout.fillWidth: true + Repeater { + model: shellSurfaces + Button { + id: minimizeButton + checkable: true + text: modelData.windowTitle + onCheckedChanged: modelData.minimized = checked + checked: modelData.minimized + } + } + } + } + } + } + + //! [ExampleShell] + ExampleShell { + id: shell + onShellSurfaceCreated: (shellSurface) => { + shellSurfaces.append({shellSurface: shellSurface}); + } + } + //! [ExampleShell] +} |