summaryrefslogtreecommitdiffstats
path: root/src/plugins/shellintegration/qt-shell
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/shellintegration/qt-shell')
-rw-r--r--src/plugins/shellintegration/qt-shell/CMakeLists.txt34
-rw-r--r--src/plugins/shellintegration/qt-shell/main.cpp31
-rw-r--r--src/plugins/shellintegration/qt-shell/qt-shell.json3
-rw-r--r--src/plugins/shellintegration/qt-shell/qwaylandqtshellintegration.cpp36
-rw-r--r--src/plugins/shellintegration/qt-shell/qwaylandqtshellintegration.h35
-rw-r--r--src/plugins/shellintegration/qt-shell/qwaylandqtsurface.cpp216
-rw-r--r--src/plugins/shellintegration/qt-shell/qwaylandqtsurface_p.h72
7 files changed, 427 insertions, 0 deletions
diff --git a/src/plugins/shellintegration/qt-shell/CMakeLists.txt b/src/plugins/shellintegration/qt-shell/CMakeLists.txt
new file mode 100644
index 000000000..b4f9f8b5c
--- /dev/null
+++ b/src/plugins/shellintegration/qt-shell/CMakeLists.txt
@@ -0,0 +1,34 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## QWaylandQtShellIntegrationPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(QWaylandQtShellIntegrationPlugin
+ OUTPUT_NAME qt-shell
+ PLUGIN_TYPE wayland-shell-integration
+ SOURCES
+ main.cpp
+ qwaylandqtshellintegration.cpp qwaylandqtshellintegration.h
+ qwaylandqtsurface.cpp qwaylandqtsurface_p.h
+ LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::WaylandClientPrivate
+ Wayland::Client
+)
+
+qt6_generate_wayland_protocol_client_sources(QWaylandQtShellIntegrationPlugin
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../extensions/qt-shell-unstable-v1.xml
+)
+
+## Scopes:
+#####################################################################
+
+qt_internal_extend_target(QWaylandQtShellIntegrationPlugin CONDITION QT_FEATURE_xkbcommon
+ LIBRARIES
+ XKB::XKB
+)
diff --git a/src/plugins/shellintegration/qt-shell/main.cpp b/src/plugins/shellintegration/qt-shell/main.cpp
new file mode 100644
index 000000000..41b6028f6
--- /dev/null
+++ b/src/plugins/shellintegration/qt-shell/main.cpp
@@ -0,0 +1,31 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtWaylandClient/private/qwaylandshellintegrationplugin_p.h>
+#include "qwaylandqtshellintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandQtShellIntegrationPlugin : public QWaylandShellIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QWaylandShellIntegrationFactoryInterface_iid FILE "qt-shell.json")
+
+public:
+ QWaylandShellIntegration *create(const QString &key, const QStringList &paramList) override;
+};
+
+QWaylandShellIntegration *QWaylandQtShellIntegrationPlugin::create(const QString &key, const QStringList &paramList)
+{
+ Q_UNUSED(key);
+ Q_UNUSED(paramList);
+ return new QWaylandQtShellIntegration();
+}
+
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/shellintegration/qt-shell/qt-shell.json b/src/plugins/shellintegration/qt-shell/qt-shell.json
new file mode 100644
index 000000000..aa6df6235
--- /dev/null
+++ b/src/plugins/shellintegration/qt-shell/qt-shell.json
@@ -0,0 +1,3 @@
+{
+ "Keys":[ "qt-shell" ]
+}
diff --git a/src/plugins/shellintegration/qt-shell/qwaylandqtshellintegration.cpp b/src/plugins/shellintegration/qt-shell/qwaylandqtshellintegration.cpp
new file mode 100644
index 000000000..17b87033f
--- /dev/null
+++ b/src/plugins/shellintegration/qt-shell/qwaylandqtshellintegration.cpp
@@ -0,0 +1,36 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandqtshellintegration.h"
+
+#include <QtCore/qsize.h>
+#include <QtCore/qdebug.h>
+
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+
+#include "qwaylandqtsurface_p.h"
+
+#include <mutex>
+
+#include <unistd.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandQtShellIntegration::QWaylandQtShellIntegration()
+ : QWaylandShellIntegrationTemplate(1)
+{
+ QWaylandWindow::fixedToplevelPositions = false;
+}
+
+QWaylandShellSurface *QWaylandQtShellIntegration::createShellSurface(QWaylandWindow *window)
+{
+ auto *surface = surface_create(wlSurfaceForWindow(window));
+ return new QWaylandQtSurface(surface, window);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/shellintegration/qt-shell/qwaylandqtshellintegration.h b/src/plugins/shellintegration/qt-shell/qwaylandqtshellintegration.h
new file mode 100644
index 000000000..18d033569
--- /dev/null
+++ b/src/plugins/shellintegration/qt-shell/qwaylandqtshellintegration.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDQTINTEGRATION_H
+#define QWAYLANDQTINTEGRATION_H
+
+#include <QtCore/qmutex.h>
+
+#include <QtWaylandClient/private/qwaylandshellintegration_p.h>
+#include <QScopedPointer>
+#include "qwayland-qt-shell-unstable-v1.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandWindow;
+class QWaylandDisplay;
+
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandQtShellIntegration
+ : public QWaylandShellIntegrationTemplate<QWaylandQtShellIntegration>
+ , public QtWayland::zqt_shell_v1
+{
+public:
+ QWaylandQtShellIntegration();
+
+ QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDQTINTEGRATION_H
diff --git a/src/plugins/shellintegration/qt-shell/qwaylandqtsurface.cpp b/src/plugins/shellintegration/qt-shell/qwaylandqtsurface.cpp
new file mode 100644
index 000000000..ddbb7783c
--- /dev/null
+++ b/src/plugins/shellintegration/qt-shell/qwaylandqtsurface.cpp
@@ -0,0 +1,216 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandqtsurface_p.h"
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatformwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandQtSurface::QWaylandQtSurface(struct ::zqt_shell_surface_v1 *shell_surface, QWaylandWindow *window)
+ : QWaylandShellSurface(window)
+ , QtWayland::zqt_shell_surface_v1(shell_surface)
+{
+ sendSizeHints();
+}
+
+QWaylandQtSurface::~QWaylandQtSurface()
+{
+ zqt_shell_surface_v1::destroy();
+}
+
+void QWaylandQtSurface::resetConfiguration()
+{
+ m_pendingPosition = QPoint(-1, -1);
+ m_pendingSize = QSize();
+ m_pendingPositionValid = false;
+ m_pendingStates = m_currentStates;
+}
+
+void QWaylandQtSurface::applyConfigure()
+{
+ if (m_pendingSize.isValid() && m_pendingPositionValid)
+ setGeometryFromApplyConfigure(m_pendingPosition, m_pendingSize);
+ else if (m_pendingSize.isValid())
+ resizeFromApplyConfigure(m_pendingSize);
+ else if (m_pendingPositionValid)
+ repositionFromApplyConfigure(m_pendingPosition);
+
+ if (m_pendingStates != m_currentStates) {
+ QWindowSystemInterface::handleWindowStateChanged(platformWindow()->window(), m_pendingStates);
+ m_currentStates = m_pendingStates;
+ }
+
+ ack_configure(m_currentConfigureSerial);
+
+ resetConfiguration();
+ m_currentConfigureSerial = UINT32_MAX;
+}
+
+void QWaylandQtSurface::setTitle(const QString &title)
+{
+ set_window_title(title);
+}
+
+void QWaylandQtSurface::zqt_shell_surface_v1_set_capabilities(uint32_t capabilities)
+{
+ m_capabilities = capabilities;
+}
+
+void QWaylandQtSurface::zqt_shell_surface_v1_set_position(uint32_t serial, int32_t x, int32_t y)
+{
+ if (serial < m_currentConfigureSerial && m_currentConfigureSerial != UINT32_MAX)
+ return;
+
+ if (serial != m_currentConfigureSerial) {
+ m_currentConfigureSerial = serial;
+ resetConfiguration();
+ }
+
+ m_pendingPosition = QPoint(x, y);
+ m_pendingPositionValid = true;
+}
+
+void QWaylandQtSurface::zqt_shell_surface_v1_resize(uint32_t serial, int32_t width, int32_t height)
+{
+ if (serial < m_currentConfigureSerial && m_currentConfigureSerial != UINT32_MAX)
+ return;
+
+ if (serial != m_currentConfigureSerial) {
+ m_currentConfigureSerial = serial;
+ resetConfiguration();
+ }
+
+ m_pendingSize = QSize(width, height);
+}
+
+void QWaylandQtSurface::zqt_shell_surface_v1_configure(uint32_t serial)
+{
+ if (serial < m_currentConfigureSerial)
+ return;
+
+ if (serial > m_currentConfigureSerial) {
+ m_currentConfigureSerial = serial;
+ resetConfiguration();
+ }
+
+ applyConfigureWhenPossible();
+}
+
+void QWaylandQtSurface::zqt_shell_surface_v1_close()
+{
+ platformWindow()->window()->close();
+}
+
+void QWaylandQtSurface::zqt_shell_surface_v1_set_frame_margins(uint32_t left, uint32_t right,
+ uint32_t top, uint32_t bottom)
+{
+ QPlatformWindow *win = platformWindow();
+ m_frameMargins = QMargins(left, top, right, bottom);
+ m_pendingPosition = win->geometry().topLeft();
+ m_pendingPositionValid = true;
+ m_pendingSize = win->geometry().size();
+ applyConfigureWhenPossible();
+}
+
+bool QWaylandQtSurface::requestActivate()
+{
+ request_activate();
+ return true;
+}
+
+void QWaylandQtSurface::propagateSizeHints()
+{
+ sendSizeHints();
+}
+
+void QWaylandQtSurface::sendSizeHints()
+{
+ QPlatformWindow *win = platformWindow();
+ if (win) {
+ const int minWidth = qMax(0, win->windowMinimumSize().width());
+ const int minHeight = qMax(0, win->windowMinimumSize().height());
+ set_minimum_size(minWidth, minHeight);
+
+ int maxWidth = qMax(0, win->windowMaximumSize().width());
+ if (maxWidth == QWINDOWSIZE_MAX)
+ maxWidth = -1;
+ int maxHeight = qMax(0, win->windowMaximumSize().height());
+ if (maxHeight == QWINDOWSIZE_MAX)
+ maxHeight = -1;
+ set_maximum_size(maxWidth, maxHeight);
+ }
+}
+
+void QWaylandQtSurface::zqt_shell_surface_v1_set_window_state(uint32_t serial, uint32_t state)
+{
+ if (serial < m_currentConfigureSerial && m_currentConfigureSerial != UINT32_MAX)
+ return;
+
+ if (serial != m_currentConfigureSerial) {
+ m_currentConfigureSerial = serial;
+ resetConfiguration();
+ }
+ m_pendingStates = Qt::WindowStates(state);
+}
+
+void QWaylandQtSurface::setWindowGeometry(const QRect &rect)
+{
+ set_size(rect.width(), rect.height());
+}
+
+void QWaylandQtSurface::setWindowPosition(const QPoint &position)
+{
+ reposition(position.x(), position.y());
+}
+
+void QWaylandQtSurface::setWindowFlags(Qt::WindowFlags flags)
+{
+ set_window_flags(flags);
+}
+
+void QWaylandQtSurface::requestWindowStates(Qt::WindowStates states)
+{
+ change_window_state(states & ~Qt::WindowActive);
+}
+
+bool QWaylandQtSurface::resize(QWaylandInputDevice *inputDevice, Qt::Edges edge)
+{
+ if (m_capabilities & ZQT_SHELL_SURFACE_V1_CAPABILITIES_INTERACTIVE_RESIZE) {
+ start_system_resize(getSerial(inputDevice), uint(edge));
+ return true;
+ }
+
+ return false;
+}
+
+bool QWaylandQtSurface::move(QWaylandInputDevice *inputDevice)
+{
+ if (m_capabilities & ZQT_SHELL_SURFACE_V1_CAPABILITIES_INTERACTIVE_RESIZE) {
+ start_system_move(getSerial(inputDevice));
+ return true;
+ }
+
+ return false;
+}
+
+QMargins QWaylandQtSurface::serverSideFrameMargins() const
+{
+ return m_frameMargins;
+}
+
+void QWaylandQtSurface::raise()
+{
+ QtWayland::zqt_shell_surface_v1::raise();
+}
+
+void QWaylandQtSurface::lower()
+{
+ QtWayland::zqt_shell_surface_v1::lower();
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/shellintegration/qt-shell/qwaylandqtsurface_p.h b/src/plugins/shellintegration/qt-shell/qwaylandqtsurface_p.h
new file mode 100644
index 000000000..6431bd552
--- /dev/null
+++ b/src/plugins/shellintegration/qt-shell/qwaylandqtsurface_p.h
@@ -0,0 +1,72 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDQTSURFACE_H
+#define QWAYLANDQTSURFACE_H
+
+#include <QtCore/qpoint.h>
+#include <QtWaylandClient/private/qwaylandshellsurface_p.h>
+#include "qwayland-qt-shell-unstable-v1.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandWindow;
+class QWaylandInputDevice;
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandQtSurface : public QWaylandShellSurface
+ , public QtWayland::zqt_shell_surface_v1
+{
+public:
+ QWaylandQtSurface(struct ::zqt_shell_surface_v1 *shell_surface, QWaylandWindow *window);
+ ~QWaylandQtSurface() override;
+
+ void applyConfigure() override;
+ void setWindowGeometry(const QRect &rect) override;
+ void setWindowPosition(const QPoint &position) override;
+
+ void setWindowFlags(Qt::WindowFlags flags) override;
+ void requestWindowStates(Qt::WindowStates states) override;
+ void setTitle(const QString &title) override;
+
+ bool resize(QWaylandInputDevice *, Qt::Edges) override;
+ bool move(QWaylandInputDevice *) override;
+ bool requestActivate() override;
+
+ void propagateSizeHints() override;
+
+ QMargins serverSideFrameMargins() const override;
+
+ void raise() override;
+ void lower() override;
+
+ std::any surfaceRole() const override { return object(); };
+
+private:
+ void resetConfiguration();
+ void sendSizeHints();
+ void zqt_shell_surface_v1_close() override;
+ void zqt_shell_surface_v1_resize(uint32_t serial, int32_t width, int32_t height) override;
+ void zqt_shell_surface_v1_set_position(uint32_t serial, int32_t x, int32_t y) override;
+ void zqt_shell_surface_v1_configure(uint32_t serial) override;
+ void zqt_shell_surface_v1_set_window_state(uint32_t serial, uint32_t state) override;
+ void zqt_shell_surface_v1_set_frame_margins(uint32_t left, uint32_t right,
+ uint32_t top, uint32_t bottom) override;
+ void zqt_shell_surface_v1_set_capabilities(uint32_t capabilities) override;
+
+ QSize m_pendingSize;
+ QPoint m_pendingPosition = { -1, -1 };
+ bool m_pendingPositionValid = false;
+ Qt::WindowStates m_pendingStates = Qt::WindowNoState;
+ Qt::WindowStates m_currentStates = Qt::WindowNoState;
+ QMargins m_frameMargins;
+ uint32_t m_currentConfigureSerial = UINT32_MAX;
+ uint32_t m_capabilities = 0;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDQTSURFACE_H