summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/wayland/minimal-cpp/window.cpp5
-rw-r--r--examples/wayland/multi-screen/qml/Screen.qml6
-rw-r--r--examples/wayland/pure-qml/qml/main.qml18
-rw-r--r--examples/wayland/server-buffer/README29
-rw-r--r--examples/wayland/server-buffer/compositor/compositor.pro27
-rw-r--r--examples/wayland/server-buffer/compositor/compositor.qrc7
-rw-r--r--examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpgbin0 -> 21801 bytes
-rw-r--r--examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.txt5
-rw-r--r--examples/wayland/server-buffer/compositor/images/background.pngbin0 -> 9528 bytes
-rw-r--r--examples/wayland/server-buffer/compositor/main.cpp76
-rw-r--r--examples/wayland/server-buffer/compositor/qml/main.qml92
-rw-r--r--examples/wayland/server-buffer/compositor/sharebufferextension.cpp135
-rw-r--r--examples/wayland/server-buffer/compositor/sharebufferextension.h100
-rw-r--r--examples/wayland/server-buffer/cpp-client/cpp-client.pro13
-rw-r--r--examples/wayland/server-buffer/cpp-client/main.cpp136
-rw-r--r--examples/wayland/server-buffer/cpp-client/sharebufferextension.cpp83
-rw-r--r--examples/wayland/server-buffer/cpp-client/sharebufferextension.h83
-rw-r--r--examples/wayland/server-buffer/server-buffer.pro6
-rw-r--r--examples/wayland/server-buffer/share-buffer.xml46
-rw-r--r--examples/wayland/wayland.pro3
-rw-r--r--src/client/hardwareintegration/qwaylandserverbufferintegration_p.h4
-rw-r--r--src/client/qwaylanddnd.cpp7
-rw-r--r--src/client/qwaylanddnd_p.h2
-rw-r--r--src/client/qwaylandscreen.cpp17
-rw-r--r--src/client/qwaylandscreen_p.h7
-rw-r--r--src/client/qwaylandshmbackingstore.cpp51
-rw-r--r--src/client/qwaylandwindow.cpp56
-rw-r--r--src/client/qwaylandwindow_p.h12
-rw-r--r--src/client/qwaylandwindowmanagerintegration.cpp22
-rw-r--r--src/client/qwaylandwindowmanagerintegration_p.h2
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp2
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-overview.qdoc56
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc4
-rw-r--r--src/compositor/extensions/extensions.pri6
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp6
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.h1
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6.cpp1901
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6.h261
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6_p.h239
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6integration.cpp202
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6integration_p.h131
-rw-r--r--src/compositor/hardware_integration/qwlserverbufferintegration_p.h6
-rw-r--r--src/extensions/shm-emulation-server-buffer.xml63
-rw-r--r--src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.cpp36
-rw-r--r--src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.h13
-rw-r--r--src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.cpp37
-rw-r--r--src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.h14
-rw-r--r--src/hardwareintegration/client/shm-emulation-server/shm-emulation-server.pri12
-rw-r--r--src/hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.cpp143
-rw-r--r--src/hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.h93
-rw-r--r--src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp54
-rw-r--r--src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.h8
-rw-r--r--src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp67
-rw-r--r--src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.h8
-rw-r--r--src/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pri13
-rw-r--r--src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp146
-rw-r--r--src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.h99
-rw-r--r--src/imports/compositor/qwaylandquickcompositorplugin.cpp7
-rw-r--r--src/plugins/hardwareintegration/client/client.pro3
-rw-r--r--src/plugins/hardwareintegration/client/shm-emulation-server/main.cpp66
-rw-r--r--src/plugins/hardwareintegration/client/shm-emulation-server/shm-emulation-server.json3
-rw-r--r--src/plugins/hardwareintegration/client/shm-emulation-server/shm-emulation-server.pro15
-rw-r--r--src/plugins/hardwareintegration/compositor/compositor.pro3
-rw-r--r--src/plugins/hardwareintegration/compositor/shm-emulation-server/main.cpp62
-rw-r--r--src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.json3
-rw-r--r--src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro12
-rw-r--r--src/qtwaylandscanner/qtwaylandscanner.cpp32
-rw-r--r--tests/auto/client/client/mocksurface.h5
-rw-r--r--tests/auto/compositor/compositor/tst_compositor.cpp48
70 files changed, 4725 insertions, 207 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 2108ac6fd..138038d54 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,3 +1,3 @@
load(qt_build_config)
-MODULE_VERSION = 5.9.3
+MODULE_VERSION = 5.10.0
diff --git a/examples/wayland/minimal-cpp/window.cpp b/examples/wayland/minimal-cpp/window.cpp
index 893371832..a23bba3ae 100644
--- a/examples/wayland/minimal-cpp/window.cpp
+++ b/examples/wayland/minimal-cpp/window.cpp
@@ -55,6 +55,7 @@
#include <QMatrix4x4>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
+#include <QRandomGenerator>
Window::Window()
: m_compositor(0)
@@ -74,7 +75,7 @@ static int sillyrandom(int range)
{
if (range <= 0)
range = 200;
- return qrand() % range;
+ return QRandomGenerator::bounded(range);
}
void Window::paintGL()
@@ -90,8 +91,6 @@ void Window::paintGL()
functions->glEnable(GL_BLEND);
functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- qsrand(31337);
-
Q_FOREACH (View *view, m_compositor->views()) {
if (view->isCursor())
continue;
diff --git a/examples/wayland/multi-screen/qml/Screen.qml b/examples/wayland/multi-screen/qml/Screen.qml
index 815140710..21f2d1266 100644
--- a/examples/wayland/multi-screen/qml/Screen.qml
+++ b/examples/wayland/multi-screen/qml/Screen.qml
@@ -48,7 +48,7 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.8
import QtWayland.Compositor 1.0
import QtQuick.Window 2.3
@@ -95,5 +95,9 @@ WaylandOutput {
visible: mouseTracker.containsMouse
}
}
+ 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
index 6ee450d43..9ed4acd24 100644
--- a/examples/wayland/pure-qml/qml/main.qml
+++ b/examples/wayland/pure-qml/qml/main.qml
@@ -49,7 +49,7 @@
****************************************************************************/
import QtQuick 2.0
-import QtWayland.Compositor 1.0
+import QtWayland.Compositor 1.1
WaylandCompositor {
id: comp
@@ -83,8 +83,9 @@ WaylandCompositor {
}
}
+ property variant viewsBySurface: ({})
+
XdgShellV5 {
- property variant viewsBySurface: ({})
onXdgSurfaceCreated: {
var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": xdgSurface } );
viewsBySurface[xdgSurface.surface] = item;
@@ -96,6 +97,19 @@ WaylandCompositor {
}
}
+ XdgShellV6 {
+ onToplevelCreated: {
+ var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": xdgSurface } );
+ viewsBySurface[xdgSurface.surface] = item;
+ }
+ onPopupCreated: {
+ var parentView = viewsBySurface[popup.parentXdgSurface.surface];
+ var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": xdgSurface } );
+ viewsBySurface[xdgSurface.surface] = item;
+ //TODO: set popup position
+ }
+ }
+
TextInputManager {
}
diff --git a/examples/wayland/server-buffer/README b/examples/wayland/server-buffer/README
new file mode 100644
index 000000000..4e5eebbb1
--- /dev/null
+++ b/examples/wayland/server-buffer/README
@@ -0,0 +1,29 @@
+This is the example to demonstrate the server buffer interfaces
+
+Compile up both compositor and client.
+
+If you have the drm-egl-server buffer integration (and you are running Mesa)
+then start the compositor with:
+
+$ QT_WAYLAND_SERVER_BUFFER_INTEGRATION=drm-egl-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
new file mode 100644
index 000000000..8ff20ad2e
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/compositor.pro
@@ -0,0 +1,27 @@
+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/compositor.qrc b/examples/wayland/server-buffer/compositor/compositor.qrc
new file mode 100644
index 000000000..b50594b55
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/compositor.qrc
@@ -0,0 +1,7 @@
+<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/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg b/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg
new file mode 100644
index 000000000..eb1b73f84
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg
Binary files differ
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
new file mode 100644
index 000000000..3a26c00d3
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/images/Siberischer_tiger_de_edit02.txt
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 000000000..292160cd8
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/images/background.png
Binary files differ
diff --git a/examples/wayland/server-buffer/compositor/main.cpp b/examples/wayland/server-buffer/compositor/main.cpp
new file mode 100644
index 000000000..689a3bbe7
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/main.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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
new file mode 100644
index 000000000..7df8ab7bb
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/qml/main.qml
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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
new file mode 100644
index 000000000..8277dad34
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/sharebufferextension.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** 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)
+ , m_server_buffer_integration(nullptr)
+ , m_server_buffers_created(false)
+{
+}
+
+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 = resource->handle->client;
+ 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
new file mode 100644
index 000000000..f84d9c4df
--- /dev/null
+++ b/examples/wayland/server-buffer/compositor/sharebufferextension.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** 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;
+ bool m_server_buffers_created;
+};
+
+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
new file mode 100644
index 000000000..7f785f983
--- /dev/null
+++ b/examples/wayland/server-buffer/cpp-client/cpp-client.pro
@@ -0,0 +1,13 @@
+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
new file mode 100644
index 000000000..b0b3712b9
--- /dev/null
+++ b/examples/wayland/server-buffer/cpp-client/main.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+ **
+ ** 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(nullptr)
+ {
+ 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;
+ ShareBufferExtension *m_extension;
+ 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
new file mode 100644
index 000000000..47b24822c
--- /dev/null
+++ b/examples/wayland/server-buffer/cpp-client/sharebufferextension.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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
new file mode 100644
index 000000000..6ea19c08b
--- /dev/null
+++ b/examples/wayland/server-buffer/cpp-client/sharebufferextension.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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;
+};
+
+QT_END_NAMESPACE
+
+#endif // SHAREBUFFEREXTENSION_H
diff --git a/examples/wayland/server-buffer/server-buffer.pro b/examples/wayland/server-buffer/server-buffer.pro
new file mode 100644
index 000000000..0c737ea8c
--- /dev/null
+++ b/examples/wayland/server-buffer/server-buffer.pro
@@ -0,0 +1,6 @@
+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
new file mode 100644
index 000000000..ceb6b11fd
--- /dev/null
+++ b/examples/wayland/server-buffer/share-buffer.xml
@@ -0,0 +1,46 @@
+<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/wayland.pro b/examples/wayland/wayland.pro
index de3a38249..9da43fbd7 100644
--- a/examples/wayland/wayland.pro
+++ b/examples/wayland/wayland.pro
@@ -15,6 +15,7 @@ qtHaveModule(quick) {
SUBDIRS += ivi-compositor
qtHaveModule(waylandclient) {
SUBDIRS += \
- custom-extension
+ custom-extension \
+ server-buffer
}
}
diff --git a/src/client/hardwareintegration/qwaylandserverbufferintegration_p.h b/src/client/hardwareintegration/qwaylandserverbufferintegration_p.h
index 67f857db8..3b8b3a6de 100644
--- a/src/client/hardwareintegration/qwaylandserverbufferintegration_p.h
+++ b/src/client/hardwareintegration/qwaylandserverbufferintegration_p.h
@@ -59,6 +59,8 @@
QT_BEGIN_NAMESPACE
+class QOpenGLTexture;
+
namespace QtWaylandClient {
class QWaylandDisplay;
@@ -74,7 +76,7 @@ public:
QWaylandServerBuffer();
virtual ~QWaylandServerBuffer();
- virtual void bindTextureToBuffer() = 0;
+ virtual QOpenGLTexture *toOpenGlTexture() = 0;
Format format() const;
QSize size() const;
diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp
index 54c075c4a..fe620506d 100644
--- a/src/client/qwaylanddnd.cpp
+++ b/src/client/qwaylanddnd.cpp
@@ -62,13 +62,6 @@ QWaylandDrag::~QWaylandDrag()
{
}
-QMimeData * QWaylandDrag::platformDropData()
-{
- if (drag())
- return drag()->mimeData();
- return 0;
-}
-
void QWaylandDrag::startDrag()
{
QBasicDrag::startDrag();
diff --git a/src/client/qwaylanddnd_p.h b/src/client/qwaylanddnd_p.h
index 2a99432c5..8a1d7f1f1 100644
--- a/src/client/qwaylanddnd_p.h
+++ b/src/client/qwaylanddnd_p.h
@@ -71,8 +71,6 @@ public:
QWaylandDrag(QWaylandDisplay *display);
~QWaylandDrag();
- QMimeData *platformDropData() override;
-
void updateTarget(const QString &mimeType);
void setResponse(const QPlatformDragQtResponse &response);
void finishDrag(const QPlatformDropQtResponse &response);
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index 334e0ec46..5b43428d9 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -89,6 +89,16 @@ QWaylandDisplay * QWaylandScreen::display() const
return mWaylandDisplay;
}
+QString QWaylandScreen::manufacturer() const
+{
+ return mManufacturer;
+}
+
+QString QWaylandScreen::model() const
+{
+ return mModel;
+}
+
QRect QWaylandScreen::geometry() const
{
// Scale geometry for QScreen. This makes window and screen
@@ -203,12 +213,11 @@ void QWaylandScreen::output_geometry(int32_t x, int32_t y,
int32_t transform)
{
Q_UNUSED(subpixel);
- Q_UNUSED(make);
- mTransform = transform;
+ mManufacturer = make;
+ mModel = model;
- if (!model.isEmpty())
- mOutputName = model;
+ mTransform = transform;
mPhysicalSize = QSize(width, height);
mGeometry.moveTopLeft(QPoint(x, y));
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
index 3d4df6e66..674e1a913 100644
--- a/src/client/qwaylandscreen_p.h
+++ b/src/client/qwaylandscreen_p.h
@@ -72,6 +72,9 @@ public:
void init();
QWaylandDisplay *display() const;
+ QString manufacturer() const override;
+ QString model() const override;
+
QRect geometry() const override;
int depth() const override;
QImage::Format format() const override;
@@ -92,7 +95,7 @@ public:
#if QT_CONFIG(cursor)
QPlatformCursor *cursor() const override;
- QWaylandCursor *waylandCursor() const { return mWaylandCursor; };
+ QWaylandCursor *waylandCursor() const { return mWaylandCursor; }
#endif
uint32_t outputId() const { return m_outputId; }
@@ -114,6 +117,8 @@ private:
int m_outputId;
QWaylandDisplay *mWaylandDisplay;
+ QString mManufacturer;
+ QString mModel;
QRect mGeometry;
int mScale;
int mDepth;
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
index 045748a16..2085bc597 100644
--- a/src/client/qwaylandshmbackingstore.cpp
+++ b/src/client/qwaylandshmbackingstore.cpp
@@ -44,6 +44,8 @@
#include "qwaylandabstractdecoration_p.h"
#include <QtCore/qdebug.h>
+#include <QtCore/qstandardpaths.h>
+#include <QtCore/qtemporaryfile.h>
#include <QtGui/QPainter>
#include <QMutexLocker>
#include <QLoggingCategory>
@@ -52,10 +54,14 @@
#include <wayland-client-protocol.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
#include <sys/mman.h>
+#ifdef Q_OS_LINUX
+# include <sys/syscall.h>
+// from linux/memfd.h:
+# define MFD_CLOEXEC 0x0001U
+#endif
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -72,28 +78,36 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
{
int stride = size.width() * 4;
int alloc = stride * size.height();
- char filename[] = "/tmp/wayland-shm-XXXXXX";
- int fd = mkstemp(filename);
- if (fd < 0) {
- qWarning("mkstemp %s failed: %s", filename, strerror(errno));
- return;
+ int fd = -1;
+
+#ifdef SYS_memfd_create
+ fd = syscall(SYS_memfd_create, "wayland-shm", MFD_CLOEXEC);
+#endif
+
+ QScopedPointer<QFile> filePointer;
+
+ if (fd == -1) {
+ auto tmpFile = new QTemporaryFile (QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) +
+ QLatin1String("/wayland-shm-XXXXXX"));
+ tmpFile->open();
+ filePointer.reset(tmpFile);
+ } else {
+ auto file = new QFile;
+ file->open(fd, QIODevice::ReadWrite | QIODevice::Unbuffered, QFile::AutoCloseHandle);
+ filePointer.reset(file);
}
- int flags = fcntl(fd, F_GETFD);
- if (flags != -1)
- fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
-
- if (ftruncate(fd, alloc) < 0) {
- qWarning("ftruncate failed: %s", strerror(errno));
- close(fd);
+ if (!filePointer->isOpen() || !filePointer->resize(alloc)) {
+ qWarning("QWaylandShmBuffer: failed: %s", qUtf8Printable(filePointer->errorString()));
return;
}
+ fd = filePointer->handle();
+
+ // map ourselves: QFile::map() will unmap when the object is destroyed,
+ // but we want this mapping to persist (unmapping in destructor)
uchar *data = (uchar *)
mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- unlink(filename);
-
if (data == (uchar *) MAP_FAILED) {
- qWarning("mmap /dev/zero failed: %s", strerror(errno));
- close(fd);
+ qErrnoWarning("QWaylandShmBuffer: mmap failed");
return;
}
@@ -105,7 +119,6 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
mShmPool = wl_shm_create_pool(shm->object(), fd, alloc);
init(wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(),
stride, wl_format));
- close(fd);
}
QWaylandShmBuffer::~QWaylandShmBuffer(void)
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 6d7c0885c..cff380e8f 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -111,7 +111,7 @@ QWaylandWindow::~QWaylandWindow()
delete mWindowDecoration;
if (isInitialized())
- reset();
+ reset(false);
QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
for (int i = 0; i < inputDevices.size(); ++i)
@@ -133,8 +133,11 @@ void QWaylandWindow::initWindow()
if (window()->type() == Qt::Desktop)
return;
- if (!isInitialized())
+ if (!isInitialized()) {
initializeWlSurface();
+ QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
+ QGuiApplication::sendEvent(window(), &e);
+ }
if (shouldCreateSubSurface()) {
Q_ASSERT(!mSubSurfaceWindow);
@@ -212,7 +215,7 @@ void QWaylandWindow::initWindow()
// but since we're creating the shellsurface only now we reset mState to
// make sure the state gets sent out to the compositor
mState = Qt::WindowNoState;
- setWindowStateInternal(window()->windowState());
+ setWindowStateInternal(window()->windowStates());
handleContentOrientationChange(window()->contentOrientation());
mFlags = window()->flags();
}
@@ -241,8 +244,12 @@ bool QWaylandWindow::shouldCreateSubSurface() const
return QPlatformWindow::parent() != Q_NULLPTR;
}
-void QWaylandWindow::reset()
+void QWaylandWindow::reset(bool sendDestroyEvent)
{
+ if (isInitialized() && sendDestroyEvent) {
+ QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
+ QGuiApplication::sendEvent(window(), &e);
+ }
delete mShellSurface;
mShellSurface = 0;
delete mSubSurfaceWindow;
@@ -677,7 +684,7 @@ void QWaylandWindow::setOrientationMask(Qt::ScreenOrientations mask)
mShellSurface->setContentOrientationMask(mask);
}
-void QWaylandWindow::setWindowState(Qt::WindowState state)
+void QWaylandWindow::setWindowState(Qt::WindowStates state)
{
if (setWindowStateInternal(state))
QWindowSystemInterface::flushWindowSystemEvents(); // Required for oldState to work on WindowStateChanged
@@ -695,16 +702,16 @@ void QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
bool QWaylandWindow::createDecoration()
{
// so far only xdg-shell support this "unminimize" trick, may be moved elsewhere
- if (mState == Qt::WindowMinimized) {
+ if (mState & Qt::WindowMinimized) {
QWaylandXdgSurface *xdgSurface = qobject_cast<QWaylandXdgSurface *>(mShellSurface);
if ( xdgSurface ) {
- if (xdgSurface->isFullscreen()) {
- setWindowStateInternal(Qt::WindowFullScreen);
- } else if (xdgSurface->isMaximized()) {
- setWindowStateInternal(Qt::WindowMaximized);
- } else {
- setWindowStateInternal(Qt::WindowNoState);
- }
+ Qt::WindowStates states;
+ if (xdgSurface->isFullscreen())
+ states |= Qt::WindowFullScreen;
+ if (xdgSurface->isMaximized())
+ states |= Qt::WindowMaximized;
+
+ setWindowStateInternal(states);
}
}
@@ -962,7 +969,7 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
return true;
}
-bool QWaylandWindow::setWindowStateInternal(Qt::WindowState state)
+bool QWaylandWindow::setWindowStateInternal(Qt::WindowStates state)
{
if (mState == state) {
return false;
@@ -975,19 +982,14 @@ bool QWaylandWindow::setWindowStateInternal(Qt::WindowState state)
if (mShellSurface) {
createDecoration();
- switch (state) {
- case Qt::WindowFullScreen:
- mShellSurface->setFullscreen();
- break;
- case Qt::WindowMaximized:
- mShellSurface->setMaximized();
- break;
- case Qt::WindowMinimized:
- mShellSurface->setMinimized();
- break;
- default:
- mShellSurface->setNormal();
- }
+ if (state & Qt::WindowMaximized)
+ mShellSurface->setMaximized();
+ if (state & Qt::WindowFullScreen)
+ mShellSurface->setFullscreen();
+ if (state & Qt::WindowMinimized)
+ mShellSurface->setMinimized();
+ if (!state)
+ mShellSurface->setNormal();
}
QWindowSystemInterface::handleWindowStateChanged(window(), mState);
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index bd4a35909..961b7881d 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -147,7 +147,7 @@ public:
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
void setOrientationMask(Qt::ScreenOrientations mask);
- void setWindowState(Qt::WindowState state) override;
+ void setWindowState(Qt::WindowStates state) override;
void setWindowFlags(Qt::WindowFlags flags) override;
void raise() override;
@@ -172,8 +172,8 @@ public:
bool createDecoration();
- inline bool isMaximized() const { return mState == Qt::WindowMaximized; }
- inline bool isFullscreen() const { return mState == Qt::WindowFullScreen; }
+ inline bool isMaximized() const { return mState & Qt::WindowMaximized; }
+ inline bool isFullscreen() const { return mState & Qt::WindowFullScreen; }
#if QT_CONFIG(cursor)
void setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor);
@@ -241,7 +241,7 @@ protected:
QIcon mWindowIcon;
- Qt::WindowState mState;
+ Qt::WindowStates mState;
Qt::WindowFlags mFlags;
QRegion mMask;
@@ -251,13 +251,13 @@ private slots:
void handleScreenRemoved(QScreen *qScreen);
private:
- bool setWindowStateInternal(Qt::WindowState flags);
+ bool setWindowStateInternal(Qt::WindowStates flags);
void setGeometry_helper(const QRect &rect);
void initWindow();
void initializeWlSurface();
bool shouldCreateShellSurface() const;
bool shouldCreateSubSurface() const;
- void reset();
+ void reset(bool sendDestroyEvent = true);
void sendExposeEvent(const QRect &rect);
static void closePopups(QWaylandWindow *parent);
QWaylandScreen *calculateScreenFromSurfaceEvents() const;
diff --git a/src/client/qwaylandwindowmanagerintegration.cpp b/src/client/qwaylandwindowmanagerintegration.cpp
index 60825aec2..c519126e5 100644
--- a/src/client/qwaylandwindowmanagerintegration.cpp
+++ b/src/client/qwaylandwindowmanagerintegration.cpp
@@ -109,28 +109,6 @@ void QWaylandWindowManagerIntegration::windowmanager_quit()
QGuiApplication::quit();
}
-QByteArray QWaylandWindowManagerIntegration::desktopEnvironment() const
-{
- const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP");
- if (!xdgCurrentDesktop.isEmpty())
- return xdgCurrentDesktop.toUpper(); // KDE, GNOME, UNITY, LXDE, MATE, XFCE...
-
- // Classic fallbacks
- if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION"))
- return QByteArrayLiteral("KDE");
- if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID"))
- return QByteArrayLiteral("GNOME");
-
- // Fallback to checking $DESKTOP_SESSION (unreliable)
- const QByteArray desktopSession = qgetenv("DESKTOP_SESSION");
- if (desktopSession == "gnome")
- return QByteArrayLiteral("GNOME");
- if (desktopSession == "xfce")
- return QByteArrayLiteral("XFCE");
-
- return QByteArrayLiteral("UNKNOWN");
-}
-
void QWaylandWindowManagerIntegration::openUrl_helper(const QUrl &url)
{
Q_ASSERT(isInitialized());
diff --git a/src/client/qwaylandwindowmanagerintegration_p.h b/src/client/qwaylandwindowmanagerintegration_p.h
index cf6ca6605..e399d4f0b 100644
--- a/src/client/qwaylandwindowmanagerintegration_p.h
+++ b/src/client/qwaylandwindowmanagerintegration_p.h
@@ -77,8 +77,6 @@ public:
explicit QWaylandWindowManagerIntegration(QWaylandDisplay *waylandDisplay);
virtual ~QWaylandWindowManagerIntegration();
- QByteArray desktopEnvironment() const override;
-
bool openUrl(const QUrl &url) override;
bool openDocument(const QUrl &url) override;
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index f31bf39e9..a993467ac 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -222,9 +222,11 @@ void QWaylandBufferMaterial::bind()
case 3:
if (m_textures[2])
m_textures[2]->bind(GL_TEXTURE2);
+ Q_FALLTHROUGH();
case 2:
if (m_textures[1])
m_textures[1]->bind(GL_TEXTURE1);
+ Q_FALLTHROUGH();
case 1:
if (m_textures[0])
m_textures[0]->bind(GL_TEXTURE0);
diff --git a/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc b/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
index 1c3cc13ce..6be6444cc 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
@@ -30,10 +30,58 @@
\title Qt Wayland Compositor
\brief An API to develop display servers supporting the Wayland protocol
- Qt Wayland Compositor is a module that provides QML and C++ APIs for
- developing custom display servers based on the
- \l{http://wayland.freedesktop.org}{Wayland protocol}. The server displays
- content from client applications that support the Wayland protocol.
+ \l {https://wayland.freedesktop.org/} {Wayland} is a display server
+ protocol to help in creating multi-process systems, where multiple client
+ applications may render content on the same display, by going via
+ a compositor process.
+
+ Compared to a system with a single-process design, a multi-process system
+ gives several benefits:
+
+ \list
+ \li Easier resource management, through the regular operating system mechanisms.
+ \li Better security, as each application can run with its own permissions or
+ sandbox.
+ \li Clearer separation of application UI and compositor UI, so each
+ can be modified independently.
+ \endlist
+
+ In a typical Wayland-based system, multiple client processes will render their
+ own contents to off-screen buffers. The information about these buffers will
+ then be passed to a display server process by using the Wayland protocol.
+ Finally, the display server process will composite and position the contents
+ on a physical display.
+
+ Qt Wayland Compositor is a module that provides convenient and powerful
+ QML and C++ APIs for developing custom display servers based on this protocol.
+ The server displays content from client applications that support the Wayland
+ protocol. The design philosophy of Wayland is to keep the core protocol simple
+ and minimal, and to expand on this with use-case-specific extensions. Qt Wayland
+ Compositor supports many common extensions by default, and also has APIs that
+ enables the creation of new, custom extensions.
+
+ In one typical use case, a display server written with Qt Wayland Compositor will
+ be a subsystem inside a larger application manager process. Qt Wayland Compositor
+ provides the APIs to communicate with clients and display their contents on screen,
+ using C++ for low-level access and the full set of Qt Quick effects, animations and
+ convenience when using the QML APIs. A typical application manager would, in addition
+ to this, implement features such as application life cycle, virtual keyboard input,
+ security and IPC. Qt provides APIs that can be used to develop the remaining parts
+ of an application manager in other modules. The \l {https://www.qt.io/qt-automotive-suite/}
+ {Qt Automotive Suite} provides a complete application manager which includes a
+ display server developed using Qt Wayland Compositor.
+
+ \section1 Features of Qt Wayland Compositor
+
+ The Qt Wayland Compositor API includes features needed to create a display server.
+
+ \list
+ \li A QML API that can be used to display and manipulate client content, fully
+ integrated with all the features in Qt Quick.
+ \li A C++ API for low-level access and control.
+ \li Support for common extensions, including XDG Shell and IVI Application.
+ \li APIs to easily expand support to include custom extensions.
+ \endlist
\section1 Environment Variables and Command-line Arguments
diff --git a/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc b/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
index 195204383..1dadb7102 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
@@ -26,7 +26,7 @@
****************************************************************************/
/*!
- \qmlmodule QtWayland.Compositor 1.0
+ \qmlmodule QtWayland.Compositor 1.1
\title Qt Wayland Compositor QML Types
\ingroup qmlmodules
\brief Provides QML types for writing custom Wayland display servers.
@@ -38,7 +38,7 @@
import statement:
\code
- import QtWayland.Compositor 1.0
+ import QtWayland.Compositor 1.1
\endcode
To link against the module, add this line to your \l qmake \c .pro file:
diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri
index 9c5b37eac..9cb0bcfa1 100644
--- a/src/compositor/extensions/extensions.pri
+++ b/src/compositor/extensions/extensions.pri
@@ -8,6 +8,7 @@ WAYLANDSERVERSOURCES += \
../extensions/qt-windowmanager.xml \
../3rdparty/protocol/text-input-unstable-v2.xml \
../3rdparty/protocol/xdg-shell.xml \
+ ../3rdparty/protocol/xdg-shell-unstable-v6.xml \
../3rdparty/protocol/ivi-application.xml \
HEADERS += \
@@ -26,6 +27,8 @@ HEADERS += \
extensions/qwaylandqtwindowmanager_p.h \
extensions/qwaylandxdgshellv5.h \
extensions/qwaylandxdgshellv5_p.h \
+ extensions/qwaylandxdgshellv6.h \
+ extensions/qwaylandxdgshellv6_p.h \
extensions/qwaylandshellsurface.h \
extensions/qwaylandiviapplication.h \
extensions/qwaylandiviapplication_p.h \
@@ -42,6 +45,7 @@ SOURCES += \
extensions/qwaylandtextinputmanager.cpp \
extensions/qwaylandqtwindowmanager.cpp \
extensions/qwaylandxdgshellv5.cpp \
+ extensions/qwaylandxdgshellv6.cpp \
extensions/qwaylandiviapplication.cpp \
extensions/qwaylandivisurface.cpp \
@@ -52,12 +56,14 @@ qtHaveModule(quick):contains(QT_CONFIG, opengl) {
extensions/qwaylandivisurfaceintegration_p.h \
extensions/qwaylandwlshellintegration_p.h \
extensions/qwaylandxdgshellv5integration_p.h \
+ extensions/qwaylandxdgshellv6integration_p.h \
SOURCES += \
extensions/qwaylandquickshellsurfaceitem.cpp \
extensions/qwaylandivisurfaceintegration.cpp \
extensions/qwaylandwlshellintegration.cpp \
extensions/qwaylandxdgshellv5integration.cpp \
+ extensions/qwaylandxdgshellv6integration.cpp \
}
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
index 289f706ca..2b603099b 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
@@ -78,6 +78,12 @@ QWaylandQuickShellSurfaceItem::QWaylandQuickShellSurfaceItem(QQuickItem *parent)
{
}
+QWaylandQuickShellSurfaceItem::~QWaylandQuickShellSurfaceItem()
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ delete d->m_shellIntegration;
+}
+
/*!
* \internal
*/
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
index 549f43457..152d5c53e 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
@@ -56,6 +56,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellSurfaceItem : public QWaylan
Q_PROPERTY(QQuickItem *moveItem READ moveItem WRITE setMoveItem NOTIFY moveItemChanged)
public:
QWaylandQuickShellSurfaceItem(QQuickItem *parent = nullptr);
+ ~QWaylandQuickShellSurfaceItem();
QWaylandShellSurface *shellSurface() const;
void setShellSurface(QWaylandShellSurface *shellSurface);
diff --git a/src/compositor/extensions/qwaylandxdgshellv6.cpp b/src/compositor/extensions/qwaylandxdgshellv6.cpp
new file mode 100644
index 000000000..4b1d46b8a
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgshellv6.cpp
@@ -0,0 +1,1901 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandxdgshellv6.h"
+#include "qwaylandxdgshellv6_p.h"
+
+#ifdef QT_WAYLAND_COMPOSITOR_QUICK
+#include "qwaylandxdgshellv6integration_p.h"
+#endif
+
+#include <QtWaylandCompositor/QWaylandCompositor>
+#include <QtWaylandCompositor/QWaylandSeat>
+#include <QtWaylandCompositor/QWaylandSurface>
+#include <QtWaylandCompositor/QWaylandSurfaceRole>
+#include <QtWaylandCompositor/QWaylandResource>
+
+#include <QtCore/QObject>
+
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandXdgShellV6Private::QWaylandXdgShellV6Private()
+ : QWaylandCompositorExtensionPrivate()
+ , zxdg_shell_v6()
+{
+}
+
+void QWaylandXdgShellV6Private::ping(QtWaylandServer::zxdg_shell_v6::Resource *resource, uint32_t serial)
+{
+ m_pings.insert(serial);
+ send_ping(resource->handle, serial);
+}
+
+void QWaylandXdgShellV6Private::registerXdgSurface(QWaylandXdgSurfaceV6 *xdgSurface)
+{
+ m_xdgSurfaces.insert(xdgSurface->surface()->client()->client(), xdgSurface);
+}
+
+void QWaylandXdgShellV6Private::unregisterXdgSurface(QWaylandXdgSurfaceV6 *xdgSurface)
+{
+ auto xdgSurfacePrivate = QWaylandXdgSurfaceV6Private::get(xdgSurface);
+ if (!m_xdgSurfaces.remove(xdgSurfacePrivate->resource()->client(), xdgSurface))
+ qWarning("%s Unexpected state. Can't find registered xdg surface\n", Q_FUNC_INFO);
+}
+
+Qt::Edges QWaylandXdgShellV6Private::convertToEdges(uint xdgEdges)
+{
+ return Qt::Edges(((xdgEdges & 0b1100) >> 1) | ((xdgEdges & 0b0010) << 2) | (xdgEdges & 0b0001));
+}
+
+QWaylandXdgSurfaceV6 *QWaylandXdgShellV6Private::xdgSurfaceFromSurface(QWaylandSurface *surface)
+{
+ for (QWaylandXdgSurfaceV6 *xdgSurface : qAsConst(m_xdgSurfaces)) {
+ if (surface == xdgSurface->surface())
+ return xdgSurface;
+ }
+ return nullptr;
+}
+
+void QWaylandXdgShellV6Private::zxdg_shell_v6_destroy(Resource *resource)
+{
+ if (!m_xdgSurfaces.values(resource->client()).empty())
+ wl_resource_post_error(resource->handle, ZXDG_SHELL_V6_ERROR_DEFUNCT_SURFACES,
+ "xdg_shell was destroyed before children");
+
+ wl_resource_destroy(resource->handle);
+}
+
+void QWaylandXdgShellV6Private::zxdg_shell_v6_create_positioner(QtWaylandServer::zxdg_shell_v6::Resource *resource, uint32_t id)
+{
+ QWaylandResource positionerResource(wl_resource_create(resource->client(), &zxdg_positioner_v6_interface,
+ wl_resource_get_version(resource->handle), id));
+
+ new QWaylandXdgPositionerV6(positionerResource);
+}
+
+void QWaylandXdgShellV6Private::zxdg_shell_v6_get_xdg_surface(Resource *resource, uint32_t id, wl_resource *surfaceResource)
+{
+ Q_Q(QWaylandXdgShellV6);
+ QWaylandSurface *surface = QWaylandSurface::fromResource(surfaceResource);
+
+ if (surface->role() != nullptr) {
+ wl_resource_post_error(resource->handle, ZXDG_SHELL_V6_ERROR_ROLE,
+ "wl_surface@%d, already has role %s\n",
+ wl_resource_get_id(surface->resource()),
+ surface->role()->name().constData());
+ return;
+ }
+
+ if (surface->hasContent()) {
+ //TODO: According to the spec, this is a client error, but there's no appropriate error code
+ qWarning() << "get_xdg_surface requested on a zxdg_surface_v6 with content";
+ }
+
+ QWaylandResource xdgSurfaceResource(wl_resource_create(resource->client(), &zxdg_surface_v6_interface,
+ wl_resource_get_version(resource->handle), id));
+
+ QWaylandXdgSurfaceV6 *xdgSurface = new QWaylandXdgSurfaceV6(q, surface, xdgSurfaceResource);
+
+ registerXdgSurface(xdgSurface);
+ emit q->xdgSurfaceCreated(xdgSurface);
+}
+
+void QWaylandXdgShellV6Private::zxdg_shell_v6_pong(Resource *resource, uint32_t serial)
+{
+ Q_UNUSED(resource);
+ Q_Q(QWaylandXdgShellV6);
+ if (m_pings.remove(serial))
+ emit q->pong(serial);
+ else
+ qWarning("Received an unexpected pong!");
+}
+
+/*!
+ * \qmltype XdgShellV6
+ * \inqmlmodule QtWayland.Compositor
+ * \since 5.10
+ * \brief Provides an extension for desktop-style user interfaces.
+ *
+ * The XdgShellV6 extension provides a way to associate a XdgToplevelV6 or XdgPopupV6
+ * with a regular Wayland surface. Using the XdgToplevelV6 interface, the client
+ * can request that the surface is resized, moved, and so on.
+ *
+ * XdgShellV6 corresponds to the Wayland interface, \c zxdg_shell_v6.
+ *
+ * To provide the functionality of the shell extension in a compositor, create
+ * an instance of the XdgShellV6 component and add it to the list of extensions
+ * supported by the compositor:
+ * \code
+ * import QtWayland.Compositor 1.1
+ *
+ * WaylandCompositor {
+ * XdgShellV6 {
+ * // ...
+ * }
+ * }
+ * \endcode
+ */
+
+/*!
+ * \class QWaylandXdgShellV6
+ * \inmodule QtWaylandCompositor
+ * \since 5.10
+ * \brief The QWaylandXdgShellV6 class is an extension for desktop-style user interfaces.
+ *
+ * The QWaylandXdgShellV6 extension provides a way to associate a QWaylandXdgToplevelV6 or
+ * QWaylandXdgPopupV6 with a regular Wayland surface. Using the QWaylandXdgToplevelV6 interface,
+ * the client can request that the surface is resized, moved, and so on.
+ *
+ * QWaylandXdgShellV6 corresponds to the Wayland interface, \c zxdg_shell_v6.
+ */
+
+/*!
+ * Constructs a QWaylandXdgShellV6 object.
+ */
+QWaylandXdgShellV6::QWaylandXdgShellV6()
+ : QWaylandShellTemplate<QWaylandXdgShellV6>(*new QWaylandXdgShellV6Private())
+{
+}
+
+/*!
+ * Constructs a QWaylandXdgShellV6 object for the provided \a compositor.
+ */
+QWaylandXdgShellV6::QWaylandXdgShellV6(QWaylandCompositor *compositor)
+ : QWaylandShellTemplate<QWaylandXdgShellV6>(compositor, *new QWaylandXdgShellV6Private())
+{
+}
+
+/*!
+ * Initializes the shell extension.
+ */
+void QWaylandXdgShellV6::initialize()
+{
+ Q_D(QWaylandXdgShellV6);
+ QWaylandShellTemplate::initialize();
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ if (!compositor) {
+ qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandXdgShellV6";
+ return;
+ }
+ d->init(compositor->display(), 1);
+
+ handleSeatChanged(compositor->defaultSeat(), nullptr);
+
+ connect(compositor, &QWaylandCompositor::defaultSeatChanged,
+ this, &QWaylandXdgShellV6::handleSeatChanged);
+}
+
+/*!
+ * Returns the Wayland interface for the QWaylandXdgShellV6.
+ */
+const struct wl_interface *QWaylandXdgShellV6::interface()
+{
+ return QWaylandXdgShellV6Private::interface();
+}
+
+QByteArray QWaylandXdgShellV6::interfaceName()
+{
+ return QWaylandXdgShellV6Private::interfaceName();
+}
+
+/*!
+ * \qmlmethod void QtWaylandCompositor::XdgShellV6::ping()
+ *
+ * Sends a ping event to the client. If the client replies to the event the
+ * \a pong signal will be emitted.
+ */
+
+/*!
+ * Sends a ping event to the client. If the client replies to the event the
+ * \a pong signal will be emitted.
+ */
+uint QWaylandXdgShellV6::ping(QWaylandClient *client)
+{
+ Q_D(QWaylandXdgShellV6);
+
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ Q_ASSERT(compositor);
+
+ uint32_t serial = compositor->nextSerial();
+
+ QWaylandXdgShellV6Private::Resource *clientResource = d->resourceMap().value(client->client(), nullptr);
+ Q_ASSERT(clientResource);
+
+ d->ping(clientResource, serial);
+ return serial;
+}
+
+void QWaylandXdgShellV6::handleSeatChanged(QWaylandSeat *newSeat, QWaylandSeat *oldSeat)
+{
+ if (oldSeat != nullptr) {
+ disconnect(oldSeat, &QWaylandSeat::keyboardFocusChanged,
+ this, &QWaylandXdgShellV6::handleFocusChanged);
+ }
+
+ if (newSeat != nullptr) {
+ connect(newSeat, &QWaylandSeat::keyboardFocusChanged,
+ this, &QWaylandXdgShellV6::handleFocusChanged);
+ }
+}
+
+void QWaylandXdgShellV6::handleFocusChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface)
+{
+ Q_D(QWaylandXdgShellV6);
+
+ QWaylandXdgSurfaceV6 *newXdgSurface = d->xdgSurfaceFromSurface(newSurface);
+ QWaylandXdgSurfaceV6 *oldXdgSurface = d->xdgSurfaceFromSurface(oldSurface);
+
+ if (newXdgSurface)
+ QWaylandXdgSurfaceV6Private::get(newXdgSurface)->handleFocusReceived();
+
+ if (oldXdgSurface)
+ QWaylandXdgSurfaceV6Private::get(oldXdgSurface)->handleFocusLost();
+}
+
+QWaylandXdgSurfaceV6Private::QWaylandXdgSurfaceV6Private()
+ : QWaylandCompositorExtensionPrivate()
+ , zxdg_surface_v6()
+ , m_xdgShell(nullptr)
+ , m_surface(nullptr)
+ , m_toplevel(nullptr)
+ , m_popup(nullptr)
+ , m_unsetWindowGeometry(true)
+ , m_windowType(Qt::WindowType::Window)
+{
+}
+
+void QWaylandXdgSurfaceV6Private::setWindowType(Qt::WindowType windowType)
+{
+ if (m_windowType == windowType)
+ return;
+
+ m_windowType = windowType;
+
+ Q_Q(QWaylandXdgSurfaceV6);
+ emit q->windowTypeChanged();
+}
+
+void QWaylandXdgSurfaceV6Private::handleFocusLost()
+{
+ if (m_toplevel)
+ QWaylandXdgToplevelV6Private::get(m_toplevel)->handleFocusLost();
+}
+
+void QWaylandXdgSurfaceV6Private::handleFocusReceived()
+{
+ if (m_toplevel)
+ QWaylandXdgToplevelV6Private::get(m_toplevel)->handleFocusReceived();
+}
+
+QRect QWaylandXdgSurfaceV6Private::calculateFallbackWindowGeometry() const
+{
+ // TODO: The unset window geometry should include subsurfaces as well, so this solution
+ // won't work too well on those kinds of clients.
+ return QRect(QPoint(0, 0), m_surface->size() / m_surface->bufferScale());
+}
+
+void QWaylandXdgSurfaceV6Private::updateFallbackWindowGeometry()
+{
+ Q_Q(QWaylandXdgSurfaceV6);
+ if (!m_unsetWindowGeometry)
+ return;
+
+ const QRect unsetGeometry = calculateFallbackWindowGeometry();
+ if (unsetGeometry == m_windowGeometry)
+ return;
+
+ m_windowGeometry = unsetGeometry;
+ emit q->windowGeometryChanged();
+}
+
+void QWaylandXdgSurfaceV6Private::zxdg_surface_v6_destroy_resource(QtWaylandServer::zxdg_surface_v6::Resource *resource)
+{
+ Q_UNUSED(resource);
+ Q_Q(QWaylandXdgSurfaceV6);
+ QWaylandXdgShellV6Private::get(m_xdgShell)->unregisterXdgSurface(q);
+ delete q;
+}
+
+void QWaylandXdgSurfaceV6Private::zxdg_surface_v6_destroy(QtWaylandServer::zxdg_surface_v6::Resource *resource)
+{
+ wl_resource_destroy(resource->handle);
+}
+
+void QWaylandXdgSurfaceV6Private::zxdg_surface_v6_get_toplevel(QtWaylandServer::zxdg_surface_v6::Resource *resource, uint32_t id)
+{
+ Q_Q(QWaylandXdgSurfaceV6);
+
+ if (m_toplevel || m_popup) {
+ wl_resource_post_error(resource->handle, ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED,
+ "zxdg_surface_v6 already has a role object");
+ return;
+ }
+
+ if (!m_surface->setRole(QWaylandXdgToplevelV6::role(), resource->handle, ZXDG_SHELL_V6_ERROR_ROLE))
+ return;
+
+ QWaylandResource topLevelResource(wl_resource_create(resource->client(), &zxdg_toplevel_v6_interface,
+ wl_resource_get_version(resource->handle), id));
+
+ m_toplevel = new QWaylandXdgToplevelV6(q, topLevelResource);
+ emit q->toplevelCreated();
+ emit m_xdgShell->toplevelCreated(m_toplevel, q);
+}
+
+void QWaylandXdgSurfaceV6Private::zxdg_surface_v6_get_popup(QtWaylandServer::zxdg_surface_v6::Resource *resource, uint32_t id, wl_resource *parentResource, wl_resource *positionerResource)
+{
+ Q_Q(QWaylandXdgSurfaceV6);
+
+ if (m_toplevel || m_popup) {
+ wl_resource_post_error(resource->handle, ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED,
+ "zxdg_surface_v6 already has a role object");
+ return;
+ }
+
+ QWaylandXdgSurfaceV6 *parent = QWaylandXdgSurfaceV6::fromResource(parentResource);
+ if (!parent) {
+ wl_resource_post_error(resource->handle, ZXDG_SHELL_V6_ERROR_INVALID_POPUP_PARENT,
+ "zxdg_surface_v6.get_popup with invalid popup parent");
+ return;
+ }
+
+ QWaylandXdgPositionerV6 *positioner = QWaylandXdgPositionerV6::fromResource(positionerResource);
+ if (!positioner) {
+ wl_resource_post_error(resource->handle, ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
+ "zxdg_surface_v6.get_popup without positioner");
+ return;
+ }
+ if (!positioner->m_data.isComplete()) {
+ QWaylandXdgPositionerV6Data p = positioner->m_data;
+ wl_resource_post_error(resource->handle, ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
+ "zxdg_surface_v6.get_popup with invalid positioner (size: %dx%d, anchorRect: %dx%d)",
+ p.size.width(), p.size.height(), p.anchorRect.width(), p.anchorRect.height());
+ return;
+ }
+
+ if (!m_surface->setRole(QWaylandXdgPopupV6::role(), resource->handle, ZXDG_SHELL_V6_ERROR_ROLE))
+ return;
+
+ QWaylandResource popupResource(wl_resource_create(resource->client(), &zxdg_popup_v6_interface,
+ wl_resource_get_version(resource->handle), id));
+
+ m_popup = new QWaylandXdgPopupV6(q, parent, positioner, popupResource);
+ emit q->popupCreated();
+ emit m_xdgShell->popupCreated(m_popup, q);
+}
+
+void QWaylandXdgSurfaceV6Private::zxdg_surface_v6_ack_configure(QtWaylandServer::zxdg_surface_v6::Resource *resource, uint32_t serial)
+{
+ if (m_toplevel) {
+ QWaylandXdgToplevelV6Private::get(m_toplevel)->handleAckConfigure(serial);
+ } else if (m_popup) {
+ QWaylandXdgPopupV6Private::get(m_popup)->handleAckConfigure(serial);
+ } else {
+ wl_resource_post_error(resource->handle, ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+ "ack_configure requested on an unconstructed zxdg_surface_v6");
+ }
+}
+
+void QWaylandXdgSurfaceV6Private::zxdg_surface_v6_set_window_geometry(QtWaylandServer::zxdg_surface_v6::Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ Q_Q(QWaylandXdgSurfaceV6);
+
+ if (!q->surface()->role()) {
+ wl_resource_post_error(resource->handle, ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+ "set_window_geometry requested on an unconstructed zxdg_surface_v6");
+ return;
+ }
+
+ if (width <= 0 || height <= 0) {
+ // The protocol spec says "setting an invalid size will raise an error". But doesn't tell
+ // which error to raise, and there's no fitting error in the zxdg_surface_v6_error enum.
+ // So until this is fixed, just output a warning and return.
+ qWarning() << "Invalid (non-positive) dimensions received in set_window_geometry";
+ return;
+ }
+
+ m_unsetWindowGeometry = false;
+
+ QRect geometry(x, y, width, height);
+
+ if (m_windowGeometry == geometry)
+ return;
+
+ m_windowGeometry = geometry;
+ emit q->windowGeometryChanged();
+}
+
+/*!
+ * \qmltype XdgSurfaceV6
+ * \inqmlmodule QtWayland.Compositor
+ * \since 5.10
+ * \brief XdgSurfaceV6 provides desktop-style compositor-specific features to an xdg surface.
+ *
+ * This type is part of the \l{XdgShellV6} extension and provides a way to
+ * extend the functionality of an existing \l{WaylandSurface} with features
+ * specific to desktop-style compositors, such as resizing and moving the
+ * surface.
+ *
+ * It corresponds to the Wayland interface \c zxdg_surface_v6.
+ */
+
+/*!
+ * \class QWaylandXdgSurfaceV6
+ * \inmodule QtWaylandCompositor
+ * \since 5.8
+ * \brief The QWaylandXdgSurfaceV6 class provides desktop-style compositor-specific features to an xdg surface.
+ *
+ * This class is part of the QWaylandXdgShellV6 extension and provides a way to
+ * extend the functionality of an existing QWaylandSurface with features
+ * specific to desktop-style compositors, such as resizing and moving the
+ * surface.
+ *
+ * It corresponds to the Wayland interface \c zxdg_surface_v6.
+ */
+
+/*!
+ * Constructs a QWaylandXdgSurfaceV6.
+ */
+QWaylandXdgSurfaceV6::QWaylandXdgSurfaceV6()
+ : QWaylandShellSurfaceTemplate<QWaylandXdgSurfaceV6>(*new QWaylandXdgSurfaceV6Private)
+{
+}
+
+/*!
+ * Constructs a QWaylandXdgSurfaceV6 for \a surface and initializes it with the
+ * given \a xdgShell, \a surface, and resource \a res.
+ */
+QWaylandXdgSurfaceV6::QWaylandXdgSurfaceV6(QWaylandXdgShellV6 *xdgShell, QWaylandSurface *surface, const QWaylandResource &res)
+ : QWaylandShellSurfaceTemplate<QWaylandXdgSurfaceV6>(*new QWaylandXdgSurfaceV6Private)
+{
+ initialize(xdgShell, surface, res);
+}
+
+/*!
+ * \qmlmethod void QtWaylandCompositor::XdgSurfaceV6::initialize(object xdgShell, object surface, object client, int id)
+ *
+ * Initializes the XdgSurface, associating it with the given \a xdgShell, \a surface,
+ * \a client, and \a id.
+ */
+
+/*!
+ * Initializes the QWaylandXdgSurfaceV6, associating it with the given \a xdgShell, \a surface
+ * and \a resource.
+ */
+void QWaylandXdgSurfaceV6::initialize(QWaylandXdgShellV6 *xdgShell, QWaylandSurface *surface, const QWaylandResource &resource)
+{
+ Q_D(QWaylandXdgSurfaceV6);
+ d->m_xdgShell = xdgShell;
+ d->m_surface = surface;
+ d->init(resource.resource());
+ setExtensionContainer(surface);
+ d->m_windowGeometry = d->calculateFallbackWindowGeometry();
+ connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandXdgSurfaceV6::handleSurfaceSizeChanged);
+ connect(surface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandXdgSurfaceV6::handleBufferScaleChanged);
+ emit shellChanged();
+ emit surfaceChanged();
+ QWaylandCompositorExtension::initialize();
+}
+
+/*!
+ * \qmlproperty enum QtWaylandCompositor::XdgSurfaceV6::windowType
+ *
+ * This property holds the window type of the XdgSurfaceV6.
+ */
+
+/*!
+ * \property QWaylandXdgSurfaceV6::windowType
+ *
+ * This property holds the window type of the QWaylandXdgSurfaceV6.
+ */
+Qt::WindowType QWaylandXdgSurfaceV6::windowType() const
+{
+ Q_D(const QWaylandXdgSurfaceV6);
+ return d->m_windowType;
+}
+
+/*!
+ * \qmlproperty rect QtWaylandCompositor::XdgSurfaceV6::windowGeometry
+ *
+ * This property holds the window geometry of the QWaylandXdgSurfaceV6. The window
+ * geometry describes the window's visible bounds from the user's perspective.
+ * The geometry includes title bars and borders if drawn by the client, but
+ * excludes drop shadows. It is meant to be used for aligning and tiling
+ * windows.
+ */
+
+/*!
+ * \property QWaylandXdgSurfaceV6::windowGeometry
+ *
+ * This property holds the window geometry of the QWaylandXdgSurfaceV6. The window
+ * geometry describes the window's visible bounds from the user's perspective.
+ * The geometry includes title bars and borders if drawn by the client, but
+ * excludes drop shadows. It is meant to be used for aligning and tiling
+ * windows.
+ */
+QRect QWaylandXdgSurfaceV6::windowGeometry() const
+{
+ Q_D(const QWaylandXdgSurfaceV6);
+ return d->m_windowGeometry;
+}
+
+/*!
+ * \internal
+ */
+void QWaylandXdgSurfaceV6::initialize()
+{
+ QWaylandCompositorExtension::initialize();
+}
+
+void QWaylandXdgSurfaceV6::handleSurfaceSizeChanged()
+{
+ Q_D(QWaylandXdgSurfaceV6);
+ d->updateFallbackWindowGeometry();
+}
+
+void QWaylandXdgSurfaceV6::handleBufferScaleChanged()
+{
+ Q_D(QWaylandXdgSurfaceV6);
+ d->updateFallbackWindowGeometry();
+}
+
+/*!
+ * \qmlproperty XdgShellV6 QtWaylandCompositor::XdgSurfaceV6::shell
+ *
+ * This property holds the shell associated with this XdgSurface.
+ */
+
+/*!
+ * \property QWaylandXdgSurfaceV6::shell
+ *
+ * This property holds the shell associated with this QWaylandXdgSurfaceV6.
+ */
+QWaylandXdgShellV6 *QWaylandXdgSurfaceV6::shell() const
+{
+ Q_D(const QWaylandXdgSurfaceV6);
+ return d->m_xdgShell;
+}
+
+/*!
+ * \qmlproperty WaylandSurface QtWaylandCompositor::XdgSurfaceV6::surface
+ *
+ * This property holds the surface associated with this XdgSurface.
+ */
+
+/*!
+ * \property QWaylandXdgSurfaceV6::surface
+ *
+ * This property holds the surface associated with this QWaylandXdgSurfaceV6.
+ */
+QWaylandSurface *QWaylandXdgSurfaceV6::surface() const
+{
+ Q_D(const QWaylandXdgSurfaceV6);
+ return d->m_surface;
+}
+
+QWaylandXdgToplevelV6 *QWaylandXdgSurfaceV6::toplevel() const
+{
+ Q_D(const QWaylandXdgSurfaceV6);
+ return d->m_toplevel;
+}
+
+QWaylandXdgPopupV6 *QWaylandXdgSurfaceV6::popup() const
+{
+ Q_D(const QWaylandXdgSurfaceV6);
+ return d->m_popup;
+}
+
+/*!
+ * Returns the Wayland interface for the QWaylandXdgSurfaceV6.
+ */
+const wl_interface *QWaylandXdgSurfaceV6::interface()
+{
+ return QWaylandXdgSurfaceV6Private::interface();
+}
+
+/*!
+ * \internal
+ */
+QByteArray QWaylandXdgSurfaceV6::interfaceName()
+{
+ return QWaylandXdgSurfaceV6Private::interfaceName();
+}
+
+/*!
+ * Returns the QWaylandXdgSurfaceV6 corresponding to the \a resource.
+ */
+QWaylandXdgSurfaceV6 *QWaylandXdgSurfaceV6::fromResource(wl_resource *resource)
+{
+ auto xsResource = QWaylandXdgSurfaceV6Private::Resource::fromResource(resource);
+ if (!xsResource)
+ return nullptr;
+ return static_cast<QWaylandXdgSurfaceV6Private *>(xsResource->zxdg_surface_v6_object)->q_func();
+}
+
+#ifdef QT_WAYLAND_COMPOSITOR_QUICK
+QWaylandQuickShellIntegration *QWaylandXdgSurfaceV6::createIntegration(QWaylandQuickShellSurfaceItem *item)
+{
+ Q_D(const QWaylandXdgSurfaceV6);
+
+ if (d->m_toplevel)
+ return new QtWayland::XdgToplevelV6Integration(item);
+
+ if (d->m_popup)
+ return new QtWayland::XdgPopupV6Integration(item);
+
+ return nullptr;
+}
+#endif
+
+/*!
+ * \qmltype XdgToplevelV6
+ * \inqmlmodule QtWayland.Compositor
+ * \since 5.10
+ * \brief XdgToplevelV6 represents the toplevel window specific parts of an xdg surface
+ *
+ * This type is part of the \l{XdgShellV6} extension and provides a way to
+ * extend the functionality of an QWaylandXdgSurfaceV6 with features
+ * specific to desktop-style windows.
+ *
+ * It corresponds to the Wayland interface \c zxdg_toplevel_v6.
+ */
+
+/*!
+ * \class QWaylandXdgToplevelV6
+ * \inmodule QtWaylandCompositor
+ * \since 5.10
+ * \brief The QWaylandXdgToplevelV6 class represents the toplevel window specific parts of an xdg surface
+ *
+ * This class is part of the QWaylandXdgShellV6 extension and provides a way to
+ * extend the functionality of an QWaylandXdgSurfaceV6 with features
+ * specific to desktop-style windows.
+ *
+ * It corresponds to the Wayland interface \c zxdg_toplevel_v6.
+ */
+
+/*!
+ * Constructs a QWaylandXdgToplevelV6.
+ */
+QWaylandXdgToplevelV6::QWaylandXdgToplevelV6(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandResource &resource)
+ : QObject(*new QWaylandXdgToplevelV6Private(xdgSurface, resource))
+{
+ QVector<QWaylandXdgToplevelV6::State> states;
+ sendConfigure({0, 0}, states);
+}
+
+/*!
+ * \qmlproperty XdgToplevelV6 QtWaylandCompositor::XdgToplevelV6::parentToplevel
+ *
+ * This property holds the XdgToplevelV6 parent of this XdgToplevelV6.
+ */
+
+/*!
+ * \property QWaylandXdgSurfaceV6::parentToplevel
+ *
+ * This property holds the XdgToplevelV6 parent of this XdgToplevelV6.
+ *
+ */
+QWaylandXdgToplevelV6 *QWaylandXdgToplevelV6::parentToplevel() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_parentToplevel;
+}
+
+/*!
+ * \qmlproperty string QtWaylandCompositor::XdgToplevelV6::title
+ *
+ * This property holds the title of the XdgToplevelV6.
+ */
+
+/*!
+ * \property QWaylandXdgToplevelV6::title
+ *
+ * This property holds the title of the QWaylandXdgToplevelV6.
+ */
+QString QWaylandXdgToplevelV6::title() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_title;
+}
+
+/*!
+ * \qmlproperty string QtWaylandCompositor::XdgToplevelV6::appId
+ *
+ * This property holds the app id of the XdgToplevelV6.
+ */
+
+/*!
+ * \property QWaylandXdgToplevelV6::appId
+ *
+ * This property holds the app id of the QWaylandXdgToplevelV6.
+ */
+QString QWaylandXdgToplevelV6::appId() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_appId;
+}
+
+/*!
+ * \qmlproperty size QtWaylandCompositor::XdgToplevelV6::maxSize
+ *
+ * This property holds the maximum size of the XdgToplevelV6 as requested by the client.
+ *
+ * The compositor is free to ignore this value and request a larger size.
+ */
+
+/*!
+ * \property QWaylandXdgToplevelV6::maxSize
+ *
+ * This property holds the maximum size of the QWaylandXdgToplevelV6.
+ *
+ * The compositor is free to ignore this value and request a larger size.
+ */
+QSize QWaylandXdgToplevelV6::maxSize() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_maxSize;
+}
+
+/*!
+ * \qmlproperty size QtWaylandCompositor::XdgToplevelV6::minSize
+ *
+ * This property holds the minimum size of the XdgToplevelV6 as requested by the client.
+ *
+ * The compositor is free to ignore this value and request a smaller size.
+ */
+
+/*!
+ * \property QWaylandXdgToplevelV6::minSize
+ *
+ * This property holds the minimum size of the QWaylandXdgToplevelV6.
+ *
+ * The compositor is free to ignore this value and request a smaller size.
+ */
+QSize QWaylandXdgToplevelV6::minSize() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_minSize;
+}
+
+/*!
+ * \property QWaylandXdgToplevelV6::states
+ *
+ * This property holds the last states the client acknowledged for this QWaylandToplevelV6.
+ */
+QVector<QWaylandXdgToplevelV6::State> QWaylandXdgToplevelV6::states() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_lastAckedConfigure.states;
+}
+
+/*!
+ * \qmlproperty bool QtWaylandCompositor::XdgToplevelV6::maximized
+ *
+ * This property holds whether the client has acknowledged that it should be maximized.
+ */
+
+/*!
+ * \property QWaylandXdgToplevelV6::maximized
+ *
+ * This property holds whether the client has acknowledged that it should be maximized.
+ */
+bool QWaylandXdgToplevelV6::maximized() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevelV6::State::MaximizedState);
+}
+
+/*!
+ * \qmlproperty bool QtWaylandCompositor::XdgToplevelV6::fullscreen
+ *
+ * This property holds whether the client has acknowledged that it should be fullscreen.
+ */
+
+/*!
+ * \property QWaylandXdgToplevelV6::fullscreen
+ *
+ * This property holds whether the client has acknowledged that it should be fullscreen.
+ */
+bool QWaylandXdgToplevelV6::fullscreen() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevelV6::State::FullscreenState);
+}
+
+/*!
+ * \qmlproperty bool QtWaylandCompositor::XdgToplevelV6::resizing
+ *
+ * This property holds whether the client has acknowledged that it is being resized.
+ */
+
+/*!
+ * \property QWaylandXdgToplevelV6::resizing
+ *
+ * This property holds whether the client has acknowledged that it is being resized.
+ */
+bool QWaylandXdgToplevelV6::resizing() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevelV6::State::ResizingState);
+}
+
+/*!
+ * \qmlproperty bool QtWaylandCompositor::XdgToplevelV6::activated
+ *
+ * This property holds whether toplevel is drawing itself as having input focus.
+ */
+
+/*!
+ * \property QWaylandXdgToplevelV6::activated
+ *
+ * This property holds whether toplevel is drawing itself as having input focus.
+ */
+bool QWaylandXdgToplevelV6::activated() const
+{
+ Q_D(const QWaylandXdgToplevelV6);
+ return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevelV6::State::ActivatedState);
+}
+
+/*!
+ * \qmlmethod size QtWaylandCompositor::XdgToplevelV6::sizeForResize(size size, point delta, uint edges)
+ *
+ * Convenience for computing the new size given the current \a size, a \a delta, and
+ * the \a edges active in the drag.
+ */
+
+/*!
+ * Convenience for computing the new size given the current \a size, a \a delta, and
+ * the \a edges active in the drag.
+ */
+QSize QWaylandXdgToplevelV6::sizeForResize(const QSizeF &size, const QPointF &delta, Qt::Edges edges) const
+{
+ qreal width = size.width();
+ qreal height = size.height();
+ if (edges & Qt::LeftEdge)
+ width -= delta.x();
+ else if (edges & Qt::RightEdge)
+ width += delta.x();
+
+ if (edges & Qt::TopEdge)
+ height -= delta.y();
+ else if (edges & Qt::BottomEdge)
+ height += delta.y();
+
+ return QSizeF(width, height).toSize();
+}
+
+/*!
+ * Sends a configure event to the client. Parameter \a size contains the pixel size
+ * of the surface. A size of zero means the client is free to decide the size.
+ * Known \a states are enumerated in QWaylandXdgToplevelV6::State.
+ */
+uint QWaylandXdgToplevelV6::sendConfigure(const QSize &size, const QVector<QWaylandXdgToplevelV6::State> &states)
+{
+ Q_D(QWaylandXdgToplevelV6);
+ auto statesBytes = QByteArray::fromRawData(reinterpret_cast<const char *>(states.data()),
+ states.size() * static_cast<int>(sizeof(State)));
+ uint32_t serial = d->m_xdgSurface->surface()->compositor()->nextSerial();
+ d->m_pendingConfigures.append(QWaylandXdgToplevelV6Private::ConfigureEvent{states, size, serial});
+ d->send_configure(size.width(), size.height(), statesBytes);
+ QWaylandXdgSurfaceV6Private::get(d->m_xdgSurface)->send_configure(serial);
+ return serial;
+}
+
+/*!
+ * \qmlmethod int QtWaylandCompositor::XdgToplevelV6::sendConfigure(size size, list<int> states)
+ *
+ * Sends a configure event to the client. \a size contains the pixel size of the surface.
+ * A size of zero means the client is free to decide the size.
+ * Known \a states are enumerated in XdgToplevelV6::State.
+ */
+uint QWaylandXdgToplevelV6::sendConfigure(const QSize &size, const QVector<int> &states)
+{
+ QVector<State> s;
+ for (auto state : states)
+ s << State(state);
+ return sendConfigure(size, s);
+}
+
+/*!
+ * \qmlmethod void QtWaylandCompositor::XdgToplevelV6::sendClose()
+ *
+ * Sends a close event to the client. The client may choose to ignore the event.
+ */
+
+/*!
+ * Sends a close event to the client. The client may choose to ignore the event.
+ */
+void QWaylandXdgToplevelV6::sendClose()
+{
+ Q_D(QWaylandXdgToplevelV6);
+ d->send_close();
+}
+
+/*!
+ * \qmlmethod void QtWaylandCompositor::XdgToplevelV6::sendMaximized()
+ *
+ * Convenience for sending a configure event with the maximized state set, and
+ * fullscreen and resizing removed. The activated state is left in its current state.
+ */
+
+/*!
+ * Convenience for sending a configure event with the maximized state set, and
+ * fullscreen and resizing removed. The activated state is left in its current state.
+ */
+uint QWaylandXdgToplevelV6::sendMaximized(const QSize &size)
+{
+ Q_D(QWaylandXdgToplevelV6);
+ QWaylandXdgToplevelV6Private::ConfigureEvent conf = d->lastSentConfigure();
+
+ if (!conf.states.contains(QWaylandXdgToplevelV6::State::MaximizedState))
+ conf.states.append(QWaylandXdgToplevelV6::State::MaximizedState);
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::FullscreenState);
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::ResizingState);
+
+ return sendConfigure(size, conf.states);
+}
+
+/*!
+ * \qmlmethod void QtWaylandCompositor::XdgToplevelV6::sendUnmaximized()
+ *
+ * Convenience for sending a configure event with the maximized, fullscreen and
+ * resizing states removed, and fullscreen and resizing removed. The activated
+ * state is left in its current state.
+ *
+ * \a size is the new size of the window. If \a size is zero, the client decides the size.
+ */
+
+/*!
+ * Convenience for sending a configure event with the maximized, fullscreen and
+ * resizing states removed, and fullscreen and resizing removed. The activated
+ * state is left in its current state.
+ *
+ * \a size is the new size of the window. If \a size is zero, the client decides the size.
+ */
+uint QWaylandXdgToplevelV6::sendUnmaximized(const QSize &size)
+{
+ Q_D(QWaylandXdgToplevelV6);
+ QWaylandXdgToplevelV6Private::ConfigureEvent conf = d->lastSentConfigure();
+
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::MaximizedState);
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::FullscreenState);
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::ResizingState);
+
+ return sendConfigure(size, conf.states);
+
+}
+
+/*!
+ * \qmlmethod void QtWaylandCompositor::XdgToplevelV6::sendFullscreen()
+ *
+ * Convenience for sending a configure event with the fullscreen state set, and
+ * maximized and resizing removed. The activated state is left in its current state.
+ *
+ * \a size is the new size of the window.
+ */
+
+/*!
+ * Convenience for sending a configure event with the fullscreen state set, and
+ * maximized and resizing removed. The activated state is left in its current state.
+ *
+ * \a size is the new size of the window.
+ */
+uint QWaylandXdgToplevelV6::sendFullscreen(const QSize &size)
+{
+ Q_D(QWaylandXdgToplevelV6);
+ QWaylandXdgToplevelV6Private::ConfigureEvent conf = d->lastSentConfigure();
+
+ if (!conf.states.contains(QWaylandXdgToplevelV6::State::FullscreenState))
+ conf.states.append(QWaylandXdgToplevelV6::State::FullscreenState);
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::MaximizedState);
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::ResizingState);
+
+ return sendConfigure(size, conf.states);
+}
+
+/*!
+ * \qmlmethod void QtWaylandCompositor::XdgToplevelV6::sendResizing()
+ *
+ * Convenience for sending a configure event with the resizing state set, and
+ * maximized and fullscreen removed. The activated state is left in its current state.
+ *
+ * \a size is the new size of the window.
+ */
+
+/*!
+ * Convenience for sending a configure event with the resizing state set, and
+ * maximized and fullscreen removed. The activated state is left in its current state.
+ *
+ * \a size is the new size of the window.
+ */
+uint QWaylandXdgToplevelV6::sendResizing(const QSize &maxSize)
+{
+ Q_D(QWaylandXdgToplevelV6);
+ QWaylandXdgToplevelV6Private::ConfigureEvent conf = d->lastSentConfigure();
+
+ if (!conf.states.contains(QWaylandXdgToplevelV6::State::ResizingState))
+ conf.states.append(QWaylandXdgToplevelV6::State::ResizingState);
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::MaximizedState);
+ conf.states.removeOne(QWaylandXdgToplevelV6::State::FullscreenState);
+
+ return sendConfigure(maxSize, conf.states);
+}
+
+/*!
+ * Returns the surface role for the QWaylandToplevelV6.
+ */
+QWaylandSurfaceRole *QWaylandXdgToplevelV6::role()
+{
+ return &QWaylandXdgToplevelV6Private::s_role;
+}
+
+QList<int> QWaylandXdgToplevelV6::statesAsInts() const
+{
+ QList<int> list;
+ Q_FOREACH (uint state, states()) {
+ list << static_cast<int>(state);
+ }
+ return list;
+}
+
+QWaylandSurfaceRole QWaylandXdgToplevelV6Private::s_role("zxdg_toplevel_v6");
+
+QWaylandXdgToplevelV6Private::QWaylandXdgToplevelV6Private(QWaylandXdgSurfaceV6 *xdgSurface, const QWaylandResource &resource)
+ : m_xdgSurface(xdgSurface)
+ , m_parentToplevel(nullptr)
+ , m_lastAckedConfigure({{}, QSize(0, 0), 0})
+{
+ init(resource.resource());
+}
+
+void QWaylandXdgToplevelV6Private::handleAckConfigure(uint serial)
+{
+ Q_Q(QWaylandXdgToplevelV6);
+ ConfigureEvent config;
+ Q_FOREVER {
+ if (m_pendingConfigures.empty()) {
+ qWarning("Toplevel received an unexpected ack_configure!");
+ return;
+ }
+
+ // This won't work unless there always is a toplevel.configure for each xdgsurface.configure
+ config = m_pendingConfigures.takeFirst();
+
+ if (config.serial == serial)
+ break;
+ }
+
+ QVector<uint> changedStates;
+ std::set_symmetric_difference(
+ m_lastAckedConfigure.states.begin(), m_lastAckedConfigure.states.end(),
+ config.states.begin(), config.states.end(),
+ std::back_inserter(changedStates));
+
+ m_lastAckedConfigure = config;
+
+ for (uint state : changedStates) {
+ switch (state) {
+ case state_maximized:
+ emit q->maximizedChanged();
+ break;
+ case state_fullscreen:
+ emit q->fullscreenChanged();
+ break;
+ case state_resizing:
+ emit q->resizingChanged();
+ break;
+ case state_activated:
+ emit q->activatedChanged();
+ break;
+ }
+ }
+
+ if (!changedStates.empty())
+ emit q->statesChanged();
+}
+
+void QWaylandXdgToplevelV6Private::handleFocusLost()
+{
+ Q_Q(QWaylandXdgToplevelV6);
+ QWaylandXdgToplevelV6Private::ConfigureEvent current = lastSentConfigure();
+ current.states.removeOne(QWaylandXdgToplevelV6::State::ActivatedState);
+ q->sendConfigure(current.size, current.states);
+}
+
+void QWaylandXdgToplevelV6Private::handleFocusReceived()
+{
+ Q_Q(QWaylandXdgToplevelV6);
+ QWaylandXdgToplevelV6Private::ConfigureEvent current = lastSentConfigure();
+ if (!current.states.contains(QWaylandXdgToplevelV6::State::ActivatedState)) {
+ current.states.push_back(QWaylandXdgToplevelV6::State::ActivatedState);
+ q->sendConfigure(current.size, current.states);
+ }
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_destroy_resource(QtWaylandServer::zxdg_toplevel_v6::Resource *resource)
+{
+ Q_UNUSED(resource);
+ Q_Q(QWaylandXdgToplevelV6);
+ delete q;
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_destroy(QtWaylandServer::zxdg_toplevel_v6::Resource *resource)
+{
+ wl_resource_destroy(resource->handle);
+ //TODO: Should the xdg surface be desroyed as well? Or is it allowed to recreate a new toplevel for it?
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_set_parent(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, wl_resource *parent)
+{
+ Q_UNUSED(resource);
+ QWaylandXdgToplevelV6 *parentToplevel = nullptr;
+ if (parent) {
+ parentToplevel = static_cast<QWaylandXdgToplevelV6Private *>(
+ QWaylandXdgToplevelV6Private::Resource::fromResource(parent)->zxdg_toplevel_v6_object)->q_func();
+ }
+
+ Q_Q(QWaylandXdgToplevelV6);
+
+ if (m_parentToplevel != parentToplevel) {
+ m_parentToplevel = parentToplevel;
+ emit q->parentToplevelChanged();
+ }
+
+ if (m_parentToplevel && m_xdgSurface->windowType() != Qt::WindowType::SubWindow) {
+ // There's a parent now, which means the surface is transient
+ QWaylandXdgSurfaceV6Private::get(m_xdgSurface)->setWindowType(Qt::WindowType::SubWindow);
+ } else if (!m_parentToplevel && m_xdgSurface->windowType() != Qt::WindowType::Window) {
+ // When the surface has no parent it is toplevel
+ QWaylandXdgSurfaceV6Private::get(m_xdgSurface)->setWindowType(Qt::WindowType::Window);
+ }
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_set_title(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, const QString &title)
+{
+ Q_UNUSED(resource);
+ if (title == m_title)
+ return;
+ Q_Q(QWaylandXdgToplevelV6);
+ m_title = title;
+ emit q->titleChanged();
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_set_app_id(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, const QString &app_id)
+{
+ Q_UNUSED(resource);
+ if (app_id == m_appId)
+ return;
+ Q_Q(QWaylandXdgToplevelV6);
+ m_appId = app_id;
+ emit q->appIdChanged();
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_show_window_menu(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, wl_resource *seatResource, uint32_t serial, int32_t x, int32_t y)
+{
+ Q_UNUSED(resource);
+ Q_UNUSED(serial);
+ QPoint position(x, y);
+ auto seat = QWaylandSeat::fromSeatResource(seatResource);
+ Q_Q(QWaylandXdgToplevelV6);
+ emit q->showWindowMenu(seat, position);
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_move(Resource *resource, wl_resource *seatResource, uint32_t serial)
+{
+ Q_UNUSED(resource);
+ Q_UNUSED(serial);
+ Q_Q(QWaylandXdgToplevelV6);
+ QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource);
+ emit q->startMove(seat);
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_resize(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, wl_resource *seatResource, uint32_t serial, uint32_t edges)
+{
+ Q_UNUSED(resource);
+ Q_UNUSED(serial);
+ Q_Q(QWaylandXdgToplevelV6);
+ QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource);
+ emit q->startResize(seat, QWaylandXdgShellV6Private::convertToEdges(edges));
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_set_max_size(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, int32_t width, int32_t height)
+{
+ Q_UNUSED(resource);
+
+ QSize maxSize(width, height);
+ if (width == 0 && height == 0)
+ maxSize = QSize(); // Wayland size of zero means unspecified which best translates to invalid
+
+ if (m_maxSize == maxSize)
+ return;
+
+ if (width < 0 || height < 0) {
+ // The spec says raise a protocol error, but there's no matching error defined
+ qWarning() << "Received a zxdg_toplevel_v6.set_max_size request with a negative size";
+ return;
+ }
+
+ if (m_minSize.isValid() && maxSize.isValid() &&
+ (maxSize.width() < m_minSize.width() || maxSize.height() < m_minSize.height())) {
+ // The spec says raise a protocol error, but there's no matching error defined
+ qWarning() << "Received a zxdg_toplevel_v6.set_max_size request with a size smaller than the minimium size";
+ return;
+ }
+
+ else
+ m_maxSize = maxSize;
+
+ Q_Q(QWaylandXdgToplevelV6);
+ emit q->maxSizeChanged();
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_set_min_size(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, int32_t width, int32_t height)
+{
+ Q_UNUSED(resource);
+
+ QSize minSize(width, height);
+ if (width == 0 && height == 0)
+ minSize = QSize(); // Wayland size of zero means unspecified
+
+ if (m_minSize == minSize)
+ return;
+
+ if (width < 0 || height < 0) {
+ // The spec says raise a protocol error, but there's no matching error defined
+ qWarning() << "Received a zxdg_toplevel_v6.set_min_size request with a negative size";
+ return;
+ }
+
+ if (m_maxSize.isValid() && minSize.isValid() &&
+ (minSize.width() > m_maxSize.width() || minSize.height() > m_maxSize.height())) {
+ // The spec says raise a protocol error, but there's no matching error defined
+ qWarning() << "Received a zxdg_toplevel_v6.set_min_size request with a size larger than the maximum size";
+ return;
+ }
+
+ else
+ m_minSize = minSize;
+
+ Q_Q(QWaylandXdgToplevelV6);
+ emit q->minSizeChanged();
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_set_maximized(QtWaylandServer::zxdg_toplevel_v6::Resource *resource)
+{
+ Q_UNUSED(resource);
+ Q_Q(QWaylandXdgToplevelV6);
+ emit q->setMaximized();
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_unset_maximized(QtWaylandServer::zxdg_toplevel_v6::Resource *resource)
+{
+ Q_UNUSED(resource);
+ Q_Q(QWaylandXdgToplevelV6);
+ emit q->unsetMaximized();
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_set_fullscreen(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, wl_resource *output_res)
+{
+ Q_UNUSED(resource);
+ Q_Q(QWaylandXdgToplevelV6);
+ QWaylandOutput *output = output_res ? QWaylandOutput::fromResource(output_res) : nullptr;
+ emit q->setFullscreen(output);
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_unset_fullscreen(QtWaylandServer::zxdg_toplevel_v6::Resource *resource)
+{
+ Q_UNUSED(resource);
+ Q_Q(QWaylandXdgToplevelV6);
+ emit q->unsetFullscreen();
+}
+
+void QWaylandXdgToplevelV6Private::zxdg_toplevel_v6_set_minimized(QtWaylandServer::zxdg_toplevel_v6::Resource *resource)
+{
+ Q_UNUSED(resource);
+ Q_Q(QWaylandXdgToplevelV6);
+ emit q->setMinimized();
+}
+
+/*!
+ * \qmltype XdgPopupV6
+ * \inqmlmodule QtWayland.Compositor
+ * \since 5.10
+ * \brief XdgPopupV6 represents the popup specific parts of and xdg surface
+ *
+ * This type is part of the \l{XdgShellV6} extension and provides a way to extend
+ * extend the functionality of an \l{XdgSurfaceV6} with features
+ * specific to desktop-style menus for an xdg surface.
+ *
+ * It corresponds to the Wayland interface \c zxdg_popup_v6.
+ */
+
+/*!
+ * \class QWaylandXdgPopupV6
+ * \inmodule QtWaylandCompositor
+ * \since 5.10
+ * \brief The QWaylandXdgPopupV6 class represents the popup specific parts of an xdg surface
+ *
+ * This class is part of the QWaylandXdgShellV6 extension and provides a way to
+ * extend the functionality of a QWaylandXdgSurfaceV6 with features
+ * specific to desktop-style menus for an xdg surface.
+ *
+ * It corresponds to the Wayland interface \c zxdg_popup_v6.
+ */
+
+/*!
+ * Constructs a QWaylandXdgPopupV6.
+ */
+QWaylandXdgPopupV6::QWaylandXdgPopupV6(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandXdgSurfaceV6 *parentXdgSurface,
+ QWaylandXdgPositionerV6 *positioner, QWaylandResource &resource)
+ : QObject(*new QWaylandXdgPopupV6Private(xdgSurface, parentXdgSurface, positioner, resource))
+{
+}
+
+/*!
+ * \qmlproperty XdgSurfaceV6 QtWaylandCompositor::XdgPopupV6::xdgSurface
+ *
+ * This property holds the XdgSurfaceV6 associated with this XdgPopupV6.
+ */
+
+/*!
+ * \property QWaylandXdgPopupV6::xdgSurface
+ *
+ * This property holds the QWaylandXdgSurfaceV6 associated with this QWaylandXdgPopupV6.
+ */
+QWaylandXdgSurfaceV6 *QWaylandXdgPopupV6::xdgSurface() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_xdgSurface;
+}
+
+/*!
+ * \qmlproperty XdgSurfaceV6 QtWaylandCompositor::XdgPopupV6::parentXdgSurface
+ *
+ * This property holds the XdgSurfaceV6 associated with the parent of this XdgPopupV6.
+ */
+
+/*!
+ * \property QWaylandXdgPopupV6::parentXdgSurface
+ *
+ * This property holds the QWaylandXdgSurfaceV6 associated with the parent of this
+ * QWaylandXdgPopupV6.
+ */
+QWaylandXdgSurfaceV6 *QWaylandXdgPopupV6::parentXdgSurface() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_parentXdgSurface;
+}
+
+/*!
+ * \qmlproperty rect QtWaylandCompositor::XdgPopupV6::configuredGeometry
+ *
+ * The window geometry the popup received in the configure event. Relative to the
+ * upper left corner of the parent surface.
+ */
+
+/*!
+ * \property QWaylandXdgPopupV6::configuredGeometry
+ *
+ * The window geometry the popup received in the configure event. Relative to the
+ * upper left corner of the parent surface.
+ */
+QRect QWaylandXdgPopupV6::configuredGeometry() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_geometry;
+}
+
+/*!
+ * \qmlproperty rect QtWaylandCompositor::XdgPopupV6::anchorRect
+ *
+ * The anchor rectangle relative to the parent window geometry that the child
+ * surface should be placed relative to.
+ */
+
+/*!
+ * \property QWaylandXdgPopupV6::anchorRect
+ *
+ * Returns the anchor rectangle relative to the parent window geometry that the child
+ * surface should be placed relative to.
+ */
+QRect QWaylandXdgPopupV6::anchorRect() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_positionerData.anchorRect;
+}
+
+/*!
+ * \qmlproperty enumeration QtWaylandCompositor::XdgPopupV6::anchorEdges
+ *
+ * This property holds the set of edges on the anchor rect that the child surface should be placed
+ * relative to. If no edges are specified in a direction, the anchor point should be
+ * centered between the edges.
+ *
+ * The possible values are:
+ * \value Qt.TopEdge The top edge of the rectangle.
+ * \value Qt.LeftEdge The left edge of the rectangle.
+ * \value Qt.RightEdge The right edge of the rectangle.
+ * \value Qt.BottomEdge The bottom edge of the rectangle.
+ */
+
+/*!
+ * \property QWaylandXdgPopupV6::anchorEdges
+ *
+ * Returns the set of edges on the anchor rect that the child surface should be placed
+ * relative to. If no edges are specified in a direction, the anchor point should be
+ * centered between the edges.
+ */
+Qt::Edges QWaylandXdgPopupV6::anchorEdges() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_positionerData.anchorEdges;
+}
+
+/*!
+ * \qmlproperty rect QtWaylandCompositor::XdgPopupV6::gravityEdges
+ *
+ * Specifies in what direction the surface should be positioned, relative to the anchor
+ * point.
+ *
+ * The possible values are:
+ * \value Qt.TopEdge The surface should slide towards the top of the screen.
+ * \value Qt.LeftEdge The surface should slide towards the left of the screen.
+ * \value Qt.RightEdge The surface should slide towards the right of the screen.
+ * \value Qt.BottomEdge The surface should slide towards the bottom of the screen.
+ */
+
+/*!
+ * \property QWaylandXdgPopupV6::gravityEdges
+ *
+ * Specifies in what direction the surface should be positioned, relative to the anchor
+ * point.
+ */
+Qt::Edges QWaylandXdgPopupV6::gravityEdges() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_positionerData.gravityEdges;
+}
+
+/*!
+ * \qmlproperty enumeration QtWaylandCompositor::XdgPopupV6::slideConstraints
+ *
+ * This property holds the orientations in which the child should slide to fit within the screen.
+ *
+ * Possible values:
+ * \value Qt.Horizontal Horizontal
+ * \value Qt.Vertical Vertical
+ */
+
+/*!
+ * \property QWaylandXdgPopup::slideConstraints
+ *
+ * This property holds the orientations in which the child should slide to fit within the screen.
+ */
+Qt::Orientations QWaylandXdgPopupV6::slideConstraints() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ const uint flags = d->m_positionerData.constraintAdjustments;
+
+ Qt::Orientations constraints = 0;
+
+ if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X)
+ constraints |= Qt::Horizontal;
+ if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
+ constraints |= Qt::Vertical;
+
+ return constraints;
+}
+
+/*!
+ * \qmlproperty enumeration QtWaylandCompositor::XdgPopupV6::flipConstraints
+ *
+ * This property holds the orientations in which the child should flip to fit within the screen.
+ *
+ * Possible values:
+ * \value Qt.Horizontal Horizontal
+ * \value Qt.Vertical Vertical
+ */
+
+/*!
+ * \property QWaylandXdgPopup::flipConstraints
+ *
+ * This property holds the orientations in which the child should flip to fit within the screen.
+ */
+Qt::Orientations QWaylandXdgPopupV6::flipConstraints() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ const uint flags = d->m_positionerData.constraintAdjustments;
+
+ Qt::Orientations constraints = 0;
+
+ if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X)
+ constraints |= Qt::Horizontal;
+ if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y)
+ constraints |= Qt::Vertical;
+
+ return constraints;
+}
+
+/*!
+ * \qmlproperty enumeration QtWaylandCompositor::XdgPopupV6::resizeConstraints
+ *
+ * This property holds the orientations in which the child should resize to fit within the screen.
+ *
+ * Possible values:
+ * \value Qt.Horizontal Horizontal
+ * \value Qt.Vertical Vertical
+ */
+
+/*!
+ * \property QWaylandXdgPopup::resizeConstraints
+ *
+ * This property holds the orientations in which the child should resize to fit within the screen.
+ */
+Qt::Orientations QWaylandXdgPopupV6::resizeConstraints() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ const uint flags = d->m_positionerData.constraintAdjustments;
+
+ Qt::Orientations constraints = 0;
+
+ if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X)
+ constraints |= Qt::Horizontal;
+ if (flags & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y)
+ constraints |= Qt::Vertical;
+
+ return constraints;
+}
+
+/*!
+ * \qmlproperty point QtWaylandCompositor::XdgPopupV6::offset
+ *
+ * The position relative to the position of the anchor on the anchor rectangle and
+ * the anchor on the surface.
+ */
+
+/*!
+ * \property QWaylandXdgPopup::offset
+ *
+ * Returns the surface position relative to the position of the anchor on the anchor
+ * rectangle and the anchor on the surface.
+ */
+QPoint QWaylandXdgPopupV6::offset() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_positionerData.offset;
+}
+
+/*!
+ * \qmlproperty size QtWaylandCompositor::XdgPopupV6::positionerSize
+ *
+ * The size requested for the window geometry by the positioner object.
+ */
+
+/*!
+ * \property QWaylandXdgPopup::positionerSize
+ *
+ * Returns the size requested for the window geometry by the positioner object.
+ */
+QSize QWaylandXdgPopupV6::positionerSize() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_positionerData.size;
+}
+
+/*!
+ * \qmlproperty point QtWaylandCompositor::XdgPopupV6::unconstrainedPosition
+ *
+ * The position of the surface relative to the parent window geometry if the surface
+ * is not constrained. I.e. when not moved to fit inside the screen or similar.
+ */
+
+/*!
+ * \property QWaylandXdgPopup::unconstrainedPosition
+ *
+ * The position of the surface relative to the parent window geometry if the surface
+ * is not constrained. I.e. when not moved to fit inside the screen or similar.
+ */
+QPoint QWaylandXdgPopupV6::unconstrainedPosition() const
+{
+ Q_D(const QWaylandXdgPopupV6);
+ return d->m_positionerData.unconstrainedPosition();
+}
+
+/*!
+ * \qmlmethod int QtWaylandCompositor::XdgPopupV6::sendConfigure(rect geometry)
+ *
+ * Sends a configure event to the client. \a geometry contains the window geometry
+ * relative to the upper left corner of the window geometry of the parent surface.
+ *
+ * This implicitly sends a configure event to the corresponding XdgSurfaceV6 as well.
+ */
+
+/*!
+ * Sends a configure event to the client. \a geometry contains the window geometry
+ * relative to the upper left corner of the window geometry of the parent surface.
+ *
+ * This implicitly sends a configure event to the corresponding QWaylandXdgSurfaceV6
+ * as well.
+ */
+uint QWaylandXdgPopupV6::sendConfigure(const QRect &geometry)
+{
+ Q_D(QWaylandXdgPopupV6);
+ return d->sendConfigure(geometry);
+}
+
+/*!
+ * Returns the surface role for the QWaylandPopupV6.
+ */
+QWaylandSurfaceRole *QWaylandXdgPopupV6::role()
+{
+ return &QWaylandXdgPopupV6Private::s_role;
+}
+
+QWaylandXdgPopupV6Private::QWaylandXdgPopupV6Private(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandXdgSurfaceV6 *parentXdgSurface,
+ QWaylandXdgPositionerV6 *positioner, const QWaylandResource &resource)
+ : m_xdgSurface(xdgSurface)
+ , m_parentXdgSurface(parentXdgSurface)
+{
+ init(resource.resource());
+ m_positionerData = positioner->m_data;
+
+ if (!m_positionerData.isComplete())
+ qWarning() << "Trying to create xdg popup with incomplete positioner";
+
+ QWaylandXdgSurfaceV6Private::get(m_xdgSurface)->setWindowType(Qt::WindowType::Popup);
+
+ //TODO: positioner rect may not extend parent's window geometry, enforce this?
+ //TODO: Need an API for sending a different initial configure
+ sendConfigure(QRect(m_positionerData.unconstrainedPosition(), m_positionerData.size));
+}
+
+void QWaylandXdgPopupV6Private::handleAckConfigure(uint serial)
+{
+ Q_Q(QWaylandXdgPopupV6);
+ ConfigureEvent config;
+ Q_FOREVER {
+ if (m_pendingConfigures.empty()) {
+ qWarning("Popup received an unexpected ack_configure!");
+ return;
+ }
+
+ // This won't work unless there always is a popup.configure for each xdgsurface.configure
+ config = m_pendingConfigures.takeFirst();
+
+ if (config.serial == serial)
+ break;
+ }
+
+ if (m_geometry == config.geometry)
+ return;
+
+ m_geometry = config.geometry;
+ emit q->configuredGeometryChanged();
+}
+
+uint QWaylandXdgPopupV6Private::sendConfigure(const QRect &geometry)
+{
+ uint32_t serial = m_xdgSurface->surface()->compositor()->nextSerial();
+ m_pendingConfigures.append(QWaylandXdgPopupV6Private::ConfigureEvent{geometry, serial});
+ send_configure(geometry.x(), geometry.y(), geometry.width(), geometry.height());
+ QWaylandXdgSurfaceV6Private::get(m_xdgSurface)->send_configure(serial);
+ return serial;
+}
+
+void QWaylandXdgPopupV6Private::zxdg_popup_v6_destroy(QtWaylandServer::zxdg_popup_v6::Resource *resource)
+{
+ Q_UNUSED(resource);
+ qWarning() << Q_FUNC_INFO << "Not implemented"; //TODO
+}
+
+void QWaylandXdgPopupV6Private::zxdg_popup_v6_grab(QtWaylandServer::zxdg_popup_v6::Resource *resource, wl_resource *seat, uint32_t serial)
+{
+ Q_UNUSED(resource);
+ Q_UNUSED(serial);
+ Q_UNUSED(seat);
+ qWarning() << Q_FUNC_INFO << "Not implemented"; //TODO
+ //switch keyboard focus
+ //eventually send configure with activated.
+}
+
+QWaylandSurfaceRole QWaylandXdgPopupV6Private::s_role("zxdg_popup_v6");
+
+QWaylandXdgPositionerV6Data::QWaylandXdgPositionerV6Data()
+ : anchorEdges(0)
+ , gravityEdges(0)
+ , constraintAdjustments(ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE)
+ , offset(0, 0)
+{}
+
+bool QWaylandXdgPositionerV6Data::isComplete() const
+{
+ return size.width() > 0 && size.height() > 0 && anchorRect.size().width() > 0 && anchorRect.size().height() > 0;
+}
+
+QPoint QWaylandXdgPositionerV6Data::anchorPoint() const
+{
+ int yPosition = 0;
+ if (anchorEdges & Qt::TopEdge)
+ yPosition = anchorRect.top();
+ else if (anchorEdges & Qt::BottomEdge)
+ yPosition = anchorRect.bottom() + 1;
+ else
+ yPosition = anchorRect.top() + anchorRect.height() / 2;
+
+ int xPosition = 0;
+ if (anchorEdges & Qt::LeftEdge)
+ xPosition = anchorRect.left();
+ else if (anchorEdges & Qt::RightEdge)
+ xPosition = anchorRect.right() + 1;
+ else
+ xPosition = anchorRect.left() + anchorRect.width() / 2;
+
+ return QPoint(xPosition, yPosition);
+}
+
+QPoint QWaylandXdgPositionerV6Data::unconstrainedPosition() const
+{
+ int gravityOffsetY = 0;
+ if (gravityEdges & Qt::TopEdge)
+ gravityOffsetY = -size.height();
+ else if (!(gravityEdges & Qt::BottomEdge))
+ gravityOffsetY = -size.height() / 2;
+
+ int gravityOffsetX = 0;
+ if (gravityEdges & Qt::LeftEdge)
+ gravityOffsetX = -size.width();
+ else if (!(gravityEdges & Qt::RightEdge))
+ gravityOffsetX = -size.width() / 2;
+
+ QPoint gravityOffset(gravityOffsetX, gravityOffsetY);
+ return anchorPoint() + gravityOffset + offset;
+}
+
+QWaylandXdgPositionerV6::QWaylandXdgPositionerV6(const QWaylandResource &resource)
+{
+ init(resource.resource());
+}
+
+void QWaylandXdgPositionerV6::zxdg_positioner_v6_destroy_resource(QtWaylandServer::zxdg_positioner_v6::Resource *resource)
+{
+ Q_UNUSED(resource);
+ delete this;
+}
+
+void QWaylandXdgPositionerV6::zxdg_positioner_v6_destroy(QtWaylandServer::zxdg_positioner_v6::Resource *resource)
+{
+ wl_resource_destroy(resource->handle);
+}
+
+void QWaylandXdgPositionerV6::zxdg_positioner_v6_set_size(QtWaylandServer::zxdg_positioner_v6::Resource *resource, int32_t width, int32_t height)
+{
+ Q_UNUSED(resource);
+
+ if (width <= 0 || height <= 0) {
+ wl_resource_post_error(resource->handle, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "zxdg_positioner_v6.set_size requested with non-positive dimensions");
+ return;
+ }
+
+ QSize size(width, height);
+ m_data.size = size;
+}
+
+void QWaylandXdgPositionerV6::zxdg_positioner_v6_set_anchor_rect(QtWaylandServer::zxdg_positioner_v6::Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ Q_UNUSED(resource);
+
+ if (width <= 0 || height <= 0) {
+ wl_resource_post_error(resource->handle, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "zxdg_positioner_v6.set_anchor_rect requested with non-positive dimensions");
+ return;
+ }
+
+ QRect anchorRect(x, y, width, height);
+ m_data.anchorRect = anchorRect;
+}
+
+void QWaylandXdgPositionerV6::zxdg_positioner_v6_set_anchor(QtWaylandServer::zxdg_positioner_v6::Resource *resource, uint32_t anchor)
+{
+ Q_UNUSED(resource);
+
+ Qt::Edges anchorEdges = QWaylandXdgShellV6Private::convertToEdges(anchor);
+
+ if ((anchorEdges & Qt::BottomEdge && anchorEdges & Qt::TopEdge) ||
+ (anchorEdges & Qt::LeftEdge && anchorEdges & Qt::RightEdge)) {
+ wl_resource_post_error(resource->handle, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "zxdg_positioner_v6.set_anchor requested with parallel edges");
+ return;
+ }
+
+ m_data.anchorEdges = anchorEdges;
+}
+
+void QWaylandXdgPositionerV6::zxdg_positioner_v6_set_gravity(QtWaylandServer::zxdg_positioner_v6::Resource *resource, uint32_t gravity)
+{
+ Q_UNUSED(resource);
+ Qt::Edges gravityEdges = QWaylandXdgShellV6Private::convertToEdges(gravity);
+
+ if ((gravityEdges & Qt::BottomEdge && gravityEdges & Qt::TopEdge) ||
+ (gravityEdges & Qt::LeftEdge && gravityEdges & Qt::RightEdge)) {
+ wl_resource_post_error(resource->handle, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "zxdg_positioner_v6.set_gravity requested with parallel edges");
+ return;
+ }
+
+ m_data.gravityEdges = gravityEdges;
+}
+
+void QWaylandXdgPositionerV6::zxdg_positioner_v6_set_constraint_adjustment(QtWaylandServer::zxdg_positioner_v6::Resource *resource, uint32_t constraint_adjustment)
+{
+ Q_UNUSED(resource);
+ m_data.constraintAdjustments = constraint_adjustment;
+}
+
+void QWaylandXdgPositionerV6::zxdg_positioner_v6_set_offset(QtWaylandServer::zxdg_positioner_v6::Resource *resource, int32_t x, int32_t y)
+{
+ Q_UNUSED(resource);
+ m_data.offset = QPoint(x, y);
+}
+
+QWaylandXdgPositionerV6 *QWaylandXdgPositionerV6::fromResource(wl_resource *resource)
+{
+ return static_cast<QWaylandXdgPositionerV6 *>(Resource::fromResource(resource)->zxdg_positioner_v6_object);
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandxdgshellv6.h b/src/compositor/extensions/qwaylandxdgshellv6.h
new file mode 100644
index 000000000..8c5eee8a2
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgshellv6.h
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXDGSHELLV6_H
+#define QWAYLANDXDGSHELLV6_H
+
+#include <QtWaylandCompositor/QWaylandCompositorExtension>
+#include <QtWaylandCompositor/QWaylandResource>
+#include <QtWaylandCompositor/QWaylandShell>
+#include <QtWaylandCompositor/QWaylandShellSurface>
+
+#include <QtCore/QRect>
+
+struct wl_resource;
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandClient;
+class QWaylandOutput;
+class QWaylandSeat;
+class QWaylandSurface;
+class QWaylandSurfaceRole;
+class QWaylandXdgShellV6Private;
+class QWaylandXdgSurfaceV6;
+class QWaylandXdgSurfaceV6Private;
+class QWaylandXdgToplevelV6;
+class QWaylandXdgToplevelV6Private;
+class QWaylandXdgPopupV6;
+class QWaylandXdgPopupV6Private;
+class QWaylandXdgPositionerV6;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShellV6 : public QWaylandShellTemplate<QWaylandXdgShellV6>
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandXdgShellV6)
+public:
+ QWaylandXdgShellV6();
+ QWaylandXdgShellV6(QWaylandCompositor *compositor);
+
+ void initialize() override;
+
+ static const struct wl_interface *interface();
+ static QByteArray interfaceName();
+
+public Q_SLOTS:
+ uint ping(QWaylandClient *client);
+
+Q_SIGNALS:
+ void xdgSurfaceCreated(QWaylandXdgSurfaceV6 *xdgSurface);
+ void toplevelCreated(QWaylandXdgToplevelV6 *toplevel, QWaylandXdgSurfaceV6 *xdgSurface);
+ void popupCreated(QWaylandXdgPopupV6 *popup, QWaylandXdgSurfaceV6 *xdgSurface);
+ void pong(uint serial);
+
+private Q_SLOTS:
+ void handleSeatChanged(QWaylandSeat *newSeat, QWaylandSeat *oldSeat);
+ void handleFocusChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface);
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgSurfaceV6 : public QWaylandShellSurfaceTemplate<QWaylandXdgSurfaceV6>
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandXdgSurfaceV6)
+ Q_PROPERTY(QWaylandXdgShellV6 *shell READ shell NOTIFY shellChanged)
+ Q_PROPERTY(QWaylandSurface *surface READ surface NOTIFY surfaceChanged)
+ Q_PROPERTY(QWaylandXdgToplevelV6 *toplevel READ toplevel NOTIFY toplevelCreated)
+ Q_PROPERTY(QWaylandXdgPopupV6 *popup READ popup NOTIFY popupCreated)
+ Q_PROPERTY(QRect windowGeometry READ windowGeometry NOTIFY windowGeometryChanged)
+
+public:
+ QWaylandXdgSurfaceV6();
+ QWaylandXdgSurfaceV6(QWaylandXdgShellV6* xdgShell, QWaylandSurface *surface, const QWaylandResource &resource);
+
+ Q_INVOKABLE void initialize(QWaylandXdgShellV6* xdgShell, QWaylandSurface *surface, const QWaylandResource &resource);
+
+ Qt::WindowType windowType() const override;
+
+ QWaylandXdgShellV6 *shell() const;
+ QWaylandSurface *surface() const;
+ QWaylandXdgToplevelV6 *toplevel() const;
+ QWaylandXdgPopupV6 *popup() const;
+ QRect windowGeometry() const;
+
+ static const struct wl_interface *interface();
+ static QByteArray interfaceName();
+ static QWaylandXdgSurfaceV6 *fromResource(::wl_resource *resource);
+
+#ifdef QT_WAYLAND_COMPOSITOR_QUICK
+ QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) override;
+#endif
+
+Q_SIGNALS:
+ void shellChanged();
+ void surfaceChanged();
+ void toplevelCreated();
+ void popupCreated();
+ void windowGeometryChanged();
+
+private:
+ void initialize() override;
+
+private Q_SLOTS:
+ void handleSurfaceSizeChanged();
+ void handleBufferScaleChanged();
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgToplevelV6 : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandXdgToplevelV6)
+ Q_PROPERTY(QWaylandXdgToplevelV6 *parentToplevel READ parentToplevel NOTIFY parentToplevelChanged)
+ Q_PROPERTY(QString title READ title NOTIFY titleChanged)
+ Q_PROPERTY(QString appId READ appId NOTIFY appIdChanged)
+ Q_PROPERTY(QSize maxSize READ maxSize NOTIFY maxSizeChanged)
+ Q_PROPERTY(QSize minSize READ minSize NOTIFY minSizeChanged)
+ Q_PROPERTY(QList<int> states READ statesAsInts NOTIFY statesChanged)
+ Q_PROPERTY(bool maximized READ maximized NOTIFY maximizedChanged)
+ Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged)
+ Q_PROPERTY(bool resizing READ resizing NOTIFY resizingChanged)
+ Q_PROPERTY(bool activated READ activated NOTIFY activatedChanged)
+public:
+ enum State : uint {
+ MaximizedState = 1,
+ FullscreenState = 2,
+ ResizingState = 3,
+ ActivatedState = 4
+ };
+ Q_ENUM(State)
+
+ QWaylandXdgToplevelV6(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandResource &resource);
+
+ QWaylandXdgToplevelV6 *parentToplevel() const;
+
+ QString title() const;
+ QString appId() const;
+ QSize maxSize() const;
+ QSize minSize() const;
+ QVector<QWaylandXdgToplevelV6::State> states() const;
+ bool maximized() const;
+ bool fullscreen() const;
+ bool resizing() const;
+ bool activated() const;
+
+ Q_INVOKABLE QSize sizeForResize(const QSizeF &size, const QPointF &delta, Qt::Edges edges) const;
+ uint sendConfigure(const QSize &size, const QVector<State> &states);
+ Q_INVOKABLE uint sendConfigure(const QSize &size, const QVector<int> &states);
+ Q_INVOKABLE void sendClose();
+ Q_INVOKABLE uint sendMaximized(const QSize &size);
+ Q_INVOKABLE uint sendUnmaximized(const QSize &size = QSize(0, 0));
+ Q_INVOKABLE uint sendFullscreen(const QSize &size);
+ Q_INVOKABLE uint sendResizing(const QSize &maxSize);
+
+ static QWaylandSurfaceRole *role();
+
+Q_SIGNALS:
+ void parentToplevelChanged();
+ void titleChanged();
+ void appIdChanged();
+ void maxSizeChanged();
+ void minSizeChanged();
+ void startMove(QWaylandSeat *seat);
+ void startResize(QWaylandSeat *seat, Qt::Edges edges);
+ void statesChanged();
+ void maximizedChanged();
+ void fullscreenChanged();
+ void resizingChanged();
+ void activatedChanged();
+
+ void showWindowMenu(QWaylandSeat *seat, const QPoint &localSurfacePosition);
+ void setMaximized();
+ void unsetMaximized();
+ void setFullscreen(QWaylandOutput *output);
+ void unsetFullscreen();
+ void setMinimized();
+
+private:
+ QList<int> statesAsInts() const;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPopupV6 : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandXdgPopupV6)
+ Q_PROPERTY(QWaylandXdgSurfaceV6 *xdgSurface READ xdgSurface)
+ Q_PROPERTY(QWaylandXdgSurfaceV6 *parentXdgSurface READ parentXdgSurface)
+ Q_PROPERTY(QRect configuredGeometry READ configuredGeometry NOTIFY configuredGeometryChanged)
+
+ // Positioner properties
+ Q_PROPERTY(QRect anchorRect READ anchorRect CONSTANT)
+ Q_PROPERTY(Qt::Edges anchorEdges READ anchorEdges CONSTANT)
+ Q_PROPERTY(Qt::Edges gravityEdges READ gravityEdges CONSTANT)
+ Q_PROPERTY(Qt::Orientations slideConstraints READ slideConstraints CONSTANT)
+ Q_PROPERTY(Qt::Orientations flipConstraints READ flipConstraints CONSTANT)
+ Q_PROPERTY(Qt::Orientations resizeConstraints READ resizeConstraints CONSTANT)
+ Q_PROPERTY(QPoint offset READ offset CONSTANT)
+ Q_PROPERTY(QSize positionerSize READ positionerSize CONSTANT)
+ Q_PROPERTY(QPoint unconstrainedPosition READ unconstrainedPosition CONSTANT)
+public:
+ QWaylandXdgSurfaceV6 *xdgSurface() const;
+ QWaylandXdgSurfaceV6 *parentXdgSurface() const;
+ QRect configuredGeometry() const;
+
+ // Positioner properties
+ QRect anchorRect() const;
+ Qt::Edges anchorEdges() const ;
+ Qt::Edges gravityEdges() const ;
+ Qt::Orientations slideConstraints() const;
+ Qt::Orientations flipConstraints() const;
+ Qt::Orientations resizeConstraints() const;
+ QPoint offset() const;
+ QSize positionerSize() const;
+ QPoint unconstrainedPosition() const;
+
+ Q_INVOKABLE uint sendConfigure(const QRect &geometry);
+
+ static QWaylandSurfaceRole *role();
+
+Q_SIGNALS:
+ void configuredGeometryChanged();
+
+private:
+ QWaylandXdgPopupV6(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandXdgSurfaceV6 *parentXdgSurface,
+ QWaylandXdgPositionerV6 *positioner, QWaylandResource &resource);
+ friend class QWaylandXdgSurfaceV6Private;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDXDGSHELLV6_H
diff --git a/src/compositor/extensions/qwaylandxdgshellv6_p.h b/src/compositor/extensions/qwaylandxdgshellv6_p.h
new file mode 100644
index 000000000..98bcb70f7
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgshellv6_p.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXDGSHELLV6_P_H
+#define QWAYLANDXDGSHELLV6_P_H
+
+#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwayland-server-xdg-shell-unstable-v6.h>
+
+#include <QtWaylandCompositor/QWaylandXdgShellV6>
+
+#include <QtCore/QSet>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+struct Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPositionerV6Data {
+ QSize size;
+ QRect anchorRect;
+ Qt::Edges anchorEdges;
+ Qt::Edges gravityEdges;
+ uint constraintAdjustments;
+ QPoint offset;
+ QWaylandXdgPositionerV6Data();
+ bool isComplete() const;
+ QPoint anchorPoint() const;
+ QPoint unconstrainedPosition() const;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShellV6Private
+ : public QWaylandCompositorExtensionPrivate
+ , public QtWaylandServer::zxdg_shell_v6
+{
+ Q_DECLARE_PUBLIC(QWaylandXdgShellV6)
+public:
+ QWaylandXdgShellV6Private();
+ void ping(Resource *resource, uint32_t serial);
+ void registerXdgSurface(QWaylandXdgSurfaceV6 *xdgSurface);
+ void unregisterXdgSurface(QWaylandXdgSurfaceV6 *xdgSurface);
+ static QWaylandXdgShellV6Private *get(QWaylandXdgShellV6 *xdgShell) { return xdgShell->d_func(); }
+ static Qt::Edges convertToEdges(uint xdgEdges);
+
+ QSet<uint32_t> m_pings;
+ QMultiMap<struct wl_client *, QWaylandXdgSurfaceV6 *> m_xdgSurfaces;
+
+ QWaylandXdgSurfaceV6 *xdgSurfaceFromSurface(QWaylandSurface *surface);
+
+protected:
+ void zxdg_shell_v6_destroy(Resource *resource) override;
+ void zxdg_shell_v6_create_positioner(Resource *resource, uint32_t id) override;
+ void zxdg_shell_v6_get_xdg_surface(Resource *resource, uint32_t id,
+ struct ::wl_resource *surface) override;
+ void zxdg_shell_v6_pong(Resource *resource, uint32_t serial) override;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgSurfaceV6Private
+ : public QWaylandCompositorExtensionPrivate
+ , public QtWaylandServer::zxdg_surface_v6
+{
+ Q_DECLARE_PUBLIC(QWaylandXdgSurfaceV6)
+public:
+ QWaylandXdgSurfaceV6Private();
+ void setWindowType(Qt::WindowType windowType);
+ void handleFocusLost();
+ void handleFocusReceived();
+ static QWaylandXdgSurfaceV6Private *get(QWaylandXdgSurfaceV6 *xdgSurface) { return xdgSurface->d_func(); }
+
+ QRect calculateFallbackWindowGeometry() const;
+ void updateFallbackWindowGeometry();
+
+private:
+ QWaylandXdgShellV6 *m_xdgShell;
+ QWaylandSurface *m_surface;
+
+ QWaylandXdgToplevelV6 *m_toplevel;
+ QWaylandXdgPopupV6 *m_popup;
+ QRect m_windowGeometry;
+ bool m_unsetWindowGeometry;
+ QMargins m_windowMargins;
+ Qt::WindowType m_windowType;
+
+ void zxdg_surface_v6_destroy_resource(Resource *resource) override;
+ void zxdg_surface_v6_destroy(Resource *resource) override;
+ void zxdg_surface_v6_get_toplevel(Resource *resource, uint32_t id) override;
+ void zxdg_surface_v6_get_popup(Resource *resource, uint32_t id, struct ::wl_resource *parent, struct ::wl_resource *positioner) override;
+ void zxdg_surface_v6_ack_configure(Resource *resource, uint32_t serial) override;
+ void zxdg_surface_v6_set_window_geometry(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgToplevelV6Private : public QObjectPrivate, public QtWaylandServer::zxdg_toplevel_v6
+{
+ Q_DECLARE_PUBLIC(QWaylandXdgToplevelV6)
+public:
+ struct ConfigureEvent {
+ QVector<QWaylandXdgToplevelV6::State> states;
+ QSize size;
+ uint serial;
+ };
+
+ QWaylandXdgToplevelV6Private(QWaylandXdgSurfaceV6 *xdgSurface, const QWaylandResource& resource);
+ ConfigureEvent lastSentConfigure() const { return m_pendingConfigures.empty() ? m_lastAckedConfigure : m_pendingConfigures.first(); }
+ void handleAckConfigure(uint serial); //TODO: move?
+ void handleFocusLost();
+ void handleFocusReceived();
+
+ static QWaylandXdgToplevelV6Private *get(QWaylandXdgToplevelV6 *toplevel) { return toplevel->d_func(); }
+
+protected:
+
+ void zxdg_toplevel_v6_destroy_resource(Resource *resource) override;
+
+ void zxdg_toplevel_v6_destroy(Resource *resource) override;
+ void zxdg_toplevel_v6_set_parent(Resource *resource, struct ::wl_resource *parent) override;
+ void zxdg_toplevel_v6_set_title(Resource *resource, const QString &title) override;
+ void zxdg_toplevel_v6_set_app_id(Resource *resource, const QString &app_id) override;
+ void zxdg_toplevel_v6_show_window_menu(Resource *resource, struct ::wl_resource *seat, uint32_t serial, int32_t x, int32_t y) override;
+ void zxdg_toplevel_v6_move(Resource *resource, struct ::wl_resource *seatResource, uint32_t serial) override;
+ void zxdg_toplevel_v6_resize(Resource *resource, struct ::wl_resource *seat, uint32_t serial, uint32_t edges) override;
+ void zxdg_toplevel_v6_set_max_size(Resource *resource, int32_t width, int32_t height) override;
+ void zxdg_toplevel_v6_set_min_size(Resource *resource, int32_t width, int32_t height) override;
+ void zxdg_toplevel_v6_set_maximized(Resource *resource) override;
+ void zxdg_toplevel_v6_unset_maximized(Resource *resource) override;
+ void zxdg_toplevel_v6_set_fullscreen(Resource *resource, struct ::wl_resource *output) override;
+ void zxdg_toplevel_v6_unset_fullscreen(Resource *resource) override;
+ void zxdg_toplevel_v6_set_minimized(Resource *resource) override;
+
+public:
+ QWaylandXdgSurfaceV6 *m_xdgSurface;
+ QWaylandXdgToplevelV6 *m_parentToplevel;
+ QList<ConfigureEvent> m_pendingConfigures;
+ ConfigureEvent m_lastAckedConfigure;
+ QString m_title;
+ QString m_appId;
+ QSize m_maxSize;
+ QSize m_minSize;
+
+ static QWaylandSurfaceRole s_role;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPopupV6Private : public QObjectPrivate, public QtWaylandServer::zxdg_popup_v6
+{
+ Q_DECLARE_PUBLIC(QWaylandXdgPopupV6)
+public:
+ struct ConfigureEvent {
+ QRect geometry;
+ uint serial;
+ };
+
+ QWaylandXdgPopupV6Private(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandXdgSurfaceV6 *parentXdgSurface,
+ QWaylandXdgPositionerV6 *positioner, const QWaylandResource& resource);
+
+ void handleAckConfigure(uint serial);
+
+ static QWaylandXdgPopupV6Private *get(QWaylandXdgPopupV6 *popup) { return popup->d_func(); }
+
+ static QWaylandSurfaceRole s_role;
+
+private:
+ uint sendConfigure(const QRect &geometry);
+
+protected:
+ void zxdg_popup_v6_destroy(Resource *resource) override;
+ void zxdg_popup_v6_grab(Resource *resource, struct ::wl_resource *seat, uint32_t serial) override;
+
+private:
+ QWaylandXdgSurfaceV6 *m_xdgSurface;
+ QWaylandXdgSurfaceV6 *m_parentXdgSurface;
+ QWaylandXdgPositionerV6Data m_positionerData;
+ QRect m_geometry;
+ QList<ConfigureEvent> m_pendingConfigures;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPositionerV6 : public QtWaylandServer::zxdg_positioner_v6
+{
+public:
+ QWaylandXdgPositionerV6(const QWaylandResource& resource);
+ static QWaylandXdgPositionerV6 *fromResource(wl_resource *resource);
+
+protected:
+ void zxdg_positioner_v6_destroy_resource(Resource *resource) override; //TODO: do something special here?
+
+ void zxdg_positioner_v6_destroy(Resource *resource) override;
+ void zxdg_positioner_v6_set_size(Resource *resource, int32_t width, int32_t height) override;
+ void zxdg_positioner_v6_set_anchor_rect(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override;
+ void zxdg_positioner_v6_set_anchor(Resource *resource, uint32_t anchor) override;
+ void zxdg_positioner_v6_set_gravity(Resource *resource, uint32_t gravity) override;
+ void zxdg_positioner_v6_set_constraint_adjustment(Resource *resource, uint32_t constraint_adjustment) override;
+ void zxdg_positioner_v6_set_offset(Resource *resource, int32_t x, int32_t y) override;
+
+public:
+ QWaylandXdgPositionerV6Data m_data;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDXDGSHELLV6_P_H
diff --git a/src/compositor/extensions/qwaylandxdgshellv6integration.cpp b/src/compositor/extensions/qwaylandxdgshellv6integration.cpp
new file mode 100644
index 000000000..17ee10db7
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgshellv6integration.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandxdgshellv6integration_p.h"
+
+#include <QtWaylandCompositor/QWaylandXdgSurfaceV6>
+#include <QtWaylandCompositor/QWaylandCompositor>
+#include <QtWaylandCompositor/QWaylandSeat>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWayland {
+
+XdgToplevelV6Integration::XdgToplevelV6Integration(QWaylandQuickShellSurfaceItem *item)
+ : QWaylandQuickShellIntegration(item)
+ , m_item(item)
+ , m_xdgSurface(qobject_cast<QWaylandXdgSurfaceV6 *>(item->shellSurface()))
+ , m_toplevel(m_xdgSurface->toplevel())
+ , grabberState(GrabberState::Default)
+{
+ Q_ASSERT(m_toplevel);
+
+ m_item->setSurface(m_xdgSurface->surface());
+ connect(m_toplevel, &QWaylandXdgToplevelV6::startMove, this, &XdgToplevelV6Integration::handleStartMove);
+ connect(m_toplevel, &QWaylandXdgToplevelV6::startResize, this, &XdgToplevelV6Integration::handleStartResize);
+ connect(m_toplevel, &QWaylandXdgToplevelV6::setMaximized, this, &XdgToplevelV6Integration::handleSetMaximized);
+ connect(m_toplevel, &QWaylandXdgToplevelV6::unsetMaximized, this, &XdgToplevelV6Integration::handleUnsetMaximized);
+ connect(m_toplevel, &QWaylandXdgToplevelV6::maximizedChanged, this, &XdgToplevelV6Integration::handleMaximizedChanged);
+ connect(m_toplevel, &QWaylandXdgToplevelV6::activatedChanged, this, &XdgToplevelV6Integration::handleActivatedChanged);
+ connect(m_xdgSurface->surface(), &QWaylandSurface::sizeChanged, this, &XdgToplevelV6Integration::handleSurfaceSizeChanged);
+}
+
+bool XdgToplevelV6Integration::mouseMoveEvent(QMouseEvent *event)
+{
+ if (grabberState == GrabberState::Resize) {
+ Q_ASSERT(resizeState.seat == m_item->compositor()->seatFor(event));
+ if (!resizeState.initialized) {
+ resizeState.initialMousePos = event->windowPos();
+ resizeState.initialized = true;
+ return true;
+ }
+ QPointF delta = m_item->mapToSurface(event->windowPos() - resizeState.initialMousePos);
+ QSize newSize = m_toplevel->sizeForResize(resizeState.initialWindowSize, delta, resizeState.resizeEdges);
+ m_toplevel->sendResizing(newSize);
+ } else if (grabberState == GrabberState::Move) {
+ Q_ASSERT(moveState.seat == m_item->compositor()->seatFor(event));
+ QQuickItem *moveItem = m_item->moveItem();
+ if (!moveState.initialized) {
+ moveState.initialOffset = moveItem->mapFromItem(nullptr, event->windowPos());
+ moveState.initialized = true;
+ return true;
+ }
+ if (!moveItem->parentItem())
+ return true;
+ QPointF parentPos = moveItem->parentItem()->mapFromItem(nullptr, event->windowPos());
+ moveItem->setPosition(parentPos - moveState.initialOffset);
+ }
+ return false;
+}
+
+bool XdgToplevelV6Integration::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_UNUSED(event);
+
+ if (grabberState == GrabberState::Move) {
+ grabberState = GrabberState::Default;
+ return true;
+ }
+ return false;
+}
+
+void XdgToplevelV6Integration::handleStartMove(QWaylandSeat *seat)
+{
+ grabberState = GrabberState::Move;
+ moveState.seat = seat;
+ moveState.initialized = false;
+}
+
+void XdgToplevelV6Integration::handleStartResize(QWaylandSeat *seat, Qt::Edges edges)
+{
+ grabberState = GrabberState::Resize;
+ resizeState.seat = seat;
+ resizeState.resizeEdges = edges;
+ resizeState.initialWindowSize = m_xdgSurface->windowGeometry().size();
+ resizeState.initialPosition = m_item->moveItem()->position();
+ resizeState.initialSurfaceSize = m_item->surface()->size();
+ resizeState.initialized = false;
+}
+
+void XdgToplevelV6Integration::handleSetMaximized()
+{
+ if (!m_item->view()->isPrimary())
+ return;
+
+ maximizeState.initialWindowSize = m_xdgSurface->windowGeometry().size();
+ maximizeState.initialPosition = m_item->moveItem()->position();
+
+ QWaylandOutput *output = m_item->view()->output();
+ m_toplevel->sendMaximized(output->availableGeometry().size() / output->scaleFactor());
+}
+
+void XdgToplevelV6Integration::handleUnsetMaximized()
+{
+ if (!m_item->view()->isPrimary())
+ return;
+
+ m_toplevel->sendUnmaximized(maximizeState.initialWindowSize);
+}
+
+void XdgToplevelV6Integration::handleMaximizedChanged()
+{
+ if (m_toplevel->maximized()) {
+ QWaylandOutput *output = m_item->view()->output();
+ m_item->moveItem()->setPosition(output->position() + output->availableGeometry().topLeft());
+ } else {
+ m_item->moveItem()->setPosition(maximizeState.initialPosition);
+ }
+}
+
+void XdgToplevelV6Integration::handleActivatedChanged()
+{
+ if (m_toplevel->activated())
+ m_item->raise();
+}
+
+void XdgToplevelV6Integration::handleSurfaceSizeChanged()
+{
+ if (grabberState == GrabberState::Resize) {
+ qreal x = resizeState.initialPosition.x();
+ qreal y = resizeState.initialPosition.y();
+ if (resizeState.resizeEdges & Qt::TopEdge)
+ y += resizeState.initialSurfaceSize.height() - m_item->surface()->size().height();
+
+ if (resizeState.resizeEdges & Qt::LeftEdge)
+ x += resizeState.initialSurfaceSize.width() - m_item->surface()->size().width();
+ m_item->moveItem()->setPosition(QPointF(x, y));
+ }
+}
+
+XdgPopupV6Integration::XdgPopupV6Integration(QWaylandQuickShellSurfaceItem *item)
+ : m_item(item)
+ , m_xdgSurface(qobject_cast<QWaylandXdgSurfaceV6 *>(item->shellSurface()))
+ , m_popup(m_xdgSurface->popup())
+{
+ Q_ASSERT(m_popup);
+
+ m_item->setSurface(m_xdgSurface->surface());
+ handleGeometryChanged();
+
+ connect(m_popup, &QWaylandXdgPopupV6::configuredGeometryChanged, this, &XdgPopupV6Integration::handleGeometryChanged);
+}
+
+void XdgPopupV6Integration::handleGeometryChanged()
+{
+ if (m_item->view()->output()) {
+ const QPoint windowOffset = m_popup->parentXdgSurface()->windowGeometry().topLeft();
+ const QPoint position = m_popup->unconstrainedPosition() + windowOffset;
+ //TODO: positioner size or other size...?
+ const float scaleFactor = m_item->view()->output()->scaleFactor();
+ //TODO check positioner constraints etc... sliding, flipping
+ m_item->moveItem()->setPosition(position * scaleFactor);
+ } else {
+ qWarning() << "XdgPopupV6Integration popup item without output" << m_item;
+ }
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandxdgshellv6integration_p.h b/src/compositor/extensions/qwaylandxdgshellv6integration_p.h
new file mode 100644
index 000000000..36dd21b6c
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgshellv6integration_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXDGSHELLV6INTEGRATION_H
+#define QWAYLANDXDGSHELLV6INTEGRATION_H
+
+#include <QtWaylandCompositor/private/qwaylandquickshellsurfaceitem_p.h>
+#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem>
+#include <QtWaylandCompositor/QWaylandXdgToplevelV6>
+
+QT_BEGIN_NAMESPACE
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+class QWaylandXdgSurfaceV6;
+
+namespace QtWayland {
+
+class XdgToplevelV6Integration : public QWaylandQuickShellIntegration
+{
+ Q_OBJECT
+public:
+ XdgToplevelV6Integration(QWaylandQuickShellSurfaceItem *item);
+ bool mouseMoveEvent(QMouseEvent *event) override;
+ bool mouseReleaseEvent(QMouseEvent *event) override;
+
+private Q_SLOTS:
+ void handleStartMove(QWaylandSeat *seat);
+ void handleStartResize(QWaylandSeat *seat, Qt::Edges edges);
+ void handleSetMaximized();
+ void handleUnsetMaximized();
+ void handleMaximizedChanged();
+ void handleActivatedChanged();
+ void handleSurfaceSizeChanged();
+
+private:
+ QWaylandQuickShellSurfaceItem *m_item;
+ QWaylandXdgSurfaceV6 *m_xdgSurface;
+ QWaylandXdgToplevelV6 *m_toplevel;
+
+ enum class GrabberState {
+ Default,
+ Resize,
+ Move
+ };
+ GrabberState grabberState;
+
+ struct {
+ QWaylandSeat *seat;
+ QPointF initialOffset;
+ bool initialized;
+ } moveState;
+
+ struct {
+ QWaylandSeat *seat;
+ Qt::Edges resizeEdges;
+ QSizeF initialWindowSize;
+ QPointF initialMousePos;
+ QPointF initialPosition;
+ QSize initialSurfaceSize;
+ bool initialized;
+ } resizeState;
+
+ struct {
+ QSize initialWindowSize;
+ QPointF initialPosition;
+ } maximizeState;
+};
+
+class XdgPopupV6Integration : public QWaylandQuickShellIntegration
+{
+ Q_OBJECT
+public:
+ XdgPopupV6Integration(QWaylandQuickShellSurfaceItem *item);
+
+private Q_SLOTS:
+ void handleGeometryChanged();
+
+private:
+ QWaylandQuickShellSurfaceItem *m_item;
+ QWaylandXdgSurfaceV6 *m_xdgSurface;
+ QWaylandXdgPopupV6 *m_popup;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDXDGSHELLV6INTEGRATION_H
diff --git a/src/compositor/hardware_integration/qwlserverbufferintegration_p.h b/src/compositor/hardware_integration/qwlserverbufferintegration_p.h
index 4754e751f..c27fd4e44 100644
--- a/src/compositor/hardware_integration/qwlserverbufferintegration_p.h
+++ b/src/compositor/hardware_integration/qwlserverbufferintegration_p.h
@@ -64,6 +64,8 @@ QT_BEGIN_NAMESPACE
class QWaylandCompositor;
class QOpenGLContext;
+class QOpenGLTexture;
+class QImage;
namespace QtWayland {
class Display;
@@ -81,7 +83,7 @@ public:
virtual struct ::wl_resource *resourceForClient(struct ::wl_client *) = 0;
- virtual void bindTextureToBuffer() = 0;
+ virtual QOpenGLTexture *toOpenGlTexture() = 0;
virtual bool isYInverted() const;
@@ -101,7 +103,7 @@ public:
virtual void initializeHardware(QWaylandCompositor *);
virtual bool supportsFormat(ServerBuffer::Format format) const = 0;
- virtual ServerBuffer *createServerBuffer(const QSize &size, ServerBuffer::Format format) = 0;
+ virtual ServerBuffer *createServerBufferFromImage(const QImage &qimage, ServerBuffer::Format format) = 0;
};
}
diff --git a/src/extensions/shm-emulation-server-buffer.xml b/src/extensions/shm-emulation-server-buffer.xml
new file mode 100644
index 000000000..7fb7069f2
--- /dev/null
+++ b/src/extensions/shm-emulation-server-buffer.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="shm_emulation_server_buffer">
+ <copyright>
+ Copyright (C) 2017 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_shm_emulation_server_buffer" version="1">
+ <description summary="shm-based server buffer for testing on desktop">
+ This is software-based implementation of the qt_server_buffer extension.
+ It is intended for testing and debugging purposes only.
+ </description>
+ <enum name="format">
+ <entry name="RGBA32" value="0"/>
+ <entry name="A8" value="1"/>
+ </enum>
+ <event name="server_buffer_created">
+ <description summary="shm buffer information">
+ Informs the client about a newly created server buffer.
+ The "key" argument contains a QSharedMemory key.
+ </description>
+ <arg name="id" type="new_id" interface="qt_server_buffer"/>
+ <arg name="key" type="string"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="bytes_per_line" type="int"/>
+ <arg name="format" type="int"/>
+ </event>
+ </interface>
+</protocol>
+
diff --git a/src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.cpp b/src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.cpp
index 5ded6ff0d..fe2adbf56 100644
--- a/src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.cpp
+++ b/src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.cpp
@@ -41,6 +41,7 @@
#include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QDebug>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
#include <EGL/egl.h>
@@ -98,23 +99,35 @@ DrmServerBuffer::~DrmServerBuffer()
m_integration->eglDestroyImageKHR(m_image);
}
-void DrmServerBuffer::bindTextureToBuffer()
+QOpenGLTexture *DrmServerBuffer::toOpenGlTexture()
{
if (!QOpenGLContext::currentContext())
qWarning("DrmServerBuffer: creating texture with no current context");
- m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
+ if (!m_texture) {
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+ }
+ m_texture->bind();
+ m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_texture->release();
+ m_texture->setSize(m_size.width(), m_size.height());
+ return m_texture;
}
-void DrmEglServerBufferIntegration::initialize(QWaylandDisplay *display)
+void DrmEglServerBufferIntegration::initializeEgl()
{
- m_egl_display = eglGetDisplay((EGLNativeDisplayType) display->wl_display());
- if (EGL_NO_DISPLAY) {
+ if (m_egl_initialized)
+ return;
+ m_egl_initialized = true;
+
+ m_egl_display = eglGetDisplay((EGLNativeDisplayType) m_display->wl_display());
+ if (m_egl_display == EGL_NO_DISPLAY) {
qWarning("Failed to initialize drm egl server buffer integration. Could not get egl display from wl_display.");
return;
}
@@ -136,8 +149,13 @@ void DrmEglServerBufferIntegration::initialize(QWaylandDisplay *display)
qWarning("Failed to initialize drm egl server buffer integration. Could not resolve glEGLImageTargetTexture2DOES");
return;
}
+ m_egl_initialized = true;
+}
- QtWayland::wl_registry::init(wl_display_get_registry(display->wl_display()));
+void DrmEglServerBufferIntegration::initialize(QWaylandDisplay *display)
+{
+ m_display = display;
+ display->addRegistryListener(&wlDisplayHandleGlobal, this);
}
QWaylandServerBuffer *DrmEglServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer)
@@ -145,12 +163,12 @@ QWaylandServerBuffer *DrmEglServerBufferIntegration::serverBuffer(struct qt_serv
return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer));
}
-void DrmEglServerBufferIntegration::registry_global(uint32_t name, const QString &interface, uint32_t version)
+void DrmEglServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
{
Q_UNUSED(version);
if (interface == QStringLiteral("qt_drm_egl_server_buffer")) {
- struct ::wl_registry *registry = QtWayland::wl_registry::object();
- QtWayland::qt_drm_egl_server_buffer::init(registry, name, 1);
+ auto *integration = static_cast<DrmEglServerBufferIntegration *>(data);
+ integration->QtWayland::qt_drm_egl_server_buffer::init(registry, id, 1);
}
}
diff --git a/src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.h b/src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.h
index f848f190e..f1b722997 100644
--- a/src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.h
+++ b/src/hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.h
@@ -71,15 +71,15 @@ class DrmServerBuffer : public QWaylandServerBuffer
public:
DrmServerBuffer(DrmEglServerBufferIntegration *integration, int32_t name, int32_t width, int32_t height, int32_t stride, int32_t format);
~DrmServerBuffer();
- void bindTextureToBuffer() override;
+ QOpenGLTexture* toOpenGlTexture() override;
private:
DrmEglServerBufferIntegration *m_integration;
EGLImageKHR m_image;
+ QOpenGLTexture *m_texture = nullptr;
};
class DrmEglServerBufferIntegration
: public QWaylandServerBufferIntegration
- , public QtWayland::wl_registry
, public QtWayland::qt_drm_egl_server_buffer
{
public:
@@ -91,17 +91,24 @@ public:
inline EGLBoolean eglDestroyImageKHR (EGLImageKHR image);
inline void glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
protected:
- void registry_global(uint32_t name, const QString &interface, uint32_t version) override;
void drm_egl_server_buffer_server_buffer_created(struct ::qt_server_buffer *id, int32_t name, int32_t width, int32_t height, int32_t stride, int32_t format) override;
private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+ void initializeEgl();
+
PFNEGLCREATEIMAGEKHRPROC m_egl_create_image;
PFNEGLDESTROYIMAGEKHRPROC m_egl_destroy_image;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_gl_egl_image_target_texture;
+ QWaylandDisplay *m_display = nullptr;
EGLDisplay m_egl_display;
+ bool m_egl_initialized = false;
};
EGLImageKHR DrmEglServerBufferIntegration::eglCreateImageKHR(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
+ if (!m_egl_initialized)
+ initializeEgl();
if (!m_egl_create_image) {
qWarning("DrmEglServerBufferIntegration: Trying to used unresolved function eglCreateImageKHR");
return EGL_NO_IMAGE_KHR;
diff --git a/src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.cpp b/src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.cpp
index 21af476fd..51b904e75 100644
--- a/src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.cpp
+++ b/src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.cpp
@@ -41,6 +41,7 @@
#include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QDebug>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
#include <hybris/eglplatformcommon/hybris_nativebufferext.h>
#include <EGL/egl.h>
@@ -59,6 +60,7 @@ LibHybrisServerBuffer::LibHybrisServerBuffer(LibHybrisEglServerBufferIntegration
, int32_t format)
: QWaylandServerBuffer()
, m_integration(integration)
+ , m_texture(nullptr)
, m_stride(stride)
, m_hybrisFormat(format)
{
@@ -76,18 +78,28 @@ LibHybrisServerBuffer::~LibHybrisServerBuffer()
m_integration->eglDestroyImageKHR(m_image);
}
-void LibHybrisServerBuffer::bindTextureToBuffer()
+QOpenGLTexture * LibHybrisServerBuffer::toOpenGlTexture()
{
if (!QOpenGLContext::currentContext()) {
qWarning("LibHybrisServerBuffer: creating texture with no current context");
}
+ if (!m_texture) {
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+ }
+
+ m_texture->bind();
m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_texture->release();
+ m_texture->setSize(m_size.width(), m_size.height());
+
+ return m_texture;
}
void LibHybrisServerBuffer::libhybris_buffer_add_fd(int32_t fd)
@@ -114,10 +126,14 @@ void LibHybrisServerBuffer::libhybris_buffer_add_fd(int32_t fd)
}
}
-void LibHybrisEglServerBufferIntegration::initialize(QWaylandDisplay *display)
+void LibHybrisEglServerBufferIntegration::initializeEgl()
{
- m_egl_display = eglGetDisplay((EGLNativeDisplayType) display->wl_display());
- if (EGL_NO_DISPLAY) {
+ if (m_egl_initialized)
+ return;
+ m_egl_initialized = true;
+
+ m_egl_display = eglGetDisplay((EGLNativeDisplayType) m_display->wl_display());
+ if (m_egl_display == EGL_NO_DISPLAY) {
qWarning("Failed to initialize libhybris egl server buffer integration. Could not get egl display from wl_display.");
return;
}
@@ -145,8 +161,13 @@ void LibHybrisEglServerBufferIntegration::initialize(QWaylandDisplay *display)
qWarning("Failed to initialize libhybris egl server buffer integration. Could not resolve eglHybrisCreateRemoteBuffer");
return;
}
+ m_egl_initialized = true;
+}
- QtWayland::wl_registry::init(wl_display_get_registry(display->wl_display()));
+void LibHybrisEglServerBufferIntegration::initialize(QWaylandDisplay *display)
+{
+ m_display = display;
+ display->addRegistryListener(&wlDisplayHandleGlobal, this);
}
QWaylandServerBuffer *LibHybrisEglServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer)
@@ -154,12 +175,12 @@ QWaylandServerBuffer *LibHybrisEglServerBufferIntegration::serverBuffer(struct q
return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer));
}
-void LibHybrisEglServerBufferIntegration::registry_global(uint32_t name, const QString &interface, uint32_t version)
+void LibHybrisEglServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
{
Q_UNUSED(version);
if (interface == QStringLiteral("qt_libhybris_egl_server_buffer")) {
- struct ::wl_registry *registry = QtWayland::wl_registry::object();
- QtWayland::qt_libhybris_egl_server_buffer::init(registry, name, 1);
+ auto *integration = static_cast<LibHybrisEglServerBufferIntegration *>(data);
+ integration->QtWayland::qt_libhybris_egl_server_buffer::init(registry, id, 1);
}
}
diff --git a/src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.h b/src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.h
index e9f0689a2..b3c9c464d 100644
--- a/src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.h
+++ b/src/hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.h
@@ -75,7 +75,7 @@ class LibHybrisServerBuffer : public QWaylandServerBuffer, public QtWayland::qt_
public:
LibHybrisServerBuffer(LibHybrisEglServerBufferIntegration *integration, int32_t numFds, wl_array *ints, int32_t name, int32_t width, int32_t height, int32_t stride, int32_t format);
~LibHybrisServerBuffer();
- void bindTextureToBuffer() override;
+ QOpenGLTexture* toOpenGlTexture() override;
protected:
void libhybris_buffer_add_fd(int32_t fd) override;
@@ -83,6 +83,7 @@ protected:
private:
LibHybrisEglServerBufferIntegration *m_integration;
EGLImageKHR m_image;
+ QOpenGLTexture *m_texture;
int m_numFds;
QVector<int32_t> m_ints;
QVector<int32_t> m_fds;
@@ -92,7 +93,6 @@ private:
class LibHybrisEglServerBufferIntegration
: public QWaylandServerBufferIntegration
- , public QtWayland::wl_registry
, public QtWayland::qt_libhybris_egl_server_buffer
{
public:
@@ -106,19 +106,27 @@ public:
inline EGLBoolean eglHybrisCreateRemoteBuffer(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint stride, int num_ints, int *ints, int num_fds, int *fds, EGLClientBuffer *buffer);
protected:
- void registry_global(uint32_t name, const QString &interface, uint32_t version) override;
void libhybris_egl_server_buffer_server_buffer_created(struct ::qt_libhybris_buffer *id, struct ::qt_server_buffer *qid,
int32_t numFds, wl_array *ints, int32_t name, int32_t width, int32_t height, int32_t stride, int32_t format) override;
private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+ void initializeEgl();
+
PFNEGLCREATEIMAGEKHRPROC m_egl_create_image;
PFNEGLDESTROYIMAGEKHRPROC m_egl_destroy_image;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_gl_egl_image_target_texture;
PFNEGLHYBRISCREATEREMOTEBUFFERPROC m_egl_create_buffer;
+ QWaylandDisplay *m_display = nullptr;
EGLDisplay m_egl_display;
+ bool m_egl_initialized = false;
};
EGLImageKHR LibHybrisEglServerBufferIntegration::eglCreateImageKHR(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
+ if (!m_egl_initialized)
+ initializeEgl();
+
if (!m_egl_create_image) {
qWarning("LibHybrisEglServerBufferIntegration: Trying to used unresolved function eglCreateImageKHR");
return EGL_NO_IMAGE_KHR;
diff --git a/src/hardwareintegration/client/shm-emulation-server/shm-emulation-server.pri b/src/hardwareintegration/client/shm-emulation-server/shm-emulation-server.pri
new file mode 100644
index 000000000..1a78290d7
--- /dev/null
+++ b/src/hardwareintegration/client/shm-emulation-server/shm-emulation-server.pri
@@ -0,0 +1,12 @@
+INCLUDEPATH += $$PWD
+
+QMAKE_USE += wayland-client
+
+SOURCES += \
+ $$PWD/shmserverbufferintegration.cpp
+
+HEADERS += \
+ $$PWD/shmserverbufferintegration.h
+
+CONFIG += wayland-scanner
+WAYLANDCLIENTSOURCES += $$PWD/../../../extensions/shm-emulation-server-buffer.xml
diff --git a/src/hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.cpp b/src/hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.cpp
new file mode 100644
index 000000000..bc597ebf8
--- /dev/null
+++ b/src/hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shmserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QDebug>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
+#include <QtGui/QImage>
+#include <QtCore/QSharedMemory>
+
+QT_BEGIN_NAMESPACE
+
+static QOpenGLTexture *createTextureFromShm(const QString &key, int w, int h, int bpl, int format)
+{
+ QSharedMemory shm(key);
+ bool ok;
+ ok = shm.attach(QSharedMemory::ReadOnly);
+ if (!ok) {
+ qWarning() << "Could not attach to" << key;
+ return nullptr;
+ }
+ ok = shm.lock();
+ if (!ok) {
+ qWarning() << "Could not lock" << key << "for reading";
+ return nullptr;
+ }
+
+ QImage::Format imageFormat;
+ switch (format) {
+ case QtWayland::qt_shm_emulation_server_buffer::format_RGBA32:
+ imageFormat = QImage::Format_RGBA8888;
+ break;
+ case QtWayland::qt_shm_emulation_server_buffer::format_A8:
+ imageFormat = QImage::Format_Alpha8;
+ break;
+ default:
+ qWarning() << "ShmServerBuffer: unknown format" << format;
+ imageFormat = QImage::Format_RGBA8888;
+ break;
+ }
+
+ QImage image(static_cast<const uchar*>(shm.constData()), w, h, bpl, imageFormat);
+
+ if (!QOpenGLContext::currentContext())
+ qWarning("ShmServerBuffer: creating texture with no current context");
+
+ auto *tex = new QOpenGLTexture(image, QOpenGLTexture::DontGenerateMipMaps);
+ shm.unlock();
+ return tex;
+}
+
+
+namespace QtWaylandClient {
+ShmServerBuffer::ShmServerBuffer(ShmServerBufferIntegration *integration, const QString &key, int32_t width, int32_t height, int32_t bytes_per_line, int32_t format)
+ : QWaylandServerBuffer()
+ , m_integration(integration)
+ , m_texture(nullptr)
+ , m_key(key)
+ , m_bpl(bytes_per_line)
+ , m_format(format)
+{
+ m_size = QSize(width, height);
+}
+
+ShmServerBuffer::~ShmServerBuffer()
+{
+}
+
+QOpenGLTexture *ShmServerBuffer::toOpenGlTexture()
+{
+ if (!m_texture)
+ m_texture = createTextureFromShm(m_key, m_size.width(), m_size.height(), m_bpl, m_format);
+
+ return m_texture;
+}
+
+void ShmServerBufferIntegration::initialize(QWaylandDisplay *display)
+{
+ m_display = display;
+ display->addRegistryListener(&wlDisplayHandleGlobal, this);
+}
+
+QWaylandServerBuffer *ShmServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer)
+{
+ return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer));
+}
+
+void ShmServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+ if (interface == "qt_shm_emulation_server_buffer") {
+ auto *integration = static_cast<ShmServerBufferIntegration *>(data);
+ integration->QtWayland::qt_shm_emulation_server_buffer::init(registry, id, 1);
+ }
+}
+
+
+void QtWaylandClient::ShmServerBufferIntegration::shm_emulation_server_buffer_server_buffer_created(qt_server_buffer *id, const QString &key, int32_t width, int32_t height, int32_t bytes_per_line, int32_t format)
+{
+ auto *server_buffer = new ShmServerBuffer(this, key, width, height, bytes_per_line, format);
+ qt_server_buffer_set_user_data(id, server_buffer);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.h b/src/hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.h
new file mode 100644
index 000000000..ce4032ba4
--- /dev/null
+++ b/src/hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHMSERVERBUFFERINTEGRATION_H
+#define SHMSERVERBUFFERINTEGRATION_H
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+#include "qwayland-shm-emulation-server-buffer.h"
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+
+#include "shmserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtCore/QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class ShmServerBufferIntegration;
+
+class ShmServerBuffer : public QWaylandServerBuffer
+{
+public:
+ ShmServerBuffer(ShmServerBufferIntegration *integration, const QString &key, int32_t width, int32_t height, int32_t bytes_per_line, int32_t format);
+ ~ShmServerBuffer();
+ QOpenGLTexture* toOpenGlTexture() override;
+private:
+ ShmServerBufferIntegration *m_integration;
+ QOpenGLTexture *m_texture;
+ QString m_key;
+ int m_bpl;
+ int m_format;
+};
+
+class ShmServerBufferIntegration
+ : public QWaylandServerBufferIntegration
+ , public QtWayland::qt_shm_emulation_server_buffer
+{
+public:
+ void initialize(QWaylandDisplay *display) override;
+
+ virtual QWaylandServerBuffer *serverBuffer(struct qt_server_buffer *buffer) override;
+
+protected:
+ void shm_emulation_server_buffer_server_buffer_created(qt_server_buffer *id, const QString &key, int32_t width, int32_t height, int32_t bytes_per_line, int32_t format) override;
+
+private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+ QWaylandDisplay *m_display = nullptr;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp b/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp
index fe7f12fd0..35fdc8277 100644
--- a/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp
+++ b/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp
@@ -40,12 +40,14 @@
#include "drmeglserverbufferintegration.h"
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
QT_BEGIN_NAMESPACE
-DrmEglServerBuffer::DrmEglServerBuffer(DrmEglServerBufferIntegration *integration, const QSize &size, QtWayland::ServerBuffer::Format format)
- : QtWayland::ServerBuffer(size,format)
+DrmEglServerBuffer::DrmEglServerBuffer(DrmEglServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format)
+ : QtWayland::ServerBuffer(qimage.size(),format)
, m_integration(integration)
+ , m_texture(nullptr)
{
m_format = format;
@@ -82,38 +84,42 @@ DrmEglServerBuffer::DrmEglServerBuffer(DrmEglServerBufferIntegration *integratio
qWarning("DrmEglServerBuffer: Failed to export egl image");
}
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+ m_texture->bind();
+
+ m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, qimage.width(), qimage.height(), GL_RGBA, GL_UNSIGNED_BYTE, qimage.constBits());
+
+ m_texture->release();
+ m_texture->setSize(m_size.width(), m_size.height());
}
struct ::wl_resource *DrmEglServerBuffer::resourceForClient(struct ::wl_client *client)
{
- QMultiMap<struct ::wl_client *, Resource *>::iterator it = resourceMap().find(client);
- if (it == resourceMap().end()) {
- QMultiMap<struct ::wl_client *, QtWaylandServer::qt_drm_egl_server_buffer::Resource *>::iterator drm_egl_it = m_integration->resourceMap().find(client);
- if (drm_egl_it == m_integration->resourceMap().end()) {
+ auto *bufferResource = resourceMap().value(client);
+ if (!bufferResource) {
+ auto integrationResource = m_integration->resourceMap().value(client);
+ if (!integrationResource) {
qWarning("DrmEglServerBuffer::resourceForClient: Trying to get resource for ServerBuffer. But client is not bound to the drm_egl interface");
return 0;
}
- struct ::wl_resource *drm_egl_resource = (*drm_egl_it)->handle;
- Resource *resource = add(client, 1, 1);
- m_integration->send_server_buffer_created(drm_egl_resource, resource->handle, m_name, m_size.width(), m_size.height(), m_stride, m_drm_format);
+ struct ::wl_resource *drm_egl_integration_resource = integrationResource->handle;
+ Resource *resource = add(client, 1);
+ m_integration->send_server_buffer_created(drm_egl_integration_resource, resource->handle, m_name, m_size.width(), m_size.height(), m_stride, m_drm_format);
return resource->handle;
}
- return (*it)->handle;
+ return bufferResource->handle;
}
-void DrmEglServerBuffer::bindTextureToBuffer()
+
+QOpenGLTexture *DrmEglServerBuffer::toOpenGlTexture()
{
- if (!QOpenGLContext::currentContext()) {
- qWarning("DrmEglServerBuffer: No current context when creating buffer. Texture loading will fail");
- return;
+ if (!m_texture) {
+ qWarning("DrmEglServerBuffer::toOpenGlTexture: no texture defined");
}
-
- m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ return m_texture;
}
DrmEglServerBufferIntegration::DrmEglServerBufferIntegration()
@@ -130,7 +136,7 @@ void DrmEglServerBufferIntegration::initializeHardware(QWaylandCompositor *compo
m_egl_display = static_cast<EGLDisplay>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("egldisplay"));
if (!m_egl_display) {
- qWarning("Cant initialize drm egl server buffer integration. Missing egl display from platformplugin");
+ qWarning("Can't initialize drm egl server buffer integration. Missing egl display from platform plugin");
return;
}
@@ -183,9 +189,9 @@ bool DrmEglServerBufferIntegration::supportsFormat(QtWayland::ServerBuffer::Form
}
}
-QtWayland::ServerBuffer *DrmEglServerBufferIntegration::createServerBuffer(const QSize &size, QtWayland::ServerBuffer::Format format)
+QtWayland::ServerBuffer *DrmEglServerBufferIntegration::createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format)
{
- return new DrmEglServerBuffer(this, size, format);
+ return new DrmEglServerBuffer(this, qimage, format);
}
QT_END_NAMESPACE
diff --git a/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.h b/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.h
index 239a1f7d1..e1cc8768f 100644
--- a/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.h
+++ b/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.h
@@ -72,14 +72,15 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy,
QT_BEGIN_NAMESPACE
class DrmEglServerBufferIntegration;
+class QImage;
class DrmEglServerBuffer : public QtWayland::ServerBuffer, public QtWaylandServer::qt_server_buffer
{
public:
- DrmEglServerBuffer(DrmEglServerBufferIntegration *integration, const QSize &size, QtWayland::ServerBuffer::Format format);
+ DrmEglServerBuffer(DrmEglServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format);
struct ::wl_resource *resourceForClient(struct ::wl_client *) override;
- void bindTextureToBuffer() override;
+ QOpenGLTexture *toOpenGlTexture() override;
private:
DrmEglServerBufferIntegration *m_integration;
@@ -88,6 +89,7 @@ private:
int32_t m_name;
int32_t m_stride;
+ QOpenGLTexture *m_texture;
QtWaylandServer::qt_drm_egl_server_buffer::format m_drm_format;
};
@@ -102,7 +104,7 @@ public:
void initializeHardware(QWaylandCompositor *) override;
bool supportsFormat(QtWayland::ServerBuffer::Format format) const override;
- QtWayland::ServerBuffer *createServerBuffer(const QSize &size, QtWayland::ServerBuffer::Format format) override;
+ QtWayland::ServerBuffer *createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format) override;
EGLDisplay display() const { return m_egl_display; }
diff --git a/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp b/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp
index 2312a468b..de9e1cf6e 100644
--- a/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp
+++ b/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp
@@ -40,13 +40,15 @@
#include "libhybriseglserverbufferintegration.h"
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
#include <hybris/eglplatformcommon/hybris_nativebufferext.h>
#include <wayland-server.h>
QT_BEGIN_NAMESPACE
-LibHybrisEglServerBuffer::LibHybrisEglServerBuffer(LibHybrisEglServerBufferIntegration *integration, const QSize &size, QtWayland::ServerBuffer::Format format)
- : QtWayland::ServerBuffer(size,format)
+LibHybrisEglServerBuffer::LibHybrisEglServerBuffer(LibHybrisEglServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format)
+ : QtWayland::ServerBuffer(qimage.size(),format)
, m_integration(integration)
+ , m_texture(nullptr)
{
m_format = format;
@@ -63,7 +65,7 @@ LibHybrisEglServerBuffer::LibHybrisEglServerBuffer(LibHybrisEglServerBufferInteg
break;
}
- if (!m_integration->eglHybrisCreateNativeBuffer(size.width(), size.height(), HYBRIS_USAGE_HW_TEXTURE, egl_format, &m_stride, &m_buffer)) {
+ if (!m_integration->eglHybrisCreateNativeBuffer(m_size.width(), m_size.height(), HYBRIS_USAGE_HW_TEXTURE, egl_format, &m_stride, &m_buffer)) {
qWarning("LibHybrisEglServerBuffer: Failed to create egl buffer");
return;
}
@@ -76,48 +78,53 @@ LibHybrisEglServerBuffer::LibHybrisEglServerBuffer(LibHybrisEglServerBufferInteg
m_integration->eglHybrisSerializeNativeBuffer(m_buffer, m_ints.data(), m_fds.data());
m_image = m_integration->eglCreateImageKHR(EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, m_buffer, 0);
+
+ if (!QOpenGLContext::currentContext()) {
+ qWarning("LibHybrisEglServerBuffer: No current context when creating buffer. Texture loading will fail");
+ return;
+ }
+
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+
+ m_texture->bind();
+
+ m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, qimage.width(), qimage.height(), GL_RGBA, GL_UNSIGNED_BYTE, qimage.constBits());
+
+ m_texture->release();
+ m_texture->setSize(m_size.width(), m_size.height());
}
struct ::wl_resource *LibHybrisEglServerBuffer::resourceForClient(struct ::wl_client *client)
{
- QMultiMap<struct ::wl_client *, Resource *>::iterator it = resourceMap().find(client);
- if (it == resourceMap().end()) {
- QMultiMap<struct ::wl_client *, QtWaylandServer::qt_libhybris_egl_server_buffer::Resource *>::iterator egl_it = m_integration->resourceMap().find(client);
- if (egl_it == m_integration->resourceMap().end()) {
+ auto *bufferResource = resourceMap().value(client);
+ if (!bufferResource) {
+ auto integrationResource = m_integration->resourceMap().value(client);
+ if (!integrationResource) {
qWarning("LibHybrisEglServerBuffer::resourceForClient: Trying to get resource for ServerBuffer. But client is not bound to the libhybris_egl interface");
return 0;
}
- struct ::wl_resource *egl_resource = (*egl_it)->handle;
- Resource *resource = add(client, 1, 1);
- wl_resource *bufRes = wl_client_new_object(client, &qt_libhybris_buffer_interface, 0, 0);
+ struct ::wl_resource *egl_integration_resource = integrationResource->handle;
+ Resource *resource = add(client, 1);
+ wl_resource *bufRes = wl_resource_create(client, &qt_libhybris_buffer_interface,-1, 0);
- m_integration->send_server_buffer_created(egl_resource, resource->handle, bufRes, m_fds.size(), QByteArray((char *)m_ints.data(), m_ints.size() * sizeof(int32_t)),
+ m_integration->send_server_buffer_created(egl_integration_resource, resource->handle, bufRes, m_fds.size(), QByteArray((char *)m_ints.data(), m_ints.size() * sizeof(int32_t)),
m_name, m_size.width(), m_size.height(), m_stride, m_format);
- m_qtbuffers.insert(resource, bufRes);
-
for (int i = 0; i < m_fds.size(); ++i) {
send_add_fd(resource->handle, m_fds.at(i));
}
- return bufRes;
+ return resource->handle;
}
- return m_qtbuffers.value(*it);
+ return bufferResource->handle;
}
-void LibHybrisEglServerBuffer::bindTextureToBuffer()
+QOpenGLTexture *LibHybrisEglServerBuffer::toOpenGlTexture()
{
- if (!QOpenGLContext::currentContext()) {
- qWarning("LibHybrisEglServerBuffer: No current context when creating buffer. Texture loading will fail");
- return;
- }
-
- m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ return m_texture;
}
LibHybrisEglServerBufferIntegration::LibHybrisEglServerBufferIntegration()
@@ -134,7 +141,7 @@ void LibHybrisEglServerBufferIntegration::initializeHardware(QWaylandCompositor
m_egl_display = static_cast<EGLDisplay>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("egldisplay"));
if (!m_egl_display) {
- qWarning("Cant initialize libhybris egl server buffer integration. Missing egl display from platformplugin");
+ qWarning("Can't initialize libhybris egl server buffer integration. Missing egl display from platform plugin");
return;
}
@@ -187,9 +194,9 @@ bool LibHybrisEglServerBufferIntegration::supportsFormat(QtWayland::ServerBuffer
}
}
-QtWayland::ServerBuffer *LibHybrisEglServerBufferIntegration::createServerBuffer(const QSize &size, QtWayland::ServerBuffer::Format format)
+QtWayland::ServerBuffer *LibHybrisEglServerBufferIntegration::createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format)
{
- return new LibHybrisEglServerBuffer(this, size, format);
+ return new LibHybrisEglServerBuffer(this, qimage, format);
}
QT_END_NAMESPACE
diff --git a/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.h b/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.h
index e874e416b..0e1593447 100644
--- a/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.h
+++ b/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.h
@@ -78,10 +78,10 @@ class LibHybrisEglServerBufferIntegration;
class LibHybrisEglServerBuffer : public QtWayland::ServerBuffer, public QtWaylandServer::qt_libhybris_buffer
{
public:
- LibHybrisEglServerBuffer(LibHybrisEglServerBufferIntegration *integration, const QSize &size, QtWayland::ServerBuffer::Format format);
+ LibHybrisEglServerBuffer(LibHybrisEglServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format);
struct ::wl_resource *resourceForClient(struct ::wl_client *) override;
- void bindTextureToBuffer() override;
+ QOpenGLTexture *toOpenGlTexture() override;
private:
LibHybrisEglServerBufferIntegration *m_integration;
@@ -91,10 +91,10 @@ private:
int32_t m_name;
int32_t m_stride;
+ QOpenGLTexture *m_texture;
QtWaylandServer::qt_libhybris_egl_server_buffer::format m_hybris_format;
QVector<int32_t> m_ints;
QVector<int32_t> m_fds;
- QHash<Resource *, wl_resource *> m_qtbuffers;
};
class LibHybrisEglServerBufferIntegration :
@@ -108,7 +108,7 @@ public:
void initializeHardware(QWaylandCompositor *);
bool supportsFormat(QtWayland::ServerBuffer::Format format) const override;
- QtWayland::ServerBuffer *createServerBuffer(const QSize &size, QtWayland::ServerBuffer::Format format) override;
+ QtWayland::ServerBuffer *createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format) override;
EGLDisplay display() const { return m_egl_display; }
diff --git a/src/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pri b/src/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pri
new file mode 100644
index 000000000..4d12024c9
--- /dev/null
+++ b/src/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pri
@@ -0,0 +1,13 @@
+INCLUDEPATH += $$PWD
+
+QMAKE_USE_PRIVATE += wayland-server
+
+SOURCES += \
+ $$PWD/shmserverbufferintegration.cpp
+
+
+HEADERS += \
+ $$PWD/shmserverbufferintegration.h
+
+CONFIG += wayland-scanner
+WAYLANDSERVERSOURCES += $$PWD/../../../extensions/shm-emulation-server-buffer.xml
diff --git a/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp b/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp
new file mode 100644
index 000000000..7a86785b0
--- /dev/null
+++ b/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shmserverbufferintegration.h"
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
+#include <QtCore/QSharedMemory>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+ShmServerBuffer::ShmServerBuffer(ShmServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format)
+ : QtWayland::ServerBuffer(qimage.size(),format)
+ , m_integration(integration)
+ , m_width(qimage.width())
+ , m_height(qimage.height())
+ , m_bpl(qimage.bytesPerLine())
+{
+ m_format = format;
+ switch (m_format) {
+ case RGBA32:
+ m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_RGBA32;
+ break;
+ case A8:
+ m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_A8;
+ break;
+ default:
+ qWarning("ShmServerBuffer: unsupported format");
+ m_shm_format = QtWaylandServer::qt_shm_emulation_server_buffer::format_RGBA32;
+ break;
+ }
+
+ QString key = "qt_shm_emulation_" + QString::number(qimage.cacheKey());
+ m_shm = new QSharedMemory(key);
+ int shm_size = qimage.byteCount();
+ bool ok = m_shm->create(shm_size) && m_shm->lock();
+ if (ok) {
+ memcpy(m_shm->data(), qimage.constBits(), shm_size);
+ m_shm->unlock();
+ } else {
+ qWarning() << "Could not create shared memory" << key << shm_size;
+ }
+}
+
+ShmServerBuffer::~ShmServerBuffer()
+{
+ delete m_shm;
+}
+
+struct ::wl_resource *ShmServerBuffer::resourceForClient(struct ::wl_client *client)
+{
+ auto *bufferResource = resourceMap().value(client);
+ if (!bufferResource) {
+ auto integrationResource = m_integration->resourceMap().value(client);
+ if (!integrationResource) {
+ qWarning("ShmServerBuffer::resourceForClient: Trying to get resource for ServerBuffer. But client is not bound to the shm_emulation interface");
+ return nullptr;
+ }
+ struct ::wl_resource *shm_integration_resource = integrationResource->handle;
+ Resource *resource = add(client, 1);
+ m_integration->send_server_buffer_created(shm_integration_resource, resource->handle, m_shm->key(), m_width, m_height, m_bpl, m_shm_format);
+ return resource->handle;
+ }
+ return bufferResource->handle;
+}
+
+
+QOpenGLTexture *ShmServerBuffer::toOpenGlTexture()
+{
+ if (!m_texture) {
+ qWarning("ShmServerBuffer::toOpenGlTexture: no texture defined");
+ }
+ return m_texture;
+}
+
+ShmServerBufferIntegration::ShmServerBufferIntegration()
+{
+}
+
+ShmServerBufferIntegration::~ShmServerBufferIntegration()
+{
+}
+
+void ShmServerBufferIntegration::initializeHardware(QWaylandCompositor *compositor)
+{
+ Q_ASSERT(QGuiApplication::platformNativeInterface());
+
+ QtWaylandServer::qt_shm_emulation_server_buffer::init(compositor->display(), 1);
+}
+
+bool ShmServerBufferIntegration::supportsFormat(QtWayland::ServerBuffer::Format format) const
+{
+ switch (format) {
+ case QtWayland::ServerBuffer::RGBA32:
+ return true;
+ case QtWayland::ServerBuffer::A8:
+ return true;
+ default:
+ return false;
+ }
+}
+
+QtWayland::ServerBuffer *ShmServerBufferIntegration::createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format)
+{
+ return new ShmServerBuffer(this, qimage, format);
+}
+
+QT_END_NAMESPACE
diff --git a/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.h b/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.h
new file mode 100644
index 000000000..c303e5f18
--- /dev/null
+++ b/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHMSERVERBUFFERINTEGRATION_H
+#define SHMSERVERBUFFERINTEGRATION_H
+
+#include <QtWaylandCompositor/private/qwlserverbufferintegration_p.h>
+
+#include "qwayland-server-shm-emulation-server-buffer.h"
+
+#include <QtGui/QImage>
+#include <QtGui/QWindow>
+#include <QtGui/qpa/qplatformnativeinterface.h>
+#include <QtGui/QGuiApplication>
+
+#include <QtWaylandCompositor/qwaylandcompositor.h>
+#include <QtWaylandCompositor/private/qwayland-server-server-buffer-extension.h>
+
+QT_BEGIN_NAMESPACE
+
+class ShmServerBufferIntegration;
+class QSharedMemory;
+
+class ShmServerBuffer : public QtWayland::ServerBuffer, public QtWaylandServer::qt_server_buffer
+{
+public:
+ ShmServerBuffer(ShmServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format);
+ ~ShmServerBuffer();
+
+ struct ::wl_resource *resourceForClient(struct ::wl_client *) override;
+ QOpenGLTexture *toOpenGlTexture() override;
+
+private:
+ ShmServerBufferIntegration *m_integration;
+
+ QSharedMemory *m_shm;
+ int m_width;
+ int m_height;
+ int m_bpl;
+ QOpenGLTexture *m_texture = nullptr;
+ QtWaylandServer::qt_shm_emulation_server_buffer::format m_shm_format;
+};
+
+class ShmServerBufferIntegration :
+ public QtWayland::ServerBufferIntegration,
+ public QtWaylandServer::qt_shm_emulation_server_buffer
+{
+public:
+ ShmServerBufferIntegration();
+ ~ShmServerBufferIntegration();
+
+ void initializeHardware(QWaylandCompositor *) override;
+
+ bool supportsFormat(QtWayland::ServerBuffer::Format format) const override;
+ QtWayland::ServerBuffer *createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format) override;
+
+
+private:
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp
index 832ba04d5..0d6dbf782 100644
--- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp
+++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp
@@ -61,6 +61,7 @@
#include <QtWaylandCompositor/QWaylandWlShell>
#include <QtWaylandCompositor/QWaylandTextInputManager>
#include <QtWaylandCompositor/QWaylandXdgShellV5>
+#include <QtWaylandCompositor/QWaylandXdgShellV6>
#include <QtWaylandCompositor/QWaylandIviApplication>
#include <QtWaylandCompositor/QWaylandIviSurface>
@@ -74,6 +75,7 @@ Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandQtWindowManager)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandIviApplication)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandWlShell)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV5)
+Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV6)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandTextInputManager)
class QmlUrlResolver
@@ -153,6 +155,11 @@ public:
qmlRegisterType<QWaylandXdgSurfaceV5>(uri, 1, 0, "XdgSurfaceV5");
qmlRegisterType<QWaylandXdgPopupV5>(uri, 1, 0, "XdgPopupV5");
qmlRegisterType<QWaylandTextInputManagerQuickExtension>(uri, 1, 0, "TextInputManager");
+
+ qmlRegisterType<QWaylandXdgShellV6QuickExtension>(uri, 1, 1, "XdgShellV6");
+ qmlRegisterType<QWaylandXdgSurfaceV6>(uri, 1, 1, "XdgSurfaceV6");
+ qmlRegisterUncreatableType<QWaylandXdgToplevelV6>(uri, 1, 1, "XdgToplevelV6", QObject::tr("Cannot create instance of XdgShellToplevelV6"));
+ qmlRegisterUncreatableType<QWaylandXdgPopupV6>(uri, 1, 1, "XdgPopupV6", QObject::tr("Cannot create instance of XdgShellPopupV6"));
}
};
//![class decl]
diff --git a/src/plugins/hardwareintegration/client/client.pro b/src/plugins/hardwareintegration/client/client.pro
index a5967c710..f1c71f084 100644
--- a/src/plugins/hardwareintegration/client/client.pro
+++ b/src/plugins/hardwareintegration/client/client.pro
@@ -13,3 +13,6 @@ qtConfig(drm-egl-server): \
SUBDIRS += drm-egl-server
qtConfig(libhybris-egl-server): \
SUBDIRS += libhybris-egl-server
+
+### TODO: make shm-emulation configurable
+SUBDIRS += shm-emulation-server
diff --git a/src/plugins/hardwareintegration/client/shm-emulation-server/main.cpp b/src/plugins/hardwareintegration/client/shm-emulation-server/main.cpp
new file mode 100644
index 000000000..8c3ba8420
--- /dev/null
+++ b/src/plugins/hardwareintegration/client/shm-emulation-server/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtWaylandClient/private/qwaylandserverbufferintegrationplugin_p.h>
+#include "shmserverbufferintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class ShmServerBufferPlugin : public QWaylandServerBufferIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QWaylandServerBufferIntegrationFactoryInterface_iid FILE "shm-emulation-server.json")
+public:
+ QWaylandServerBufferIntegration *create(const QString&, const QStringList&) override;
+};
+
+QWaylandServerBufferIntegration *ShmServerBufferPlugin::create(const QString& system, const QStringList& paramList)
+{
+ Q_UNUSED(paramList);
+ Q_UNUSED(system);
+ return new ShmServerBufferIntegration();
+}
+
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/hardwareintegration/client/shm-emulation-server/shm-emulation-server.json b/src/plugins/hardwareintegration/client/shm-emulation-server/shm-emulation-server.json
new file mode 100644
index 000000000..1bf8ded87
--- /dev/null
+++ b/src/plugins/hardwareintegration/client/shm-emulation-server/shm-emulation-server.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "shm-emulation-server" ]
+}
diff --git a/src/plugins/hardwareintegration/client/shm-emulation-server/shm-emulation-server.pro b/src/plugins/hardwareintegration/client/shm-emulation-server/shm-emulation-server.pro
new file mode 100644
index 000000000..8b1c6e5f2
--- /dev/null
+++ b/src/plugins/hardwareintegration/client/shm-emulation-server/shm-emulation-server.pro
@@ -0,0 +1,15 @@
+# We have a bunch of C code with casts, so we can't have this option
+QMAKE_CXXFLAGS_WARN_ON -= -Wcast-qual
+
+QT += waylandclient-private
+
+include(../../../../hardwareintegration/client/shm-emulation-server/shm-emulation-server.pri)
+
+OTHER_FILES += \
+ shm-emulation-server.json
+
+SOURCES += main.cpp
+
+PLUGIN_TYPE = wayland-graphics-integration-client
+PLUGIN_CLASS_NAME = ShmServerBufferPlugin
+load(qt_plugin)
diff --git a/src/plugins/hardwareintegration/compositor/compositor.pro b/src/plugins/hardwareintegration/compositor/compositor.pro
index 299116257..0b2a4292c 100644
--- a/src/plugins/hardwareintegration/compositor/compositor.pro
+++ b/src/plugins/hardwareintegration/compositor/compositor.pro
@@ -13,3 +13,6 @@ qtConfig(drm-egl-server): \
SUBDIRS += drm-egl-server
qtConfig(libhybris-egl-server): \
SUBDIRS += libhybris-egl-server
+
+### TODO: make shm-emulation configurable
+SUBDIRS += shm-emulation-server
diff --git a/src/plugins/hardwareintegration/compositor/shm-emulation-server/main.cpp b/src/plugins/hardwareintegration/compositor/shm-emulation-server/main.cpp
new file mode 100644
index 000000000..9496361e9
--- /dev/null
+++ b/src/plugins/hardwareintegration/compositor/shm-emulation-server/main.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtWaylandCompositor/private/qwlserverbufferintegrationplugin_p.h>
+#include "shmserverbufferintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+class ShmServerBufferIntegrationPlugin : public QtWayland::ServerBufferIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QtWaylandServerBufferIntegrationFactoryInterface_iid FILE "shm-emulation-server.json")
+public:
+ QtWayland::ServerBufferIntegration *create(const QString&, const QStringList&) override;
+};
+
+QtWayland::ServerBufferIntegration *ShmServerBufferIntegrationPlugin::create(const QString& system, const QStringList& paramList)
+{
+ Q_UNUSED(paramList);
+ Q_UNUSED(system);
+ return new ShmServerBufferIntegration();
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.json b/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.json
new file mode 100644
index 000000000..1bf8ded87
--- /dev/null
+++ b/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "shm-emulation-server" ]
+}
diff --git a/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro b/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro
new file mode 100644
index 000000000..56a1bac21
--- /dev/null
+++ b/src/plugins/hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pro
@@ -0,0 +1,12 @@
+QT = waylandcompositor waylandcompositor-private core-private gui-private
+
+OTHER_FILES += shm-emulation-server.json
+
+SOURCES += \
+ main.cpp
+
+include($PWD/../../../../../hardwareintegration/compositor/shm-emulation-server/shm-emulation-server.pri)
+
+PLUGIN_TYPE = wayland-graphics-integration-server
+PLUGIN_CLASS_NAME = ShmServerBufferIntegrationPlugin
+load(qt_plugin)
diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp
index 01dfa9215..ed36a1386 100644
--- a/src/qtwaylandscanner/qtwaylandscanner.cpp
+++ b/src/qtwaylandscanner/qtwaylandscanner.cpp
@@ -432,7 +432,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" class Resource\n");
printf(" {\n");
printf(" public:\n");
- printf(" Resource() : %s_object(0), handle(0) {}\n", interfaceNameStripped);
+ printf(" Resource() : %s_object(nullptr), handle(nullptr) {}\n", interfaceNameStripped);
printf(" virtual ~Resource() {}\n");
printf("\n");
printf(" %s *%s_object;\n", interfaceName, interfaceNameStripped);
@@ -458,8 +458,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" QMultiMap<struct ::wl_client*, Resource*> resourceMap() { return m_resource_map; }\n");
printf(" const QMultiMap<struct ::wl_client*, Resource*> resourceMap() const { return m_resource_map; }\n");
printf("\n");
- printf(" bool isGlobal() const { return m_global != 0; }\n");
- printf(" bool isResource() const { return m_resource != 0; }\n");
+ printf(" bool isGlobal() const { return m_global != nullptr; }\n");
+ printf(" bool isResource() const { return m_resource != nullptr; }\n");
printf("\n");
printf(" static const struct ::wl_interface *interface();\n");
printf(" static QByteArray interfaceName() { return interface()->name; }\n");
@@ -572,8 +572,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" %s::%s(struct ::wl_client *client, int id, int version)\n", interfaceName, interfaceName);
printf(" : m_resource_map()\n");
- printf(" , m_resource(0)\n");
- printf(" , m_global(0)\n");
+ printf(" , m_resource(nullptr)\n");
+ printf(" , m_global(nullptr)\n");
printf(" {\n");
printf(" init(client, id, version);\n");
printf(" }\n");
@@ -581,8 +581,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" %s::%s(struct ::wl_display *display, int version)\n", interfaceName, interfaceName);
printf(" : m_resource_map()\n");
- printf(" , m_resource(0)\n");
- printf(" , m_global(0)\n");
+ printf(" , m_resource(nullptr)\n");
+ printf(" , m_global(nullptr)\n");
printf(" {\n");
printf(" init(display, version);\n");
printf(" }\n");
@@ -590,8 +590,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" %s::%s(struct ::wl_resource *resource)\n", interfaceName, interfaceName);
printf(" : m_resource_map()\n");
- printf(" , m_resource(0)\n");
- printf(" , m_global(0)\n");
+ printf(" , m_resource(nullptr)\n");
+ printf(" , m_global(nullptr)\n");
printf(" {\n");
printf(" init(resource);\n");
printf(" }\n");
@@ -599,8 +599,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" %s::%s()\n", interfaceName, interfaceName);
printf(" : m_resource_map()\n");
- printf(" , m_resource(0)\n");
- printf(" , m_global(0)\n");
+ printf(" , m_resource(nullptr)\n");
+ printf(" , m_global(nullptr)\n");
printf(" {\n");
printf(" }\n");
printf("\n");
@@ -689,7 +689,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
bool hasRequests = !interface.requests.isEmpty();
- QByteArray interfaceMember = hasRequests ? "&m_" + interface.name + "_interface" : QByteArray("0");
+ QByteArray interfaceMember = hasRequests ? "&m_" + interface.name + "_interface" : QByteArray("nullptr");
//We should consider changing bind so that it doesn't special case id == 0
//and use function overloading instead. Jan do you have a lot of code dependent on this behavior?
@@ -717,7 +717,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" {\n");
printf(" if (wl_resource_instance_of(resource, &::%s_interface, %s))\n", interfaceName, interfaceMember.constData());
printf(" return static_cast<Resource *>(resource->data);\n");
- printf(" return 0;\n");
+ printf(" return nullptr;\n");
printf(" }\n");
if (hasRequests) {
@@ -993,7 +993,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf("\n");
printf(" %s::%s()\n", interfaceName, interfaceName);
- printf(" : m_%s(0)\n", interfaceName);
+ printf(" : m_%s(nullptr)\n", interfaceName);
printf(" {\n");
printf(" }\n");
printf("\n");
@@ -1021,7 +1021,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" bool %s::isInitialized() const\n", interfaceName);
printf(" {\n");
- printf(" return m_%s != 0;\n", interfaceName);
+ printf(" return m_%s != nullptr;\n", interfaceName);
printf(" }\n");
printf("\n");
@@ -1087,7 +1087,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
}
printf(");\n");
if (e.type == "destructor")
- printf(" m_%s = 0;\n", interfaceName);
+ printf(" m_%s = nullptr;\n", interfaceName);
printf(" }\n");
}
diff --git a/tests/auto/client/client/mocksurface.h b/tests/auto/client/client/mocksurface.h
index e34d6596e..5155599bb 100644
--- a/tests/auto/client/client/mocksurface.h
+++ b/tests/auto/client/client/mocksurface.h
@@ -26,6 +26,9 @@
**
****************************************************************************/
+#ifndef MOCKSURFACE_H
+#define MOCKSURFACE_H
+
#include <qglobal.h>
#include "qwayland-server-wayland.h"
@@ -69,3 +72,5 @@ private:
};
}
+
+#endif // MOCKSURFACE_H
diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp
index 6f00b6e61..c51c13bd6 100644
--- a/tests/auto/compositor/compositor/tst_compositor.cpp
+++ b/tests/auto/compositor/compositor/tst_compositor.cpp
@@ -39,6 +39,7 @@
#include <QtGui/QScreen>
#include <QtWaylandCompositor/QWaylandXdgShellV5>
+#include <QtWaylandCompositor/private/qwaylandxdgshellv6_p.h>
#include <QtWaylandCompositor/QWaylandIviApplication>
#include <QtWaylandCompositor/QWaylandIviSurface>
#include <QtWaylandCompositor/QWaylandSurface>
@@ -78,6 +79,9 @@ private slots:
void emitsErrorOnSameIviId();
void sendsIviConfigure();
void destroysIviSurfaces();
+
+ void convertsXdgEdgesToQtEdges();
+ void xdgShellV6Positioner();
};
void tst_WaylandCompositor::init() {
@@ -835,5 +839,49 @@ void tst_WaylandCompositor::destroysIviSurfaces()
QTRY_VERIFY(destroySpy.count() == 1);
}
+void tst_WaylandCompositor::convertsXdgEdgesToQtEdges()
+{
+ const uint wlLeft = ZXDG_POSITIONER_V6_ANCHOR_LEFT;
+ QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlLeft), Qt::LeftEdge);
+
+ const uint wlRight = ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
+ QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlRight), Qt::RightEdge);
+
+ const uint wlTop = ZXDG_POSITIONER_V6_ANCHOR_TOP;
+ QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlTop), Qt::TopEdge);
+
+ const uint wlBottom = ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
+ QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlBottom), Qt::BottomEdge);
+
+ QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlBottom | wlLeft), Qt::Edges(Qt::BottomEdge | Qt::LeftEdge));
+ QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlTop | wlRight), Qt::Edges(Qt::TopEdge | Qt::RightEdge));
+}
+
+void tst_WaylandCompositor::xdgShellV6Positioner()
+{
+ QWaylandXdgPositionerV6Data p;
+ QVERIFY(!p.isComplete());
+
+ p.size = QSize(100, 50);
+ p.anchorRect = QRect(QPoint(1, 2), QSize(800, 600));
+ QVERIFY(p.isComplete());
+
+ p.anchorEdges = Qt::TopEdge | Qt::LeftEdge;
+ p.gravityEdges = Qt::BottomEdge | Qt::RightEdge;
+ QCOMPARE(p.unconstrainedPosition(), QPoint(1, 2));
+
+ p.anchorEdges = Qt::RightEdge;
+ QCOMPARE(p.unconstrainedPosition(), QPoint(1 + 800, 2 + 600 / 2));
+
+ p.gravityEdges = Qt::BottomEdge;
+ QCOMPARE(p.unconstrainedPosition(), QPoint(1 + 800 - 100 / 2, 2 + 600 / 2));
+
+ p.gravityEdges = Qt::TopEdge;
+ QCOMPARE(p.unconstrainedPosition(), QPoint(1 + 800 - 100 / 2, 2 + 600 / 2 - 50));
+
+ p.offset = QPoint(4, 8);
+ QCOMPARE(p.unconstrainedPosition(), QPoint(1 + 800 - 100 / 2 + 4, 2 + 600 / 2 - 50 + 8));
+}
+
#include <tst_compositor.moc>
QTEST_MAIN(tst_WaylandCompositor);