diff options
author | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2018-05-24 11:46:11 +0200 |
---|---|---|
committer | Johan Helsing <johan.helsing@qt.io> | 2018-05-29 07:29:32 +0000 |
commit | d26abdb7a1a0265d09683c0259e1b5ea9a866b09 (patch) | |
tree | b1110bd7884c76d6b35cb085daebc60a1a998d74 /src/plugins | |
parent | 89d3c4a13b3e27dd511064812bb52d00cedb9479 (diff) | |
download | qtwayland-d26abdb7a1a0265d09683c0259e1b5ea9a866b09.tar.gz |
Client: Add shell integration for xdg-shell stable
[ChangeLog][QPA plugin] Added support for xdg-shell stable.
Mostly a copy of xdg_shell unstable v6 with prefixes and suffixes
removed. Otherwise, this is what changed:
- The global is now named "xdg_wm_base", since "xdg_shell" was taken by
xdg-shell <= v5.
- Anchors and gravities are not bitfields anymore.
Task-number: QTBUG-66783
Change-Id: I8ca881aae52cc07b22ff5e26df13a9a1566f58f4
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src/plugins')
8 files changed, 758 insertions, 0 deletions
diff --git a/src/plugins/shellintegration/shellintegration.pro b/src/plugins/shellintegration/shellintegration.pro index 9be4e82a..48b6efa3 100644 --- a/src/plugins/shellintegration/shellintegration.pro +++ b/src/plugins/shellintegration/shellintegration.pro @@ -2,6 +2,7 @@ TEMPLATE = subdirs SUBDIRS += \ ivi-shell \ + xdg-shell \ xdg-shell-v5 \ xdg-shell-v6 \ wl-shell \ diff --git a/src/plugins/shellintegration/xdg-shell/main.cpp b/src/plugins/shellintegration/xdg-shell/main.cpp new file mode 100644 index 00000000..a9ea4bc1 --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/main.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "qwaylandxdgshellintegration_p.h" + +#include <QtWaylandClient/private/qwaylandshellintegrationplugin_p.h> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +class QWaylandXdgShellIntegrationPlugin : public QWaylandShellIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QWaylandShellIntegrationFactoryInterface_iid FILE "xdg-shell.json") + +public: + QWaylandShellIntegration *create(const QString &key, const QStringList ¶mList) override; +}; + +QWaylandShellIntegration *QWaylandXdgShellIntegrationPlugin::create(const QString &key, const QStringList ¶mList) +{ + Q_UNUSED(key); + Q_UNUSED(paramList); + return new QWaylandXdgShellIntegration(); +} + +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp new file mode 100644 index 00000000..4097cece --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp @@ -0,0 +1,337 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2017 Eurogiciel, author: <philippe.coval@eurogiciel.fr> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the config.tests 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 "qwaylandxdgshell_p.h" + +#include <QtWaylandClient/private/qwaylanddisplay_p.h> +#include <QtWaylandClient/private/qwaylandwindow_p.h> +#include <QtWaylandClient/private/qwaylandinputdevice_p.h> +#include <QtWaylandClient/private/qwaylandscreen_p.h> +#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface) + : QtWayland::xdg_toplevel(xdgSurface->get_toplevel()) + , m_xdgSurface(xdgSurface) +{ + requestWindowStates(xdgSurface->window()->window()->windowStates()); +} + +QWaylandXdgSurface::Toplevel::~Toplevel() +{ + if (m_applied.states & Qt::WindowActive) { + QWaylandWindow *window = m_xdgSurface->window(); + window->display()->handleWindowDeactivated(window); + } + if (isInitialized()) + destroy(); +} + +void QWaylandXdgSurface::Toplevel::applyConfigure() +{ + if (!(m_applied.states & (Qt::WindowMaximized|Qt::WindowFullScreen))) + m_normalSize = m_xdgSurface->m_window->window()->frameGeometry().size(); + + if (m_pending.size.isEmpty() && !m_normalSize.isEmpty()) + m_pending.size = m_normalSize; + + if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive)) + m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window); + + if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive)) + m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window); + + // TODO: none of the other plugins send WindowActive either, but is it on purpose? + Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive; + + m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive); + m_xdgSurface->m_window->resizeFromApplyConfigure(m_pending.size); + m_applied = m_pending; +} + +void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states) +{ + m_pending.size = QSize(width, height); + + auto *xdgStates = static_cast<uint32_t *>(states->data); + size_t numStates = states->size / sizeof(uint32_t); + + m_pending.states = Qt::WindowNoState; + + for (size_t i = 0; i < numStates; i++) { + switch (xdgStates[i]) { + case XDG_TOPLEVEL_STATE_ACTIVATED: + m_pending.states |= Qt::WindowActive; + break; + case XDG_TOPLEVEL_STATE_MAXIMIZED: + m_pending.states |= Qt::WindowMaximized; + break; + case XDG_TOPLEVEL_STATE_FULLSCREEN: + m_pending.states |= Qt::WindowFullScreen; + break; + default: + break; + } + } +} + +void QWaylandXdgSurface::Toplevel::xdg_toplevel_close() +{ + m_xdgSurface->m_window->window()->close(); +} + +void QWaylandXdgSurface::Toplevel::requestWindowStates(Qt::WindowStates states) +{ + // Re-send what's different from the applied state + Qt::WindowStates changedStates = m_applied.states ^ states; + + if (changedStates & Qt::WindowMaximized) { + if (states & Qt::WindowMaximized) + set_maximized(); + else + unset_maximized(); + } + + if (changedStates & Qt::WindowFullScreen) { + if (states & Qt::WindowFullScreen) + set_fullscreen(nullptr); + else + unset_fullscreen(); + } + + // Minimized state is not reported by the protocol, so always send it + if (states & Qt::WindowMinimized) { + set_minimized(); + m_xdgSurface->window()->handleWindowStatesChanged(states & ~Qt::WindowMinimized); + } +} + +QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent, + QtWayland::xdg_positioner *positioner) + : xdg_popup(xdgSurface->get_popup(parent->object(), positioner->object())) + , m_xdgSurface(xdgSurface) +{ +} + +QWaylandXdgSurface::Popup::~Popup() +{ + if (isInitialized()) + destroy(); +} + +void QWaylandXdgSurface::Popup::applyConfigure() +{ +} + +void QWaylandXdgSurface::Popup::xdg_popup_popup_done() +{ + m_xdgSurface->m_window->window()->close(); +} + +QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *surface, QWaylandWindow *window) + : QWaylandShellSurface(window) + , xdg_surface(surface) + , m_shell(shell) + , m_window(window) +{ +} + +QWaylandXdgSurface::~QWaylandXdgSurface() +{ + if (m_toplevel) + xdg_toplevel_destroy(m_toplevel->object()); + if (m_popup) + xdg_popup_destroy(m_popup->object()); + destroy(); +} + +void QWaylandXdgSurface::resize(QWaylandInputDevice *inputDevice, xdg_toplevel_resize_edge edges) +{ + Q_ASSERT(m_toplevel && m_toplevel->isInitialized()); + m_toplevel->resize(inputDevice->wl_seat(), inputDevice->serial(), edges); +} + +void QWaylandXdgSurface::resize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize edges) +{ + auto xdgEdges = reinterpret_cast<enum xdg_toplevel_resize_edge const * const>(&edges); + resize(inputDevice, *xdgEdges); +} + + +bool QWaylandXdgSurface::move(QWaylandInputDevice *inputDevice) +{ + if (m_toplevel && m_toplevel->isInitialized()) { + m_toplevel->move(inputDevice->wl_seat(), inputDevice->serial()); + return true; + } + return false; +} + +void QWaylandXdgSurface::setTitle(const QString &title) +{ + if (m_toplevel) + m_toplevel->set_title(title); +} + +void QWaylandXdgSurface::setAppId(const QString &appId) +{ + if (m_toplevel) + m_toplevel->set_app_id(appId); +} + +void QWaylandXdgSurface::setType(Qt::WindowType type, QWaylandWindow *transientParent) +{ + QWaylandDisplay *display = m_window->display(); + if ((type == Qt::Popup || type == Qt::ToolTip) && transientParent && display->lastInputDevice()) { + setPopup(transientParent, display->lastInputDevice(), display->lastInputSerial(), type == Qt::Popup); + } else { + setToplevel(); + if (transientParent) { + auto parentXdgSurface = static_cast<QWaylandXdgSurface *>(transientParent->shellSurface()); + if (parentXdgSurface) + m_toplevel->set_parent(parentXdgSurface->m_toplevel->object()); + } + } +} + +bool QWaylandXdgSurface::handleExpose(const QRegion ®ion) +{ + if (!m_configured && !region.isEmpty()) { + m_exposeRegion = region; + return true; + } + return false; +} + +void QWaylandXdgSurface::applyConfigure() +{ + Q_ASSERT(m_pendingConfigureSerial != 0); + + if (m_toplevel) + m_toplevel->applyConfigure(); + if (m_popup) + m_popup->applyConfigure(); + + m_configured = true; + ack_configure(m_pendingConfigureSerial); + + m_pendingConfigureSerial = 0; +} + +bool QWaylandXdgSurface::wantsDecorations() const +{ + return m_toplevel && !(m_toplevel->m_pending.states & Qt::WindowFullScreen); +} + +void QWaylandXdgSurface::requestWindowStates(Qt::WindowStates states) +{ + if (m_toplevel) + m_toplevel->requestWindowStates(states); + else + qCWarning(lcQpaWayland) << "Non-toplevel surfaces can't request window states"; +} + +void QWaylandXdgSurface::setToplevel() +{ + Q_ASSERT(!m_toplevel && !m_popup); + m_toplevel = new Toplevel(this); +} + +void QWaylandXdgSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial, bool grab) +{ + Q_ASSERT(!m_toplevel && !m_popup); + + auto parentXdgSurface = static_cast<QWaylandXdgSurface *>(parent->shellSurface()); + auto positioner = new QtWayland::xdg_positioner(m_shell->create_positioner()); + // set_popup expects a position relative to the parent + QPoint transientPos = m_window->geometry().topLeft(); // this is absolute + transientPos -= parent->geometry().topLeft(); + if (parent->decoration()) { + transientPos.setX(transientPos.x() + parent->decoration()->margins().left()); + transientPos.setY(transientPos.y() + parent->decoration()->margins().top()); + } + positioner->set_anchor_rect(transientPos.x(), transientPos.y(), 1, 1); + positioner->set_anchor(QtWayland::xdg_positioner::anchor_top_left); + positioner->set_gravity(QtWayland::xdg_positioner::gravity_bottom_right); + positioner->set_size(m_window->geometry().width(), m_window->geometry().height()); + m_popup = new Popup(this, parentXdgSurface, positioner); + positioner->destroy(); + delete positioner; + if (grab) { + m_popup->grab(device->wl_seat(), serial); + } +} + +void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial) +{ + m_window->applyConfigureWhenPossible(); + m_pendingConfigureSerial = serial; + if (!m_exposeRegion.isEmpty()) { + QWindowSystemInterface::handleExposeEvent(m_window->window(), m_exposeRegion); + m_exposeRegion = QRegion(); + } +} + +QWaylandXdgShell::QWaylandXdgShell(struct ::wl_registry *registry, uint32_t id, uint32_t availableVersion) + : QtWayland::xdg_wm_base(registry, id, qMin(availableVersion, 1u)) +{ +} + +QWaylandXdgShell::~QWaylandXdgShell() +{ + destroy(); +} + +QWaylandXdgSurface *QWaylandXdgShell::getXdgSurface(QWaylandWindow *window) +{ + return new QWaylandXdgSurface(this, get_xdg_surface(window->object()), window); +} + +void QWaylandXdgShell::xdg_wm_base_ping(uint32_t serial) +{ + pong(serial); +} + +} + +QT_END_NAMESPACE diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h new file mode 100644 index 00000000..1b312bd2 --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2017 Eurogiciel, author: <philippe.coval@eurogiciel.fr> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the config.tests 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 QWAYLANDXDGSHELL_H +#define QWAYLANDXDGSHELL_H + +// +// 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. +// + +#include "qwayland-xdg-shell.h" + +#include <QtWaylandClient/qtwaylandclientglobal.h> +#include <QtWaylandClient/private/qwaylandshellsurface_p.h> + +#include <QtCore/QSize> +#include <QtGui/QRegion> + +#include <wayland-client.h> + +QT_BEGIN_NAMESPACE + +class QWindow; + +namespace QtWaylandClient { + +class QWaylandWindow; +class QWaylandInputDevice; +class QWaylandXdgShell; + +class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgSurface : public QWaylandShellSurface, public QtWayland::xdg_surface +{ + Q_OBJECT +public: + QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *surface, QWaylandWindow *window); + ~QWaylandXdgSurface() override; + + void resize(QWaylandInputDevice *inputDevice, enum xdg_toplevel_resize_edge edges); + void resize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize edges) override; + bool move(QWaylandInputDevice *inputDevice) override; + void setTitle(const QString &title) override; + void setAppId(const QString &appId) override; + + void setType(Qt::WindowType type, QWaylandWindow *transientParent) override; + bool isExposed() const override { return m_configured; } + bool handleExpose(const QRegion &) override; + bool handlesActiveState() const { return m_toplevel; } + void applyConfigure() override; + bool wantsDecorations() const override; + +protected: + void requestWindowStates(Qt::WindowStates states) override; + void xdg_surface_configure(uint32_t serial) override; + +private: + class Toplevel: public QtWayland::xdg_toplevel + { + public: + Toplevel(QWaylandXdgSurface *xdgSurface); + ~Toplevel() override; + + void applyConfigure(); + + void xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states) override; + void xdg_toplevel_close() override; + + void requestWindowStates(Qt::WindowStates states); + struct { + QSize size = {0, 0}; + Qt::WindowStates states = Qt::WindowNoState; + } m_pending, m_applied; + QSize m_normalSize; + + QWaylandXdgSurface *m_xdgSurface = nullptr; + }; + + class Popup : public QtWayland::xdg_popup { + public: + Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent, QtWayland::xdg_positioner *positioner); + ~Popup() override; + + void applyConfigure(); + void xdg_popup_popup_done() override; + + QWaylandXdgSurface *m_xdgSurface = nullptr; + }; + + void setToplevel(); + void setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial, bool grab); + + QWaylandXdgShell *m_shell = nullptr; + QWaylandWindow *m_window = nullptr; + Toplevel *m_toplevel = nullptr; + Popup *m_popup = nullptr; + bool m_configured = false; + QRegion m_exposeRegion; + uint m_pendingConfigureSerial = 0; +}; + +class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgShell : public QtWayland::xdg_wm_base +{ +public: + QWaylandXdgShell(struct ::wl_registry *registry, uint32_t id, uint32_t availableVersion); + + QWaylandXdgSurface *getXdgSurface(QWaylandWindow *window); + + ~QWaylandXdgShell() override; + +private: + void xdg_wm_base_ping(uint32_t serial) override; +}; + +QT_END_NAMESPACE + +} + +#endif // QWAYLANDXDGSHELL_H diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp new file mode 100644 index 00000000..54d5b55e --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 "qwaylandxdgshellintegration_p.h" + +#include <QtWaylandClient/private/qwaylandwindow_p.h> +#include <QtWaylandClient/private/qwaylanddisplay_p.h> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +bool QWaylandXdgShellIntegration::initialize(QWaylandDisplay *display) +{ + for (QWaylandDisplay::RegistryGlobal global : display->globals()) { + if (global.interface == QLatin1String("xdg_wm_base")) { + m_xdgShell.reset(new QWaylandXdgShell(display->wl_registry(), global.id, global.version)); + break; + } + } + + if (!m_xdgShell) { + qCDebug(lcQpaWayland) << "Couldn't find global xdg_wm_base for xdg-shell stable"; + return false; + } + + return QWaylandShellIntegration::initialize(display); +} + +QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWindow *window) +{ + return m_xdgShell->getXdgSurface(window); +} + +void QWaylandXdgShellIntegration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) +{ + if (newFocus) { + auto *xdgSurface = qobject_cast<QWaylandXdgSurface *>(newFocus->shellSurface()); + if (xdgSurface && !xdgSurface->handlesActiveState()) + m_display->handleWindowActivated(newFocus); + } + if (oldFocus && qobject_cast<QWaylandXdgSurface *>(oldFocus->shellSurface())) { + auto *xdgSurface = qobject_cast<QWaylandXdgSurface *>(oldFocus->shellSurface()); + if (xdgSurface && !xdgSurface->handlesActiveState()) + m_display->handleWindowDeactivated(oldFocus); + } +} + +} + +QT_END_NAMESPACE diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h new file mode 100644 index 00000000..b6caa6c9 --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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 QWAYLANDXDGSHELLINTEGRATION_P_H +#define QWAYLANDXDGSHELLINTEGRATION_P_H + +// +// 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. +// + +#include "qwaylandxdgshell_p.h" + +#include <QtWaylandClient/private/qwaylandshellintegration_p.h> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgShellIntegration : public QWaylandShellIntegration +{ +public: + QWaylandXdgShellIntegration() {} + bool initialize(QWaylandDisplay *display) override; + QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override; + void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override; + +private: + QScopedPointer<QWaylandXdgShell> m_xdgShell; +}; + +} + +QT_END_NAMESPACE + +#endif // QWAYLANDXDGSHELLINTEGRATION_P_H diff --git a/src/plugins/shellintegration/xdg-shell/xdg-shell.json b/src/plugins/shellintegration/xdg-shell/xdg-shell.json new file mode 100644 index 00000000..2de86b8d --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/xdg-shell.json @@ -0,0 +1,3 @@ +{ + "Keys":[ "xdg-shell" ] +} diff --git a/src/plugins/shellintegration/xdg-shell/xdg-shell.pro b/src/plugins/shellintegration/xdg-shell/xdg-shell.pro new file mode 100644 index 00000000..b6d4a9b2 --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/xdg-shell.pro @@ -0,0 +1,23 @@ +QT += gui-private waylandclient-private +CONFIG += wayland-scanner + +QMAKE_USE += wayland-client + +WAYLANDCLIENTSOURCES += \ + ../../../3rdparty/protocol/xdg-shell.xml + +HEADERS += \ + qwaylandxdgshell_p.h \ + qwaylandxdgshellintegration_p.h \ + +SOURCES += \ + main.cpp \ + qwaylandxdgshell.cpp \ + qwaylandxdgshellintegration.cpp \ + +OTHER_FILES += \ + xdg-shell.json + +PLUGIN_TYPE = wayland-shell-integration +PLUGIN_CLASS_NAME = QWaylandXdgShellIntegrationPlugin +load(qt_plugin) |