diff options
Diffstat (limited to 'examples/wayland/custom-extension')
21 files changed, 543 insertions, 646 deletions
diff --git a/examples/wayland/custom-extension/CMakeLists.txt b/examples/wayland/custom-extension/CMakeLists.txt new file mode 100644 index 000000000..af6e7febd --- /dev/null +++ b/examples/wayland/custom-extension/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(custom-extension) + +add_subdirectory(qml-client) +add_subdirectory(compositor) +add_subdirectory(cpp-client) diff --git a/examples/wayland/custom-extension/client-common/customextension.cpp b/examples/wayland/custom-extension/client-common/customextension.cpp index aa0cb58a4..4f898ea9b 100644 --- a/examples/wayland/custom-extension/client-common/customextension.cpp +++ b/examples/wayland/custom-extension/client-common/customextension.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "customextension.h" #include <QtGui/QGuiApplication> @@ -72,7 +25,7 @@ static inline struct ::wl_surface *getWlSurface(QWindow *window) QWindow *CustomExtension::windowForSurface(struct ::wl_surface *surface) { - for (QWindow *w : qAsConst(m_windows)) { + for (QWindow *w : std::as_const(m_windows)) { if (getWlSurface(w) == surface) return w; } @@ -81,12 +34,13 @@ QWindow *CustomExtension::windowForSurface(struct ::wl_surface *surface) bool CustomExtension::eventFilter(QObject *object, QEvent *event) { - if (event->type() == QEvent::PlatformSurface - && static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { + if (event->type() == QEvent::Expose) { QWindow *window = qobject_cast<QWindow*>(object); Q_ASSERT(window); - window->removeEventFilter(this); - QtWayland::qt_example_extension::register_surface(getWlSurface(window)); + if (window->isExposed()) { + window->removeEventFilter(this); + QtWayland::qt_example_extension::register_surface(getWlSurface(window)); + } } return false; } @@ -102,8 +56,10 @@ void CustomExtension::sendWindowRegistration(QWindow *window) void CustomExtension::registerWindow(QWindow *window) { m_windows << window; - if (isActive()) + if (isActive()) { + m_activated = true; sendWindowRegistration(window); + } } CustomExtensionObject *CustomExtension::createCustomObject(const QString &color, const QString &text) @@ -112,10 +68,12 @@ CustomExtensionObject *CustomExtension::createCustomObject(const QString &color, return new CustomExtensionObject(obj, text); } +//! [sendBounce] void CustomExtension::sendBounce(QWindow *window, uint ms) { QtWayland::qt_example_extension::bounce(getWlSurface(window), ms); } +//! [sendBounce] void CustomExtension::sendSpin(QWindow *window, uint ms) { @@ -125,7 +83,8 @@ void CustomExtension::sendSpin(QWindow *window, uint ms) void CustomExtension::handleExtensionActive() { if (isActive() && !m_activated) { - for (QWindow *w : qAsConst(m_windows)) + m_activated = true; + for (QWindow *w : std::as_const(m_windows)) sendWindowRegistration(w); } } @@ -145,7 +104,7 @@ void CustomExtension::example_extension_set_font_size(wl_surface *surface, uint3 void CustomExtension::example_extension_set_window_decoration(uint32_t state) { bool shown = state; - for (QWindow *w : qAsConst(m_windows)) { + for (QWindow *w : std::as_const(m_windows)) { Qt::WindowFlags f = w->flags(); if (shown) f &= ~Qt::FramelessWindowHint; diff --git a/examples/wayland/custom-extension/client-common/customextension.h b/examples/wayland/custom-extension/client-common/customextension.h index 7a188c3d6..5dd770199 100644 --- a/examples/wayland/custom-extension/client-common/customextension.h +++ b/examples/wayland/custom-extension/client-common/customextension.h @@ -1,68 +1,26 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef CUSTOMEXTENSION_H #define CUSTOMEXTENSION_H #include <QtWaylandClient/QWaylandClientExtension> #include <QtGui/QWindow> +#include <QtQml/QQmlEngine> + #include "qwayland-custom.h" QT_BEGIN_NAMESPACE class CustomExtensionObject; +//! [CustomExtension] class CustomExtension : public QWaylandClientExtensionTemplate<CustomExtension> , public QtWayland::qt_example_extension +//! [CustomExtension] { Q_OBJECT + QML_ELEMENT public: CustomExtension(); Q_INVOKABLE void registerWindow(QWindow *window); @@ -114,7 +72,6 @@ protected: public slots: void setText(const QString &text); - signals: void textChanged(const QString &text); void clicked(); diff --git a/examples/wayland/custom-extension/compositor/CMakeLists.txt b/examples/wayland/custom-extension/compositor/CMakeLists.txt new file mode 100644 index 000000000..200e7766d --- /dev/null +++ b/examples/wayland/custom-extension/compositor/CMakeLists.txt @@ -0,0 +1,63 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(custom-extension-compositor) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/custom-extension/compositor") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml WaylandCompositor) + +qt6_policy(SET QTP0001 NEW) +qt_add_executable(custom-extension-compositor + customextension.cpp customextension.h + main.cpp +) + +qt6_generate_wayland_protocol_server_sources(custom-extension-compositor + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../protocol/custom.xml +) + +set_target_properties(custom-extension-compositor PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(custom-extension-compositor PUBLIC + Qt::Core + Qt::Gui + Qt::Qml + Qt::WaylandCompositor +) + +# Resources: +set(compositor_resource_files + "images/background.png" + "qml/CompositorScreen.qml" + "qml/main.qml" +) + +qt6_add_resources(custom-extension-compositor "compositor" + PREFIX + "/" + FILES + ${compositor_resource_files} +) + +qt6_add_qml_module(custom-extension-compositor + URI io.qt.examples.customextension + VERSION 1.0 +) + +install(TARGETS custom-extension-compositor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/custom-extension/compositor/compositor.pro b/examples/wayland/custom-extension/compositor/compositor.pro index 751b5ca3d..263b9fbdd 100644 --- a/examples/wayland/custom-extension/compositor/compositor.pro +++ b/examples/wayland/custom-extension/compositor/compositor.pro @@ -2,6 +2,10 @@ QT += core gui qml QT += waylandcompositor +CONFIG += qmltypes +QML_IMPORT_NAME = io.qt.examples.customextension +QML_IMPORT_MAJOR_VERSION = 1 + CONFIG += wayland-scanner CONFIG += c++11 SOURCES += \ @@ -10,7 +14,7 @@ SOURCES += \ OTHER_FILES = \ qml/main.qml \ - qml/Screen.qml \ + qml/CompositorScreen.qml \ images/background.jpg WAYLANDSERVERSOURCES += \ @@ -18,7 +22,7 @@ WAYLANDSERVERSOURCES += \ RESOURCES += compositor.qrc -TARGET = custom-compositor +TARGET = custom-extension-compositor HEADERS += \ customextension.h diff --git a/examples/wayland/custom-extension/compositor/compositor.qrc b/examples/wayland/custom-extension/compositor/compositor.qrc index db3a8075a..6ab847a7c 100644 --- a/examples/wayland/custom-extension/compositor/compositor.qrc +++ b/examples/wayland/custom-extension/compositor/compositor.qrc @@ -2,6 +2,6 @@ <qresource prefix="/"> <file>images/background.png</file> <file>qml/main.qml</file> - <file>qml/Screen.qml</file> + <file>qml/CompositorScreen.qml</file> </qresource> </RCC> diff --git a/examples/wayland/custom-extension/compositor/customextension.cpp b/examples/wayland/custom-extension/compositor/customextension.cpp index d9f637a12..0d19a62e2 100644 --- a/examples/wayland/custom-extension/compositor/customextension.cpp +++ b/examples/wayland/custom-extension/compositor/customextension.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "customextension.h" @@ -55,7 +8,7 @@ #include <QDebug> CustomExtension::CustomExtension(QWaylandCompositor *compositor) - :QWaylandCompositorExtensionTemplate(compositor) + : QWaylandCompositorExtensionTemplate(compositor) { } @@ -66,6 +19,7 @@ void CustomExtension::initialize() init(compositor->display(), 1); } +//! [setFontSize] void CustomExtension::setFontSize(QWaylandSurface *surface, uint pixelSize) { if (surface) { @@ -76,6 +30,7 @@ void CustomExtension::setFontSize(QWaylandSurface *surface, uint pixelSize) } } } +//! [setFontSize] void CustomExtension::showDecorations(QWaylandClient *client, bool shown) { @@ -86,7 +41,6 @@ void CustomExtension::showDecorations(QWaylandClient *client, bool shown) send_set_window_decoration(target->handle, shown); } } - } void CustomExtension::close(QWaylandSurface *surface) @@ -100,6 +54,7 @@ void CustomExtension::close(QWaylandSurface *surface) } } +//! [example_extension_bounce] void CustomExtension::example_extension_bounce(QtWaylandServer::qt_example_extension::Resource *resource, wl_resource *wl_surface, uint32_t duration) { Q_UNUSED(resource); @@ -107,6 +62,7 @@ void CustomExtension::example_extension_bounce(QtWaylandServer::qt_example_exten qDebug() << "server received bounce" << surface << duration; emit bounce(surface, duration); } +//! [example_extension_bounce] void CustomExtension::example_extension_spin(QtWaylandServer::qt_example_extension::Resource *resource, wl_resource *wl_surface, uint32_t duration) { @@ -137,7 +93,6 @@ CustomExtensionObject::CustomExtensionObject(const QString &color, const QString , m_color(color) , m_text(text) { - } void CustomExtensionObject::sendClicked() diff --git a/examples/wayland/custom-extension/compositor/customextension.h b/examples/wayland/custom-extension/compositor/customextension.h index dc44dfc2a..e377d5f57 100644 --- a/examples/wayland/custom-extension/compositor/customextension.h +++ b/examples/wayland/custom-extension/compositor/customextension.h @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef CUSTOMEXTENSION_H #define CUSTOMEXTENSION_H @@ -56,14 +9,18 @@ #include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate> #include <QtWaylandCompositor/QWaylandQuickExtension> #include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandSurface> #include "qwayland-server-custom.h" class CustomExtensionObject; +//! [CustomExtension] class CustomExtension : public QWaylandCompositorExtensionTemplate<CustomExtension> , public QtWaylandServer::qt_example_extension { Q_OBJECT + QML_ELEMENT +//! [CustomExtension] public: CustomExtension(QWaylandCompositor *compositor = nullptr); void initialize() override; @@ -72,7 +29,6 @@ signals: void surfaceAdded(QWaylandSurface *surface); void bounce(QWaylandSurface *surface, uint ms); void spin(QWaylandSurface *surface, uint ms); - void customObjectCreated(CustomExtensionObject *obj); public slots: @@ -80,11 +36,12 @@ public slots: void showDecorations(QWaylandClient *client, bool); void close(QWaylandSurface *surface); +//! [example_extension_bounce] protected: void example_extension_bounce(Resource *resource, wl_resource *surface, uint32_t duration) override; +//! [example_extension_bounce] void example_extension_spin(Resource *resource, wl_resource *surface, uint32_t duration) override; void example_extension_register_surface(Resource *resource, wl_resource *surface) override; - void example_extension_create_local_object(Resource *resource, uint32_t id, const QString &color, const QString &text) override; }; diff --git a/examples/wayland/custom-extension/compositor/main.cpp b/examples/wayland/custom-extension/compositor/main.cpp index 91de8f798..69e34d2dc 100644 --- a/examples/wayland/custom-extension/compositor/main.cpp +++ b/examples/wayland/custom-extension/compositor/main.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QtCore/QUrl> #include <QtCore/QDebug> @@ -58,15 +11,12 @@ #include "customextension.h" -static void registerTypes() -{ - qmlRegisterType<CustomExtensionQuickExtension>("com.theqtcompany.customextension", 1, 0, "CustomExtension"); -} - 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-extension/compositor/qml/Screen.qml b/examples/wayland/custom-extension/compositor/qml/CompositorScreen.qml index 1e6d3e402..ea2cb9b16 100644 --- a/examples/wayland/custom-extension/compositor/qml/Screen.qml +++ b/examples/wayland/custom-extension/compositor/qml/CompositorScreen.qml @@ -1,61 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.0 -import QtQuick.Window 2.2 -import QtWayland.Compositor 1.0 +import QtQuick +import QtQuick.Window +import QtWayland.Compositor WaylandOutput { id: output property alias surfaceArea: background sizeFollowsWindow: true + window: Window { id: screen @@ -67,7 +21,7 @@ WaylandOutput { Rectangle { id: sidebar - width: 150 + width: 250 anchors.left: parent.left anchors.top: parent.top anchors.bottom: parent.bottom @@ -81,19 +35,20 @@ WaylandOutput { Repeater { model: comp.itemList Rectangle { - height: 36 + height: 54 width: sidebar.width - 5 color: "white" radius: 5 Text { - text: "window: " + modelData.shellSurface.title + "[" + modelData.shellSurface.className - + (modelData.isCustom ? "]\nfont size: " + modelData.fontSize :"]\n No extension") + text: "window: " + modelData.shellSurface.toplevel.title + "\n[" + + modelData.shellSurface.toplevel.appId + + (modelData.isCustom ? "]\nfont size: " + modelData.fontSize : "]\nNo extension") color: modelData.isCustom ? "black" : "darkgray" } MouseArea { enabled: modelData.isCustom anchors.fill: parent - onWheel: { + onWheel: (wheel) => { if (wheel.angleDelta.y > 0) modelData.fontSize++ else if (wheel.angleDelta.y < 0 && modelData.fontSize > 3) @@ -121,7 +76,7 @@ WaylandOutput { anchors.top: parent.top anchors.bottom: parent.bottom - windowSystemCursorEnabled: true + windowSystemCursorEnabled: !clientCursor.visible Image { id: background anchors.fill: parent @@ -130,8 +85,7 @@ WaylandOutput { smooth: false } WaylandCursorItem { - id: cursor - inputEventsEnabled: false + id: clientCursor x: mouseTracker.mouseX y: mouseTracker.mouseY diff --git a/examples/wayland/custom-extension/compositor/qml/main.qml b/examples/wayland/custom-extension/compositor/qml/main.qml index a7d762276..9907263da 100644 --- a/examples/wayland/custom-extension/compositor/qml/main.qml +++ b/examples/wayland/custom-extension/compositor/qml/main.qml @@ -1,57 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.0 -import QtWayland.Compositor 1.0 - -import com.theqtcompany.customextension 1.0 +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell + +import io.qt.examples.customextension 1.0 WaylandCompositor { id: comp @@ -67,7 +21,7 @@ WaylandCompositor { } } - Screen { + CompositorScreen { compositor: comp } @@ -80,36 +34,38 @@ WaylandCompositor { property int fontSize: 12 onSurfaceDestroyed: { - var index = itemList.indexOf(chrome); + var index = itemList.indexOf(chrome) if (index > -1) { var listCopy = itemList - listCopy.splice(index, 1); + listCopy.splice(index, 1) itemList = listCopy } chrome.destroy() } + transform: [ Rotation { id: xRot - origin.x: chrome.width/2; origin.y: chrome.height/2; + origin.x: chrome.width / 2; origin.y: chrome.height / 2 angle: 0 axis { x: 1; y: 0; z: 0 } }, Rotation { id: yRot - origin.x: chrome.width/2; origin.y: chrome.height/2; + origin.x: chrome.width / 2; origin.y: chrome.height / 2 angle: 0 axis { x: 0; y: 1; z: 0 } } ] + NumberAnimation { id: spinAnimation running: false loops: 2 - target: yRot; - property: "angle"; - from: 0; to: 360; - duration: 400; + target: yRot + property: "angle" + from: 0; to: 360 + duration: 400 } function doSpin(ms) { @@ -128,18 +84,21 @@ WaylandCompositor { easing.type: Easing.OutBounce duration: 1000 } + function doBounce(ms) { console.log("bounce " + ms) // using the 'ms' argument is left as an exercise for the reader... bounceAnimation.start() } + +//! [setFontSize] onFontSizeChanged: { custom.setFontSize(surface, fontSize) } +//! [setFontSize] } } - Component { id: customObjectComponent Rectangle { @@ -149,7 +108,7 @@ WaylandCompositor { width: 100 height: 100 - radius: width/2 + radius: width / 2 x: Math.random() * (defaultOutput.surfaceArea.width - 100) y: Math.random() * (defaultOutput.surfaceArea.height - 100) @@ -166,53 +125,59 @@ WaylandCompositor { Connections { target: obj - onResourceDestroyed: { + function onResourceDestroyed() { customItem.destroy() } } } } - WlShell { - id: defaultShell - onWlShellSurfaceCreated: { - var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": shellSurface } ); - var w = defaultOutput.surfaceArea.width/2 - var h = defaultOutput.surfaceArea.height/2 - item.x = Math.random()*w - item.y = Math.random()*h + XdgShell { + onToplevelCreated: (toplevel, xdgSurface) => { + var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": xdgSurface } ) + var w = defaultOutput.surfaceArea.width / 2 + var h = defaultOutput.surfaceArea.height / 2 + item.x = Math.random() * w + item.y = Math.random() * h var listCopy = itemList // List properties cannot be modified through Javascript operations listCopy.push(item) itemList = listCopy } } +//! [CustomExtension] CustomExtension { id: custom - onSurfaceAdded: { + onSurfaceAdded: (surface) => { var item = itemForSurface(surface) item.isCustom = true } - onBounce: { + + onBounce: (surface, ms) => { var item = itemForSurface(surface) item.doBounce(ms) } - onSpin: { + + onSpin: (surface, ms) => { var item = itemForSurface(surface) item.doSpin(ms) } - onCustomObjectCreated: { - var item = customObjectComponent.createObject(defaultOutput.surfaceArea, { "color": obj.color, "text": obj.text, "obj": obj } ); + + onCustomObjectCreated: (obj) => { + var item = customObjectComponent.createObject(defaultOutput.surfaceArea, + { "color": obj.color, + "text": obj.text, + "obj": obj } ) } } function setDecorations(shown) { var n = itemList.length for (var i = 0; i < n; i++) { - // TODO: we only need to do it once for each client if (itemList[i].isCustom) custom.showDecorations(itemList[i].surface.client, shown) } } +//! [CustomExtension] } diff --git a/examples/wayland/custom-extension/cpp-client/CMakeLists.txt b/examples/wayland/custom-extension/cpp-client/CMakeLists.txt new file mode 100644 index 000000000..1687ade05 --- /dev/null +++ b/examples/wayland/custom-extension/cpp-client/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(custom-extension-cpp-client) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/custom-extension/cpp-client") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui WaylandClient) + +qt_add_executable(custom-extension-cpp-client + ../client-common/customextension.cpp ../client-common/customextension.h + main.cpp +) + +qt6_generate_wayland_protocol_client_sources(custom-extension-cpp-client + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../protocol/custom.xml +) + +set_target_properties(custom-extension-cpp-client PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(custom-extension-cpp-client PUBLIC + Qt::Core + Qt::Gui + Qt::GuiPrivate + Qt::WaylandClient +) + +install(TARGETS custom-extension-cpp-client + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/custom-extension/cpp-client/cpp-client.pro b/examples/wayland/custom-extension/cpp-client/cpp-client.pro index 388a09bfa..6b178514e 100644 --- a/examples/wayland/custom-extension/cpp-client/cpp-client.pro +++ b/examples/wayland/custom-extension/cpp-client/cpp-client.pro @@ -9,5 +9,7 @@ SOURCES += main.cpp \ HEADERS += \ ../client-common/customextension.h +TARGET = custom-extension-cpp-client + target.path = $$[QT_INSTALL_EXAMPLES]/wayland/custom-extension/cpp-client INSTALLS += target diff --git a/examples/wayland/custom-extension/cpp-client/main.cpp b/examples/wayland/custom-extension/cpp-client/main.cpp index 78eac44b9..c3951ea9d 100644 --- a/examples/wayland/custom-extension/cpp-client/main.cpp +++ b/examples/wayland/custom-extension/cpp-client/main.cpp @@ -1,69 +1,19 @@ -/**************************************************************************** - ** - ** Copyright (C) 2017 The Qt Company Ltd. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the examples of the Qt Wayland module - ** - ** $QT_BEGIN_LICENSE:BSD$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** BSD License Usage - ** Alternatively, you may use this file under the terms of the BSD license - ** as follows: - ** - ** "Redistribution and use in source and binary forms, with or without - ** modification, are permitted provided that the following conditions are - ** met: - ** * Redistributions of source code must retain the above copyright - ** notice, this list of conditions and the following disclaimer. - ** * Redistributions in binary form must reproduce the above copyright - ** notice, this list of conditions and the following disclaimer in - ** the documentation and/or other materials provided with the - ** distribution. - ** * Neither the name of The Qt Company Ltd nor the names of its - ** contributors may be used to endorse or promote products derived - ** from this software without specific prior written permission. - ** - ** - ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QGuiApplication> #include <QRasterWindow> #include <QPainter> #include <QMouseEvent> #include <QPlatformSurfaceEvent> - -#include "../client-common/customextension.h" - #include <QDebug> -#include <QtGui/qpa/qplatformnativeinterface.h> #include <QTimer> +#include "../client-common/customextension.h" + class TestWindow : public QRasterWindow { Q_OBJECT - public: TestWindow(CustomExtension *customExtension) : m_extension(customExtension) @@ -72,8 +22,12 @@ public: , rect3(50, 350, 100, 100) , rect4(200,350, 100, 100) { + setTitle(tr("C++ Client")); m_extension->registerWindow(this); + +//! [connection] connect(m_extension, &CustomExtension::fontSize, this, &TestWindow::handleSetFontSize); +//! [connection] } public slots: @@ -86,6 +40,7 @@ public slots: qDebug() << "sending spin..."; m_extension->sendSpin(this, 500); } + void doBounce() { if (!m_extension->isActive()) { @@ -105,7 +60,7 @@ public slots: CustomExtensionObject *newObject() { m_objectCount++; - QColor col = QColor::fromHsv(0, 511/(m_objectCount+1), 255); + QColor col = QColor::fromHsv(0, 511 / (m_objectCount + 1), 255); return m_extension->createCustomObject(col.name(), QString::number(m_objectCount)); } @@ -123,36 +78,38 @@ protected: { QPainter p(this); p.setFont(m_font); - p.fillRect(QRect(0,0,width(),height()),Qt::gray); - p.fillRect(rect1, QColor("#C0FFEE")); + p.fillRect(QRect(0, 0, width(), height()), Qt::gray); + p.fillRect(rect1, QColor::fromString("#C0FFEE")); p.drawText(rect1, Qt::TextWordWrap, "Press here to send spin request."); - p.fillRect(rect2, QColor("#decaff")); + p.fillRect(rect2, QColor::fromString("#decaff")); p.drawText(rect2, Qt::TextWordWrap, "Press here to send bounce request."); - p.fillRect(rect3, QColor("#7EA")); + p.fillRect(rect3, QColor::fromString("#7EA")); p.drawText(rect3, Qt::TextWordWrap, "Create new window."); - p.fillRect(rect4, QColor("#7EABA6")); + p.fillRect(rect4, QColor::fromString("#7EABA6")); p.drawText(rect4, Qt::TextWordWrap, "Create custom object."); } +//! [mousePressEvent] void mousePressEvent(QMouseEvent *ev) override { - if (rect1.contains(ev->pos())) + if (rect1.contains(ev->position())) doSpin(); - else if (rect2.contains(ev->pos())) + else if (rect2.contains(ev->position())) doBounce(); - else if (rect3.contains(ev->pos())) + else if (rect3.contains(ev->position())) newWindow(); - else if (rect4.contains(ev->pos())) + else if (rect4.contains(ev->position())) newObject(); } +//! [mousePressEvent] private: CustomExtension *m_extension = nullptr; - QRect rect1; - QRect rect2; - QRect rect3; - QRect rect4; + QRectF rect1; + QRectF rect2; + QRectF rect3; + QRectF rect4; QFont m_font; static int m_objectCount; static int m_hue; diff --git a/examples/wayland/custom-extension/doc/images/custom-extension.png b/examples/wayland/custom-extension/doc/images/custom-extension.png Binary files differnew file mode 100644 index 000000000..95cddad12 --- /dev/null +++ b/examples/wayland/custom-extension/doc/images/custom-extension.png diff --git a/examples/wayland/custom-extension/doc/src/custom-extension.qdoc b/examples/wayland/custom-extension/doc/src/custom-extension.qdoc new file mode 100644 index 000000000..7b2cb0802 --- /dev/null +++ b/examples/wayland/custom-extension/doc/src/custom-extension.qdoc @@ -0,0 +1,148 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + * \title Custom Extension + * \example custom-extension + * \examplecategory {Embedded} + * \brief Custom Extension shows how to implement a custom Wayland extension. + * \ingroup qtwaylandcompositor-examples + * + * It's easy to write new extensions for Wayland. They are defined using a XML-based format and + * the \c wayland-scanner tool converts this to glue code in C. Qt expands on this with the + * \c qtwaylandscanner, which generates additional glue code in Qt and C++. + * + * \image custom-extension.png + * + * The Custom Extension example shows how to use these tools to extend the Wayland protocol and + * send custom requests and events between a Wayland client and a server. + * + * The example consists of four items: + * \list + * \li The definition of the protocol itself. + * \li A compositor that supports the extension. + * \li A C++-based client that supports the extension. + * \li A QML-based client that supports the extension. + * \endlist + * + * \section1 The Protocol Definition + * + * The XML file \c custom.xml defines the protocol. It contains an interface called + * "qt_example_extension". This is the name which will be broadcast from the server and which the + * client will attach to in order to send requests and receive events. This name should be unique, + * so it is good to use a prefix that sets it apart from official interfaces. + * + * An interface typically consists of two types of remote procedure calls: + * \e requests and \e events. "Requests" are calls the client makes on the server-side, and + * "events" are calls the server makes on the client-side. + * + * The example extension contains a set of \e requests which instructs the server to apply certain + * transforms to the client window. For instance, if the client sends a "bounce" request, then the + * server should respond to this by making the window bounce on the screen. + * + * Similarly, it has a set of \e events which the server can use to provide instructions for the + * client. For instance, the "set_font_size" event is an instruction for the client to set its + * default font size to a specific size. + * + * The protocol defines the existence of requests and events, as well as the arguments they + * take. When \c qtwaylandscanner is run on it, it will generate the code needed to marshall the + * procedure call and its arguments and to transmit this over the connection. On the other end, this + * becomes a call to a virtual function which can be implemented to provide the actual response. + * + * In order to have \c qtwaylandscanner run automatically as part of the build, we use the + * CMake functions \l{qt_generate_wayland_protocol_server_sources}{qt_generate_wayland_protocol_server_sources()} and + * \l{qt_generate_wayland_protocol_client_sources}{qt_generate_wayland_protocol_client_sources()} for generating the server-side and + * client-side glue code, respectively. (When using \c qmake, the \c WAYLANDSERVERSOURCES and + * \c WAYLANDCLIENTSOURCES variables achieve the same.) + * + * \section1 The Compositor Implementation + * + * The Compositor application itself is implemented using QML and Qt Quick, but the extension is + * implemented in C++. + * + * The first step is to create a subclass of the glue code generated by \c qtwaylandscanner so + * that we can access its functionality. We add the \l QML_ELEMENT macro to the class in order to + * make it accessible from QML. + * + * \snippet custom-extension/compositor/customextension.h CustomExtension + * + * In addition to inheriting from the generated class, we also inherit the class + * \l QWaylandCompositorExtensionTemplate which provides some additional convenience when dealing + * with extensions, using the + * \l{https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern}{Curiously Recurring Template Pattern}. + * + * Note that the \l QWaylandCompositorExtensionTemplate must be first in the inheritance list, since + * it is a \l{QObject}-based class. + * + * The subclass has re-implementations of virtual functions in the generated base class, where + * we can handle requests issued by a client. + * + * \snippet custom-extension/compositor/customextension.h example_extension_bounce + * + * In these re-implementations, we simply translate the request to a \e signal emission, so that we + * can handle it in the actual QML code of the compositor. + * + * \snippet custom-extension/compositor/customextension.cpp example_extension_bounce + * + * In addition, the subclass defines \e slots for each of the events, so that these can be either + * called from QML or be connected to signals. The slots simply call the generated functions which + * send the events to the client. + * + * \snippet custom-extension/compositor/customextension.cpp setFontSize + * + * Since we added the \l QML_ELEMENT macro to the class definition (and added the corresponding + * build steps to the build system files), it can be instantiated in QML. + * + * We make it a direct child of the \l WaylandCompositor object in order for the compositor to + * register it as an extension. + * + * \snippet custom-extension/compositor/qml/main.qml CustomExtension + * + * The object has signal handlers for the requests it may get from the client and reacts to them + * accordingly. In addition, we can call its slots to send events. + * + * \snippet custom-extension/compositor/qml/main.qml setFontSize + * + * \section1 The C++ Client Implementation + * + * Both clients share the C++ implementation of the interface. Like in the compositor, we make + * a subclass of the generated code which also inherits from a template class. In this case, + * we inherit QWaylandClientExtensionTemplate. + * + * \snippet custom-extension/client-common/customextension.h CustomExtension + * + * The approach is very similar to that of the compositor, except inverted: Requests are implemented + * as slots which call the generated functions, and events virtual functions which we re-implement + * to emit signals. + * + * \snippet custom-extension/client-common/customextension.cpp sendBounce + * + * The client code itself is very simple and only intended to show how to trigger the behavior. In + * a custom paint event, it draws a set of rectangles and labels. When any of these are clicked, it + * issues requests to the server. + * + * \snippet custom-extension/cpp-client/main.cpp mousePressEvent + * + * To update the font size when the \c set_font_size event is received, the signal in our extension + * class is connected to a slot. + * + * \snippet custom-extension/cpp-client/main.cpp connection + * + * The slot will update the font size and repaint the window. + * + * \section1 The QML Client Implementation + * + * The QML client is similar to the C++ client. It relies on the same implementation of the custom + * extension as the C++ client, and instantiates this in QML to enable it. + * + * \snippet custom-extension/qml-client/main.qml CustomExtension + * + * The UI consists of some clickable rectangles, and uses \l TapHandler to send the corresponding + * requests when a rectangle is clicked. + * + * \snippet custom-extension/qml-client/main.qml sendBounce + * + * For simplicity, the example has been limited to only demonstrate the \c bounce and \c spin + * requests as well as the \c set_font_size event. Adding support for the additional features is + * left as an exercise for the reader. + */ diff --git a/examples/wayland/custom-extension/protocol/custom.xml b/examples/wayland/custom-extension/protocol/custom.xml index 2e9a84260..e4aab6262 100644 --- a/examples/wayland/custom-extension/protocol/custom.xml +++ b/examples/wayland/custom-extension/protocol/custom.xml @@ -2,40 +2,7 @@ <copyright> Copyright (C) 2015 The Qt Company Ltd. - Contact: http://www.qt.io/licensing/ - - This file is part of the examples of the Qt Wayland module - - $QT_BEGIN_LICENSE:BSD$ - You may use this file under the terms of the BSD license as follows: - - "Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of The Qt Company Ltd nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." - - $QT_END_LICENSE$ + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause </copyright> <interface name="qt_example_extension" version="1"> diff --git a/examples/wayland/custom-extension/qml-client/CMakeLists.txt b/examples/wayland/custom-extension/qml-client/CMakeLists.txt new file mode 100644 index 000000000..13798b96b --- /dev/null +++ b/examples/wayland/custom-extension/qml-client/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(custom-extension-qml-client) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/custom-extension/qml-client") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick WaylandClient) + +qt6_policy(SET QTP0001 NEW) +qt_add_executable(custom-extension-qml-client + ../client-common/customextension.cpp ../client-common/customextension.h + main.cpp +) + +qt6_generate_wayland_protocol_client_sources(custom-extension-qml-client + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../protocol/custom.xml +) + +set_target_properties(custom-extension-qml-client PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(custom-extension-qml-client PUBLIC + Qt::Core + Qt::Gui + Qt::GuiPrivate + Qt::Qml + Qt::Quick + Qt::WaylandClient +) + +# Resources: +set(qml_resource_files + "main.qml" +) + +qt6_add_resources(custom-extension-qml-client "qml" + PREFIX + "/" + FILES + ${qml_resource_files} +) + +target_include_directories(custom-extension-qml-client PUBLIC ../client-common/) + +qt6_add_qml_module(custom-extension-qml-client + URI io.qt.examples.customextension + VERSION 1.0 +) + +install(TARGETS custom-extension-qml-client + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/custom-extension/qml-client/main.cpp b/examples/wayland/custom-extension/qml-client/main.cpp index 16b034993..126c6b915 100644 --- a/examples/wayland/custom-extension/qml-client/main.cpp +++ b/examples/wayland/custom-extension/qml-client/main.cpp @@ -1,66 +1,16 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Erik Larsson. -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Erik Larsson. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include <QGuiApplication> +#include <QtGui/QGuiApplication> #include <QtQml/QQmlApplicationEngine> - -#include <QtQml/qqml.h> #include <QtQml/QQmlEngine> + #include "../client-common/customextension.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); - qmlRegisterType<CustomExtension>("com.theqtcompany.customextension", 1, 0, "CustomExtension"); - QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); diff --git a/examples/wayland/custom-extension/qml-client/main.qml b/examples/wayland/custom-extension/qml-client/main.qml index 11dc49c54..da81055bc 100644 --- a/examples/wayland/custom-extension/qml-client/main.qml +++ b/examples/wayland/custom-extension/qml-client/main.qml @@ -1,107 +1,91 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Erik Larsson. -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Erik Larsson. +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.0 -import QtQuick.Window 2.0 -import com.theqtcompany.customextension 1.0 +import QtQuick +import QtQuick.Window +import io.qt.examples.customextension Window { id: topLevelWindow + title: "QML Client" visible: true - Rectangle { - anchors.fill: parent - color: "#f1eece" - } - property alias textItem: bounceText - Text { - id: bounceText - text: "press here to bounce" - } + width: 800 + height: 600 - MouseArea { - anchors.fill: parent - onClicked: { - if (customExtension.active) - customExtension.sendBounce(topLevelWindow, 1000) - } - } + property real fontSize: height / 50 - MouseArea { + Column { anchors.centerIn: parent - width: 100; height: 100 - onClicked: { - if (customExtension.active) - customExtension.sendSpin(topLevelWindow, 500) + width: topLevelWindow.width / 4 + height: 2 * (width + topLevelWindow.height / 12) + spacing: topLevelWindow.height / 12 + + Rectangle { + id: rect1 + color: "#C0FFEE" + width: parent.width + height: width + clip: true + + Text { + anchors.centerIn: parent + text: "Press here to send spin request." + font.pixelSize: fontSize + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + + TapHandler { + onTapped: { + if (customExtension.active) + customExtension.sendSpin(topLevelWindow, 500) + } + } } Rectangle { - anchors.fill: parent - color: "#fab1ed" + id: rect2 + color: "#decaff" + width: parent.width + height: parent.height / 2 + clip: true + Text { - text: "spin" + anchors.centerIn: parent + text: "Press here to send bounce request." + font.pixelSize: fontSize + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + +//! [sendBounce] + TapHandler { + onTapped: { + if (customExtension.active) + customExtension.sendBounce(topLevelWindow, 1000) + } } +//! [sendBounce] } } +//! [CustomExtension] CustomExtension { id: customExtension onActiveChanged: { - console.log("Custom extension is active:", active) registerWindow(topLevelWindow) } - onFontSize: { - // signal arguments: window and pixelSize - // we are free to interpret the protocol as we want, so - // let's change the font size of just one of the text items - window.textItem.font.pixelSize = pixelSize + onFontSize: (window, pixelSize) => { + topLevelWindow.fontSize = pixelSize } } +//! [CustomExtension] } diff --git a/examples/wayland/custom-extension/qml-client/qml-client.pro b/examples/wayland/custom-extension/qml-client/qml-client.pro index a8fa420af..8bddb730b 100644 --- a/examples/wayland/custom-extension/qml-client/qml-client.pro +++ b/examples/wayland/custom-extension/qml-client/qml-client.pro @@ -2,6 +2,12 @@ TEMPLATE = app QT += qml quick waylandclient gui-private CONFIG += wayland-scanner +CONFIG += qmltypes +QML_IMPORT_NAME = io.qt.examples.customextension +QML_IMPORT_MAJOR_VERSION = 1 + +INCLUDEPATH += $$PWD/../client-common + WAYLANDCLIENTSOURCES += ../protocol/custom.xml SOURCES += main.cpp \ @@ -10,6 +16,8 @@ SOURCES += main.cpp \ HEADERS += \ ../client-common/customextension.h +TARGET = custom-extension-qml-client + RESOURCES += qml.qrc target.path = $$[QT_INSTALL_EXAMPLES]/wayland/custom-extension/qml-client |