diff options
Diffstat (limited to 'examples')
172 files changed, 3677 insertions, 5789 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 000000000..f2354f266 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +qt_examples_build_begin(EXTERNAL_BUILD) + +add_subdirectory(wayland) + +qt_examples_build_end() diff --git a/examples/wayland/CMakeLists.txt b/examples/wayland/CMakeLists.txt new file mode 100644 index 000000000..24abe5236 --- /dev/null +++ b/examples/wayland/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +if(QT_FEATURE_wayland_server) +if(QT_FEATURE_opengl) + qt_internal_add_example(minimal-cpp) +endif() +if(TARGET Qt::Quick) + qt_internal_add_example(minimal-qml) + qt_internal_add_example(spanning-screens) + qt_internal_add_example(fancy-compositor) + qt_internal_add_example(multi-output) + qt_internal_add_example(multi-screen) + qt_internal_add_example(overview-compositor) + qt_internal_add_example(ivi-compositor) + qt_internal_add_example(server-side-decoration) + qt_internal_add_example(qtshell) +endif() +if(TARGET Qt::Quick AND TARGET Qt::WaylandClient) + qt_internal_add_example(custom-extension) + qt_internal_add_example(custom-shell) +endif() +endif() 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 diff --git a/examples/wayland/custom-shell/CMakeLists.txt b/examples/wayland/custom-shell/CMakeLists.txt new file mode 100644 index 000000000..1b0fe1653 --- /dev/null +++ b/examples/wayland/custom-shell/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.16) +project(custom-shell) + +add_subdirectory(client-plugin) +add_subdirectory(compositor) diff --git a/examples/wayland/custom-shell/client-plugin/CMakeLists.txt b/examples/wayland/custom-shell/client-plugin/CMakeLists.txt new file mode 100644 index 000000000..39569b80f --- /dev/null +++ b/examples/wayland/custom-shell/client-plugin/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.14) +project(exampleshellplugin LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/custom-shell/plugins") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui WaylandClient) + +qt_add_plugin(exampleshellplugin) +target_sources(exampleshellplugin PRIVATE + main.cpp + exampleshellintegration.cpp exampleshellintegration.h + examplesurface.cpp examplesurface.h +) + +qt6_generate_wayland_protocol_client_sources(exampleshellplugin + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../protocol/example-shell.xml +) + +set_target_properties(exampleshellplugin PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/../plugins/wayland-shell-integration" +) + +target_link_libraries(exampleshellplugin PUBLIC + Qt::Core + Qt::Gui + Qt::GuiPrivate + Qt::WaylandClient + Qt::WaylandClientPrivate + Wayland::Client +) + +install(TARGETS exampleshellplugin + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/custom-shell/client-plugin/client-plugin.pro b/examples/wayland/custom-shell/client-plugin/client-plugin.pro new file mode 100644 index 000000000..96a01c231 --- /dev/null +++ b/examples/wayland/custom-shell/client-plugin/client-plugin.pro @@ -0,0 +1,33 @@ +QT += gui-private waylandclient-private +CONFIG += plugin wayland-scanner +TEMPLATE = lib + +QMAKE_USE += wayland-client + +qtConfig(xkbcommon): \ + QMAKE_USE += xkbcommon + +WAYLANDCLIENTSOURCES += \ + ../protocol/example-shell.xml + +HEADERS += \ + exampleshellintegration.h \ + examplesurface.h + +SOURCES += \ + main.cpp \ + exampleshellintegration.cpp \ + examplesurface.cpp + +OTHER_FILES += \ + example-shell.json + +DESTDIR = ../plugins/wayland-shell-integration +TARGET = $$qtLibraryTarget(exampleshellplugin) + +### Everything below this line is just to make the example work inside the Qt source tree. +### Do not include the following lines in your own code. + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/customshell/plugins/wayland-shell-integration +INSTALLS += target +CONFIG += install_ok diff --git a/examples/wayland/custom-shell/client-plugin/example-shell.json b/examples/wayland/custom-shell/client-plugin/example-shell.json new file mode 100644 index 000000000..c36490af5 --- /dev/null +++ b/examples/wayland/custom-shell/client-plugin/example-shell.json @@ -0,0 +1,3 @@ +{ + "Keys":[ "example-shell" ] +} diff --git a/examples/wayland/custom-shell/client-plugin/exampleshellintegration.cpp b/examples/wayland/custom-shell/client-plugin/exampleshellintegration.cpp new file mode 100644 index 000000000..b979640a7 --- /dev/null +++ b/examples/wayland/custom-shell/client-plugin/exampleshellintegration.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "exampleshellintegration.h" +#include "examplesurface.h" + +//! [constructor] +ExampleShellIntegration::ExampleShellIntegration() + : QWaylandShellIntegrationTemplate(/* Supported protocol version */ 1) +{ +} +//! [constructor] + +//! [createShellSurface] +QWaylandShellSurface *ExampleShellIntegration::createShellSurface(QWaylandWindow *window) +{ + if (!isActive()) + return nullptr; + auto *surface = surface_create(wlSurfaceForWindow(window)); + return new ExampleShellSurface(surface, window); +} +//! [createShellSurface] diff --git a/examples/wayland/custom-shell/client-plugin/exampleshellintegration.h b/examples/wayland/custom-shell/client-plugin/exampleshellintegration.h new file mode 100644 index 000000000..f7f9de909 --- /dev/null +++ b/examples/wayland/custom-shell/client-plugin/exampleshellintegration.h @@ -0,0 +1,23 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef EXAMPLESHELLINTEGRATION_H +#define EXAMPLESHELLINTEGRATION_H +#include <QtWaylandClient/private/qwaylandclientshellapi_p.h> +#include "qwayland-example-shell.h" + +using namespace QtWaylandClient; + +//! [shell-integration] +class Q_WAYLANDCLIENT_EXPORT ExampleShellIntegration + : public QWaylandShellIntegrationTemplate<ExampleShellIntegration> + , public QtWayland::qt_example_shell +{ +public: + ExampleShellIntegration(); + + QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override; +}; +//! [shell-integration] + +#endif // EXAMPLESHELLINTEGRATION_H diff --git a/examples/wayland/custom-shell/client-plugin/examplesurface.cpp b/examples/wayland/custom-shell/client-plugin/examplesurface.cpp new file mode 100644 index 000000000..eb17331c3 --- /dev/null +++ b/examples/wayland/custom-shell/client-plugin/examplesurface.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "examplesurface.h" +#include <qpa/qwindowsysteminterface.h> +#include <qpa/qplatformwindow.h> + +ExampleShellSurface::ExampleShellSurface(struct ::qt_example_shell_surface *shell_surface, QWaylandWindow *window) + : QWaylandShellSurface(window) + , QtWayland::qt_example_shell_surface(shell_surface) +{ +} + +ExampleShellSurface::~ExampleShellSurface() +{ +} + +bool ExampleShellSurface::wantsDecorations() const +{ + return true; +} + +//! [setTitle] +void ExampleShellSurface::setTitle(const QString &windowTitle) +{ + set_window_title(windowTitle); +} +//! [setTitle] + +void ExampleShellSurface::requestWindowStates(Qt::WindowStates states) +{ + set_minimized(states & Qt::WindowMinimized); +} + +//! [applyConfigure] +void ExampleShellSurface::applyConfigure() +{ + if (m_stateChanged) + QWindowSystemInterface::handleWindowStateChanged(platformWindow()->window(), m_pendingStates); + m_stateChanged = false; +} +//! [applyConfigure] + +void ExampleShellSurface::example_shell_surface_minimize(uint32_t minimized) +{ + m_pendingStates = minimized ? Qt::WindowMinimized : Qt::WindowNoState; + m_stateChanged = true; + applyConfigureWhenPossible(); +} diff --git a/examples/wayland/custom-shell/client-plugin/examplesurface.h b/examples/wayland/custom-shell/client-plugin/examplesurface.h new file mode 100644 index 000000000..e5d6fb92a --- /dev/null +++ b/examples/wayland/custom-shell/client-plugin/examplesurface.h @@ -0,0 +1,38 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef EXAMPLESHELLSURFACE_H +#define EXAMPLESHELLSURFACE_H + +#include <QtWaylandClient/private/qwaylandclientshellapi_p.h> +#include "qwayland-example-shell.h" + +using namespace QtWaylandClient; + +//! [ExampleShellSurface] +class ExampleShellSurface : public QWaylandShellSurface + , public QtWayland::qt_example_shell_surface +//! [ExampleShellSurface] +{ +public: + ExampleShellSurface(struct ::qt_example_shell_surface *shell_surface, QWaylandWindow *window); + ~ExampleShellSurface() override; + +//! [virtuals] + bool wantsDecorations() const override; + void setTitle(const QString &) override; + void requestWindowStates(Qt::WindowStates states) override; + void applyConfigure() override; +//! [virtuals] + +protected: +//! [events] + void example_shell_surface_minimize(uint32_t minimized) override; +//! [events] + +private: + Qt::WindowStates m_pendingStates; + bool m_stateChanged = false; +}; + +#endif // EXAMPLESHELLSURFACE_H diff --git a/examples/wayland/custom-shell/client-plugin/main.cpp b/examples/wayland/custom-shell/client-plugin/main.cpp new file mode 100644 index 000000000..4ae488880 --- /dev/null +++ b/examples/wayland/custom-shell/client-plugin/main.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "exampleshellintegration.h" + +//! [include] +#include <QtWaylandClient/private/qwaylandclientshellapi_p.h> +//! [include] + +#include "qwayland-example-shell.h" + +using namespace QtWaylandClient; + +//! [plugin] +class QWaylandExampleShellIntegrationPlugin : public QWaylandShellIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QWaylandShellIntegrationFactoryInterface_iid FILE "example-shell.json") + +public: + QWaylandShellIntegration *create(const QString &key, const QStringList ¶mList) override; +}; + +QWaylandShellIntegration *QWaylandExampleShellIntegrationPlugin::create(const QString &key, const QStringList ¶mList) +{ + Q_UNUSED(key); + Q_UNUSED(paramList); + return new ExampleShellIntegration(); +} +//! [plugin] + +#include "main.moc" 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/server-buffer/compositor/compositor.qrc b/examples/wayland/custom-shell/compositor/compositor.qrc index b50594b55..59c00f5f9 100644 --- a/examples/wayland/server-buffer/compositor/compositor.qrc +++ b/examples/wayland/custom-shell/compositor/compositor.qrc @@ -1,7 +1,6 @@ <RCC> <qresource prefix="/"> <file>images/background.png</file> - <file>images/Siberischer_tiger_de_edit02.jpg</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] +} diff --git a/examples/wayland/custom-shell/custom-shell.pro b/examples/wayland/custom-shell/custom-shell.pro new file mode 100644 index 000000000..246115d32 --- /dev/null +++ b/examples/wayland/custom-shell/custom-shell.pro @@ -0,0 +1,5 @@ +TEMPLATE=subdirs + +SUBDIRS += compositor client-plugin + +OTHER_FILES += protocol/example-shell.xml diff --git a/examples/wayland/custom-shell/doc/images/custom-shell.jpg b/examples/wayland/custom-shell/doc/images/custom-shell.jpg Binary files differnew file mode 100644 index 000000000..81f1ed205 --- /dev/null +++ b/examples/wayland/custom-shell/doc/images/custom-shell.jpg diff --git a/examples/wayland/custom-shell/doc/src/custom-shell.qdoc b/examples/wayland/custom-shell/doc/src/custom-shell.qdoc new file mode 100644 index 000000000..ba0fd8bf7 --- /dev/null +++ b/examples/wayland/custom-shell/doc/src/custom-shell.qdoc @@ -0,0 +1,227 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + * \title Custom Shell + * \example custom-shell + * \examplecategory {Embedded} + * \brief Custom Shell shows how to implement a custom shell extension. + * \ingroup qtwaylandcompositor-examples + * + * \l{Shell Extensions - Qt Wayland Compositor}{Shell extensions} to Wayland are protocols that + * manage window state, position and size. Most compositors will support one or more of built-in + * extensions, but in some circumstances it can be useful to be able to write a custom one which + * contains the exact features your applications need. + * + * \image custom-shell.jpg + * + * This requires that you implement the shell extension on both the server-side and client-side + * of the Wayland connection, so it is mainly useful when you are building a platform and are in + * control of both the compositor and its client applications. + * + * The Custom Shell example shows the implementation of a simple shell extension. It is divided into + * three parts: + * \list + * \li A protocol description for a custom shell interface. + * \li A plugin for connecting to the interface in a client application. + * \li An example compositor with a server-side implementation of the interface. + * \endlist + * + * The protocol description follows the standard XML format read by \c{wayland-scanner}. It will + * not be covered in detail here, but it covers the following features: + * + * \list + * \li An interface for creating a shell surfaces for a \c{wl_surface}. This allows the protocol + * to add functionality on top of the existing \c{wl_surface} APIs. + * \li A request to set a window title on the shell surface. + * \li A request to minimize/de-minimize the shell surface. + * \li An event informing the client of the shell surface's current minimized state. + * \endlist + * + * 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 Client Plugin + * + * In order for the shell integration to be discovered by a Qt client, we must reimplement + * the QWaylandShellIntegrationPlugin. + * + * \snippet custom-shell/client-plugin/main.cpp plugin + * + * This attaches the "example-shell" key to the shell integration and provides a way for the + * \c ExampleShellIntegration class to be instantiated when a client connects to the interface. + * + * The APIs for creating shell extensions are available in the header \c qwaylandclientshellapi_p.h. + * + * \snippet custom-shell/client-plugin/main.cpp include + * + * This header requires including private API because unlike public Qt APIs, it does not come with + * binary compatibility guarantees. The APIs are still considered stable and will remain source + * compatible, and are similar in this respect to other plugin APIs in Qt. + * + * The \c ExampleShellIntegration is the client-side entry point for creating shell surfaces as + * described above. It extends the QWaylandShellIntegrationTemplate class, using the + * \l{https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern}{Curiously Recurring Template Pattern}. + * + * \snippet custom-shell/client-plugin/exampleshellintegration.h shell-integration + * + * It also inherits from the \c QtWayland::qt_example_shell class, which is generated by + * \c qtwaylandscanner based on the XML description of the protocol. + * + * The constructor specifies the version of the protocol that we support: + * + * \snippet custom-shell/client-plugin/exampleshellintegration.cpp constructor + * + * The example_shell protocol is currently at version one, so we pass a \c{1} to the parent + * class. This is used in protocol negotiation, and makes sure that older clients will continue + * working if the compositor uses a newer version of the protocol. + * + * When the \c ExampleShellIntegration is initialized, the application is connected to the server, + * and has received the broadcast of global interfaces the compositor supports. + * If successful, it can issue requests for the interface. In this + * case, there is only one request to support: Creating a shell surface. It uses the built-in + * function \c wlSurfaceForWindow() to convert the QWaylandWindow to a \c{wl_surface}, then it issues the + * request. It then extends the returned surface with a \c ExampleShellSurface object which will + * handle the requests and events on the \c qt_example_shell_surface interface. + * + * \snippet custom-shell/client-plugin/exampleshellintegration.cpp createShellSurface + * + * The \c ExampleShellSurface extends two classes. + * + * \snippet custom-shell/client-plugin/examplesurface.h ExampleShellSurface + * + * The first is the \c QtWayland::qt_example_shell_surface class which is generated based on the XML + * description of the protocol. This provides virtual functions for events and ordinary member + * functions for the requests in the protocol. + * + * The \c QtWayland::qt_example_shell_surface class only has a single event. + * + * \snippet custom-shell/client-plugin/examplesurface.h events + * + * The \c ExampleShellSurface reimplements this to update its internal window state. When the + * window state is change, it stores the pending state until later and calls + * \c{applyConfigureWhenPossible()} in QWaylandShellSurface. State, size and position changes should + * be organized like this. That way, we ensure that changes do not interfere with rendering to the + * surface, and multiple related changes can easily be applied as one. + * + * When it is safe to reconfigure the surface, the virtual \c applyConfigure() function is called. + * + * \snippet custom-shell/client-plugin/examplesurface.cpp applyConfigure + * + * This is where we actually commit the new (minimized or de-minimized) state to the window. + * + * The second super class is QWaylandShellSurface. This is the interface used by Wayland's QPA + * plugin and QWaylandWindow to communicate with the shell. The \c ExampleShellSurface reimplements + * a few virtual functions from this interface as well. + * + * \snippet custom-shell/client-plugin/examplesurface.h virtuals + * + * For example, when the Qt applications sets the title of a window, this translates into a call to + * the virtual \c setTitle() function. + * + * \snippet custom-shell/client-plugin/examplesurface.cpp setTitle + * + * In the \c ExampleShellSurface this in turn translates to a request on our custom shell surface + * interface. + * + * \section1 The Compositor + * + * The final part of the example is the compositor itself. This has the same general structure as + * the other compositor examples. See the + * \l{Minimal QML}{Minimal QML example} for more details on + * the building blocks of a \l{Qt Wayland Compositor}. + * + * One notable difference in the Custom Shell compositor is the instantiation of the shell + * extension. Where the \l{Minimal QML}{the Minimal QML example} + * instantiates the shell extensions \l{IviApplication}, \l{XdgShell} and \l{WlShell}, the + * Custom Shell example only creates an instance of the \c ExampleShell extension. + * + * \snippet custom-shell/compositor/qml/main.qml ExampleShell + * + * We create the instance of the shell extension as a direct child of the WaylandCompositor in + * order to have it registered as a global interface. This will be broadcasted to clients as they + * connect, and they will be able to attach to the interface as outlined in the previous section. + * + * The \c ExampleShell is a subclass of the generated \c QtWaylandServer::qt_example_shell + * interface, which contains the API defined in the protocol XML. It is also a subclass of + * \l{QWaylandCompositorExtensionTemplate}, which ensures the objects are recognized by + * QWaylandCompositor as extensions. + * + * \snippet custom-shell/compositor/exampleshell.h ExampleShell + * + * This dual inheritance is a typical pattern in Qt Wayland Compositor when building extensions. + * The QWaylandCompositorExtensionTemplate class creates the connection between + * QWaylandCompositorExtension and the \c qt_example_shell class generated by \c qtwaylandscanner. + * + * Equivalently, the \c ExampleShellSurface class extends the generated + * \c QtWaylandServer::qt_example_shell_surface class as well as \l{QWaylandShellSurfaceTemplate}, + * which makes it a subclass of the ShellSurface class and establishes the connection between + * Qt Wayland Compositor and the generated protocol code. + * + * To make the type available to Qt Quick, we use the \l{Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS} + * preprocessor macro for the convenience. Among other things, this handles automatically + * initializing the extension when it has been added to the Qt Quick graph. + * + * \snippet custom-shell/compositor/exampleshell.cpp initialize + * + * The default implementation of the \c initialize() function register the extension with the + * compositor. In addition to this, we initialize the protocol extension itself. We do this by + * calling the generated \c init() function in the \c QtWaylandServer::qt_example_shell_surface + * class. + * + * We also reimplement the virtual function generated for the \c surface_create request. + * + * \snippet custom-shell/compositor/exampleshell.cpp surface_create + * + * This virtual function is called whenever a client issues the request on the connection. + * + * Our shell extension only supports a single QWaylandSurfaceRole, but it is still important that + * we assign it to the QWaylandSurface when we create a shell surface for it. The primary reason + * for this is that assigning conflicting roles to the same surface is considered a protocol error, + * and it is the compositor's responsibility to issue this error if it happens. Setting a role on + * the surface when we adopt it, ensures that the protocol error will be issued if the surface is + * reused with a different role later. + * + * We use built-in functions to convert between Wayland and Qt types, and create an + * \c ExampleShellSurface object. When everything is prepared, we emit the \c shellSurfaceCreated() + * signal, which in turn is intercepted in the QML code and added to the list of shell surfaces. + * + * \snippet custom-shell/compositor/qml/main.qml ExampleShell + * + * In \c{ExampleShellSurface}, we equivalently enable the shell surface part of the protocol + * extension. + * + * \section1 Running the example + * + * In order to have a client successfully connect to the new shell extension, there is a couple + * of configuration details to be handled. + * + * First of all, the client has to be able to find the shell extension's plugin. One simple way + * of doing this is to set the \c QT_PLUGIN_PATH to point to the plugin install directory. Since + * Qt will look up plugins by category, the plugin path should point to the parent directory that + * contains the directory for category \c{wayland-shell-integration}. So if the installed file is + * \c{/path/to/build/plugins/wayland-shell-integration/libexampleshellplugin.so}, then you should + * set \c QT_PLUGIN_PATH as follows: + * + * \badcode + * export QT_PLUGIN_PATH=/path/to/build/plugins + * \endcode + * + * For other ways to configure the plugin directory, see the + * \l{Deploying Plugins}{plugin documentation}. + * + * The final step is to make sure the client actually attaches to the correct shell extension. + * Qt clients will automatically try to attach to the built-in shell extensions, but this can be + * overridden by setting the \c QT_WAYLAND_SHELL_INTEGRATION environment variable to the name of + * the extension to load. + * + * \badcode + * export QT_WAYLAND_SHELL_INTEGRATION=example-shell + * \endcode + * + * And that is all there is to it. The Custom Shell example is a limited shell extension with only + * a very few features, but it can be used as a starting point for building specialized extensions. + */ diff --git a/examples/wayland/custom-shell/protocol/example-shell.xml b/examples/wayland/custom-shell/protocol/example-shell.xml new file mode 100644 index 000000000..ec01b6d61 --- /dev/null +++ b/examples/wayland/custom-shell/protocol/example-shell.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="example_shell"> + <copyright> + Copyright (C) 2021 The Qt Company Ltd. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + </copyright> + + <interface name="qt_example_shell_surface" version="1"> + <request name="destroy" type="destructor"> + </request> + + <request name="set_window_title"> + <arg name="window_title" type="string" /> + </request> + + <request name="set_minimized"> + <arg name="minimized" type="uint" /> + </request> + <event name="minimize"> + <arg name="minimized" type="uint"/> + </event> + </interface> + + <interface name="qt_example_shell" version="1"> + <request name="surface_create"> + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="id" type="new_id" interface="qt_example_shell_surface"/> + </request> + <enum name="error"> + <entry name="role" value="0" summary="wl_surface already has a different role"/> + </enum> + </interface> + +</protocol> diff --git a/examples/wayland/fancy-compositor/CMakeLists.txt b/examples/wayland/fancy-compositor/CMakeLists.txt new file mode 100644 index 000000000..437542331 --- /dev/null +++ b/examples/wayland/fancy-compositor/CMakeLists.txt @@ -0,0 +1,52 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(fancy-compositor LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/fancy-compositor") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(fancy-compositor + main.cpp +) + +set_target_properties(fancy-compositor PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(fancy-compositor PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(fancy-compositor_resource_files + "images/background.jpg" + "qml/Chrome.qml" + "qml/CompositorScreen.qml" + "qml/Keyboard.qml" + "qml/main.qml" +) + +qt6_add_resources(fancy-compositor "fancy-compositor" + PREFIX + "/" + FILES + ${fancy-compositor_resource_files} +) + +install(TARGETS fancy-compositor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/fancy-compositor/doc/src/fancy-compositor.qdoc b/examples/wayland/fancy-compositor/doc/src/fancy-compositor.qdoc new file mode 100644 index 000000000..4d256d2af --- /dev/null +++ b/examples/wayland/fancy-compositor/doc/src/fancy-compositor.qdoc @@ -0,0 +1,104 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \title Fancy Compositor + \example fancy-compositor + \examplecategory {Embedded} + \brief Fancy Compositor is an example that demonstrates how to write a fancy Wayland compositor in pure QML. + \ingroup qtwaylandcompositor-examples + + \section1 Introduction + + Fancy Compositor is a small desktop-style Wayland compositor example that demonstrates the power and + ease of the \l{Qt Wayland Compositor} QML APIs. + + The Fancy Compositor example is similar to the \l{Minimal QML}{Minimal QML example}, in that it is a + full-blown Wayland compositor, implemented only using QML code. + + \section1 Initializing the Compositor + + Like the \l{Minimal QML}{Minimal QML example}, Fancy Compositor supports the main + \l{Shell Extensions - Qt Wayland Compositor}{shell extensions} that are supported by Qt. + + \snippet fancy-compositor/qml/main.qml shell extensions + + These are instantiated as children of the \l{WaylandCompositor} which automatically adds + them to the list of supported interfaces which is broadcasted to clients from the server. + + When a connected client creates a surface and binds it to one of the shell extensions, the + corresponding signal is emitted. This then calls a method inside our custom \l WaylandOutput + class, which appends the \l ShellSurface to a \l{ListModel}. + + \snippet fancy-compositor/qml/CompositorScreen.qml handleShellSurface + + This model is used as the source for a \l Repeater which creates + \l{ShellSurfaceItem}{ShellSurfaceItems} inside the compositor's \l WaylandOutput. This adds a + view of the surface in the Qt Quick scene. Since it is a \l{ShellSurfaceItem}, it also has + certain interaction options for the user of the compositor, depending on which shell extension + is in use. + + \snippet fancy-compositor/qml/CompositorScreen.qml repeater + + \section1 Keyboard + + In addition to the basic windowing system functions, the Fancy Compositor also supports an + optional on-screen keyboard running in-process. This uses the \l{Qt Virtual Keyboard} module, + and will be enabled if the module is available. + + \snippet fancy-compositor/qml/Keyboard.qml keyboard + + The code is simple. We instantiate an \l InputPanel in the bottom of the output, and make sure + it is visible if and only if it is currently active. + + \snippet fancy-compositor/qml/CompositorScreen.qml keyboard + + The keyboard is then added to the \l WaylandOutput using a \l Loader element. The \l Loader is + used here to avoid having a hard dependency on the \l{Qt Virtual Keyboard} module. If loading + fails, then the compositor will continue operating normally, but without support for an + on-screen keyboard. + + Finally, we need a way for the compositor to communicate the text input to its clients. This + is done via a \c{text-input} extension. The Fancy Compositor example supports both the + \c{text_input_unstable_v2} protocol as well as Qt's \c{qt_text_input_method_unstable_v1} + protocol. + + \snippet fancy-compositor/qml/main.qml text input + + The \c{qt_text_input_method_unstable_v1} extension is added to the compositor by instantiating + the \l QtTextInputMethodManager as a child of the \l{WaylandCompositor}, and + \l{TextInputManager} adds \c{text_input_unstable_v2}. + + Newer Qt applications will pick \c{qt_text_input_method_unstable_v1} when it is available, + while other clients can use \c{text_input_unstable_v2}. + + \section1 Transitions + + In addition to the basic functionality, the Fancy Compositor example also demonstrates animated + transitions between states. + + The first of these is the \e{activation} transition. This is only supported on the \l{XdgShell}, + since this is the only shell extension which has an \l{XdgToplevel::}{activated} state. + + \snippet fancy-compositor/qml/Chrome.qml activation + + When a client window becomes activated under the \l XdgShell protocol, we trigger an animation + which makes the window "pop out" for 200 ms. + + The Fancy Compositor also supports a \e{destruction} animation. This triggers whenever the + window closes and surface is destroyed, whether this was because the client gracefully closed + its window, or even if it crashes. + + \snippet fancy-compositor/qml/Chrome.qml destruction + + To ensure that the content exists for the duration of the animation, we start by locking the + buffer. This means the final frame rendered by the client will remain in memory until we are + done with it. + + Again, we trigger an animation on the scale of the item. The animation in question imitates + turning off the power on a CRT screen, giving a visual clue to the user that the window is + closing, and didn't just vanish into thin air. + + Any sort of animated effect may be used for state changes such as these, with the full range + of Qt Quick at your disposal. +*/ diff --git a/examples/wayland/fancy-compositor/fancy-compositor.pro b/examples/wayland/fancy-compositor/fancy-compositor.pro new file mode 100644 index 000000000..bd6a2923f --- /dev/null +++ b/examples/wayland/fancy-compositor/fancy-compositor.pro @@ -0,0 +1,18 @@ +QT += gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + qml/main.qml \ + qml/CompositorScreen.qml \ + qml/Chrome.qml \ + qml/Keyboard.qml \ + images/background.jpg \ + +RESOURCES += fancy-compositor.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/fancy-compositor +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS fancy-compositor.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/fancy-compositor +INSTALLS += target sources diff --git a/examples/wayland/pure-qml/pure-qml.qrc b/examples/wayland/fancy-compositor/fancy-compositor.qrc index 8c95434d3..145b3f250 100644 --- a/examples/wayland/pure-qml/pure-qml.qrc +++ b/examples/wayland/fancy-compositor/fancy-compositor.qrc @@ -2,7 +2,7 @@ <qresource prefix="/"> <file>images/background.jpg</file> <file>qml/main.qml</file> - <file>qml/Screen.qml</file> + <file>qml/CompositorScreen.qml</file> <file>qml/Chrome.qml</file> <file>qml/Keyboard.qml</file> </qresource> diff --git a/examples/wayland/pure-qml/images/background.jpg b/examples/wayland/fancy-compositor/images/background.jpg Binary files differindex 445567fbd..445567fbd 100644 --- a/examples/wayland/pure-qml/images/background.jpg +++ b/examples/wayland/fancy-compositor/images/background.jpg diff --git a/examples/wayland/fancy-compositor/main.cpp b/examples/wayland/fancy-compositor/main.cpp new file mode 100644 index 000000000..dca8dfe01 --- /dev/null +++ b/examples/wayland/fancy-compositor/main.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2017 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> + +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); + + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); + + return app.exec(); +} diff --git a/examples/wayland/fancy-compositor/qml/Chrome.qml b/examples/wayland/fancy-compositor/qml/Chrome.qml new file mode 100644 index 000000000..b8d71c756 --- /dev/null +++ b/examples/wayland/fancy-compositor/qml/Chrome.qml @@ -0,0 +1,68 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWayland.Compositor + +ShellSurfaceItem { + id: chrome + + property bool isChild: parent.shellSurface !== undefined + + signal destroyAnimationFinished + + // ![destruction] + onSurfaceDestroyed: { + bufferLocked = true; + destroyAnimation.start(); + } + + SequentialAnimation { + id: destroyAnimation + + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } + NumberAnimation { target: chrome; property: "opacity"; to: chrome.isChild ? 0 : 1; duration: 150 } + } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } + ScriptAction { script: destroyAnimationFinished() } + } + // ![destruction] + + transform: [ + Scale { + id: scaleTransform + origin.x: chrome.width / 2 + origin.y: chrome.height / 2 + } + ] + + // ![activation] + Connections { + target: shellSurface.toplevel !== undefined ? shellSurface.toplevel : null + + // some signals are not available on wl_shell, so let's ignore them + ignoreUnknownSignals: true + + function onActivatedChanged() { // xdg_shell only + if (shellSurface.toplevel.activated) { + receivedFocusAnimation.start(); + } + } + } + + SequentialAnimation { + id: receivedFocusAnimation + + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } + } + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } + } + } + // ![activation] +} diff --git a/examples/wayland/fancy-compositor/qml/CompositorScreen.qml b/examples/wayland/fancy-compositor/qml/CompositorScreen.qml new file mode 100644 index 000000000..4b2ba36d6 --- /dev/null +++ b/examples/wayland/fancy-compositor/qml/CompositorScreen.qml @@ -0,0 +1,83 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window +import QtWayland.Compositor + +WaylandOutput { + id: output + + property ListModel shellSurfaces: ListModel {} + property bool isNestedCompositor: Qt.platform.pluginName.startsWith("wayland") || Qt.platform.pluginName === "xcb" + + // ![handleShellSurface] + function handleShellSurface(shellSurface) { + shellSurfaces.append({shellSurface: shellSurface}); + } + // ![handleShellSurface] + + // During development, it can be useful to start the compositor inside X11 or + // another Wayland compositor. In such cases, set sizeFollowsWindow to true to + // enable resizing of the compositor window to be forwarded to the Wayland clients + // as the output (screen) changing resolution. Consider setting it to false if you + // are running the compositor using eglfs, linuxfb or similar QPA backends. + sizeFollowsWindow: output.isNestedCompositor + + window: Window { + width: 1024 + height: 760 + visible: true + + WaylandMouseTracker { + id: mouseTracker + + anchors.fill: parent + + // Set this to false to disable the outer mouse cursor when running nested + // compositors. Otherwise you would see two mouse cursors, one for each compositor. + windowSystemCursorEnabled: output.isNestedCompositor + + Image { + id: background + + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.jpg" + smooth: true + + // ![repeater] + Repeater { + model: output.shellSurfaces + // Chrome displays a shell surface on the screen (See Chrome.qml) + Chrome { + shellSurface: modelData + onDestroyAnimationFinished: output.shellSurfaces.remove(index) + } + } + // ![repeater] + } + + // Virtual Keyboard + // ![keyboard] + Loader { + anchors.fill: parent + source: "Keyboard.qml" + } + // ![keyboard] + + // Draws the mouse cursor for a given Wayland seat + WaylandCursorItem { + inputEventsEnabled: false + x: mouseTracker.mouseX + y: mouseTracker.mouseY + seat: output.compositor.defaultSeat + } + } + + Shortcut { + sequence: "Ctrl+Alt+Backspace" + onActivated: Qt.quit() + } + } +} diff --git a/examples/wayland/fancy-compositor/qml/Keyboard.qml b/examples/wayland/fancy-compositor/qml/Keyboard.qml new file mode 100644 index 000000000..2985ffcbd --- /dev/null +++ b/examples/wayland/fancy-compositor/qml/Keyboard.qml @@ -0,0 +1,15 @@ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +// ![keyboard] +import QtQuick +import QtQuick.VirtualKeyboard + +InputPanel { + visible: active + y: active ? parent.height - height : parent.height + anchors.left: parent.left + anchors.right: parent.right +} +// ![keyboard] + diff --git a/examples/wayland/fancy-compositor/qml/main.qml b/examples/wayland/fancy-compositor/qml/main.qml new file mode 100644 index 000000000..87feedf14 --- /dev/null +++ b/examples/wayland/fancy-compositor/qml/main.qml @@ -0,0 +1,38 @@ +// 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 QtWayland.Compositor.WlShell +import QtWayland.Compositor.IviApplication + +WaylandCompositor { + id: waylandCompositor + + CompositorScreen { id: screen; compositor: waylandCompositor } + + // ![shell extensions] + // Shell surface extension. Needed to provide a window concept for Wayland clients. + // I.e. requests and events for maximization, minimization, resizing, closing etc. + XdgShell { + onToplevelCreated: (toplevel, xdgSurface) => screen.handleShellSurface(xdgSurface) + } + + // Minimalistic shell extension. Mainly used for embedded applications. + IviApplication { + onIviSurfaceCreated: (iviSurface) => screen.handleShellSurface(iviSurface) + } + + // Deprecated shell extension, still used by some clients + WlShell { + onWlShellSurfaceCreated: (shellSurface) => screen.handleShellSurface(shellSurface) + } + // ![shell extensions] + + // Extension for Input Method (QT_IM_MODULE) support at compositor-side + // ![text input] + TextInputManager {} + QtTextInputMethodManager {} + // ![text input] +} diff --git a/examples/wayland/hwlayer-compositor/.gitignore b/examples/wayland/hwlayer-compositor/.gitignore deleted file mode 100644 index 83a421caf..000000000 --- a/examples/wayland/hwlayer-compositor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -hwlayer-compositor diff --git a/examples/wayland/hwlayer-compositor/hwlayer-compositor.pro b/examples/wayland/hwlayer-compositor/hwlayer-compositor.pro deleted file mode 100644 index a6eed9079..000000000 --- a/examples/wayland/hwlayer-compositor/hwlayer-compositor.pro +++ /dev/null @@ -1,14 +0,0 @@ -QT += gui qml - -SOURCES += \ - main.cpp - -OTHER_FILES = \ - main.qml - -RESOURCES += hwlayer-compositor.qrc - -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/hwlayer-compositor -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS hwlayer-compositor.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/hwlayer-compositor -INSTALLS += target sources diff --git a/examples/wayland/hwlayer-compositor/hwlayer-compositor.qrc b/examples/wayland/hwlayer-compositor/hwlayer-compositor.qrc deleted file mode 100644 index 5f6483ac3..000000000 --- a/examples/wayland/hwlayer-compositor/hwlayer-compositor.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>main.qml</file> - </qresource> -</RCC> diff --git a/examples/wayland/hwlayer-compositor/main.cpp b/examples/wayland/hwlayer-compositor/main.cpp deleted file mode 100644 index d26466382..000000000 --- a/examples/wayland/hwlayer-compositor/main.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -#include <QtCore/QUrl> -#include <QtCore/QDebug> - -#include <QtGui/QGuiApplication> -#include <QQmlContext> - -#include <QtQml/QQmlApplicationEngine> - -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - QQmlApplicationEngine appEngine(QUrl("qrc:///main.qml")); - return app.exec(); -} diff --git a/examples/wayland/hwlayer-compositor/main.qml b/examples/wayland/hwlayer-compositor/main.qml deleted file mode 100644 index b4f088c9d..000000000 --- a/examples/wayland/hwlayer-compositor/main.qml +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -import QtQuick 2.6 -import QtQuick.Window 2.2 -import QtQuick.Controls 2.2 -import QtWayland.Compositor 1.3 - -WaylandCompositor { - WaylandOutput { - sizeFollowsWindow: true - window: Window { - color: "tomato" - id: win - width: 1024 - height: 768 - visible: true - Rectangle { - color: "lightgreen" - anchors.centerIn: parent - width: parent.width / 3 - height: parent.width / 3 - NumberAnimation on rotation { - id: rotationAnimation - running: false - from: 0 - to: 90 - loops: Animation.Infinite - duration: 1000 - } - } - Repeater { - model: shellSurfaces - ShellSurfaceItem { - id: waylandItem - onSurfaceDestroyed: shellSurfaces.remove(index) - shellSurface: shSurface - WaylandHardwareLayer { - stackingLevel: level - Component.onCompleted: console.log("Added hardware layer with stacking level", stackingLevel); - } - Component.onCompleted: console.log("Added wayland quick item"); - Behavior on x { - PropertyAnimation { - easing.type: Easing.OutBounce - duration: 1000 - } - } - Timer { - interval: 2000; running: animatePosition; repeat: true - onTriggered: waylandItem.x = waylandItem.x === 0 ? win.width - waylandItem.width : 0 - } - Behavior on opacity { - PropertyAnimation { - duration: 1000 - } - } - Timer { - interval: 2000; running: animateOpacity; repeat: true - onTriggered: waylandItem.opacity = waylandItem.opacity === 1 ? 0 : 1 - } - } - } - Column { - anchors.bottom: parent.bottom - Repeater { - model: shellSurfaces - Row { - Label { - anchors.verticalCenter: parent.verticalCenter - leftPadding: 15 - rightPadding: 15 - text: "Surface " + index - } - CheckBox { - text: "Animate position" - checked: animatePosition - onClicked: animatePosition = !animatePosition - } - CheckBox { - text: "Animate Opacity" - checked: animateOpacity - onClicked: animateOpacity = !animateOpacity - } - Label { - text: "Stacking level" - } - SpinBox { - value: level - onValueModified: level = value; - } - Button { - text: "Kill" - onClicked: shSurface.surface.client.close() - } - } - } - CheckBox { - text: "Rotation" - checked: rotationAnimation.running - onClicked: rotationAnimation.running = !rotationAnimation.running - padding: 30 - } - } - } - } - ListModel { id: shellSurfaces } - function addShellSurface(shellSurface) { - shellSurfaces.append({shSurface: shellSurface, animatePosition: false, animateOpacity: false, level: 0}); - } - XdgShell { onToplevelCreated: addShellSurface(xdgSurface) } - XdgShellV6 { onToplevelCreated: addShellSurface(xdgSurface) } - WlShell { onWlShellSurfaceCreated: addShellSurface(shellSurface) } -} diff --git a/examples/wayland/ivi-compositor/CMakeLists.txt b/examples/wayland/ivi-compositor/CMakeLists.txt new file mode 100644 index 000000000..abab05231 --- /dev/null +++ b/examples/wayland/ivi-compositor/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(ivi-compositor LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/ivi-compositor") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(ivi-compositor + main.cpp +) + +set_target_properties(ivi-compositor PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(ivi-compositor PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(ivi-compositor_resource_files + "main.qml" +) + +qt6_add_resources(ivi-compositor "ivi-compositor" + PREFIX + "/" + FILES + ${ivi-compositor_resource_files} +) + +install(TARGETS ivi-compositor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/ivi-compositor/doc/images/ivi-compositor-1.png b/examples/wayland/ivi-compositor/doc/images/ivi-compositor-1.png Binary files differnew file mode 100644 index 000000000..8ab6b0c99 --- /dev/null +++ b/examples/wayland/ivi-compositor/doc/images/ivi-compositor-1.png diff --git a/examples/wayland/ivi-compositor/doc/images/ivi-compositor-2.png b/examples/wayland/ivi-compositor/doc/images/ivi-compositor-2.png Binary files differnew file mode 100644 index 000000000..02e1a2c9f --- /dev/null +++ b/examples/wayland/ivi-compositor/doc/images/ivi-compositor-2.png diff --git a/examples/wayland/ivi-compositor/doc/images/ivi-compositor-3.png b/examples/wayland/ivi-compositor/doc/images/ivi-compositor-3.png Binary files differnew file mode 100644 index 000000000..5bde2c74d --- /dev/null +++ b/examples/wayland/ivi-compositor/doc/images/ivi-compositor-3.png diff --git a/examples/wayland/ivi-compositor/doc/src/ivi-compositor.qdoc b/examples/wayland/ivi-compositor/doc/src/ivi-compositor.qdoc index f25eb8559..9412cca7b 100644 --- a/examples/wayland/ivi-compositor/doc/src/ivi-compositor.qdoc +++ b/examples/wayland/ivi-compositor/doc/src/ivi-compositor.qdoc @@ -1,44 +1,112 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - * \title Qt Wayland Compositor Examples - IVI Compositor + * \title IVI Compositor * \example ivi-compositor + * \examplecategory {Embedded} * \brief IVI Compositor is an example that demonstrates how to use the IviApplication extension. * \ingroup qtwaylandcompositor-examples * - * IVI Compositor is a Wayland compositor example demonstrating how to create a - * compositor supporting the \c ivi-application protocol. + * \section1 Introduction * - * IVI application windows with the id 1337 will be resized to cover one half - * of the screen, while all other windows will be resized to cover the other - * half. + * This example demonstrates using the \l IviApplication shell extension in a Wayland display + * server (also known as a Wayland compositor). * - * To start a Qt application using the \c ivi-application protocol with the - * right id, you need to set QT_WAYLAND_SHELL_INTEGRATION to ivi-shell and - * QT_IVI_SURFACE_ID to 1337. + * For an introduction to the basic principles of creating a \l{Qt Wayland Compositor} with Qt, + * see the \l{Minimal QML}{Minimal QML example}. + * + * \section1 The Protocol + * + * \l IviApplication is a \l{Shell Extensions - Qt Wayland Compositor}{shell extension} that was + * designed specifically for making In-vehice Infotainment systems. + * + * It is a minimalistic protocol, and only provides the following functionality: + * + * \list 1 + * \li The client can identify itself with an \e{IVI-id}. + * \li The server can request that the client resizes itself. + * \endlist + * + * \section2 The Identification Numbers + * + * In a typical \l IviApplication setup, you will have a predefined set of applications that can + * connect to the server. Since these applications are already known when the system is designed, + * they can be assigned hardcoded numbers that identify them. Given that the client and server + * agree on these numbers ahead of time, semantics can be built into the ID numbers. + * + * For instance, if a client identifies itself as the navigation application, the server can + * recognize this and allocate a large, centered part of the screen for its window. An application + * identifying itself as a clock, on the other hand, might be delegated to a smaller area in the + * margins of the screen. + * + * By default, Qt applications will advertise their system PIDs ("process IDs") as the \e{IVI-id}. + * The client can override this by setting \c{QT_IVI_SURFACE_ID} in its environment before + * connecting to the server. + * + * \section1 The Example + * + * A Qt Wayland Compositor may support multiple shell extensions at once, but the + * \e{IVICompositor example} only supports the \l IviApplication protocol. This means that the + * clients have to also support this shell extension in order to connect to the server. + * + * The compositor window in the example is split into two horizontally: A left area which is + * designated for a specialized application with the id "1337", and a right area which is for all + * other applications. + * + * \image ivi-compositor-1.png + * + * \section2 Creating the Layout + * + * The layout of the window is created inside a \l WaylandOutput. This typically corresponds to + * a physical screen available to the compositor. If a single \l WaylandOutput is created, as in + * the \e{IVICompositor example}, it will usually correspond to the primary screen. + * + * \snippet ivi-compositor/main.qml wayland output + * + * The code creates a \l WaylandOutput for the screen and creates a \l Window on this as the top + * level container of all compositor contents. Inside this window, it creates two rectangles that + * will serve as containers for applications as they connect. + * + * \section2 Connecting Clients + * + * If no additional configuration has been done, a Qt application will connect with an \e{IVI-id} + * equal to its process ID. For instance, if we run another Qt example application with + * \c{-platform wayland}, it will be delegated to the right-hand side of the layout, granted that + * its ID is different from "1337". + * + * \image ivi-compositor-2.png + * + * However, if we set the \c{QT_IVI_SURFACE_ID} environment variable to "1337" before starting + * the example, it will be delegated to the left-hand side of the layout. + * + * \image ivi-compositor-3.png + * + * When a client connects to the \c IVIApplication interface, it will emit the \c{iviSurfaceCreated} + * signal. This is where the positioning of the application's surface is handled. + * + * \snippet ivi-compositor/main.qml connecting + * + * The \c{iviSurfaceCreated} signal receives an \l IviSurface argument which can be used to access + * the client's ID. The compositor then creates a \l ShellSurfaceItem for the surface (as defined by + * the \c chromeComponent). \c ShellSurfaceItem is the class used for placing shell surfaces into + * the Qt Quick scene, and you will see this same pattern in all the Qt Wayland Compositor examples. + * + * What makes the \e{IVICompositor example} special is that it checks the \c iviId property of the + * incoming shell surface and decides on a parent for the \l ShellSurfaceItem depending on what + * this is. If the ID is equal to "1337" it will be parented to the \c leftArea, and if not it will + * be in the \c rightArea. + * + * The implementation of the \l ShellSurfaceItem handles resizing by informing the client whenever + * the size changes (which can happen if the compositor is running inside a desktop-style windowing + * system and its window is resized). + * + * \snippet ivi-compositor/main.qml resizing + * + * The \c{sendConfigure()} method is defined in \l IviSurface and will send an event to the client. + * The client will receive a resize event with the new size, so it can relayout its contents. + * + * If multiple applications connect to the same area in the layout, they will simply be stacked + * according to normal Qt Quick ordering rules. There are no built-in mechanisms for closing + * applications or managing state, but this can easily be added as ordinary Qt Quick code. */ diff --git a/examples/wayland/ivi-compositor/main.cpp b/examples/wayland/ivi-compositor/main.cpp index 435b4e3f1..50f48df7a 100644 --- a/examples/wayland/ivi-compositor/main.cpp +++ b/examples/wayland/ivi-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 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QtCore/QUrl> #include <QtCore/QDebug> diff --git a/examples/wayland/ivi-compositor/main.qml b/examples/wayland/ivi-compositor/main.qml index 1ea965e15..555f6467c 100644 --- a/examples/wayland/ivi-compositor/main.qml +++ b/examples/wayland/ivi-compositor/main.qml @@ -1,58 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.0 -import QtWayland.Compositor 1.0 -import QtQuick.Window 2.2 +import QtQuick +import QtWayland.Compositor +import QtWayland.Compositor.IviApplication +import QtQuick.Window WaylandCompositor { + //! [wayland output] WaylandOutput { sizeFollowsWindow: true window: Window { @@ -83,23 +38,29 @@ WaylandCompositor { } } } + //! [wayland output] Component { id: chromeComponent ShellSurfaceItem { anchors.fill: parent onSurfaceDestroyed: destroy() + //! [resizing] onWidthChanged: handleResized() onHeightChanged: handleResized() function handleResized() { - shellSurface.sendConfigure(Qt.size(width, height)); + if (width > 0 && height > 0) + shellSurface.sendConfigure(Qt.size(width, height)); } + //! [resizing] } } + //! [connecting] IviApplication { - onIviSurfaceCreated: { + onIviSurfaceCreated: (iviSurface) => { var surfaceArea = iviSurface.iviId === 1337 ? leftArea : rightArea; var item = chromeComponent.createObject(surfaceArea, { "shellSurface": iviSurface } ); item.handleResized(); } } + //! [connecting] } diff --git a/examples/wayland/minimal-cpp/CMakeLists.txt b/examples/wayland/minimal-cpp/CMakeLists.txt new file mode 100644 index 000000000..36fea7ab2 --- /dev/null +++ b/examples/wayland/minimal-cpp/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(minimal-cpp LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/minimal-cpp") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui WaylandCompositor) + +qt_add_executable(minimal-cpp + compositor.cpp compositor.h + main.cpp + window.cpp window.h +) + +set_target_properties(minimal-cpp PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_include_directories(minimal-cpp PUBLIC + ../../include +) + +target_link_libraries(minimal-cpp PUBLIC + # Remove: L + #../../lib + Qt::Core + Qt::Gui + Qt::WaylandCompositor +) + +install(TARGETS minimal-cpp + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/minimal-cpp/README b/examples/wayland/minimal-cpp/README index 87c389c3b..2a4a51f3d 100644 --- a/examples/wayland/minimal-cpp/README +++ b/examples/wayland/minimal-cpp/README @@ -3,6 +3,3 @@ and running. Input events are not delivered to clients, to avoid the logic for finding the correct window and map the coordinates. This example uses the IVI-application shell protocol, positioning windows based on the ivi_id. -See the qwindow-compositor example for information on how to implement -support for key and mouse events, and everything else a proper desktop -compositor needs. diff --git a/examples/wayland/minimal-cpp/compositor.cpp b/examples/wayland/minimal-cpp/compositor.cpp index a4b989975..83b773b28 100644 --- a/examples/wayland/minimal-cpp/compositor.cpp +++ b/examples/wayland/minimal-cpp/compositor.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 "compositor.h" #include "window.h" @@ -59,11 +12,13 @@ #include <QRandomGenerator> #include <QOpenGLFunctions> +//! [getTexture] QOpenGLTexture *View::getTexture() { if (advance()) m_texture = currentBuffer().toOpenGLTexture(); return m_texture; } +//! [getTexture] QPoint View::mapToLocal(const QPoint &globalPos) const { @@ -95,6 +50,7 @@ Compositor::~Compositor() { } +//! [create] void Compositor::create() { QWaylandOutput *output = new QWaylandOutput(this, m_window); @@ -106,6 +62,7 @@ void Compositor::create() m_iviApplication = new QWaylandIviApplication(this); connect(m_iviApplication, &QWaylandIviApplication::iviSurfaceCreated, this, &Compositor::onIviSurfaceCreated); } +//! [create] View *Compositor::viewAt(const QPoint &position) { @@ -132,17 +89,20 @@ static inline QPoint mapToView(const View *view, const QPoint &position) return view ? view->mapToLocal(position) : position; } +//! [handleMousePress] void Compositor::handleMousePress(const QPoint &position, Qt::MouseButton button) { if (!m_mouseView) { - if (m_mouseView = viewAt(position)) + if ((m_mouseView = viewAt(position))) raise(m_mouseView); } auto *seat = defaultSeat(); seat->sendMouseMoveEvent(m_mouseView, mapToView(m_mouseView, position)); seat->sendMousePressEvent(button); } +//! [handleMousePress] +//! [handleMouseRelease] void Compositor::handleMouseRelease(const QPoint &position, Qt::MouseButton button, Qt::MouseButtons buttons) { auto *seat = defaultSeat(); @@ -156,6 +116,7 @@ void Compositor::handleMouseRelease(const QPoint &position, Qt::MouseButton butt m_mouseView = nullptr; } } +//! [handleMouseRelease] void Compositor::handleMouseMove(const QPoint &position) { @@ -182,7 +143,7 @@ void Compositor::handleKeyRelease(quint32 nativeScanCode) defaultSeat()->sendKeyReleaseEvent(nativeScanCode); } - +//! [surfaceCreated] void Compositor::onIviSurfaceCreated(QWaylandIviSurface *iviSurface) { View *view = new View(iviSurface->iviId()); @@ -193,12 +154,9 @@ void Compositor::onIviSurfaceCreated(QWaylandIviSurface *iviSurface) connect(view, &QWaylandView::surfaceDestroyed, this, &Compositor::viewSurfaceDestroyed); connect(iviSurface->surface(), &QWaylandSurface::redraw, this, &Compositor::triggerRender); } +//! [surfaceCreated] -void Compositor::onSurfaceDestroyed() -{ - triggerRender(); -} - +//! [surfaceDestroyed] void Compositor::viewSurfaceDestroyed() { View *view = qobject_cast<View*>(sender()); @@ -206,6 +164,7 @@ void Compositor::viewSurfaceDestroyed() delete view; triggerRender(); } +//! [surfaceDestroyed] void Compositor::triggerRender() { diff --git a/examples/wayland/minimal-cpp/compositor.h b/examples/wayland/minimal-cpp/compositor.h index e32442dd4..8ba6c8d1b 100644 --- a/examples/wayland/minimal-cpp/compositor.h +++ b/examples/wayland/minimal-cpp/compositor.h @@ -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 #ifndef COMPOSITOR_H #define COMPOSITOR_H @@ -80,7 +33,6 @@ public: void initPosition(const QSize &screenSize, const QSize &surfaceSize); private: - friend class Compositor; QOpenGLTexture *m_texture = nullptr; bool m_positionSet = false; QPoint m_pos; @@ -112,7 +64,6 @@ public: private slots: void onIviSurfaceCreated(QWaylandIviSurface *iviSurface); - void onSurfaceDestroyed(); void triggerRender(); void viewSurfaceDestroyed(); diff --git a/examples/wayland/minimal-cpp/doc/images/minimal-cpp.jpg b/examples/wayland/minimal-cpp/doc/images/minimal-cpp.jpg Binary files differnew file mode 100644 index 000000000..d7c8a1cf8 --- /dev/null +++ b/examples/wayland/minimal-cpp/doc/images/minimal-cpp.jpg diff --git a/examples/wayland/minimal-cpp/doc/src/minimal-cpp.qdoc b/examples/wayland/minimal-cpp/doc/src/minimal-cpp.qdoc new file mode 100644 index 000000000..3d6894de4 --- /dev/null +++ b/examples/wayland/minimal-cpp/doc/src/minimal-cpp.qdoc @@ -0,0 +1,67 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \title Minimal CPP + \example minimal-cpp + \examplecategory {Embedded} + \brief Minimal CPP is an example that demonstrates how to write a Wayland compositor in C++. + \ingroup qtwaylandcompositor-examples + + Minimal CPP is a minimalistic compositor example implementing a complete Qt Wayland Compositor + using C++. The C++ API of QtWaylandCompositor is low-level and intended for specialized + applications, such as supporting hardware features, or if Qt Quick is not available. The QML API + offers more convenience and functionality. For comparison, the + \l{Minimal QML}{Minimal QML example} implements more functionality with 30 lines of QML than this + example does in 300+ lines. + + \image minimal-cpp.jpg + + This example is split in two parts. The Wayland logic is contained in the \c Compositor class, + and the user interface is in the \c Window class. + + \section1 Window + + The \c Window class is fairly straight-forward. To display the Wayland surfaces, it iterates + through the compositor's views and renders them on the screen using \l QOpenGLTextureBlitter: + + \snippet minimal-cpp/window.cpp paintGL + + All keyboard and mouse events are delivered to the compositor. For example: + + \snippet minimal-cpp/window.cpp mousePressEvent + + \section1 Compositor + + The \c Compositor class is more complex, since it has to implement much of the logic that would + be handled by \l[QML]{WaylandCompositor} and \l[QML]{WaylandQuickItem} in a QML-based compositor. + + The \c create function sets up the compositor, using the IviApplication, which is the most basic + shell extension. The function is called after the OpenGL context has been initialized: + + \snippet minimal-cpp/compositor.cpp create + + All the logic for mouse events and keyboard focus has to be implemented manually, including + implicit mouse grabs (sending all mouse moves to the surface that received the initial mouse + press). Note that mouse press events in the Wayland protocol do not contain the mouse position, + so we always have to send a mouse move when we reveive a mouse press: + + \snippet minimal-cpp/compositor.cpp handleMousePress + + For a mouse release, we end the implicit grab and notify the surface at the current mouse position: + + \snippet minimal-cpp/compositor.cpp handleMousePress + + When we are notified of a new surface, we create a \c View to keep track of it, and connect + signals so we can handle updates. + + \snippet minimal-cpp/compositor.cpp surfaceCreated + + The \c View class subclasses QWaylandView, which represents a specific view of a surface. The + \l {QWaylandView::advance}{advance} function updates the view's current buffer and returns true + if there is new content. The \c getTexture function makes the buffer contents available as an + OpenGL texture for the benefit of the \c Window class: + + \snippet minimal-cpp/compositor.cpp getTexture + +*/ diff --git a/examples/wayland/minimal-cpp/main.cpp b/examples/wayland/minimal-cpp/main.cpp index 226e8923c..6b74facd4 100644 --- a/examples/wayland/minimal-cpp/main.cpp +++ b/examples/wayland/minimal-cpp/main.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 <QGuiApplication> #include "window.h" diff --git a/examples/wayland/minimal-cpp/window.cpp b/examples/wayland/minimal-cpp/window.cpp index 9f22cc68a..68f0a25d8 100644 --- a/examples/wayland/minimal-cpp/window.cpp +++ b/examples/wayland/minimal-cpp/window.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 "window.h" #include "compositor.h" @@ -71,6 +24,7 @@ void Window::initializeGL() emit glReady(); } +//! [paintGL] void Window::paintGL() { m_compositor->startRender(); @@ -111,20 +65,23 @@ void Window::paintGL() m_textureBlitter.release(); m_compositor->endRender(); } +//! [paintGL] +//! [mousePressEvent] void Window::mousePressEvent(QMouseEvent *event) { - m_compositor->handleMousePress(event->localPos().toPoint(), event->button()); + m_compositor->handleMousePress(event->position().toPoint(), event->button()); } +//! [mousePressEvent] void Window::mouseReleaseEvent(QMouseEvent *event) { - m_compositor->handleMouseRelease(event->localPos().toPoint(), event->button(), event->buttons()); + m_compositor->handleMouseRelease(event->position().toPoint(), event->button(), event->buttons()); } void Window::mouseMoveEvent(QMouseEvent *event) { - m_compositor->handleMouseMove(event->localPos().toPoint()); + m_compositor->handleMouseMove(event->position().toPoint()); } void Window::wheelEvent(QWheelEvent *event) @@ -132,10 +89,12 @@ void Window::wheelEvent(QWheelEvent *event) m_compositor->handleMouseWheel(event->angleDelta()); } +//! [keyPressEvent] void Window::keyPressEvent(QKeyEvent *e) { m_compositor->handleKeyPress(e->nativeScanCode()); } +//! [keyPressEvent] void Window::keyReleaseEvent(QKeyEvent *e) { diff --git a/examples/wayland/minimal-cpp/window.h b/examples/wayland/minimal-cpp/window.h index 7711e0bd6..fa1995fb9 100644 --- a/examples/wayland/minimal-cpp/window.h +++ b/examples/wayland/minimal-cpp/window.h @@ -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 #ifndef WINDOW_H #define WINDOW_H diff --git a/examples/wayland/minimal-qml/CMakeLists.txt b/examples/wayland/minimal-qml/CMakeLists.txt new file mode 100644 index 000000000..6834cd92f --- /dev/null +++ b/examples/wayland/minimal-qml/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(minimal-qml LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/minimal-qml") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(minimal-qml + main.cpp +) + +set_target_properties(minimal-qml PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(minimal-qml PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(minimal-qml_resource_files + "main.qml" +) + +qt6_add_resources(minimal-qml "minimal-qml" + PREFIX + "/" + FILES + ${minimal-qml_resource_files} +) + +install(TARGETS minimal-qml + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/minimal-qml/doc/images/minimal-qml.png b/examples/wayland/minimal-qml/doc/images/minimal-qml.png Binary files differnew file mode 100644 index 000000000..c950f933a --- /dev/null +++ b/examples/wayland/minimal-qml/doc/images/minimal-qml.png diff --git a/examples/wayland/minimal-qml/doc/src/minimal-qml.qdoc b/examples/wayland/minimal-qml/doc/src/minimal-qml.qdoc index 5a435f3fc..2150fece3 100644 --- a/examples/wayland/minimal-qml/doc/src/minimal-qml.qdoc +++ b/examples/wayland/minimal-qml/doc/src/minimal-qml.qdoc @@ -1,36 +1,93 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - * \title Qt Wayland Compositor Examples - Minimal QML + * \title Minimal QML * \example minimal-qml + * \examplecategory {Embedded} * \brief Minimal QML is a simple example that demonstrates how to write a Wayland compositor in QML. * \ingroup qtwaylandcompositor-examples * * Minimal QML is a desktop-style Wayland compositor example implementing a - * complete Qt Wayland Compositor with as little code as possible. + * complete Qt Wayland Compositor with as little code as possible. The compositor is implemented + * with Qt Quick and QML. + * + * \image minimal-qml.png + * + * \section1 The WaylandCompositor Object + * + * The top-level item of the compositor is a \l WaylandCompositor. This represents the Wayland + * server itself and manages the connections to clients as they come in. + * + * \snippet minimal-qml/main.qml compositor + * + * By default, the server supports the core Wayland protocol for communicating with clients. + * Usually, though, you will also want to support one or more extensions to the protocol. This + * gives the client more tools to influence its role in the windowing system. + * + * Qt supports several standard and common extensions. In addition, it is easy to create and support + * custom extensions, as long as support can be added in both the client and server code. + * + * \section1 Shell Extensions + * + * Typically, a compositor will support at least one + * \l{Shell Extensions - Qt Wayland Compositor}{shell extension}. Extensions are added to + * the compositor by instantiating them as direct children of the \l WaylandCompositor object. They + * will automatically be added to its \c extensions property and broadcast to clients when they + * connect. + * + * \snippet minimal-qml/main.qml shells + * + * The \e{Minimal QML} example supports three different shells: \l{WlShell}, \l{XdgShell} and + * \l{IviApplication}. + * + * A client can connect to either of these and it will be used as a channel for communicating + * about certain things between the client and compositor, such as creating new windows, + * negotiating size, and so on. + * + * When a client creates a new surface, its active extension will receive a signal of this. The + * signal contains a \l ShellSurface argument. Depending on which extension received the signal, + * this argument will be of a subclass of \l{ShellSurface}: \l{WlShellSurface}, \l{XdgSurface} + * or \l{IviSurface} respectively. + * + * The \l ShellSurface can be used to access features of the shell extension for the specific + * surface. In the \e{Minimal QML} example, we simply want to add the client to our scene. To + * record existence of the new window, we add it to a simple \l ListModel for safe-keeping. + * + * \snippet minimal-qml/main.qml model + * + * \section1 Creating the Scene + * + * Most of the necessary compositor code is already ready. The final step is to make sure + * applications are actually visible on the screen. + * + * For all compositors, we have to define at least one output. This is done by instantiating + * a \l WaylandOutput object as the direct child of the \l WaylandCompositor. If there is only + * a single output, this will represent the primary screen on the system. (You may also create + * multiple \l WaylandOutput objects to address multiple screens if they are available. See + * the \l{Multi Screen}{Multi Screen example} for more details + * about this.) + * + * \snippet minimal-qml/main.qml output + * + * Inside the \l{WaylandOutput}, we create a \l Window that serves as the container for + * our scene. In the example, we give this a size. The size used if the compositor is running as + * an application inside another windowing system which supports custom-sized windows. In a + * typical use case on an embedded device, where the compositor is the only display server running, + * it will probably be running on a full-screen platform plugin (such as \c{eglfs}) and the size + * set here will not matter. + * + * The final step is to create items for each of the \l ShellSurface objects that have been created. + * For this, we can use the \l ShellSurfaceItem class. + * + * \snippet minimal-qml/main.qml shell surface item + * + * We create a \l ShellSurfaceItem for each of the shell surfaces in our model, and assign them + * to the \c shellSurface property. In addition, we make sure the model is updated when the shell + * surface is destroyed. This can happen when a client manually closes a window, and if it exits + * or crashes. + * + * And this is all the code needed to create a functional Wayland compositor using Qt Quick and + * QML. For another example of a compositor written in QML but which has a few more features, take + * a look at the \l{Fancy Compositor}{Fancy Compositor example}. */ diff --git a/examples/wayland/minimal-qml/main.cpp b/examples/wayland/minimal-qml/main.cpp index 60378e860..b187aa753 100644 --- a/examples/wayland/minimal-qml/main.cpp +++ b/examples/wayland/minimal-qml/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 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QtCore/QUrl> #include <QtCore/QDebug> diff --git a/examples/wayland/minimal-qml/main.qml b/examples/wayland/minimal-qml/main.qml index 63ed9da5f..e1e1c18d3 100644 --- a/examples/wayland/minimal-qml/main.qml +++ b/examples/wayland/minimal-qml/main.qml @@ -1,65 +1,28 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.6 -import QtQuick.Window 2.2 -import QtWayland.Compositor 1.3 +import QtQuick +import QtQuick.Window +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell +import QtWayland.Compositor.WlShell +import QtWayland.Compositor.IviApplication +//! [compositor] WaylandCompositor { +//! [compositor] // The output defines the screen. + + //! [output] WaylandOutput { sizeFollowsWindow: true window: Window { width: 1024 height: 768 visible: true + //! [output] + + //! [shell surface item] Repeater { model: shellSurfaces // ShellSurfaceItem handles displaying a shell surface. @@ -67,29 +30,33 @@ WaylandCompositor { // resize/move, and forwarding of mouse and keyboard // events to the client process. ShellSurfaceItem { - autoCreatePopupItems: true shellSurface: modelData onSurfaceDestroyed: shellSurfaces.remove(index) } } + //! [shell surface item] } } + // Extensions are additions to the core Wayland // protocol. We choose to support three different // shells (window management protocols). When the // client creates a new shell surface (i.e. a window) // we append it to our list of shellSurfaces. + + //! [shells] WlShell { - onWlShellSurfaceCreated: - shellSurfaces.append({shellSurface: shellSurface}); - } - XdgShellV6 { - onToplevelCreated: - shellSurfaces.append({shellSurface: xdgSurface}); + onWlShellSurfaceCreated: (shellSurface) => shellSurfaces.append({shellSurface: shellSurface}); } XdgShell { - onToplevelCreated: - shellSurfaces.append({shellSurface: xdgSurface}); + onToplevelCreated: (toplevel, xdgSurface) => shellSurfaces.append({shellSurface: xdgSurface}); + } + IviApplication { + onIviSurfaceCreated: (iviSurface) => shellSurfaces.append({shellSurface: iviSurface}); } + //! [shells] + + //! [model] ListModel { id: shellSurfaces } + //! [model] } diff --git a/examples/wayland/multi-output/CMakeLists.txt b/examples/wayland/multi-output/CMakeLists.txt new file mode 100644 index 000000000..8e59f977a --- /dev/null +++ b/examples/wayland/multi-output/CMakeLists.txt @@ -0,0 +1,52 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(multi-output LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/multi-output") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(multi-output + main.cpp +) + +set_target_properties(multi-output PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(multi-output PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(multi-output_resource_files + "images/background.jpg" + "qml/GridScreen.qml" + "qml/ShellChrome.qml" + "qml/ShellScreen.qml" + "qml/main.qml" +) + +qt6_add_resources(multi-output "multi-output" + PREFIX + "/" + FILES + ${multi-output_resource_files} +) + +install(TARGETS multi-output + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/multi-output/doc/images/multi-output.jpg b/examples/wayland/multi-output/doc/images/multi-output.jpg Binary files differnew file mode 100644 index 000000000..bf4dbfe53 --- /dev/null +++ b/examples/wayland/multi-output/doc/images/multi-output.jpg diff --git a/examples/wayland/multi-output/doc/src/multi-output.qdoc b/examples/wayland/multi-output/doc/src/multi-output.qdoc index 233b29ba3..5614099e9 100644 --- a/examples/wayland/multi-output/doc/src/multi-output.qdoc +++ b/examples/wayland/multi-output/doc/src/multi-output.qdoc @@ -1,41 +1,54 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - \title Qt Wayland Compositor Examples - Multi Output + \title Multi Output \example multi-output + \examplecategory {Embedded} \brief Multi Output is an example that demonstrates a compositor with multiple outputs. \ingroup qtwaylandcompositor-examples - Multi Output demonstrates how to display the same clients on different - \l{WaylandOutput}{WaylandOutputs} with different types of composition. + \section1 Introduction - The example opens two different windows, one for each output. When a client connects, its - WaylandSurface is displayed in a GridView on one of the outputs, while a ShellSurface - associated with the WaylandSurface is displayed with desktop-style composition on - the other output. + The Multi Output example demonstrates how to display the same clients on different + \l{WaylandOutput}{WaylandOutputs} with different types of composition. One output shows + the clients in a uniform grid, scaled to the same size. The other output is a normal + desktop-style interactive compositor window. + + \image multi-output.jpg + + For an introduction to the basic principles of creating a \l{Qt Wayland Compositor} with Qt, + see the \l{Minimal QML}{Minimal QML example}. + + \section1 Multiple Outputs + + The example creates two different windows, one for each output. For the grid view, we connect to the + \l{WaylandCompositor::surfaceRequested}{surfaceRequested} signal. This signal is emitted for every + surface that the client creates. This allows the application to override the default response to the request + and create a custom \l{WaylandSurface}. + + \snippet multi-output/qml/main.qml onSurfaceRequested + + Upon receiving the signal, the example creates a \l WaylandQuickItem as a view of the surface. + This can be added to the Qt Quick scene like any other item. In the example, we add it to + a \l{GridView}. + + For the desktop-style window, we use the features of the \l XdgShell extension. + When the surface has been created, the \l XdgShell emits a + \l{XdgShell::toplevelCreated}{toplevelCreated} signal. + + \snippet multi-output/qml/main.qml xdgshell + + We create a \l ShellSurfaceItem to add the \l XdgToplevel to the second output. This enables + desktop-style interaction with the surface. + + When these steps are done, the client's contents are visible in both windows. The buffers + containing the client's contents are the same for both the outputs, but are visualized in two + different ways, and provide different ways for the user to interact with them. + + \note In order to support multiple Wayland outputs in the same compositor, the + \l Qt::AA_ShareOpenGLContexts attribute must be set before the \l QGuiApplication + object is constructed. + + \sa {Multi Screen}, {Overview Compositor} */ diff --git a/examples/wayland/multi-output/main.cpp b/examples/wayland/multi-output/main.cpp index 304b13c4a..225c06c91 100644 --- a/examples/wayland/multi-output/main.cpp +++ b/examples/wayland/multi-output/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 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QtCore/QUrl> #include <QtCore/QDebug> @@ -57,6 +10,8 @@ int main(int argc, char *argv[]) { + // AA_ShareOpenGLContexts is required for compositors with multiple outputs + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); QGuiApplication app(argc, argv); QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); diff --git a/examples/wayland/multi-output/qml/GridScreen.qml b/examples/wayland/multi-output/qml/GridScreen.qml index a59cb8fb4..51397a947 100644 --- a/examples/wayland/multi-output/qml/GridScreen.qml +++ b/examples/wayland/multi-output/qml/GridScreen.qml @@ -1,56 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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 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.14 +import QtQuick +import QtQuick.Window +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell WaylandOutput { id: output @@ -82,7 +36,6 @@ WaylandOutput { surface: gridSurface width: gridView.cellWidth height: gridView.cellHeight - sizeFollowsSurface: false inputEventsEnabled: false allowDiscardFrontBuffer: true MouseArea { diff --git a/examples/wayland/multi-output/qml/ShellChrome.qml b/examples/wayland/multi-output/qml/ShellChrome.qml index e28addaaf..ab4926a68 100644 --- a/examples/wayland/multi-output/qml/ShellChrome.qml +++ b/examples/wayland/multi-output/qml/ShellChrome.qml @@ -1,55 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.0 -import QtWayland.Compositor 1.0 +import QtQuick +import QtWayland.Compositor ShellSurfaceItem { id: rootChrome diff --git a/examples/wayland/multi-output/qml/ShellScreen.qml b/examples/wayland/multi-output/qml/ShellScreen.qml index aa9b4b29b..ffbb9f520 100644 --- a/examples/wayland/multi-output/qml/ShellScreen.qml +++ b/examples/wayland/multi-output/qml/ShellScreen.qml @@ -1,56 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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 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.14 +import QtQuick +import QtQuick.Window +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell WaylandOutput { id: output @@ -66,7 +20,7 @@ WaylandOutput { id: mouseTracker anchors.fill: parent - windowSystemCursorEnabled: true + windowSystemCursorEnabled: !clientCursor.visible Image { id: background anchors.fill: parent @@ -75,11 +29,10 @@ WaylandOutput { smooth: true } WaylandCursorItem { - id: cursor - inputEventsEnabled: false + id: clientCursor x: mouseTracker.mouseX y: mouseTracker.mouseY - + visible: surface != null && mouseTracker.containsMouse seat : output.compositor.defaultSeat } } diff --git a/examples/wayland/multi-output/qml/main.qml b/examples/wayland/multi-output/qml/main.qml index 45f91fd66..26e227bcf 100644 --- a/examples/wayland/multi-output/qml/main.qml +++ b/examples/wayland/multi-output/qml/main.qml @@ -1,55 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.0 -import QtWayland.Compositor 1.14 +import QtQuick +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell WaylandCompositor { id: comp @@ -93,17 +47,19 @@ WaylandCompositor { XdgOutputManagerV1 {} - WlShell { - id: defaultShell - - onWlShellSurfaceCreated: { - var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": shellSurface } ); + // ![xdgshell] + XdgShell { + onToplevelCreated: (toplevel, xdgSurface) => { + var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": xdgSurface } ); item.surface.activated.connect(item.raise); } } + // ![xdgshell] - onSurfaceRequested: { + // ![onSurfaceRequested] + onSurfaceRequested: (client, id, version) => { var surface = surfaceComponent.createObject(comp, { } ); surface.initialize(comp, client, id, version); } + // ![onSurfaceRequested] } diff --git a/examples/wayland/multi-screen/CMakeLists.txt b/examples/wayland/multi-screen/CMakeLists.txt new file mode 100644 index 000000000..2d5ac21cb --- /dev/null +++ b/examples/wayland/multi-screen/CMakeLists.txt @@ -0,0 +1,50 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(multi-screen LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/multi-screen") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(multi-screen + main.cpp +) + +set_target_properties(multi-screen PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(multi-screen PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(multi-screen_resource_files + "qml/Chrome.qml" + "qml/CompositorScreen.qml" + "qml/main.qml" +) + +qt6_add_resources(multi-screen "multi-screen" + PREFIX + "/" + FILES + ${multi-screen_resource_files} +) + +install(TARGETS multi-screen + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/multi-screen/doc/images/multi-screen.jpg b/examples/wayland/multi-screen/doc/images/multi-screen.jpg Binary files differnew file mode 100644 index 000000000..f43aca07c --- /dev/null +++ b/examples/wayland/multi-screen/doc/images/multi-screen.jpg diff --git a/examples/wayland/multi-screen/doc/src/multi-screen.qdoc b/examples/wayland/multi-screen/doc/src/multi-screen.qdoc index cd60213b5..b8113e02f 100644 --- a/examples/wayland/multi-screen/doc/src/multi-screen.qdoc +++ b/examples/wayland/multi-screen/doc/src/multi-screen.qdoc @@ -1,45 +1,68 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - * \title Qt Wayland Compositor Examples - Multi Screen + * \title Multi Screen * \example multi-screen + * \examplecategory {Embedded} * \brief Multi Screen is a desktop-style Wayland compositor for multiple screens. * \ingroup qtwaylandcompositor-examples * + * \section1 Introduction + * * Multi-screen is a desktop-style Wayland compositor example for multiple * screens. * - * When a client creates a shell surface, one ShellSurfaceItem is created on - * each screen. The ShellSurfaceItem will be visible only on one (or two) - * screens at a time. ShellSurfaceItem positions are synchronized so that when - * windows enter one screen they are moved off another at the same time. + * \image multi-screen.jpg + * + * For an introduction to the basic principles of creating a \l{Qt Wayland Compositor} with Qt, + * see the \l{Minimal QML}{Minimal QML example}. + * + * \section1 Supporting multiple screens + * + * For each available screen on the system, the example creates a \c CompositorScreen, which is + * a subclass of \l WaylandOutput. If there is only one physical screen available, the example + * emulates three screens with dummy data. + * + * \snippet multi-screen/qml/main.qml screens + * + * Each \l WaylandOutput contains a \l{Window}, which is used for containing client content, as + * is the standard setup with \l{Qt Wayland Compositor}. Since each \l Window is isolated from the + * others, we cannot share any Qt Quick items between them. Therefore, when a client connects and + * a \l ShellSurface is created, one \l ShellSurfaceItem is created on each of the screens. + * + * \snippet multi-screen/qml/main.qml createShellSurfaceItems + * + * These items serve as views of the same client content. The client's surface itself will only be + * created once, and will be shared by the surface items. + * + * Top-level surface items are created as children of the background \l Rectangle in each of the + * outputs. These views are stored for later, and if the client spawns any child windows, these are + * parented to the top-level window's item. + * + * \snippet multi-screen/qml/main.qml parenting + * + * The client content will be visible only on one or two screens at a time. \l ShellSurfaceItem + * positions are synchronized so that when windows enter one screen, they are moved off of another + * at the same time. This gives the appearance of a single item which moves seamlessly between + * screens. The global position of the client is stored in a shared + * \l{ShellSurfaceItem::moveItem}{moveItem} and relative position of each screen's + * \l ShellSurfaceItem is calculated based on this. If the \c moveItem is currently outside the + * bounds of one screen, its coordinates will reflect this, and it will not be visible on that + * screen. + * + * \snippet multi-screen/qml/Chrome.qml position sync + * + * Finally, \l{WaylandQuickItem::setPrimary()} is called at appropriate times to set the primary + * view for the \l ShellSurface, which is used when the client asks to be maximized or fullscreen. + * The primary \l ShellSurfaceItem is selected based on how much of it is currently visible. + * + * \note In order to support multiple Wayland outputs in the same compositor, the + * \l Qt::AA_ShareOpenGLContexts attribute must be set before the \l QGuiApplication + * object is constructed. In the example, we do this at the very beginning of the \c main() + * function. + * + * \snippet multi-screen/main.cpp share context * - * WaylandQuickItem::setPrimary() is called at appropriate times to set the - * primary view for the ShellSurface, which is used when the client asks to be - * maximized or fullscreen. + * \sa {Multi Output} */ diff --git a/examples/wayland/multi-screen/main.cpp b/examples/wayland/multi-screen/main.cpp index 304b13c4a..438206dfb 100644 --- a/examples/wayland/multi-screen/main.cpp +++ b/examples/wayland/multi-screen/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 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QtCore/QUrl> #include <QtCore/QDebug> @@ -57,6 +10,10 @@ int main(int argc, char *argv[]) { + // AA_ShareOpenGLContexts is required for compositors with multiple outputs + //! [share context] + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); + //! [share context] QGuiApplication app(argc, argv); QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); diff --git a/examples/wayland/multi-screen/multi-screen.pro b/examples/wayland/multi-screen/multi-screen.pro index 29e1479da..77f8258a5 100644 --- a/examples/wayland/multi-screen/multi-screen.pro +++ b/examples/wayland/multi-screen/multi-screen.pro @@ -14,5 +14,5 @@ sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/multi-screen INSTALLS += target sources DISTFILES += \ - qml/Screen.qml \ + qml/CompositorScreen.qml \ qml/Chrome.qml diff --git a/examples/wayland/multi-screen/multi-screen.qrc b/examples/wayland/multi-screen/multi-screen.qrc index 57fcd3cf6..a24e3efd5 100644 --- a/examples/wayland/multi-screen/multi-screen.qrc +++ b/examples/wayland/multi-screen/multi-screen.qrc @@ -1,7 +1,7 @@ <RCC> <qresource prefix="/"> <file>qml/main.qml</file> - <file>qml/Screen.qml</file> + <file>qml/CompositorScreen.qml</file> <file>qml/Chrome.qml</file> </qresource> </RCC> diff --git a/examples/wayland/multi-screen/qml/Chrome.qml b/examples/wayland/multi-screen/qml/Chrome.qml index 52f449468..d3485e81f 100644 --- a/examples/wayland/multi-screen/qml/Chrome.qml +++ b/examples/wayland/multi-screen/qml/Chrome.qml @@ -1,69 +1,24 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** 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 The Qt Company Ltd. +// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.0 -import QtWayland.Compositor 1.0 +import QtQuick +import QtWayland.Compositor Item { id: chrome property alias shellSurface: surfaceItem.shellSurface property alias surfaceItem: surfaceItem property alias moveItem: surfaceItem.moveItem + property alias output: surfaceItem.output + //! [position sync] x: surfaceItem.moveItem.x - surfaceItem.output.geometry.x y: surfaceItem.moveItem.y - surfaceItem.output.geometry.y + //! [position sync] ShellSurfaceItem { id: surfaceItem - autoCreatePopupItems: true onSurfaceDestroyed: chrome.destroy(); } diff --git a/examples/wayland/multi-screen/qml/CompositorScreen.qml b/examples/wayland/multi-screen/qml/CompositorScreen.qml new file mode 100644 index 000000000..e449d6fa8 --- /dev/null +++ b/examples/wayland/multi-screen/qml/CompositorScreen.qml @@ -0,0 +1,57 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWayland.Compositor +import QtQuick.Window + +WaylandOutput { + id: screen + property variant viewsBySurface: ({}) + property alias surfaceArea: background + property alias text: t.text + property alias screen: win.screen + sizeFollowsWindow: true + + property bool windowed: false + + window: Window { + id: win + x: Screen.virtualX + y: Screen.virtualY + width: 800 + height: 800 + visibility: windowed ? Window.Windowed : Window.FullScreen + visible: true + + WaylandMouseTracker { + id: mouseTracker + anchors.fill: parent + windowSystemCursorEnabled: !clientCursor.visible + + Rectangle { + anchors.fill: parent + id: background + + Text { + id: t + anchors.centerIn: parent + font.pointSize: 72 + } + } + + WaylandCursorItem { + id: clientCursor + inputEventsEnabled: false + x: mouseTracker.mouseX + y: mouseTracker.mouseY + seat: comp.defaultSeat + visible: surface != null && mouseTracker.containsMouse + } + } + Shortcut { + sequence: "Ctrl+Alt+Backspace" + onActivated: Qt.quit() + } + } +} diff --git a/examples/wayland/multi-screen/qml/Screen.qml b/examples/wayland/multi-screen/qml/Screen.qml deleted file mode 100644 index 21f2d1266..000000000 --- a/examples/wayland/multi-screen/qml/Screen.qml +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -import QtQuick 2.8 -import QtWayland.Compositor 1.0 -import QtQuick.Window 2.3 - -WaylandOutput { - id: screen - property variant viewsBySurface: ({}) - property alias surfaceArea: background - property alias text: t.text - property alias screen: win.screen - sizeFollowsWindow: true - - property bool windowed: false - - window: Window { - id: win - x: Screen.virtualX - y: Screen.virtualY - width: 800 - height: 800 - visibility: windowed ? Window.Windowed : Window.FullScreen - visible: true - - WaylandMouseTracker { - id: mouseTracker - anchors.fill: parent - windowSystemCursorEnabled: false - - Rectangle { - anchors.fill: parent - id: background - - Text { - id: t - anchors.centerIn: parent - font.pointSize: 72 - } - } - - WaylandCursorItem { - inputEventsEnabled: false - x: mouseTracker.mouseX - y: mouseTracker.mouseY - seat: comp.defaultSeat - visible: mouseTracker.containsMouse - } - } - Shortcut { - sequence: "Ctrl+Alt+Backspace" - onActivated: Qt.quit() - } - } -} diff --git a/examples/wayland/multi-screen/qml/main.qml b/examples/wayland/multi-screen/qml/main.qml index ecd32739d..1180d30b4 100644 --- a/examples/wayland/multi-screen/qml/main.qml +++ b/examples/wayland/multi-screen/qml/main.qml @@ -1,59 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** 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 The Qt Company Ltd. +// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQml 2.2 -import QtQuick 2.0 -import QtQuick.Window 2.3 as Window -import QtWayland.Compositor 1.3 -import QtQml.Models 2.1 +import QtQml +import QtQuick +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell +import QtWayland.Compositor.WlShell +import QtQml.Models WaylandCompositor { id: comp @@ -67,20 +21,22 @@ WaylandCompositor { property bool emulated: Qt.application.screens.length < 2 + //! [screens] Instantiator { id: screens model: emulated ? emulatedScreens : Qt.application.screens - delegate: Screen { + delegate: CompositorScreen { surfaceArea.color: "lightsteelblue" text: name compositor: comp - screen: modelData + screen: emulated ? Qt.application.screens[0] : modelData Component.onCompleted: if (!comp.defaultOutput) comp.defaultOutput = this position: Qt.point(virtualX, virtualY) windowed: emulated } } + //! [screens] Component { id: chromeComponent @@ -97,20 +53,18 @@ WaylandCompositor { } WlShell { - onWlShellSurfaceCreated: handleShellSurfaceCreated(shellSurface) - } - - XdgShellV6 { - onToplevelCreated: handleShellSurfaceCreated(xdgSurface) + onWlShellSurfaceCreated: (shellSurface) => handleShellSurfaceCreated(shellSurface) } XdgShell { - onToplevelCreated: handleShellSurfaceCreated(xdgSurface) + onToplevelCreated: (toplevel, xdgSurface) => handleShellSurfaceCreated(xdgSurface) } function createShellSurfaceItem(shellSurface, moveItem, output) { + // ![parenting] var parentSurfaceItem = output.viewsBySurface[shellSurface.parentSurface]; var parent = parentSurfaceItem || output.surfaceArea; + // ![parenting] var item = chromeComponent.createObject(parent, { "shellSurface": shellSurface, "moveItem": moveItem, @@ -130,7 +84,9 @@ WaylandCompositor { "width": Qt.binding(function() { return shellSurface.surface.width; }), "height": Qt.binding(function() { return shellSurface.surface.height; }) }); + //! [createShellSurfaceItems] for (var i = 0; i < screens.count; ++i) createShellSurfaceItem(shellSurface, moveItem, screens.objectAt(i)); + //! [createShellSurfaceItems] } } diff --git a/examples/wayland/overview-compositor/CMakeLists.txt b/examples/wayland/overview-compositor/CMakeLists.txt new file mode 100644 index 000000000..7afe52982 --- /dev/null +++ b/examples/wayland/overview-compositor/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(overview-compositor LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/overview-compositor") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(overview-compositor + main.cpp +) + +set_target_properties(overview-compositor PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(overview-compositor PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(overview-compositor_resource_files + "main.qml" +) + +qt6_add_resources(overview-compositor "overview-compositor" + PREFIX + "/" + FILES + ${overview-compositor_resource_files} +) + +install(TARGETS overview-compositor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/overview-compositor/doc/images/overview-compositor.jpg b/examples/wayland/overview-compositor/doc/images/overview-compositor.jpg Binary files differnew file mode 100644 index 000000000..71e56c827 --- /dev/null +++ b/examples/wayland/overview-compositor/doc/images/overview-compositor.jpg diff --git a/examples/wayland/overview-compositor/doc/src/overview-compositor.qdoc b/examples/wayland/overview-compositor/doc/src/overview-compositor.qdoc index 50408bc56..8ac3dfae0 100644 --- a/examples/wayland/overview-compositor/doc/src/overview-compositor.qdoc +++ b/examples/wayland/overview-compositor/doc/src/overview-compositor.qdoc @@ -1,34 +1,65 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - * \title Qt Wayland Compositor Examples - Overview Compositor + * \title Overview Compositor * \example overview-compositor + * \examplecategory {Embedded} * \brief Overview Compositor shows how to switch between clients in a grid. * + * \section1 Introduction + * + * Overview Compositor demonstrates selecting and activating an application + * from a grid of currently connected clients. + * + * \image overview-compositor.jpg + * + * For an introduction to the basic principles of creating a \l{Qt Wayland Compositor} with Qt, + * see the \l{Minimal QML}{Minimal QML example}. + * + * \section1 Application Grid + * + * In this example, the compositor supports two different modes of operation: + * + * \list + * \li A \e fullscreen mode, where a single application window occupies the whole compositor + * window and is interactable. + * \li An \e overview mode, where all application windows are visible in a grid. Clicking on a + * window in the grid causes it to be selected. The compositor enters fullscreen mode, + * showing the selected application window. + * \endlist + * + * When a client connects to the compositor and creates a top-level surface, the surface will be + * connected to a \l{Shell Extensions - Qt Wayland Compositor}{shell extension}. The example only + * supports the \l{XdgShell} extension, so the client will connect to this. + * + * \snippet overview-compositor/main.qml XdgShell + * + * For each surface, we tell the client to configure it as fullscreen. In addition, the surfaces + * are added to a \l ListModel for easy access. + * + * This model is used by a \l Repeater to create \l{ShellSurfaceItem}{ShellSurfaceItems} inside + * a \l{Grid}. The \l Grid component positions the items in a grid. + * + * \snippet overview-compositor/main.qml toplevels repeater + * + * For each of the items, we create a \l MouseArea which covers the item and intercepts all mouse + * and touch input. This is only active when the compositor is in \e{overview} mode, and activates + * the application that was clicked. + * + * When the compositor goes into fullscreen mode, the same \l Grid component is used, but is scaled + * and translated into a position where the single selected cell fills the compositor's window. The + * idea is to "zoom in" on the selected cell, allowing the user to interact with the application it + * contains. + * + * \snippet overview-compositor/main.qml zoom transform + * + * At the bottom side of the window, there is a button which toggles between the modes. This can + * be used to bring back the application grid while the compositor is in fullscreen mode. + * + * This example shows one way to have the compositor visualize clients in different modes. Another + * way to achieve similar effects is to create multiple Qt Quick items that refer to the same + * surface. See \l{Multi Output}{the Multi Output example} for a demonstration. + * * \ingroup qtwaylandcompositor-examples */ diff --git a/examples/wayland/overview-compositor/main.cpp b/examples/wayland/overview-compositor/main.cpp index 435b4e3f1..50f48df7a 100644 --- a/examples/wayland/overview-compositor/main.cpp +++ b/examples/wayland/overview-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 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QtCore/QUrl> #include <QtCore/QDebug> diff --git a/examples/wayland/overview-compositor/main.qml b/examples/wayland/overview-compositor/main.qml index d0482a90e..3d6f35aac 100644 --- a/examples/wayland/overview-compositor/main.qml +++ b/examples/wayland/overview-compositor/main.qml @@ -1,57 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.7 -import QtWayland.Compositor 1.3 -import QtQuick.Window 2.3 -import QtQuick.Controls 2.0 +import QtQuick +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell +import QtQuick.Window +import QtQuick.Controls WaylandCompositor { WaylandOutput { @@ -76,6 +30,7 @@ WaylandCompositor { anchors.fill: parent columns: Math.ceil(Math.sqrt(toplevels.count)) + // ![zoom transform] transform: [ Scale { xScale: grid.overview ? (1.0/grid.columns) : 1 @@ -90,7 +45,9 @@ WaylandCompositor { Behavior on y { PropertyAnimation { easing.type: Easing.InOutQuad; duration: 200 } } } ] + // ![zoom transform] + // ![toplevels repeater] Repeater { model: toplevels Item { @@ -99,8 +56,6 @@ WaylandCompositor { ShellSurfaceItem { anchors.fill: parent shellSurface: xdgSurface - autoCreatePopupItems: true - sizeFollowsSurface: false onSurfaceDestroyed: toplevels.remove(index) } MouseArea { @@ -113,6 +68,7 @@ WaylandCompositor { } } } + // ![toplevels repeater] } Button { @@ -132,10 +88,12 @@ WaylandCompositor { ListModel { id: toplevels } + // ![XdgShell] XdgShell { - onToplevelCreated: { + onToplevelCreated: (toplevel, xdgSurface) => { toplevels.append({xdgSurface}); toplevel.sendFullscreen(Qt.size(win.pixelWidth, win.pixelHeight)); } } + // ![XdgShell] } diff --git a/examples/wayland/pure-qml/doc/src/pure-qml.qdoc b/examples/wayland/pure-qml/doc/src/pure-qml.qdoc deleted file mode 100644 index 06a938bed..000000000 --- a/examples/wayland/pure-qml/doc/src/pure-qml.qdoc +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \title Qt Wayland Compositor Examples - Pure QML - \example pure-qml - \brief Pure QML is an example that demonstrates how to write a Wayland compositor in pure QML. - \ingroup qtwaylandcompositor-examples - - Pure QML is a small desktop-style Wayland compositor example that demonstrates the power and ease - of the Qt Wayland Compositor QML APIs. -*/ diff --git a/examples/wayland/pure-qml/main.cpp b/examples/wayland/pure-qml/main.cpp deleted file mode 100644 index 38ed5c939..000000000 --- a/examples/wayland/pure-qml/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -#include <QtCore/QUrl> -#include <QtCore/QDebug> - -#include <QtGui/QGuiApplication> - -#include <QtQml/QQmlApplicationEngine> - -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); - - QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); - - return app.exec(); -} diff --git a/examples/wayland/pure-qml/pure-qml.pro b/examples/wayland/pure-qml/pure-qml.pro deleted file mode 100644 index 20fc529ed..000000000 --- a/examples/wayland/pure-qml/pure-qml.pro +++ /dev/null @@ -1,18 +0,0 @@ -QT += gui qml - -SOURCES += \ - main.cpp - -OTHER_FILES = \ - qml/main.qml \ - qml/Screen.qml \ - qml/Chrome.qml \ - qml/Keyboard.qml \ - images/background.jpg \ - -RESOURCES += pure-qml.qrc - -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/pure-qml -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS pure-qml.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/pure-qml -INSTALLS += target sources diff --git a/examples/wayland/pure-qml/qml/Chrome.qml b/examples/wayland/pure-qml/qml/Chrome.qml deleted file mode 100644 index a63ee705c..000000000 --- a/examples/wayland/pure-qml/qml/Chrome.qml +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -import QtQuick 2.0 -import QtWayland.Compositor 1.0 - -ShellSurfaceItem { - id: chrome - - property bool isChild: parent.shellSurface !== undefined - - signal destroyAnimationFinished - - // If the client asks to show popups on this surface, automatically create child ShellSurfaceItems - autoCreatePopupItems: true - - onSurfaceDestroyed: { - bufferLocked = true; - destroyAnimation.start(); - } - - transform: [ - Scale { - id: scaleTransform - origin.x: chrome.width / 2 - origin.y: chrome.height / 2 - } - ] - - Connections { - target: shellSurface - - // some signals are not available on wl_shell, so let's ignore them - ignoreUnknownSignals: true - - onActivatedChanged: { // xdg_shell only - if (shellSurface.activated) { - receivedFocusAnimation.start(); - } - } - } - - SequentialAnimation { - id: destroyAnimation - - ParallelAnimation { - NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } - NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } - NumberAnimation { target: chrome; property: "opacity"; to: chrome.isChild ? 0 : 1; duration: 150 } - } - NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } - ScriptAction { script: destroyAnimationFinished() } - } - - SequentialAnimation { - id: receivedFocusAnimation - - ParallelAnimation { - NumberAnimation { target: scaleTransform; property: "yScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } - NumberAnimation { target: scaleTransform; property: "xScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } - } - ParallelAnimation { - NumberAnimation { target: scaleTransform; property: "yScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } - NumberAnimation { target: scaleTransform; property: "xScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } - } - } -} diff --git a/examples/wayland/pure-qml/qml/Keyboard.qml b/examples/wayland/pure-qml/qml/Keyboard.qml deleted file mode 100644 index b2586ffd4..000000000 --- a/examples/wayland/pure-qml/qml/Keyboard.qml +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com -** 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$ -** -****************************************************************************/ - -import QtQuick 2.5 -import QtQuick.VirtualKeyboard 2.1 - -InputPanel { - visible: active - y: active ? parent.height - height : parent.height - anchors.left: parent.left - anchors.right: parent.right -} - diff --git a/examples/wayland/pure-qml/qml/Screen.qml b/examples/wayland/pure-qml/qml/Screen.qml deleted file mode 100644 index b156cb434..000000000 --- a/examples/wayland/pure-qml/qml/Screen.qml +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -import QtQuick 2.5 -import QtQuick.Window 2.2 -import QtWayland.Compositor 1.0 - -WaylandOutput { - id: output - - property ListModel shellSurfaces: ListModel {} - property bool isNestedCompositor: Qt.platform.pluginName.startsWith("wayland") || Qt.platform.pluginName === "xcb" - - function handleShellSurface(shellSurface) { - shellSurfaces.append({shellSurface: shellSurface}); - } - - // During development, it can be useful to start the compositor inside X11 or - // another Wayland compositor. In such cases, set sizeFollowsWindow to true to - // enable resizing of the compositor window to be forwarded to the Wayland clients - // as the output (screen) changing resolution. Consider setting it to false if you - // are running the compositor using eglfs, linuxfb or similar QPA backends. - sizeFollowsWindow: output.isNestedCompositor - - window: Window { - width: 1024 - height: 760 - visible: true - - WaylandMouseTracker { - id: mouseTracker - - anchors.fill: parent - - // Set this to false to disable the outer mouse cursor when running nested - // compositors. Otherwise you would see two mouse cursors, one for each compositor. - windowSystemCursorEnabled: output.isNestedCompositor - - Image { - id: background - - anchors.fill: parent - fillMode: Image.Tile - source: "qrc:/images/background.jpg" - smooth: true - - Repeater { - model: output.shellSurfaces - // Chrome displays a shell surface on the screen (See Chrome.qml) - Chrome { - shellSurface: modelData - onDestroyAnimationFinished: output.shellSurfaces.remove(index) - } - } - } - - // Virtual Keyboard - Loader { - anchors.fill: parent - source: "Keyboard.qml" - } - - // Draws the mouse cursor for a given Wayland seat - WaylandCursorItem { - inputEventsEnabled: false - x: mouseTracker.mouseX - y: mouseTracker.mouseY - seat: output.compositor.defaultSeat - } - } - - Shortcut { - sequence: "Ctrl+Alt+Backspace" - onActivated: Qt.quit() - } - } -} diff --git a/examples/wayland/pure-qml/qml/main.qml b/examples/wayland/pure-qml/qml/main.qml deleted file mode 100644 index 483de7514..000000000 --- a/examples/wayland/pure-qml/qml/main.qml +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -import QtQuick 2.0 -import QtWayland.Compositor 1.3 - -WaylandCompositor { - id: waylandCompositor - - Screen { id: screen; compositor: waylandCompositor } - - // Shell surface extension. Needed to provide a window concept for Wayland clients. - // I.e. requests and events for maximization, minimization, resizing, closing etc. - XdgShell { - onToplevelCreated: screen.handleShellSurface(xdgSurface) - } - - // Unstable version of xdg-shell still used by some clients - XdgShellV6 { - onToplevelCreated: screen.handleShellSurface(xdgSurface) - } - - // Deprecated shell extension, still used by some clients - WlShell { - onWlShellSurfaceCreated: screen.handleShellSurface(shellSurface) - } - - // Extension for Input Method (QT_IM_MODULE) support at compositor-side - TextInputManager {} -} diff --git a/examples/wayland/qtshell/CMakeLists.txt b/examples/wayland/qtshell/CMakeLists.txt new file mode 100644 index 000000000..64db8a672 --- /dev/null +++ b/examples/wayland/qtshell/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.14) +project(qtshell LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(qtshell + main.cpp +) + +set_target_properties(qtshell PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(qtshell PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(qtshell_resource_files + "images/background.jpg" + "qml/Chrome.qml" + "qml/CompositorScreen.qml" + "qml/main.qml" +) + +qt6_add_resources(qtshell "qtshell" + PREFIX + "/" + FILES + ${qtshell_resource_files} +) diff --git a/examples/wayland/qtshell/doc/images/qtshell.jpg b/examples/wayland/qtshell/doc/images/qtshell.jpg Binary files differnew file mode 100644 index 000000000..53b9aa189 --- /dev/null +++ b/examples/wayland/qtshell/doc/images/qtshell.jpg diff --git a/examples/wayland/qtshell/doc/src/qtshell.qdoc b/examples/wayland/qtshell/doc/src/qtshell.qdoc new file mode 100644 index 000000000..2da1c1874 --- /dev/null +++ b/examples/wayland/qtshell/doc/src/qtshell.qdoc @@ -0,0 +1,150 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + * \title QtShell Compositor + * \example qtshell + * \examplecategory {Embedded} + * \brief QtShell Compositor shows how to use the QtShell shell extension. + * \ingroup qtwaylandcompositor-examples + * + * QtShell Compositor is a desktop-style Wayland compositor example implementing a + * complete Qt Wayland Compositor which uses the specialized + * \l{Shell Extensions - Qt Wayland Compositor}{shell extension protocol} called \l{QtShell}. + * + * \image qtshell.jpg + * + * The compositor is implemented with Qt Quick and QML. + * + * \section1 Making the Connection + * + * The example lists QtShell as the only extension to the WaylandCompositor object. This means that + * any client connecting to the server must also support this extension, thus they should be Qt + * applications running against the same version of Qt as the compositor. + * + * \snippet qtshell/qml/main.qml shell + * + * When a client connects to the QtShell interface, it creates a \l{QtShellSurface}. The compositor + * is notified of this by the emission of the + * \l [QML] {QtShell::}{qtShellSurfaceCreated} signal. The + * example then adds the shell surface to a ListModel for easy access later. + * + * \snippet qtshell/qml/CompositorScreen.qml handleShellSurface + * + * The ListModel is used as the model for a \l{Repeater} which creates the Qt Quick items required + * to display the client contents on screen. + * + * \snippet qtshell/qml/CompositorScreen.qml repeater + * + * It uses the local \c Chrome type, which handles window states and decorations. + * + * \section1 Chrome + * + * The \c Chrome is the type that ensures the client contents are visible and also handles window + * state, position, size, and so on. It uses the built-in QtShellChrome as a basis, which + * automatically handles window state (maximized, minimized, fullscreen) and window activation + * (ensuring that only a single window is active at the time). + * + * Its behavior can be customized to some extent, but it is also possible to write the \c Chrome + * functionality from scratch, building from a basic \l{Item} type instead. QtShellChrome is a + * convenience class which provides typical compositor behavior, and saves us the time of + * implementing this logic in the example. + * + * However the \c Chrome is written, it should have a ShellSurfaceItem to hold the client contents. + * + * \snippet qtshell/qml/Chrome.qml shellsurfaceitem + * + * The ShellSurfaceItem is the visual representation of the client's contents in the Qt Quick scene. + * Its size should usually match the size of the client's buffer, otherwise it may look stretched or + * squeezed. QtShellChrome will automatically be sized to the \l{QtShellSurface}'s + * \l{QtShellSurface::windowGeometry}{windowGeometry}, which is size of the + * client's buffer plus the size of the frame margins. The frame margins are reserved areas on the + * sides of the \c Chrome which can be used to contain window decorations. + * + * The ShellSurfaceItem is therefore anchored to the window decorations to fill the area reserved + * for the client buffer. + * + * \section1 Window Decorations + * + * The window decoration is usually a frame around a client's contents which adds information + * (such as a window title) and the possibility of user interaction (such as resizing, closing, + * moving the window, and so on.) + * + * With \l{QtShell}, window decorations are always drawn by the compositor and not by the client. + * In order for sizes and positions to be communicated correctly, QtShell also needs to know how + * much of the window is reserved for these decorations. This can be handled automatically by + * QtShellChrome, or manually, by setting + * \l{QtShellChrome::frameMarginLeft}{frameMarginLeft}, + * \l{QtShellChrome::frameMarginRight}{frameMarginRight}, + * \l{QtShellChrome::frameMarginTop}{frameMarginTop} and + * \l{QtShellChrome::frameMarginBottom}{frameMarginBottom}. + * + * For typical cases where there are resize handles around the window and a title bar at the top, + * it is more convenient to rely on the default frame margins. The QtShell Compositor example + * does this. + * + * First, we create Qt Quick items to represent the different parts of the window's decorations. + * On the left side, for example, there should be a resize handle that the user can grab and drag in + * order to resize the window. + * + * \snippet qtshell/qml/Chrome.qml leftResizeHandle + * + * We simply make this a five-pixel wide rectangle in the example, anchored to the top, bottom and + * left side of the \c Chrome. + * + * Similarly, we add Qt Quick items that represent the right, top, bottom, top-left, top-right, + * bottom-left and bottom-right resize handles. We also add a title bar. When the decorations have + * been created and anchored correctly to the sides of the \c{Chrome}, we set corresponding + * properties in QtShellChrome. + * + * \snippet qtshell/qml/Chrome.qml decorations + * + * When the decoration properties are set, the default resizing and repositioning behavior will be + * added automatically. The user will be able to interact with the resize handles in order to resize + * the window, and drag the title bar to reposition it. The frame margins of the QtShellSurface will + * also be set automatically to account for the size of the decorations (as long as none of the + * frame margins properties have been set explicitly.) + * + * The visibility of the decorations will be handled automatically by the QtShellChrome based on + * the window flags of the QtShellSurface. + * + * \section1 Window Management + * + * As part of the decorations, it is common to have tool buttons which manage the window state + * and life span. In the example, these are added to the title bar. + * + * \snippet qtshell/qml/Chrome.qml buttons + * + * The visibility of each button is conditional on the window flag for that button, and when each + * of them is clicked, we simply call the corresponding method in QtShellChrome. The exception is + * the "close" button, which calls the + * \l{QtWaylandCompositor::QtShellSurface::sendClose()}{sendClose()} method in QtShellSurface. + * This instructs the client to close itself, and ensures a graceful shutdown of the application. + * + * \snippet qtshell/qml/CompositorScreen.qml taskbar + * + * As an additional window management tool, the example has a "task bar". This is just a row of + * tool buttons at the bottom with the window titles. The buttons can be clicked to de-minimize + * applications and bring them to the front if they are obscured by other windows. Similarly + * to the \c{Chrome}, we use a \l{Repeater} for creating the tool buttons and use the shell surface + * list as model for this. For simplicity, the example does not have any handling of overflow (when + * there are too many applications for the task bar), but in a proper compositor, this is also + * something that should be considered. + * + * Finally, to avoid maximized applications expanding to fill the area covered by the task bar, we + * create a special item to manage the parts of the WaylandOutput real estate that is available to + * client windows. + * + * \snippet qtshell/qml/CompositorScreen.qml usableArea + * + * It is simply anchored to the sides of the WaylandOutput, but its bottom anchor is at the top + * of the task bar. + * + * In the \c{Chrome}, we use this area to define the \l{QtShellChrome::maximizedRect}{maximizedRect} + * of the window. + * + * \snippet qtshell/qml/Chrome.qml maximizedRect + * + * By default, this property will match the full WaylandOutput. In our case, however, we do not want + * to include the task bar in the available area, so we override the default. + */ diff --git a/examples/wayland/qtshell/images/background.jpg b/examples/wayland/qtshell/images/background.jpg Binary files differnew file mode 100644 index 000000000..445567fbd --- /dev/null +++ b/examples/wayland/qtshell/images/background.jpg diff --git a/examples/wayland/qtshell/main.cpp b/examples/wayland/qtshell/main.cpp new file mode 100644 index 000000000..2a7ba661e --- /dev/null +++ b/examples/wayland/qtshell/main.cpp @@ -0,0 +1,21 @@ +// 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> + +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); + + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); + + return app.exec(); +} diff --git a/examples/wayland/qtshell/qml/Chrome.qml b/examples/wayland/qtshell/qml/Chrome.qml new file mode 100644 index 000000000..a6456744c --- /dev/null +++ b/examples/wayland/qtshell/qml/Chrome.qml @@ -0,0 +1,184 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtWayland.Compositor +import QtWayland.Compositor.QtShell + +QtShellChrome { + id: chrome + + property alias shellSurface: shellSurfaceItemId.shellSurface + + //! [maximizedRect] + maximizedRect: Qt.rect(usableArea.x, + usableArea.y, + usableArea.width, + usableArea.height) + //! [maximizedRect] + + //! [leftResizeHandle] + Rectangle { + id: leftResizeHandle + color: "gray" + width: visible ? 5 : 0 + anchors.topMargin: 5 + anchors.bottomMargin: 5 + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + } + //! [leftResizeHandle] + + Rectangle { + id: rightResizeHandle + color: "gray" + width: visible ? 5 : 0 + anchors.topMargin: 5 + anchors.bottomMargin: 5 + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + } + + Rectangle { + id: topResizeHandle + color: "gray" + height: visible ? 5 : 0 + anchors.leftMargin: 5 + anchors.rightMargin: 5 + anchors.left: parent.left + anchors.top: parent.top + anchors.right: parent.right + } + + Rectangle { + id: bottomResizeHandle + color: "gray" + height: visible ? 5 : 0 + anchors.leftMargin: 5 + anchors.rightMargin: 5 + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.right: parent.right + } + + Rectangle { + id: titleBar + anchors.top: topResizeHandle.bottom + anchors.left: leftResizeHandle.right + anchors.right: rightResizeHandle.left + height: visible ? xButton.height + 10 : 0 + color: shellSurface.active ? "cornflowerblue" : "lightgray" + + Text { + anchors.left: parent.left + anchors.right: rowLayout.left + anchors.verticalCenter: parent.verticalCenter + + font.pixelSize: xButton.height + text: shellSurface.windowTitle + fontSizeMode: Text.Fit + } + + //! [buttons] + RowLayout { + id: rowLayout + anchors.right: parent.right + anchors.rightMargin: 5 + + ToolButton { + text: "-" + Layout.margins: 5 + visible: (chrome.windowFlags & Qt.WindowMinimizeButtonHint) != 0 + onClicked: { + chrome.toggleMinimized() + } + } + + ToolButton { + text: "+" + Layout.margins: 5 + visible: (chrome.windowFlags & Qt.WindowMaximizeButtonHint) != 0 + onClicked: { + chrome.toggleMaximized() + } + } + + ToolButton { + id: xButton + text: "X" + Layout.margins: 5 + visible: (chrome.windowFlags & Qt.WindowCloseButtonHint) != 0 + onClicked: shellSurface.sendClose() + } + } + //! [buttons] + } + + Rectangle { + id: topLeftResizeHandle + color: "gray" + height: 5 + width: 5 + anchors.left: parent.left + anchors.top: parent.top + } + + Rectangle { + id: topRightResizeHandle + color: "gray" + height: 5 + width: 5 + anchors.right: parent.right + anchors.top: parent.top + } + + Rectangle { + id: bottomLeftResizeHandle + color: "gray" + height: 5 + width: 5 + anchors.left: parent.left + anchors.bottom: parent.bottom + } + + Rectangle { + id: bottomRightResizeHandle + color: "gray" + height: 5 + width: 5 + anchors.right: parent.right + anchors.bottom: parent.bottom + } + + //! [decorations] + leftResizeHandle: leftResizeHandle + rightResizeHandle: rightResizeHandle + topResizeHandle: topResizeHandle + bottomResizeHandle: bottomResizeHandle + bottomLeftResizeHandle: bottomLeftResizeHandle + bottomRightResizeHandle: bottomRightResizeHandle + topLeftResizeHandle: topLeftResizeHandle + topRightResizeHandle: topRightResizeHandle + titleBar: titleBar + //! [decorations] + + //! [shellsurfaceitem] + ShellSurfaceItem { + id: shellSurfaceItemId + anchors.top: titleBar.bottom + anchors.bottom: bottomResizeHandle.top + anchors.left: leftResizeHandle.right + anchors.right: rightResizeHandle.left + + moveItem: chrome + + staysOnBottom: shellSurface.windowFlags & Qt.WindowStaysOnBottomHint + staysOnTop: !staysOnBottom && shellSurface.windowFlags & Qt.WindowStaysOnTopHint + } + shellSurfaceItem: shellSurfaceItemId + //! [shellsurfaceitem] +} diff --git a/examples/wayland/qtshell/qml/CompositorScreen.qml b/examples/wayland/qtshell/qml/CompositorScreen.qml new file mode 100644 index 000000000..c41d3258d --- /dev/null +++ b/examples/wayland/qtshell/qml/CompositorScreen.qml @@ -0,0 +1,108 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtWayland.Compositor + +WaylandOutput { + id: output + + property bool isNestedCompositor: Qt.platform.pluginName.startsWith("wayland") || Qt.platform.pluginName === "xcb" + + //! [handleShellSurface] + property ListModel shellSurfaces: ListModel {} + function handleShellSurface(shellSurface) { + shellSurfaces.append({shellSurface: shellSurface}); + } + //! [handleShellSurface] + + // During development, it can be useful to start the compositor inside X11 or + // another Wayland compositor. In such cases, set sizeFollowsWindow to true to + // enable resizing of the compositor window to be forwarded to the Wayland clients + // as the output (screen) changing resolution. Consider setting it to false if you + // are running the compositor using eglfs, linuxfb or similar QPA backends. + sizeFollowsWindow: output.isNestedCompositor + + window: Window { + width: 1920 + height: 1080 + visible: true + + WaylandMouseTracker { + id: mouseTracker + + anchors.fill: parent + + // Set this to false to disable the outer mouse cursor when running nested + // compositors. Otherwise you would see two mouse cursors, one for each compositor. + windowSystemCursorEnabled: output.isNestedCompositor + + Image { + id: background + + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.jpg" + smooth: true + + //! [repeater] + Repeater { + id: chromeRepeater + model: output.shellSurfaces + // Chrome displays a shell surface on the screen (See Chrome.qml) + Chrome { + shellSurface: modelData + onClientDestroyed: + { + output.shellSurfaces.remove(index) + } + } + } + //! [repeater] + } + + Rectangle { + anchors.fill: taskbar + color: "lavenderblush" + } + + //! [taskbar] + Row { + id: taskbar + height: 40 + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + Repeater { + anchors.fill: parent + model: output.shellSurfaces + + ToolButton { + anchors.verticalCenter: parent.verticalCenter + text: modelData.windowTitle + onClicked: { + var item = chromeRepeater.itemAt(index) + if ((item.windowState & Qt.WindowMinimized) != 0) + item.toggleMinimized() + chromeRepeater.itemAt(index).activate() + } + } + } + } + //! [taskbar] + + //! [usableArea] + Item { + id: usableArea + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: taskbar.top + } + //! [usableArea] + } + } +} diff --git a/examples/wayland/qtshell/qml/main.qml b/examples/wayland/qtshell/qml/main.qml new file mode 100644 index 000000000..7a4f505d5 --- /dev/null +++ b/examples/wayland/qtshell/qml/main.qml @@ -0,0 +1,21 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWayland.Compositor +import QtWayland.Compositor.QtShell + +WaylandCompositor { + id: waylandCompositor + + CompositorScreen { id: screen; compositor: waylandCompositor } + + // Shell surface extension. Needed to provide a window concept for Wayland clients. + // I.e. requests and events for maximization, minimization, resizing, closing etc. + + //! [shell] + QtShell { + onQtShellSurfaceCreated: (qtShellSurface) => screen.handleShellSurface(qtShellSurface) + } + //! [shell] +} diff --git a/examples/wayland/qtshell/qtshell.pro b/examples/wayland/qtshell/qtshell.pro new file mode 100644 index 000000000..c3f927b68 --- /dev/null +++ b/examples/wayland/qtshell/qtshell.pro @@ -0,0 +1,16 @@ +QT += gui qml quick quick-private + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + qml/main.qml \ + qml/CompositorScreen.qml \ + qml/Chrome.qml \ + images/background.jpg \ + +RESOURCES += qtshell.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/qtshell +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/qtshell +INSTALLS += target sources diff --git a/examples/wayland/qtshell/qtshell.qrc b/examples/wayland/qtshell/qtshell.qrc new file mode 100644 index 000000000..7523ebaf4 --- /dev/null +++ b/examples/wayland/qtshell/qtshell.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.jpg</file> + <file>qml/main.qml</file> + <file>qml/CompositorScreen.qml</file> + <file>qml/Chrome.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/qwindow-compositor/compositor.cpp b/examples/wayland/qwindow-compositor/compositor.cpp deleted file mode 100644 index 220ea3d74..000000000 --- a/examples/wayland/qwindow-compositor/compositor.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "compositor.h" - -#include <QMouseEvent> -#include <QKeyEvent> -#include <QTouchEvent> - -#include <QtWaylandCompositor/QWaylandXdgShellV5> -#include <QtWaylandCompositor/QWaylandWlShellSurface> -#include <QtWaylandCompositor/qwaylandseat.h> -#include <QtWaylandCompositor/qwaylanddrag.h> - -#include <QDebug> -#include <QOpenGLContext> - -#ifndef GL_TEXTURE_EXTERNAL_OES -#define GL_TEXTURE_EXTERNAL_OES 0x8D65 -#endif - -View::View(Compositor *compositor) - : m_compositor(compositor) -{} - -QOpenGLTexture *View::getTexture() -{ - bool newContent = advance(); - QWaylandBufferRef buf = currentBuffer(); - if (!buf.hasContent()) - m_texture = nullptr; - if (newContent) { - m_texture = buf.toOpenGLTexture(); - if (surface()) { - m_size = surface()->destinationSize(); - m_origin = buf.origin() == QWaylandSurface::OriginTopLeft - ? QOpenGLTextureBlitter::OriginTopLeft - : QOpenGLTextureBlitter::OriginBottomLeft; - } - } - - return m_texture; -} - -QOpenGLTextureBlitter::Origin View::textureOrigin() const -{ - return m_origin; -} - -QSize View::size() const -{ - return surface() ? surface()->destinationSize() : m_size; -} - -bool View::isCursor() const -{ - return surface() && surface()->isCursorSurface(); -} - - -void View::onXdgSetMaximized() -{ - m_xdgSurface->sendMaximized(output()->geometry().size()); - - // An improvement here, would have been to wait for the commit after the ack_configure for the - // request above before moving the window. This would have prevented the window from being - // moved until the contents of the window had actually updated. This improvement is left as an - // exercise for the reader. - setPosition(QPoint(0, 0)); -} - -void View::onXdgUnsetMaximized() -{ - m_xdgSurface->sendUnmaximized(); -} - -void View::onXdgSetFullscreen(QWaylandOutput* clientPreferredOutput) -{ - QWaylandOutput *outputToFullscreen = clientPreferredOutput - ? clientPreferredOutput - : output(); - - m_xdgSurface->sendFullscreen(outputToFullscreen->geometry().size()); - - // An improvement here, would have been to wait for the commit after the ack_configure for the - // request above before moving the window. This would have prevented the window from being - // moved until the contents of the window had actually updated. This improvement is left as an - // exercise for the reader. - setPosition(outputToFullscreen->position()); -} - -void View::onOffsetForNextFrame(const QPoint &offset) -{ - m_offset = offset; - setPosition(position() + offset); -} - - -void View::timerEvent(QTimerEvent *event) -{ - if (event->timerId() != m_animationTimer.timerId()) - return; - - m_compositor->triggerRender(); - - if (m_animationCountUp) { - m_animationFactor += .08; - if (m_animationFactor > 1.0) { - m_animationFactor = 1.0; - m_animationTimer.stop(); - emit animationDone(); - } - } else { - m_animationFactor -= .08; - if (m_animationFactor < 0.01) { - m_animationFactor = 0.01; - m_animationTimer.stop(); - emit animationDone(); - } - } -} - -void View::startAnimation(bool countUp) -{ - m_animationCountUp = countUp; - m_animationFactor = countUp ? .1 : 1.0; - m_animationTimer.start(20, this); -} - -void View::cancelAnimation() -{ - m_animationFactor = 1.0; - m_animationTimer.stop(); -} - -void View::onXdgUnsetFullscreen() -{ - onXdgUnsetMaximized(); -} - -Compositor::Compositor(QWindow *window) - : m_window(window) - , m_wlShell(new QWaylandWlShell(this)) - , m_xdgShell(new QWaylandXdgShellV5(this)) -{ - connect(m_wlShell, &QWaylandWlShell::wlShellSurfaceCreated, this, &Compositor::onWlShellSurfaceCreated); - connect(m_xdgShell, &QWaylandXdgShellV5::xdgSurfaceCreated, this, &Compositor::onXdgSurfaceCreated); - connect(m_xdgShell, &QWaylandXdgShellV5::xdgPopupRequested, this, &Compositor::onXdgPopupRequested); -} - -Compositor::~Compositor() -{ -} - -void Compositor::create() -{ - QWaylandOutput *output = new QWaylandOutput(this, m_window); - QWaylandOutputMode mode(QSize(800, 600), 60000); - output->addMode(mode, true); - QWaylandCompositor::create(); - output->setCurrentMode(mode); - - connect(this, &QWaylandCompositor::surfaceCreated, this, &Compositor::onSurfaceCreated); - connect(defaultSeat(), &QWaylandSeat::cursorSurfaceRequest, this, &Compositor::adjustCursorSurface); - connect(defaultSeat()->drag(), &QWaylandDrag::dragStarted, this, &Compositor::startDrag); - - connect(this, &QWaylandCompositor::subsurfaceChanged, this, &Compositor::onSubsurfaceChanged); -} - -void Compositor::onSurfaceCreated(QWaylandSurface *surface) -{ - connect(surface, &QWaylandSurface::surfaceDestroyed, this, &Compositor::surfaceDestroyed); - connect(surface, &QWaylandSurface::hasContentChanged, this, &Compositor::surfaceHasContentChanged); - connect(surface, &QWaylandSurface::redraw, this, &Compositor::triggerRender); - - connect(surface, &QWaylandSurface::subsurfacePositionChanged, this, &Compositor::onSubsurfacePositionChanged); - View *view = new View(this); - view->setSurface(surface); - view->setOutput(outputFor(m_window)); - m_views << view; - connect(view, &QWaylandView::surfaceDestroyed, this, &Compositor::viewSurfaceDestroyed); - connect(surface, &QWaylandSurface::offsetForNextFrame, view, &View::onOffsetForNextFrame); -} - -void Compositor::surfaceHasContentChanged() -{ - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - if (surface->hasContent()) { - if (surface->role() == QWaylandWlShellSurface::role() - || surface->role() == QWaylandXdgSurfaceV5::role() - || surface->role() == QWaylandXdgPopupV5::role()) { - defaultSeat()->setKeyboardFocus(surface); - } - } - triggerRender(); -} - -void Compositor::surfaceDestroyed() -{ - triggerRender(); -} - -void Compositor::viewSurfaceDestroyed() -{ - View *view = qobject_cast<View*>(sender()); - view->setBufferLocked(true); - view->startAnimation(false); - connect(view, &View::animationDone, this, &Compositor::viewAnimationDone); -} - - -void Compositor::viewAnimationDone() -{ - View *view = qobject_cast<View*>(sender()); - m_views.removeAll(view); - delete view; -} - - -View * Compositor::findView(const QWaylandSurface *s) const -{ - for (View* view : m_views) { - if (view->surface() == s) - return view; - } - return nullptr; -} - -void Compositor::onWlShellSurfaceCreated(QWaylandWlShellSurface *wlShellSurface) -{ - connect(wlShellSurface, &QWaylandWlShellSurface::startMove, this, &Compositor::onStartMove); - connect(wlShellSurface, &QWaylandWlShellSurface::startResize, this, &Compositor::onWlStartResize); - connect(wlShellSurface, &QWaylandWlShellSurface::setTransient, this, &Compositor::onSetTransient); - connect(wlShellSurface, &QWaylandWlShellSurface::setPopup, this, &Compositor::onSetPopup); - - View *view = findView(wlShellSurface->surface()); - Q_ASSERT(view); - view->m_wlShellSurface = wlShellSurface; - view->startAnimation(true); -} - -void Compositor::onXdgSurfaceCreated(QWaylandXdgSurfaceV5 *xdgSurface) -{ - connect(xdgSurface, &QWaylandXdgSurfaceV5::startMove, this, &Compositor::onStartMove); - connect(xdgSurface, &QWaylandXdgSurfaceV5::startResize, this, &Compositor::onXdgStartResize); - - View *view = findView(xdgSurface->surface()); - Q_ASSERT(view); - view->m_xdgSurface = xdgSurface; - - connect(xdgSurface, &QWaylandXdgSurfaceV5::setMaximized, view, &View::onXdgSetMaximized); - connect(xdgSurface, &QWaylandXdgSurfaceV5::setFullscreen, view, &View::onXdgSetFullscreen); - connect(xdgSurface, &QWaylandXdgSurfaceV5::unsetMaximized, view, &View::onXdgUnsetMaximized); - connect(xdgSurface, &QWaylandXdgSurfaceV5::unsetFullscreen, view, &View::onXdgUnsetFullscreen); - view->startAnimation(true); -} - -void Compositor::onXdgPopupRequested(QWaylandSurface *surface, QWaylandSurface *parent, - QWaylandSeat *seat, const QPoint &position, - const QWaylandResource &resource) -{ - Q_UNUSED(seat); - - QWaylandXdgPopupV5 *xdgPopup = new QWaylandXdgPopupV5(m_xdgShell, surface, parent, position, resource); - - View *view = findView(surface); - Q_ASSERT(view); - - View *parentView = findView(parent); - Q_ASSERT(parentView); - - view->setPosition(parentView->position() + position); - view->m_xdgPopup = xdgPopup; -} - -void Compositor::onStartMove() -{ - closePopups(); - emit startMove(); -} - -void Compositor::onWlStartResize(QWaylandSeat *, QWaylandWlShellSurface::ResizeEdge edges) -{ - closePopups(); - emit startResize(int(edges), false); -} - -void Compositor::onXdgStartResize(QWaylandSeat *seat, - QWaylandXdgSurfaceV5::ResizeEdge edges) -{ - Q_UNUSED(seat); - emit startResize(int(edges), true); -} - -void Compositor::onSetTransient(QWaylandSurface *parent, const QPoint &relativeToParent, bool inactive) -{ - Q_UNUSED(inactive); - - QWaylandWlShellSurface *wlShellSurface = qobject_cast<QWaylandWlShellSurface*>(sender()); - View *view = findView(wlShellSurface->surface()); - - if (view) { - raise(view); - View *parentView = findView(parent); - if (parentView) - view->setPosition(parentView->position() + relativeToParent); - } -} - -void Compositor::onSetPopup(QWaylandSeat *seat, QWaylandSurface *parent, const QPoint &relativeToParent) -{ - Q_UNUSED(seat); - QWaylandWlShellSurface *surface = qobject_cast<QWaylandWlShellSurface*>(sender()); - View *view = findView(surface->surface()); - if (view) { - raise(view); - View *parentView = findView(parent); - if (parentView) - view->setPosition(parentView->position() + relativeToParent); - view->cancelAnimation(); - } -} - -void Compositor::onSubsurfaceChanged(QWaylandSurface *child, QWaylandSurface *parent) -{ - View *view = findView(child); - View *parentView = findView(parent); - view->setParentView(parentView); -} - -void Compositor::onSubsurfacePositionChanged(const QPoint &position) -{ - QWaylandSurface *surface = qobject_cast<QWaylandSurface*>(sender()); - if (!surface) - return; - View *view = findView(surface); - view->setPosition(position); - triggerRender(); -} - -void Compositor::triggerRender() -{ - m_window->requestUpdate(); -} - -void Compositor::startRender() -{ - QWaylandOutput *out = defaultOutput(); - if (out) - out->frameStarted(); -} - -void Compositor::endRender() -{ - QWaylandOutput *out = defaultOutput(); - if (out) - out->sendFrameCallbacks(); -} - -void Compositor::updateCursor() -{ - m_cursorView.advance(); - QImage image = m_cursorView.currentBuffer().image(); - if (!image.isNull()) - m_window->setCursor(QCursor(QPixmap::fromImage(image), m_cursorHotspotX, m_cursorHotspotY)); -} - -void Compositor::adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY) -{ - if ((m_cursorView.surface() != surface)) { - if (m_cursorView.surface()) - disconnect(m_cursorView.surface(), &QWaylandSurface::redraw, this, &Compositor::updateCursor); - if (surface) - connect(surface, &QWaylandSurface::redraw, this, &Compositor::updateCursor); - } - - m_cursorView.setSurface(surface); - m_cursorHotspotX = hotspotX; - m_cursorHotspotY = hotspotY; - - if (surface && surface->hasContent()) - updateCursor(); -} - -void Compositor::closePopups() -{ - m_wlShell->closeAllPopups(); - m_xdgShell->closeAllPopups(); -} - -void Compositor::handleMouseEvent(QWaylandView *target, QMouseEvent *me) -{ - auto popClient = popupClient(); - if (target && me->type() == QEvent::MouseButtonPress - && popClient && popClient != target->surface()->client()) { - closePopups(); - } - - QWaylandSeat *seat = defaultSeat(); - QWaylandSurface *surface = target ? target->surface() : nullptr; - switch (me->type()) { - case QEvent::MouseButtonPress: - seat->sendMousePressEvent(me->button()); - if (surface != seat->keyboardFocus()) { - if (surface == nullptr - || surface->role() == QWaylandWlShellSurface::role() - || surface->role() == QWaylandXdgSurfaceV5::role() - || surface->role() == QWaylandXdgPopupV5::role()) { - seat->setKeyboardFocus(surface); - } - } - break; - case QEvent::MouseButtonRelease: - seat->sendMouseReleaseEvent(me->button()); - break; - case QEvent::MouseMove: - seat->sendMouseMoveEvent(target, me->localPos(), me->globalPos()); - default: - break; - } -} - -void Compositor::handleResize(View *target, const QSize &initialSize, const QPoint &delta, int edge) -{ - QWaylandWlShellSurface *wlShellSurface = target->m_wlShellSurface; - if (wlShellSurface) { - QWaylandWlShellSurface::ResizeEdge edges = QWaylandWlShellSurface::ResizeEdge(edge); - QSize newSize = wlShellSurface->sizeForResize(initialSize, delta, edges); - wlShellSurface->sendConfigure(newSize, edges); - } - - QWaylandXdgSurfaceV5 *xdgSurface = target->m_xdgSurface; - if (xdgSurface) { - QWaylandXdgSurfaceV5::ResizeEdge edges = static_cast<QWaylandXdgSurfaceV5::ResizeEdge>(edge); - QSize newSize = xdgSurface->sizeForResize(initialSize, delta, edges); - xdgSurface->sendResizing(newSize); - } -} - -void Compositor::startDrag() -{ - QWaylandDrag *currentDrag = defaultSeat()->drag(); - Q_ASSERT(currentDrag); - View *iconView = findView(currentDrag->icon()); - iconView->setPosition(m_window->mapFromGlobal(QCursor::pos())); - - emit dragStarted(iconView); -} - -void Compositor::handleDrag(View *target, QMouseEvent *me) -{ - QPointF pos = me->localPos(); - QWaylandSurface *surface = nullptr; - if (target) { - pos -= target->position(); - surface = target->surface(); - } - QWaylandDrag *currentDrag = defaultSeat()->drag(); - currentDrag->dragMove(surface, pos); - if (me->buttons() == Qt::NoButton) { - m_views.removeOne(findView(currentDrag->icon())); - currentDrag->drop(); - } -} - -QWaylandClient *Compositor::popupClient() const -{ - auto client = m_wlShell->popupClient(); - return client ? client : m_xdgShell->popupClient(); -} - -// We only have a flat list of views, plus pointers from child to parent, -// so maintaining a stacking order gets a bit complex. A better data -// structure is left as an exercise for the reader. - -static int findEndOfChildTree(const QList<View*> &list, int index) -{ - int n = list.count(); - View *parent = list.at(index); - while (index + 1 < n) { - if (list.at(index+1)->parentView() != parent) - break; - index = findEndOfChildTree(list, index + 1); - } - return index; -} - -void Compositor::raise(View *view) -{ - int startPos = m_views.indexOf(view); - int endPos = findEndOfChildTree(m_views, startPos); - - int n = m_views.count(); - int tail = n - endPos - 1; - - //bubble sort: move the child tree to the end of the list - for (int i = 0; i < tail; i++) { - int source = endPos + 1 + i; - int dest = startPos + i; - for (int j = source; j > dest; j--) - m_views.swapItemsAt(j, j-1); - } -} diff --git a/examples/wayland/qwindow-compositor/compositor.h b/examples/wayland/qwindow-compositor/compositor.h deleted file mode 100644 index 8f18dc53d..000000000 --- a/examples/wayland/qwindow-compositor/compositor.h +++ /dev/null @@ -1,195 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef WINDOWCOMPOSITOR_H -#define WINDOWCOMPOSITOR_H - -#include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandSurface> -#include <QtWaylandCompositor/QWaylandView> -#include <QtWaylandCompositor/QWaylandWlShellSurface> -#include <QtWaylandCompositor/QWaylandXdgSurfaceV5> -#include <QTimer> -#include <QOpenGLTextureBlitter> - -QT_BEGIN_NAMESPACE - -class QWaylandWlShell; -class QWaylandWlShellSurface; -class QWaylandXdgShellV5; -class QOpenGLTexture; -class Compositor; - -class View : public QWaylandView -{ - Q_OBJECT -public: - View(Compositor *compositor); - QOpenGLTexture *getTexture(); - QOpenGLTextureBlitter::Origin textureOrigin() const; - QPointF position() const { return m_position; } - void setPosition(const QPointF &pos) { m_position = pos; } - QSize size() const; - bool isCursor() const; - bool hasShell() const { return m_wlShellSurface; } - void setParentView(View *parent) { m_parentView = parent; } - View *parentView() const { return m_parentView; } - QPointF parentPosition() const { return m_parentView ? (m_parentView->position() + m_parentView->parentPosition()) : QPointF(); } - QSize windowSize() { return m_xdgSurface ? m_xdgSurface->windowGeometry().size() : surface() ? surface()->destinationSize() : m_size; } - QPoint offset() const { return m_offset; } - - qreal animationFactor() const {return m_animationFactor; } - void setAnimationFactor(qreal f) {m_animationFactor = f; } - -signals: - void animationDone(); - -protected: - void timerEvent(QTimerEvent *event) override; - -private: - friend class Compositor; - Compositor *m_compositor = nullptr; - GLenum m_textureTarget = GL_TEXTURE_2D; - QOpenGLTexture *m_texture = nullptr; - QOpenGLTextureBlitter::Origin m_origin; - QPointF m_position; - QSize m_size; - QWaylandWlShellSurface *m_wlShellSurface = nullptr; - QWaylandXdgSurfaceV5 *m_xdgSurface = nullptr; - QWaylandXdgPopupV5 *m_xdgPopup = nullptr; - View *m_parentView = nullptr; - QPoint m_offset; - qreal m_animationFactor = 1.0; - QBasicTimer m_animationTimer; - bool m_animationCountUp; - -public slots: - void onXdgSetMaximized(); - void onXdgUnsetMaximized(); - void onXdgSetFullscreen(QWaylandOutput *output); - void onXdgUnsetFullscreen(); - void onOffsetForNextFrame(const QPoint &offset); - - void startAnimation(bool countUp); - void cancelAnimation(); -}; - -class Compositor : public QWaylandCompositor -{ - Q_OBJECT -public: - Compositor(QWindow *window); - ~Compositor() override; - void create() override; - - void startRender(); - void endRender(); - - QList<View*> views() const { return m_views; } - void raise(View *view); - - void handleMouseEvent(QWaylandView *target, QMouseEvent *me); - void handleResize(View *target, const QSize &initialSize, const QPoint &delta, int edge); - void handleDrag(View *target, QMouseEvent *me); - - QWaylandClient *popupClient() const; - void closePopups(); -protected: - void adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY); - -signals: - void startMove(); - void startResize(int edge, bool anchored); - void dragStarted(View *dragIcon); - void frameOffset(const QPoint &offset); - -public slots: - void triggerRender(); - -private slots: - void surfaceHasContentChanged(); - void surfaceDestroyed(); - void viewSurfaceDestroyed(); - void onStartMove(); - void onWlStartResize(QWaylandSeat *seat, QWaylandWlShellSurface::ResizeEdge edges); - void onXdgStartResize(QWaylandSeat *seat, QWaylandXdgSurfaceV5::ResizeEdge edges); - - void startDrag(); - - - void onSurfaceCreated(QWaylandSurface *surface); - void onWlShellSurfaceCreated(QWaylandWlShellSurface *wlShellSurface); - void onXdgSurfaceCreated(QWaylandXdgSurfaceV5 *xdgSurface); - void onXdgPopupRequested(QWaylandSurface *surface, QWaylandSurface *parent, QWaylandSeat *seat, - const QPoint &position, const QWaylandResource &resource); - void onSetTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, bool inactive); - void onSetPopup(QWaylandSeat *seat, QWaylandSurface *parent, const QPoint &relativeToParent); - - void onSubsurfaceChanged(QWaylandSurface *child, QWaylandSurface *parent); - void onSubsurfacePositionChanged(const QPoint &position); - - void updateCursor(); - void viewAnimationDone(); -private: - View *findView(const QWaylandSurface *s) const; - QWindow *m_window = nullptr; - QList<View*> m_views; - QWaylandWlShell *m_wlShell = nullptr; - QWaylandXdgShellV5 *m_xdgShell = nullptr; - QWaylandView m_cursorView; - int m_cursorHotspotX; - int m_cursorHotspotY; -}; - - -QT_END_NAMESPACE - -#endif // WINDOWCOMPOSITOR_H diff --git a/examples/wayland/qwindow-compositor/doc/src/qwindow-compositor.qdoc b/examples/wayland/qwindow-compositor/doc/src/qwindow-compositor.qdoc deleted file mode 100644 index c4f408c5a..000000000 --- a/examples/wayland/qwindow-compositor/doc/src/qwindow-compositor.qdoc +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \title Qt Wayland Compositor Examples - QWindow Compositor - \example qwindow-compositor - \brief QWindow Compositor is an example that demonstrates how to write a Wayland compositor in C++. - \ingroup qtwaylandcompositor-examples - - QWindow Compositor is a desktop-style Wayland compositor example that demonstrates the power - of the Qt Wayland Compositor C++ APIs. -*/ diff --git a/examples/wayland/qwindow-compositor/main.cpp b/examples/wayland/qwindow-compositor/main.cpp deleted file mode 100644 index 9d8c1f78f..000000000 --- a/examples/wayland/qwindow-compositor/main.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include <QGuiApplication> -#include "window.h" -#include "compositor.h" - -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - - Window window; - Compositor compositor(&window); - window.setCompositor(&compositor); - window.resize(800,600); - window.show(); - - return app.exec(); -} diff --git a/examples/wayland/qwindow-compositor/qwindow-compositor.pro b/examples/wayland/qwindow-compositor/qwindow-compositor.pro deleted file mode 100644 index b9261e772..000000000 --- a/examples/wayland/qwindow-compositor/qwindow-compositor.pro +++ /dev/null @@ -1,20 +0,0 @@ -QT += gui waylandcompositor - -LIBS += -L ../../lib - -HEADERS += \ - window.h \ - compositor.h - -SOURCES += main.cpp \ - window.cpp \ - compositor.cpp - -# to make QtWaylandCompositor/... style includes working without installing -INCLUDEPATH += $$PWD/../../include - - -RESOURCES += qwindow-compositor.qrc - -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/qwindow-compositor -INSTALLS += target diff --git a/examples/wayland/qwindow-compositor/qwindow-compositor.qrc b/examples/wayland/qwindow-compositor/qwindow-compositor.qrc deleted file mode 100644 index 688dd900e..000000000 --- a/examples/wayland/qwindow-compositor/qwindow-compositor.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file alias="background.jpg">../pure-qml/images/background.jpg</file> - </qresource> -</RCC> diff --git a/examples/wayland/qwindow-compositor/window.cpp b/examples/wayland/qwindow-compositor/window.cpp deleted file mode 100644 index c439d20a8..000000000 --- a/examples/wayland/qwindow-compositor/window.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "window.h" - -#include <QMouseEvent> -#include <QOpenGLWindow> -#include <QOpenGLTexture> -#include <QOpenGLFunctions> -#include <QMatrix4x4> - -#include "compositor.h" -#include <QtWaylandCompositor/qwaylandseat.h> - -Window::Window() -{ -} - -void Window::setCompositor(Compositor *comp) { - m_compositor = comp; - connect(m_compositor, &Compositor::startMove, this, &Window::startMove); - connect(m_compositor, &Compositor::startResize, this, &Window::startResize); - connect(m_compositor, &Compositor::dragStarted, this, &Window::startDrag); -} - -void Window::initializeGL() -{ - QImage backgroundImage = QImage(QLatin1String(":/background.jpg")).rgbSwapped(); - backgroundImage.invertPixels(); - m_backgroundTexture = new QOpenGLTexture(backgroundImage, QOpenGLTexture::DontGenerateMipMaps); - m_backgroundTexture->setMinificationFilter(QOpenGLTexture::Nearest); - m_backgroundImageSize = backgroundImage.size(); - m_textureBlitter.create(); - m_compositor->create(); // the compositor's hardware integration may depend on GL -} - -void Window::drawBackground() -{ - for (int y = 0; y < height(); y += m_backgroundImageSize.height()) { - for (int x = 0; x < width(); x += m_backgroundImageSize.width()) { - QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(x,y), m_backgroundImageSize), QRect(QPoint(0,0), size())); - m_textureBlitter.blit(m_backgroundTexture->textureId(), - targetTransform, - QOpenGLTextureBlitter::OriginTopLeft); - } - } -} - -QPointF Window::getAnchorPosition(const QPointF &position, int resizeEdge, const QSize &windowSize) -{ - float y = position.y(); - if (resizeEdge & QWaylandXdgSurfaceV5::ResizeEdge::TopEdge) - y += windowSize.height(); - - float x = position.x(); - if (resizeEdge & QWaylandXdgSurfaceV5::ResizeEdge::LeftEdge) - x += windowSize.width(); - - return QPointF(x, y); -} - -QPointF Window::getAnchoredPosition(const QPointF &anchorPosition, int resizeEdge, const QSize &windowSize) -{ - return anchorPosition - getAnchorPosition(QPointF(), resizeEdge, windowSize); -} - -void Window::paintGL() -{ - m_compositor->startRender(); - QOpenGLFunctions *functions = context()->functions(); - functions->glClearColor(1.f, .6f, .0f, 0.5f); - functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - m_textureBlitter.bind(); - drawBackground(); - - functions->glEnable(GL_BLEND); - functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - GLenum currentTarget = GL_TEXTURE_2D; - const auto views = m_compositor->views(); - for (View *view : views) { - if (view->isCursor()) - continue; - auto texture = view->getTexture(); - if (!texture) - continue; - if (texture->target() != currentTarget) { - currentTarget = texture->target(); - m_textureBlitter.bind(currentTarget); - } - QWaylandSurface *surface = view->surface(); - if ((surface && surface->hasContent()) || view->isBufferLocked()) { - QSize s = view->size(); - if (!s.isEmpty()) { - if (m_mouseView == view && m_grabState == ResizeGrab && m_resizeAnchored) - view->setPosition(getAnchoredPosition(m_resizeAnchorPosition, m_resizeEdge, s)); - QPointF pos = view->position() + view->parentPosition(); - QRectF surfaceGeometry(pos, s); - auto surfaceOrigin = view->textureOrigin(); - auto sf = view->animationFactor(); - QRectF targetRect(surfaceGeometry.topLeft() * sf, surfaceGeometry.size() * sf); - QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(), size())); - m_textureBlitter.blit(texture->textureId(), targetTransform, surfaceOrigin); - } - } - } - functions->glDisable(GL_BLEND); - - m_textureBlitter.release(); - m_compositor->endRender(); -} - -View *Window::viewAt(const QPointF &point) -{ - View *ret = nullptr; - const auto views = m_compositor->views(); - for (View *view : views) { - if (view == m_dragIconView) - continue; - QRectF geom(view->position(), view->size()); - if (geom.contains(point)) - ret = view; - } - return ret; -} - -void Window::startMove() -{ - m_grabState = MoveGrab; -} - -void Window::startResize(int edge, bool anchored) -{ - m_initialSize = m_mouseView->windowSize(); - m_grabState = ResizeGrab; - m_resizeEdge = edge; - m_resizeAnchored = anchored; - m_resizeAnchorPosition = getAnchorPosition(m_mouseView->position(), edge, m_mouseView->surface()->destinationSize()); -} - -void Window::startDrag(View *dragIcon) -{ - m_grabState = DragGrab; - m_dragIconView = dragIcon; - m_compositor->raise(dragIcon); -} - -void Window::mousePressEvent(QMouseEvent *e) -{ - if (mouseGrab()) - return; - if (m_mouseView.isNull()) { - m_mouseView = viewAt(e->localPos()); - if (!m_mouseView) { - m_compositor->closePopups(); - return; - } - if (e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::MetaModifier) - m_grabState = MoveGrab; //start move - else - m_compositor->raise(m_mouseView); - m_initialMousePos = e->localPos(); - m_mouseOffset = e->localPos() - m_mouseView->position(); - - QMouseEvent moveEvent(QEvent::MouseMove, e->localPos(), e->globalPos(), Qt::NoButton, Qt::NoButton, e->modifiers()); - sendMouseEvent(&moveEvent, m_mouseView); - } - sendMouseEvent(e, m_mouseView); -} - -void Window::mouseReleaseEvent(QMouseEvent *e) -{ - if (!mouseGrab()) - sendMouseEvent(e, m_mouseView); - if (e->buttons() == Qt::NoButton) { - if (m_grabState == DragGrab) { - View *view = viewAt(e->localPos()); - m_compositor->handleDrag(view, e); - } - m_mouseView = nullptr; - m_grabState = NoGrab; - } -} - -void Window::mouseMoveEvent(QMouseEvent *e) -{ - switch (m_grabState) { - case NoGrab: { - View *view = m_mouseView ? m_mouseView.data() : viewAt(e->localPos()); - sendMouseEvent(e, view); - if (!view) - setCursor(Qt::ArrowCursor); - } - break; - case MoveGrab: { - m_mouseView->setPosition(e->localPos() - m_mouseOffset); - update(); - } - break; - case ResizeGrab: { - QPoint delta = (e->localPos() - m_initialMousePos).toPoint(); - m_compositor->handleResize(m_mouseView, m_initialSize, delta, m_resizeEdge); - } - break; - case DragGrab: { - View *view = viewAt(e->localPos()); - m_compositor->handleDrag(view, e); - if (m_dragIconView) { - m_dragIconView->setPosition(e->localPos() + m_dragIconView->offset()); - update(); - } - } - break; - } -} - -void Window::sendMouseEvent(QMouseEvent *e, View *target) -{ - QPointF mappedPos = e->localPos(); - if (target) - mappedPos -= target->position(); - QMouseEvent viewEvent(e->type(), mappedPos, e->localPos(), e->button(), e->buttons(), e->modifiers()); - m_compositor->handleMouseEvent(target, &viewEvent); -} - -void Window::keyPressEvent(QKeyEvent *e) -{ - m_compositor->defaultSeat()->sendKeyPressEvent(e->nativeScanCode()); -} - -void Window::keyReleaseEvent(QKeyEvent *e) -{ - m_compositor->defaultSeat()->sendKeyReleaseEvent(e->nativeScanCode()); -} diff --git a/examples/wayland/qwindow-compositor/window.h b/examples/wayland/qwindow-compositor/window.h deleted file mode 100644 index c16e726bf..000000000 --- a/examples/wayland/qwindow-compositor/window.h +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef COMPOSITORWINDOW_H -#define COMPOSITORWINDOW_H - -#include <QOpenGLWindow> -#include <QPointer> -#include <QOpenGLTextureBlitter> - -QT_BEGIN_NAMESPACE - -class Compositor; -class View; -class QOpenGLTexture; - -class Window : public QOpenGLWindow -{ -public: - Window(); - - void setCompositor(Compositor *comp); - -protected: - void initializeGL() override; - void paintGL() override; - - void mousePressEvent(QMouseEvent *e) override; - void mouseReleaseEvent(QMouseEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - - void keyPressEvent(QKeyEvent *e) override; - void keyReleaseEvent(QKeyEvent *e) override; - -private slots: - void startMove(); - void startResize(int edge, bool anchored); - void startDrag(View *dragIcon); - -private: - enum GrabState { NoGrab, MoveGrab, ResizeGrab, DragGrab }; - - View *viewAt(const QPointF &point); - bool mouseGrab() const { return m_grabState != NoGrab ;} - void drawBackground(); - void sendMouseEvent(QMouseEvent *e, View *target); - static QPointF getAnchoredPosition(const QPointF &anchorPosition, int resizeEdge, const QSize &windowSize); - static QPointF getAnchorPosition(const QPointF &position, int resizeEdge, const QSize &windowSize); - - QOpenGLTextureBlitter m_textureBlitter; - QSize m_backgroundImageSize; - QOpenGLTexture *m_backgroundTexture = nullptr; - Compositor *m_compositor = nullptr; - QPointer<View> m_mouseView; - GrabState m_grabState = NoGrab; - QSize m_initialSize; - int m_resizeEdge; - bool m_resizeAnchored; - QPointF m_resizeAnchorPosition; - QPointF m_mouseOffset; - QPointF m_initialMousePos; - View *m_dragIconView = nullptr; -}; - -QT_END_NAMESPACE - -#endif // COMPOSITORWINDOW_H diff --git a/examples/wayland/server-buffer/README b/examples/wayland/server-buffer/README deleted file mode 100644 index da20b0f50..000000000 --- a/examples/wayland/server-buffer/README +++ /dev/null @@ -1,32 +0,0 @@ -This example shows how to use the low-level server buffer extension. This -version of Qt also provides a texture sharing extension that provides more -functionality and convenience for sharing graphical assets with Qt Quick -clients: see the texture-sharing example. - -Compile up both compositor and client. - -If you have the dmabuf-server buffer integration (and you are running Mesa) -then start the compositor with: - -$ QT_WAYLAND_SERVER_BUFFER_INTEGRATION=dmabuf-server ./compositor - - -Note: if you are running a compositor on an X11 desktop, you also need to -set QT_XCB_GL_INTEGRATION=xcb_egl as usual. - -The compositor broadcasts the name of the server buffer integration to -all clients through the hardware integration extension. Therefore, -all you need to do is to start the client with - -$ ./cpp-client -platform wayland - -The client will show all the buffers shared by the compositor. - -For testing on desktop, there is also a shared memory based server buffer -integration that works with any graphics hardware: - -$ QT_WAYLAND_SERVER_BUFFER_INTEGRATION=shm-emulation-server QT_XCB_GL_INTEGRATION=xcb_egl ./compositor - -Note: the shm-emulation-server integration does not actually share graphics -buffers, so it will not give any graphics memory savings. It is intended solely -for testing during development and should never be used in production. diff --git a/examples/wayland/server-buffer/compositor/compositor.pro b/examples/wayland/server-buffer/compositor/compositor.pro deleted file mode 100644 index 8ff20ad2e..000000000 --- a/examples/wayland/server-buffer/compositor/compositor.pro +++ /dev/null @@ -1,27 +0,0 @@ -QT += core gui qml - -QT += waylandcompositor-private - -CONFIG += wayland-scanner -CONFIG += c++11 -SOURCES += \ - main.cpp \ - sharebufferextension.cpp - -OTHER_FILES = \ - qml/main.qml \ - qml/Screen.qml \ - images/background.jpg - -WAYLANDSERVERSOURCES += \ - ../share-buffer.xml - -RESOURCES += compositor.qrc - -TARGET = compositor - -HEADERS += \ - sharebufferextension.h - -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/server-buffer/compositor -INSTALLS += target diff --git a/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg b/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg Binary files differdeleted file mode 100644 index eb1b73f84..000000000 --- a/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg +++ /dev/null diff --git a/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.txt b/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.txt deleted file mode 100644 index 3a26c00d3..000000000 --- a/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.txt +++ /dev/null @@ -1,5 +0,0 @@ -Image from https://en.wikipedia.org/wiki/File:Siberischer_tiger_de_edit02.jpg - -Author: S. Taheri, edited by Fir0002 - -License: Creative Commons Attribution-Share Alike 2.5 Generic diff --git a/examples/wayland/server-buffer/compositor/images/background.png b/examples/wayland/server-buffer/compositor/images/background.png Binary files differdeleted file mode 100644 index 292160cd8..000000000 --- a/examples/wayland/server-buffer/compositor/images/background.png +++ /dev/null diff --git a/examples/wayland/server-buffer/compositor/main.cpp b/examples/wayland/server-buffer/compositor/main.cpp deleted file mode 100644 index 689a3bbe7..000000000 --- a/examples/wayland/server-buffer/compositor/main.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include <QtCore/QUrl> -#include <QtCore/QDebug> -#include <QtGui/QGuiApplication> -#include <QtQml/QQmlApplicationEngine> - -#include <QtQml/qqml.h> -#include <QtQml/QQmlEngine> - -#include "sharebufferextension.h" - -static void registerTypes() -{ - qmlRegisterType<ShareBufferExtensionQuickExtension>("com.theqtcompany.sharebufferextension", 1, 0, "ShareBufferExtension"); -} - -int main(int argc, char *argv[]) -{ - // Make sure there is a valid OpenGL context in the main thread - qputenv("QSG_RENDER_LOOP", "basic"); - - QGuiApplication app(argc, argv); - registerTypes(); - QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); - - return app.exec(); -} diff --git a/examples/wayland/server-buffer/compositor/qml/main.qml b/examples/wayland/server-buffer/compositor/qml/main.qml deleted file mode 100644 index 7df8ab7bb..000000000 --- a/examples/wayland/server-buffer/compositor/qml/main.qml +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** 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.6 -import QtWayland.Compositor 1.0 -import QtQuick.Window 2.2 - -import com.theqtcompany.sharebufferextension 1.0 - -import QtQuick 2.6 -import QtQuick.Window 2.2 -import QtWayland.Compositor 1.0 - -WaylandCompositor { - WaylandOutput { - sizeFollowsWindow: true - window: Window { - width: 1024 - height: 768 - visible: true - Image { - id: surfaceArea - anchors.fill: parent - fillMode: Image.Tile - source: "qrc:/images/background.png" - smooth: false - } - } - } - Component { - id: chromeComponent - ShellSurfaceItem { - onSurfaceDestroyed: destroy() - } - } - - WlShell { - onWlShellSurfaceCreated: - chromeComponent.createObject(surfaceArea, { "shellSurface": shellSurface } ); - } - - ShareBufferExtension { - } - -} diff --git a/examples/wayland/server-buffer/compositor/sharebufferextension.cpp b/examples/wayland/server-buffer/compositor/sharebufferextension.cpp deleted file mode 100644 index ecc57b571..000000000 --- a/examples/wayland/server-buffer/compositor/sharebufferextension.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "sharebufferextension.h" - -#include <QWaylandSurface> - -#include <QDebug> - -#include <QQuickWindow> - -#include <QPainter> -#include <QPen> - -ShareBufferExtension::ShareBufferExtension(QWaylandCompositor *compositor) - : QWaylandCompositorExtensionTemplate(compositor) -{ -} - -void ShareBufferExtension::initialize() -{ - QWaylandCompositorExtensionTemplate::initialize(); - QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); - init(compositor->display(), 1); -} - -QtWayland::ServerBuffer *ShareBufferExtension::addImage(const QImage &img) -{ - if (!m_server_buffer_integration) { - QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); - - m_server_buffer_integration = QWaylandCompositorPrivate::get(compositor)->serverBufferIntegration(); - if (!m_server_buffer_integration) { - qWarning("Could not find a server buffer integration"); - return nullptr; - } - } - - QImage image = img.convertToFormat(QImage::Format_RGBA8888); - - auto *buffer = m_server_buffer_integration->createServerBufferFromImage(image, QtWayland::ServerBuffer::RGBA32); - - m_server_buffers.append(buffer); - return buffer; -} - -void ShareBufferExtension::createServerBuffers() -{ - QImage image(100,100,QImage::Format_ARGB32_Premultiplied); - image.fill(QColor(0x55,0x0,0x55,0x01)); - { - QPainter p(&image); - QPen pen = p.pen(); - pen.setWidthF(3); - pen.setColor(Qt::red); - p.setPen(pen); - p.drawLine(0,0,100,100); - pen.setColor(Qt::green); - p.setPen(pen); - p.drawLine(100,0,0,100); - pen.setColor(Qt::blue); - p.setPen(pen); - p.drawLine(25,15,75,15); - } - - addImage(image); - - QImage image2(":/images/Siberischer_tiger_de_edit02.jpg"); - addImage(image2); - - m_server_buffers_created = true; -} - - -void ShareBufferExtension::share_buffer_bind_resource(Resource *resource) -{ - if (!m_server_buffers_created) - createServerBuffers(); - - for (auto *buffer : qAsConst(m_server_buffers)) { - qDebug() << "sending" << buffer << "to client"; - struct ::wl_client *client = wl_resource_get_client(resource->handle); - struct ::wl_resource *buffer_resource = buffer->resourceForClient(client); - send_cross_buffer(resource->handle, buffer_resource); - } -} diff --git a/examples/wayland/server-buffer/compositor/sharebufferextension.h b/examples/wayland/server-buffer/compositor/sharebufferextension.h deleted file mode 100644 index 4719844b3..000000000 --- a/examples/wayland/server-buffer/compositor/sharebufferextension.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef SHAREBUFFEREXTENSION_H -#define SHAREBUFFEREXTENSION_H - -#include "wayland-util.h" - -#include <QtCore/QMap> - -#include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate> -#include <QtWaylandCompositor/QWaylandQuickExtension> -#include <QtWaylandCompositor/QWaylandCompositor> - -#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> -#include <QtWaylandCompositor/private/qwlserverbufferintegration_p.h> - -#include "qwayland-server-share-buffer.h" - -QT_BEGIN_NAMESPACE - -namespace QtWayland -{ - class ServerBufferIntegration; -}; - - -class ShareBufferExtension : public QWaylandCompositorExtensionTemplate<ShareBufferExtension> - , public QtWaylandServer::qt_share_buffer -{ - Q_OBJECT -public: - ShareBufferExtension(QWaylandCompositor *compositor = nullptr); - void initialize() override; - -protected slots: - QtWayland::ServerBuffer *addImage(const QImage &image); - -protected: - void share_buffer_bind_resource(Resource *resource) override; - -private: - void createServerBuffers(); - QList<QtWayland::ServerBuffer *> m_server_buffers; - QtWayland::ServerBufferIntegration *m_server_buffer_integration = nullptr; - bool m_server_buffers_created = false; -}; - -Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(ShareBufferExtension) - -QT_END_NAMESPACE - -#endif // SHAREBUFFEREXTENSION_H diff --git a/examples/wayland/server-buffer/cpp-client/cpp-client.pro b/examples/wayland/server-buffer/cpp-client/cpp-client.pro deleted file mode 100644 index 7f785f983..000000000 --- a/examples/wayland/server-buffer/cpp-client/cpp-client.pro +++ /dev/null @@ -1,13 +0,0 @@ -QT += waylandclient-private gui-private -CONFIG += wayland-scanner - -WAYLANDCLIENTSOURCES += ../share-buffer.xml - -SOURCES += main.cpp \ - sharebufferextension.cpp - -HEADERS += \ - sharebufferextension.h - -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/server-buffer/cpp-client -INSTALLS += target diff --git a/examples/wayland/server-buffer/cpp-client/main.cpp b/examples/wayland/server-buffer/cpp-client/main.cpp deleted file mode 100644 index 70509d063..000000000 --- a/examples/wayland/server-buffer/cpp-client/main.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** - ** - ** 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$ - ** - ****************************************************************************/ - -#include <QGuiApplication> -#include <QtGui/private/qguiapplication_p.h> -#include <QOpenGLWindow> -#include <QOpenGLTexture> -#include <QOpenGLTextureBlitter> -#include <QPainter> -#include <QMouseEvent> -#include <QPlatformSurfaceEvent> - -#include <QtWaylandClient/private/qwaylanddisplay_p.h> -#include <QtWaylandClient/private/qwaylandintegration_p.h> -#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h> -#include "sharebufferextension.h" - -#include <QDebug> -#include <QtGui/qpa/qplatformnativeinterface.h> -#include <QTimer> -#include <QMap> - -class TestWindow : public QOpenGLWindow -{ - Q_OBJECT - -public: - TestWindow() - { - m_extension = new ShareBufferExtension; - connect(m_extension, SIGNAL(bufferReceived(QtWaylandClient::QWaylandServerBuffer*)), this, SLOT(receiveBuffer(QtWaylandClient::QWaylandServerBuffer*))); - } - -public slots: - void receiveBuffer(QtWaylandClient::QWaylandServerBuffer *buffer) - { - m_buffers.append(buffer); - update(); - } - -protected: - - void initializeGL() override - { - m_blitter = new QOpenGLTextureBlitter; - m_blitter->create(); - } - - void paintGL() override { - glClearColor(.5, .45, .42, 1.); - glClear(GL_COLOR_BUFFER_BIT); - int x = 0; - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - for (auto buffer: m_buffers) { - m_blitter->bind(); - QPointF pos(x,0); - QSize s(buffer->size()); - QRectF targetRect(pos, s); - QOpenGLTexture *texture = buffer->toOpenGlTexture(); - auto surfaceOrigin = QOpenGLTextureBlitter::OriginTopLeft; - QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(), size())); - m_blitter->blit(texture->textureId(), targetTransform, surfaceOrigin); - m_blitter->release(); - x += s.width() + 10; - } - } - -private: - - QOpenGLTextureBlitter *m_blitter = nullptr; - ShareBufferExtension *m_extension = nullptr; - QList<QtWaylandClient::QWaylandServerBuffer*> m_buffers; - -}; - -int main (int argc, char **argv) -{ - QGuiApplication app(argc, argv); - - TestWindow window; - window.show(); - - return app.exec(); -} - -#include "main.moc" diff --git a/examples/wayland/server-buffer/cpp-client/sharebufferextension.cpp b/examples/wayland/server-buffer/cpp-client/sharebufferextension.cpp deleted file mode 100644 index 47b24822c..000000000 --- a/examples/wayland/server-buffer/cpp-client/sharebufferextension.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "sharebufferextension.h" -#include <QtWaylandClient/private/qwaylanddisplay_p.h> -#include <QtWaylandClient/private/qwaylandintegration_p.h> -#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h> -#include <QtGui/QGuiApplication> -#include <QtGui/private/qguiapplication_p.h> -#include <QtGui/QWindow> -#include <QtGui/QPlatformSurfaceEvent> -#include <QtGui/qpa/qplatformnativeinterface.h> -#include <QDebug> - -QT_BEGIN_NAMESPACE - -ShareBufferExtension::ShareBufferExtension() - : QWaylandClientExtensionTemplate(/* Supported protocol version */ 1 ) -{ - - auto *wayland_integration = static_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration()); - m_server_buffer_integration = wayland_integration->serverBufferIntegration(); - if (!m_server_buffer_integration) { - qCritical() << "This application requires a working serverBufferIntegration"; - QGuiApplication::quit(); - } -} - -void ShareBufferExtension::share_buffer_cross_buffer(struct ::qt_server_buffer *buffer) -{ - QtWaylandClient::QWaylandServerBuffer *serverBuffer = m_server_buffer_integration->serverBuffer(buffer); - emit bufferReceived(serverBuffer); -} - - -QT_END_NAMESPACE diff --git a/examples/wayland/server-buffer/cpp-client/sharebufferextension.h b/examples/wayland/server-buffer/cpp-client/sharebufferextension.h deleted file mode 100644 index 1440187da..000000000 --- a/examples/wayland/server-buffer/cpp-client/sharebufferextension.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef SHAREBUFFEREXTENSION_H -#define SHAREBUFFEREXTENSION_H - -#include <qpa/qwindowsysteminterface.h> -#include <QtWaylandClient/private/qwayland-wayland.h> -#include <QtWaylandClient/qwaylandclientextension.h> -#include "qwayland-share-buffer.h" - -QT_BEGIN_NAMESPACE - -namespace QtWaylandClient { - class QWaylandServerBuffer; - class QWaylandServerBufferIntegration; -}; - -class ShareBufferExtension : public QWaylandClientExtensionTemplate<ShareBufferExtension> - , public QtWayland::qt_share_buffer -{ - Q_OBJECT -public: - ShareBufferExtension(); - -signals: - void bufferReceived(QtWaylandClient::QWaylandServerBuffer *buffer); - -private: - void share_buffer_cross_buffer(struct ::qt_server_buffer *buffer) override; - QtWaylandClient::QWaylandServerBufferIntegration *m_server_buffer_integration = nullptr; -}; - -QT_END_NAMESPACE - -#endif // SHAREBUFFEREXTENSION_H diff --git a/examples/wayland/server-buffer/server-buffer.pro b/examples/wayland/server-buffer/server-buffer.pro deleted file mode 100644 index 0c737ea8c..000000000 --- a/examples/wayland/server-buffer/server-buffer.pro +++ /dev/null @@ -1,6 +0,0 @@ -TEMPLATE=subdirs - -SUBDIRS += cpp-client compositor - -EXAMPLE_FILES += \ - share-buffer.xml diff --git a/examples/wayland/server-buffer/share-buffer.xml b/examples/wayland/server-buffer/share-buffer.xml deleted file mode 100644 index ceb6b11fd..000000000 --- a/examples/wayland/server-buffer/share-buffer.xml +++ /dev/null @@ -1,46 +0,0 @@ -<protocol name="share_buffer"> - - <copyright> - Copyright (C) 2015 The Qt Company Ltd. - Contact: http://www.qt.io/licensing/ - - This file is part of the plugins of the Qt Toolkit. - - $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$ - </copyright> - - <interface name="qt_share_buffer" version="1"> - <event name="cross_buffer"> - <arg name="buffer" type="object" interface="qt_server_buffer"/> - </event> - </interface> -</protocol> diff --git a/examples/wayland/server-side-decoration/CMakeLists.txt b/examples/wayland/server-side-decoration/CMakeLists.txt new file mode 100644 index 000000000..b56e96947 --- /dev/null +++ b/examples/wayland/server-side-decoration/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(server-side-decoration LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/server-side-decoration") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(server-side-decoration + main.cpp +) + +set_target_properties(server-side-decoration PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(server-side-decoration PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(server-side-decoration_resource_files + "main.qml" +) + +qt6_add_resources(server-side-decoration "server-side-decoration" + PREFIX + "/" + FILES + ${server-side-decoration_resource_files} +) + +install(TARGETS server-side-decoration + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/server-side-decoration/doc/images/server-side-decoration.png b/examples/wayland/server-side-decoration/doc/images/server-side-decoration.png Binary files differnew file mode 100644 index 000000000..b8f7cc081 --- /dev/null +++ b/examples/wayland/server-side-decoration/doc/images/server-side-decoration.png diff --git a/examples/wayland/server-side-decoration/doc/src/server-side-decoration.qdoc b/examples/wayland/server-side-decoration/doc/src/server-side-decoration.qdoc index 7032152d1..ebbd1b145 100644 --- a/examples/wayland/server-side-decoration/doc/src/server-side-decoration.qdoc +++ b/examples/wayland/server-side-decoration/doc/src/server-side-decoration.qdoc @@ -1,36 +1,75 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - * \title Qt Wayland Compositor Examples - Sever Side Decoration Compositor + * \title Server Side Decoration Compositor * \example server-side-decoration + * \examplecategory {Embedded} * \brief Server Side Decoration Compositor is a simple example that demonstrates server side window decorations on xdg-shell. * \ingroup qtwaylandcompositor-examples * + * \image server-side-decoration.png + * + * \section1 Introduction + * * Server Side Decoration Compositor is a desktop-style Wayland compositor example implementing * server-side window decorations. + * + * For an introduction to the basic principles of creating a \l{Qt Wayland Compositor} with Qt, + * see the \l{Minimal QML}{Minimal QML example}. + * + * \section1 Decorations + * + * The term \e{window decorations} refers to the additional UI that accompanies most windows in the + * windowing system. Examples of this are: + * + * \list + * \li The graphical frame around the window surface, which a user can click and drag to resize + * the window. + * \li The title bar of the window, which might be used to move the window. + * \li The system tool buttons for maximizing, minimizing and closing a window. + * \endlist + * + * Traditionally in Wayland, it has been the client's task to render these decorations. At the same + * time, the position, size and state of the window is the compositor's domain. + * Some \l{Shell Extensions - Qt Wayland Compositor}{shell extensions} optionally support + * \e{server-side decorations}. This enables a compositor to communicate to clients that they should + * not draw their own window decorations. Instead, the compositor is responsible for drawing the + * window decorations. This corresponds to how decorations are handled on other windowing systems, + * such as macOS, Windows and X11. It is worth noting that certain clients may not support this at + * all. If the system is expected to run such applications, then this should also be taken into + * account. + * + * Benefits of server-side decorations: + * \list + * \li Clients do not have to reserve space for system UI in their Wayland buffers. + * \li Qt Quick and OpenGL-based clients do not have to render into a separate FBO and copy + * the content into their Wayland buffers. + * \li Client windows will have a consistent appearance, independent of which UI toolkit is in + * use. + * \li System functionality, such as resizing, closing and changing window state, is centralized + * in the server instead of being shared between the server and client. + * \endlist + * + * \section1 The Code + * + * The example compositor only supports the \l{XdgShell} extension. It initializes the extension in + * the usual way and adds surfaces to a \l ListModel in order to access them later. + * + * \snippet server-side-decoration/main.qml XdgShell + * + * In addition, the example initializes the \l XdgDecorationManagerV1 extension. This allows it + * to communicate to the client that it prefers server-side decorations. + * + * Since the interface is optional, it could be that the client does not support it and will always + * draw its own decorations. Therefore, the mode is only "preferred" and we need to check the actual + * mode of the top-level window before we decorate it. + * + * \snippet server-side-decoration/main.qml decoration + * + * For each window, we create a simple title bar above it. The title bar has a gradient, some text, + * a \l DragHandler which manages its position, and a close button. + * + * The image shows a client which supports the decoration manager extensions on the upper left-hand + * side, and the same client with client-side decorations on the lower, right-hand side. */ diff --git a/examples/wayland/server-side-decoration/main.cpp b/examples/wayland/server-side-decoration/main.cpp index e765fafb6..873bbcac5 100644 --- a/examples/wayland/server-side-decoration/main.cpp +++ b/examples/wayland/server-side-decoration/main.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QtCore/QUrl> #include <QtCore/QDebug> diff --git a/examples/wayland/server-side-decoration/main.qml b/examples/wayland/server-side-decoration/main.qml index 5847ce411..421cefa95 100644 --- a/examples/wayland/server-side-decoration/main.qml +++ b/examples/wayland/server-side-decoration/main.qml @@ -1,57 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick 2.12 -import QtQuick.Window 2.2 -import QtQuick.Layouts 1.3 -import QtWayland.Compositor 1.3 +import QtQuick +import QtQuick.Window +import QtQuick.Layouts +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell WaylandCompositor { // The output defines the screen. @@ -68,6 +22,8 @@ WaylandCompositor { Repeater { model: shellSurfaces + + // ![decoration] Column { id: chrome width: shellSurfaceItem.implicitWidth @@ -96,19 +52,22 @@ WaylandCompositor { ShellSurfaceItem { id: shellSurfaceItem moveItem: parent - autoCreatePopupItems: true shellSurface: modelData onSurfaceDestroyed: shellSurfaces.remove(index) } } + // ![decoration] } } } + + // ![XdgShell] XdgShell { - onToplevelCreated: shellSurfaces.append({shellSurface: xdgSurface}); + onToplevelCreated: (toplevel, xdgSurface) => shellSurfaces.append({shellSurface: xdgSurface}); } XdgDecorationManagerV1 { preferredMode: XdgToplevel.ServerSideDecoration } + // ![XdgShell] ListModel { id: shellSurfaces } } diff --git a/examples/wayland/spanning-screens/CMakeLists.txt b/examples/wayland/spanning-screens/CMakeLists.txt new file mode 100644 index 000000000..0e4239033 --- /dev/null +++ b/examples/wayland/spanning-screens/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(spanning-screens LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/spanning-screens") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(spanning-screens + main.cpp +) + +set_target_properties(spanning-screens PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(spanning-screens PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(spanning-screens_resource_files + "main.qml" +) + +qt6_add_resources(spanning-screens "spanning-screens" + PREFIX + "/" + FILES + ${spanning-screens_resource_files} +) + +install(TARGETS spanning-screens + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/wayland/spanning-screens/doc/images/spanning-screens.jpg b/examples/wayland/spanning-screens/doc/images/spanning-screens.jpg Binary files differnew file mode 100644 index 000000000..4f348393c --- /dev/null +++ b/examples/wayland/spanning-screens/doc/images/spanning-screens.jpg diff --git a/examples/wayland/spanning-screens/doc/src/spanning-screens.qdoc b/examples/wayland/spanning-screens/doc/src/spanning-screens.qdoc index 3ab0b91f5..7c548171c 100644 --- a/examples/wayland/spanning-screens/doc/src/spanning-screens.qdoc +++ b/examples/wayland/spanning-screens/doc/src/spanning-screens.qdoc @@ -1,36 +1,60 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - * \title Qt Wayland Compositor Examples - Spanning Screens + * \title Spanning Screens * \example spanning-screens + * \examplecategory {Embedded} * \brief Spanning Screens is an example that demonstrates how to let Wayland clients span multiple screens. * \ingroup qtwaylandcompositor-examples * - * Spanning screens is a Wayland compositor example that maximizes clients - * across a top and a bottom screen. + * \section1 Introduction + * + * Spanning screens is a Wayland compositor example that maximizes clients across a top and a bottom + * screen. + * + * \image spanning-screens.jpg + * + * For an introduction to the basic principles of creating a \l{Qt Wayland Compositor} with Qt, + * see the \l{Minimal QML}{Minimal QML example}. + * + * \section1 Supporting Multiple Screens + * + * In \l{Qt Wayland Compositor} a screen is represented by a \l{WaylandOutput}, and a \l Window is + * used to contain the \l{Qt Quick} scene representing both clients and the compositor's UI. + * + * In this example, a multi-screen setup is emulated by creating two windows on the primary screen, + * but the code can easily be modified to target multiple physical screens. + * + * \snippet spanning-screens/main.qml enable screens + * + * Since each \l Window represents an isolated \l{Qt Quick} scene, this means we need a trick to + * have the same client content display inside both windows. The way to do this in + * \l{Qt Wayland Compositor} is to create two views of the same client content: One for the "top" + * window and one for the "bottom". The views share a reference to the same underlying graphics buffer. + * This allows us to copy different areas of the client's surface onto each of the windows. + * + * \snippet spanning-screens/main.qml create items + * + * When the client connects to the \l{Shell Extensions - Qt Wayland Compositor}{shell extension} + * \l{XdgShell}, we create two references to the surface. One of them is added to the "top" output, + * and the second to the "bottom". The item on the bottom output also gets an offset corresponding + * to the height of the top output. This ensures that the part of the client surface showing on + * the bottom output starts where the top output ends. + * + * \snippet spanning-screens/main.qml size + * + * In addition, we tell the client to resize its surface so that it fills both the top and bottom + * window. The end result is a client that spans two windows, or "screens". + * + * Referencing the same client surface from multiple items is a tool which can be used for many + * things. For a demonstration of a desktop-style compositor where windows can be moved from screen + * to screen, take a look at the \l{Multi Screen}{Multi Screen example}. + * + * The \l{Multi Output}{Multi Output example} shows how client surfaces can be displayed on multiple + * outputs with different sizes and other properties. + * + * \note In order to support multiple Wayland outputs in the same compositor, the + * \l Qt::AA_ShareOpenGLContexts attribute must be set before the \l QGuiApplication + * object is constructed. */ diff --git a/examples/wayland/spanning-screens/main.cpp b/examples/wayland/spanning-screens/main.cpp index 435b4e3f1..607d14899 100644 --- a/examples/wayland/spanning-screens/main.cpp +++ b/examples/wayland/spanning-screens/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 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 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <QtCore/QUrl> #include <QtCore/QDebug> @@ -57,6 +10,8 @@ int main(int argc, char *argv[]) { + // AA_ShareOpenGLContexts is required for compositors with multiple outputs + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); QGuiApplication app(argc, argv); QQmlApplicationEngine appEngine(QUrl("qrc:///main.qml")); diff --git a/examples/wayland/spanning-screens/main.qml b/examples/wayland/spanning-screens/main.qml index ab57306bb..d47246dee 100644 --- a/examples/wayland/spanning-screens/main.qml +++ b/examples/wayland/spanning-screens/main.qml @@ -1,56 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -import QtQuick 2.6 -import QtQuick.Window 2.3 -import QtWayland.Compositor 1.3 +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell WaylandCompositor { WaylandOutput { @@ -68,10 +22,12 @@ WaylandCompositor { Text { text: "Top screen" } + // ![enable screens] // Enable the following to make the output target an actual screen, // for example when running on eglfs in a multi-display embedded system. // screen: Qt.application.screens[0] + // ![enable screens] } } @@ -99,16 +55,20 @@ WaylandCompositor { Component { id: chromeComponent - ShellSurfaceItem { - autoCreatePopupItems: true - onSurfaceDestroyed: destroy() + Item { + property alias shellSurface: ssi.shellSurface + ShellSurfaceItem { + id: ssi + onSurfaceDestroyed: destroy() + } } } XdgShell { - onToplevelCreated: { + onToplevelCreated: (toplevel, xdgSurface) => { const shellSurface = xdgSurface; + // ![create items] const topItem = chromeComponent.createObject(topSurfaceArea, { shellSurface }); @@ -117,11 +77,14 @@ WaylandCompositor { shellSurface, y: Qt.binding(function() { return -topSurfaceArea.height;}) }); + // ![create items] + // ![size] const height = topSurfaceArea.pixelHeight + bottomSurfaceArea.pixelHeight; const width = Math.max(bottomSurfaceArea.pixelWidth, topSurfaceArea.pixelWidth); const size = Qt.size(width, height); toplevel.sendFullscreen(size); + // ![size] } } } diff --git a/examples/wayland/texture-sharing/.gitignore b/examples/wayland/texture-sharing/.gitignore deleted file mode 100644 index c684448d3..000000000 --- a/examples/wayland/texture-sharing/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -custom-compositor/custom-compositor -qml-client/qml-client diff --git a/examples/wayland/texture-sharing/README b/examples/wayland/texture-sharing/README deleted file mode 100644 index 27ea76745..000000000 --- a/examples/wayland/texture-sharing/README +++ /dev/null @@ -1,27 +0,0 @@ -This example shows how to use the texture sharing extension, allowing -multiple clients to share the same copy of an image in graphics memory. - -The texture sharing extension uses the server buffer extension to transport -graphics buffers. There are different server buffer plugins for different -graphics hardware. This is specified by setting an environment variable for -the compositor process. - --On a device with Mesa and Intel integrated graphics, set: - - QT_WAYLAND_SERVER_BUFFER_INTEGRATION=dmabuf-server - --On a device with NVIDIA graphics, set: - - QT_WAYLAND_SERVER_BUFFER_INTEGRATION=vulkan-server - -'custom-compositor' shows how to write a server that creates shared textures -programmatically. - -The file 'minimal-compositor.qml' shows how to add texture sharing to an -existing compositor, using only QML. It is based on the minimal-qml example, -and can be executed with qmlscene. - -'qml-client' shows how to use shared textures in a Qt Quick client. -The compositor uses the hardware integration extension to broadcast -the name of the server buffer integration to all clients, so qml-client -can be started like any normal wayland client. diff --git a/examples/wayland/texture-sharing/custom-compositor/compositor.qrc b/examples/wayland/texture-sharing/custom-compositor/compositor.qrc deleted file mode 100644 index 86a8567f7..000000000 --- a/examples/wayland/texture-sharing/custom-compositor/compositor.qrc +++ /dev/null @@ -1,9 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>images/background.png</file> - <file>images/qt_logo.png</file> - <file>images/qt4.astc</file> - <file>images/car.ktx</file> - <file>qml/main.qml</file> - </qresource> -</RCC> diff --git a/examples/wayland/texture-sharing/custom-compositor/custom-compositor.pro b/examples/wayland/texture-sharing/custom-compositor/custom-compositor.pro deleted file mode 100644 index e80e9e153..000000000 --- a/examples/wayland/texture-sharing/custom-compositor/custom-compositor.pro +++ /dev/null @@ -1,18 +0,0 @@ -QT += core gui qml - -QT += waylandcompositor-private - -SOURCES += \ - main.cpp - -OTHER_FILES = \ - qml/main.qml \ - qml/Screen.qml \ - images/background.jpg - -RESOURCES += compositor.qrc - -TARGET = custom-compositor - -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/texture-sharing/custom-compositor -INSTALLS += target diff --git a/examples/wayland/texture-sharing/custom-compositor/images/background.png b/examples/wayland/texture-sharing/custom-compositor/images/background.png Binary files differdeleted file mode 100644 index 845830c59..000000000 --- a/examples/wayland/texture-sharing/custom-compositor/images/background.png +++ /dev/null diff --git a/examples/wayland/texture-sharing/custom-compositor/images/car.ktx b/examples/wayland/texture-sharing/custom-compositor/images/car.ktx Binary files differdeleted file mode 100644 index 2aefdd306..000000000 --- a/examples/wayland/texture-sharing/custom-compositor/images/car.ktx +++ /dev/null diff --git a/examples/wayland/texture-sharing/custom-compositor/images/qt4.astc b/examples/wayland/texture-sharing/custom-compositor/images/qt4.astc Binary files differdeleted file mode 100644 index 7f7a3f473..000000000 --- a/examples/wayland/texture-sharing/custom-compositor/images/qt4.astc +++ /dev/null diff --git a/examples/wayland/texture-sharing/custom-compositor/images/qt_logo.png b/examples/wayland/texture-sharing/custom-compositor/images/qt_logo.png Binary files differdeleted file mode 100644 index 5e2b355ea..000000000 --- a/examples/wayland/texture-sharing/custom-compositor/images/qt_logo.png +++ /dev/null diff --git a/examples/wayland/texture-sharing/custom-compositor/main.cpp b/examples/wayland/texture-sharing/custom-compositor/main.cpp deleted file mode 100644 index a39c8c381..000000000 --- a/examples/wayland/texture-sharing/custom-compositor/main.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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$ -** -****************************************************************************/ - -#include <QtCore/QUrl> -#include <QtCore/QDebug> -#include <QtGui/QGuiApplication> -#include <QtQml/QQmlApplicationEngine> - -#include <QtQml/qqml.h> -#include <QtQml/QQmlEngine> - -#include <QtGui/QPainter> -#include <QtGui/QImage> - -#include <QtCore/QDateTime> - -#include "QtWaylandCompositor/private/qwltexturesharingextension_p.h" - -class CustomSharingExtension : public QWaylandTextureSharingExtension -{ - Q_OBJECT -public: - CustomSharingExtension() {qDebug("Instantiating custom texture sharing extension.");} -protected: - bool customPixelData(const QString &key, QByteArray *data, QSize *size, uint *glInternalFormat) override - { - qDebug() << "CustomSharingExtension looking for local texture data for" << key; - if (key.startsWith("unreasonably large ")) { - int w = 10000; - int h = 10000; - int numBytes = w * h * 4; - *data = QByteArray(numBytes, 0); - quint32 *pixels = reinterpret_cast<quint32*>(data->data()); - for (int i = 0; i < w*h; ++i) - pixels[i] = 0xff7f1fff; - *glInternalFormat = GL_RGBA8; - *size = QSize(w,h); - return true; - } - - QImage img; - - if (key == QLatin1String("test pattern 1")) { - img = QImage(128,128,QImage::Format_ARGB32_Premultiplied); - img.fill(QColor(0x55,0x0,0x55,0x01)); - { - QPainter p(&img); - QPen pen = p.pen(); - pen.setWidthF(3); - pen.setColor(Qt::red); - p.setPen(pen); - p.drawLine(0,0,128,128); - pen.setColor(Qt::green); - p.setPen(pen); - p.drawLine(128,0,0,128); - pen.setColor(Qt::blue); - p.setPen(pen); - p.drawLine(32,16,96,16); - pen.setColor(Qt::black); - p.setPen(pen); - p.translate(64, 64); - p.rotate(45); - p.drawText(QRect(-48, -32, 96, 64), - QDateTime::currentDateTime().toString(), - QTextOption(Qt::AlignHCenter)); - } - } - - if (!img.isNull()) { - img = img.convertToFormat(QImage::Format_RGBA8888); - *data = QByteArray(reinterpret_cast<const char*>(img.constBits()), img.sizeInBytes()); - *size = img.size(); - *glInternalFormat = GL_RGBA8; - return true; - } - return false; - } -}; - -Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(CustomSharingExtension); - -int main(int argc, char *argv[]) -{ - QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); - QGuiApplication app(argc, argv); - QQmlApplicationEngine appEngine; - - qmlRegisterType<CustomSharingExtensionQuickExtension>("com.theqtcompany.customsharingextension", 1, 0, "CustomSharingExtension"); - appEngine.addImageProvider("wlshared", new QWaylandSharedTextureProvider); - - appEngine.load(QUrl("qrc:///qml/main.qml")); - - return app.exec(); -} - -#include "main.moc" diff --git a/examples/wayland/texture-sharing/custom-compositor/qml/main.qml b/examples/wayland/texture-sharing/custom-compositor/qml/main.qml deleted file mode 100644 index 16a412fcd..000000000 --- a/examples/wayland/texture-sharing/custom-compositor/qml/main.qml +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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.6 -import QtQuick.Window 2.2 -import QtWayland.Compositor 1.3 - -import com.theqtcompany.customsharingextension 1.0 - -WaylandCompositor { - WaylandOutput { - sizeFollowsWindow: true - window: Window { - width: 1024 - height: 768 - visible: true - Image { - id: background - anchors.fill: parent - fillMode: Image.Tile - source: "qrc:/images/background.png" - smooth: true - - Rectangle { - width: 100 - height: 100 - color: "red" - anchors.bottom: parent.bottom; - anchors.right: parent.right; - MouseArea { - anchors.fill: parent - onClicked: sharedTextureImage.source = "image://wlshared/car.ktx" - } - } - Image { - id: sharedTextureImage - anchors.bottom: parent.bottom; - anchors.right: parent.right; - source: "" - } - Image { - id: topRightImage - anchors.top: parent.top; - anchors.right: parent.right; - source: "image://wlshared/qt_logo.png" - } - } - Repeater { - model: shellSurfaces - ShellSurfaceItem { - autoCreatePopupItems: true - shellSurface: modelData - onSurfaceDestroyed: shellSurfaces.remove(index) - } - } - } - } - WlShell { - onWlShellSurfaceCreated: - shellSurfaces.append({shellSurface: shellSurface}); - } - XdgShellV6 { - onToplevelCreated: - shellSurfaces.append({shellSurface: xdgSurface}); - } - XdgShell { - onToplevelCreated: - shellSurfaces.append({shellSurface: xdgSurface}); - } - ListModel { id: shellSurfaces } - - CustomSharingExtension { - imageSearchPath: ":/images;." - } -} diff --git a/examples/wayland/texture-sharing/minimal-compositor.qml b/examples/wayland/texture-sharing/minimal-compositor.qml deleted file mode 100644 index 3f714dc58..000000000 --- a/examples/wayland/texture-sharing/minimal-compositor.qml +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -import QtQuick 2.6 -import QtQuick.Window 2.2 -import QtWayland.Compositor 1.3 - -// importing the texture sharing extension: -import QtWayland.Compositor.TextureSharingExtension 1.0 - -WaylandCompositor { - WaylandOutput { - sizeFollowsWindow: true - window: Window { - width: 1024 - height: 768 - visible: true - Repeater { - model: shellSurfaces - ShellSurfaceItem { - autoCreatePopupItems: true - shellSurface: modelData - onSurfaceDestroyed: shellSurfaces.remove(index) - } - } - } - } - WlShell { - onWlShellSurfaceCreated: - shellSurfaces.append({shellSurface: shellSurface}); - } - XdgShellV6 { - onToplevelCreated: - shellSurfaces.append({shellSurface: xdgSurface}); - } - XdgShell { - onToplevelCreated: - shellSurfaces.append({shellSurface: xdgSurface}); - } - ListModel { id: shellSurfaces } - - // instantiating the texture sharing extension: - TextureSharingExtension { - imageSearchPath: ".;/tmp;/usr/share/pixmaps" - } -} diff --git a/examples/wayland/texture-sharing/qml-client/main.cpp b/examples/wayland/texture-sharing/qml-client/main.cpp deleted file mode 100644 index 618d6701d..000000000 --- a/examples/wayland/texture-sharing/qml-client/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** - ** - ** Copyright (C) 2019 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$ - ** - ****************************************************************************/ - -#include <QGuiApplication> -#include <QtQuick/QQuickView> -#include <QStandardPaths> -#include <QFileInfo> -#include <QQmlApplicationEngine> -#include <QDebug> -#include <QDir> -#include <QTimer> - -int main(int argc, char **argv) -{ - QGuiApplication app(argc, argv); - QQmlApplicationEngine appEngine; - - appEngine.load(QUrl("qrc:///main.qml")); - - return app.exec(); -} diff --git a/examples/wayland/texture-sharing/qml-client/main.qml b/examples/wayland/texture-sharing/qml-client/main.qml deleted file mode 100644 index 371a97594..000000000 --- a/examples/wayland/texture-sharing/qml-client/main.qml +++ /dev/null @@ -1,248 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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.9 -import QtQuick.Window 2.2 - -import QtWayland.Client.TextureSharing 1.0 - -Window { - width: 800 - height: 500 - visible: true - - Rectangle { - anchors.fill: parent - color: "#C0FEFE" - - Flickable { - anchors.fill: parent - contentHeight: imageGrid.height - - Grid { - id: imageGrid - columns: 2 - width: parent.width - spacing: 25 - padding: 25 - - - // loadedImage - Text { - width: 400 - wrapMode: Text.Wrap - text: "An Image element using the shared buffer provider to load from a PNG image.<br>" + - "Source: '" + loadedImage.source + "'" + - (loadedImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") - } - Image { - id: loadedImage - fillMode: Image.PreserveAspectFit - source: "image://wlshared/qt_logo.png" - } - Rectangle { - visible: loadedImage.height <= 0 - width:100; height: 100 - color: "green" - } - - // paintedImage - Text { - width: 400 - wrapMode: Text.Wrap - text: "An Image element using the shared buffer provider.<br>" + - "This texture is created by the compositor using QPainter. <br>" + - "Source: '" + paintedImage.source + "'" + - (paintedImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") - } - Image { - id: paintedImage - fillMode: Image.PreserveAspectFit - source: "image://wlshared/test pattern 1" - } - Rectangle { - visible: paintedImage.height <= 0 - width:100; height: 100 - color: "green" - } - - // ktxImage - Text { - width: 400 - wrapMode: Text.Wrap - text: "An Image element using the shared buffer provider to load an ETC2 compressed texture." + - "<br>Source: '" + ktxImage.source + "'" + - (ktxImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") - } - Image { - id: ktxImage - source: "image://wlshared/car.ktx" - fillMode: Image.PreserveAspectFit - } - Rectangle { - visible: ktxImage.height <= 0 - width:100; height: 100 - color: "green" - } - - //astcImage - Text { - width: 400 - wrapMode: Text.Wrap - text: "An Image element using the shared buffer provider to load an ASTC compressed texture." + - "<br>Source: '" + astcImage.source + "'" + - (astcImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") - } - - Image { - id: astcImage - source: "image://wlshared/qt4.astc" - fillMode: Image.PreserveAspectFit - } - Rectangle { - visible: astcImage.height <= 0 - width:100; height: 100 - color: "green" - } - - // dynamicImage - Column { - Text { - width: 400 - wrapMode: Text.Wrap - text: "An Image element using the shared buffer provider." + - "<br>Source: '" + dynamicImage.source + "'" + - (dynamicImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") - } - Row { - spacing: 10 - Text { - text: "Enter filename:" - } - Rectangle { - color: "white" - width: sourceEdit.contentWidth + 30 - height: sourceEdit.contentHeight - TextInput { - id: sourceEdit - anchors.fill: parent - horizontalAlignment: TextInput.AlignHCenter - onEditingFinished: dynamicImage.source = text ? "image://wlshared/" + text : "" - } - } - } - } - Image { - id: dynamicImage - fillMode: Image.PreserveAspectFit - } - Rectangle { - visible: dynamicImage.height <= 0 - width:100; height: 100 - color: "green" - } - - // largeImage - Text { - width: 400 - wrapMode: Text.Wrap - text: "An Image element using the shared buffer provider.<br>" + - "Left click to load a very large image. " + - "Right click to unload the image, potentially freeing graphics memory on the server-side " + - "if no other client is using the image." + - "<br>Source: '" + largeImage.source + "'" + - "<br>Size: " + largeImage.sourceSize + - (largeImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") - } - - Rectangle { - width: 200 - height: 200 - border.color: "black" - border.width: 2 - color: "transparent" - Image { - id: largeImage - anchors.fill: parent - fillMode: Image.PreserveAspectFit - } - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.LeftButton | Qt.RightButton - onClicked: { - if (mouse.button == Qt.LeftButton) - largeImage.source = "image://wlshared/unreasonably large image" - else - largeImage.source = "" - - } - } - } - - } // Grid - } - - Rectangle { - color: "gray" - width: parent.width - height: 20 - anchors.bottom: parent.bottom - - Text { - color: "white" - anchors.fill: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text: "Scroll or drag for more" - } - } - - } -} diff --git a/examples/wayland/texture-sharing/qml-client/qml-client.pro b/examples/wayland/texture-sharing/qml-client/qml-client.pro deleted file mode 100644 index 67d5c7071..000000000 --- a/examples/wayland/texture-sharing/qml-client/qml-client.pro +++ /dev/null @@ -1,13 +0,0 @@ -QT += quick - -SOURCES += \ - main.cpp - -RESOURCES += \ - qml-client.qrc - -DISTFILES += \ - main.qml - -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/texture-sharing/qml-client -INSTALLS += target diff --git a/examples/wayland/texture-sharing/qml-client/qml-client.qrc b/examples/wayland/texture-sharing/qml-client/qml-client.qrc deleted file mode 100644 index 5f6483ac3..000000000 --- a/examples/wayland/texture-sharing/qml-client/qml-client.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>main.qml</file> - </qresource> -</RCC> diff --git a/examples/wayland/texture-sharing/texture-sharing.pro b/examples/wayland/texture-sharing/texture-sharing.pro deleted file mode 100644 index 3f7792828..000000000 --- a/examples/wayland/texture-sharing/texture-sharing.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE=subdirs - -SUBDIRS += \ - qml-client \ - custom-compositor diff --git a/examples/wayland/wayland.pro b/examples/wayland/wayland.pro index f9287481b..145e1ec64 100644 --- a/examples/wayland/wayland.pro +++ b/examples/wayland/wayland.pro @@ -5,28 +5,22 @@ TEMPLATE=subdirs qtConfig(opengl) { SUBDIRS += \ - qwindow-compositor \ minimal-cpp } qtHaveModule(quick) { SUBDIRS += minimal-qml SUBDIRS += spanning-screens - SUBDIRS += pure-qml + SUBDIRS += fancy-compositor SUBDIRS += multi-output SUBDIRS += multi-screen SUBDIRS += overview-compositor SUBDIRS += ivi-compositor SUBDIRS += server-side-decoration + SUBDIRS += qtshell qtHaveModule(waylandclient) { SUBDIRS += \ - custom-extension - - qtConfig(opengl) { - SUBDIRS += \ - server-buffer \ - texture-sharing - } + custom-extension \ + custom-shell } - SUBDIRS += hwlayer-compositor } |