summaryrefslogtreecommitdiffstats
path: root/src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2018-05-09 22:57:53 +0200
committerJohan Helsing <johan.helsing@qt.io>2018-05-18 09:37:07 +0000
commit42f71e680c6146526fb18116b1b98995543443c0 (patch)
tree465f50e000788cd699f7cbf3425c9404abea4712 /src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp
parent9ac2cdf96d36db9612effdbdb9669bd413b66b84 (diff)
Move wl-shell to a plugin
[ChangeLog][QPA plugin] The wl-shell shell integration has been moved to a plugin. This also adds API so shell integrations can return native resources for windows, as it was needed in order to continue to supporting wl_shell_surface. Change-Id: Ibc68ffcc5b0c6993d8f4e078f663e4d67340e1a5 Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp')
-rw-r--r--src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp b/src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp
new file mode 100644
index 000000000..9f2bcc00c
--- /dev/null
+++ b/src/plugins/shellintegration/wl-shell/qwaylandwlshellsurface.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** 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 "qwaylandwlshellsurface_p.h"
+
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+#include <QtWaylandClient/private/qwaylandinputdevice_p.h>
+#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h>
+#include <QtWaylandClient/private/qwaylandscreen_p.h>
+#include <QtWaylandClient/private/qwaylandextendedsurface_p.h>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandWlShellSurface::QWaylandWlShellSurface(struct ::wl_shell_surface *shell_surface, QWaylandWindow *window)
+ : QWaylandShellSurface(window)
+ , QtWayland::wl_shell_surface(shell_surface)
+ , m_window(window)
+{
+ if (window->display()->windowExtension())
+ m_extendedWindow = new QWaylandExtendedSurface(window);
+}
+
+QWaylandWlShellSurface::~QWaylandWlShellSurface()
+{
+ wl_shell_surface_destroy(object());
+ delete m_extendedWindow;
+}
+
+void QWaylandWlShellSurface::resize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize edges)
+{
+ resize(inputDevice->wl_seat(),
+ inputDevice->serial(),
+ edges);
+}
+
+bool QWaylandWlShellSurface::move(QWaylandInputDevice *inputDevice)
+{
+ move(inputDevice->wl_seat(),
+ inputDevice->serial());
+ return true;
+}
+
+void QWaylandWlShellSurface::setTitle(const QString & title)
+{
+ return QtWayland::wl_shell_surface::set_title(title);
+}
+
+void QWaylandWlShellSurface::setAppId(const QString & appId)
+{
+ return QtWayland::wl_shell_surface::set_class(appId);
+}
+
+void QWaylandWlShellSurface::raise()
+{
+ if (m_extendedWindow)
+ m_extendedWindow->raise();
+}
+
+void QWaylandWlShellSurface::lower()
+{
+ if (m_extendedWindow)
+ m_extendedWindow->lower();
+}
+
+void QWaylandWlShellSurface::setContentOrientationMask(Qt::ScreenOrientations orientation)
+{
+ if (m_extendedWindow)
+ m_extendedWindow->setContentOrientationMask(orientation);
+}
+
+void QWaylandWlShellSurface::setWindowFlags(Qt::WindowFlags flags)
+{
+ if (m_extendedWindow)
+ m_extendedWindow->setWindowFlags(flags);
+}
+
+void QWaylandWlShellSurface::sendProperty(const QString &name, const QVariant &value)
+{
+ if (m_extendedWindow)
+ m_extendedWindow->updateGenericProperty(name, value);
+}
+
+void QWaylandWlShellSurface::applyConfigure()
+{
+ if ((m_pending.states & (Qt::WindowMaximized|Qt::WindowFullScreen))
+ && !(m_applied.states & (Qt::WindowMaximized|Qt::WindowFullScreen))) {
+ m_normalSize = m_window->window()->frameGeometry().size();
+ }
+
+ if (m_pending.states != m_applied.states)
+ m_window->handleWindowStatesChanged(m_pending.states);
+
+ if (!m_pending.size.isEmpty()) {
+ int x = 0;
+ int y = 0;
+ if (m_pending.edges & resize_left)
+ x = m_applied.size.width() - m_pending.size.width();
+ if (m_pending.edges & resize_top)
+ y = m_applied.size.height() - m_pending.size.height();
+ QPoint offset(x, y);
+ m_window->resizeFromApplyConfigure(m_pending.size, offset);
+ } else if (m_pending.size.isValid() && !m_normalSize.isEmpty()) {
+ m_window->resizeFromApplyConfigure(m_normalSize);
+ }
+
+ m_applied = m_pending;
+}
+
+bool QWaylandWlShellSurface::wantsDecorations() const
+{
+ return !(m_pending.states & Qt::WindowFullScreen);
+}
+
+void QWaylandWlShellSurface::requestWindowStates(Qt::WindowStates states)
+{
+ // On wl-shell the client is in charge of states, so diff from the pending state
+ Qt::WindowStates changedStates = m_pending.states ^ states;
+ Qt::WindowStates addedStates = changedStates & states;
+
+ if (addedStates & Qt::WindowMinimized)
+ qCWarning(lcQpaWayland) << "Minimizing is not supported on wl-shell. Consider using xdg-shell instead.";
+
+ if (addedStates & Qt::WindowMaximized) {
+ set_maximized(nullptr);
+ m_window->applyConfigureWhenPossible();
+ }
+
+ if (addedStates & Qt::WindowFullScreen) {
+ set_fullscreen(WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, nullptr);
+ m_window->applyConfigureWhenPossible();
+ }
+
+ bool isNormal = ~states & (Qt::WindowMaximized | Qt::WindowFullScreen);
+ if (isNormal && (changedStates & (Qt::WindowMaximized | Qt::WindowFullScreen))) {
+ setTopLevel(); // set normal window
+ // There's usually no configure event after this, so just clear the rest of the pending
+ // configure here and queue the applyConfigure call
+ m_pending.size = {0, 0};
+ m_pending.edges = resize_none;
+ m_window->applyConfigureWhenPossible();
+ }
+
+ m_pending.states = states & ~Qt::WindowMinimized;
+}
+
+
+void QWaylandWlShellSurface::setTopLevel()
+{
+ set_toplevel();
+}
+
+static inline bool testShowWithoutActivating(const QWindow *window)
+{
+ // QWidget-attribute Qt::WA_ShowWithoutActivating.
+ const QVariant showWithoutActivating = window->property("_q_showWithoutActivating");
+ return showWithoutActivating.isValid() && showWithoutActivating.toBool();
+}
+
+void QWaylandWlShellSurface::updateTransientParent(QWindow *parent)
+{
+ QWaylandWindow *parent_wayland_window = static_cast<QWaylandWindow *>(parent->handle());
+ if (!parent_wayland_window)
+ return;
+
+ // set_transient expects a position relative to the parent
+ QPoint transientPos = m_window->geometry().topLeft(); // this is absolute
+ transientPos -= parent->geometry().topLeft();
+ if (parent_wayland_window->decoration()) {
+ transientPos.setX(transientPos.x() + parent_wayland_window->decoration()->margins().left());
+ transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
+ }
+
+ uint32_t flags = 0;
+ Qt::WindowFlags wf = m_window->window()->flags();
+ if (wf.testFlag(Qt::ToolTip)
+ || wf.testFlag(Qt::WindowTransparentForInput)
+ || testShowWithoutActivating(m_window->window()))
+ flags |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
+
+ Q_ASSERT(parent_wayland_window->object());
+ set_transient(parent_wayland_window->object(),
+ transientPos.x(),
+ transientPos.y(),
+ flags);
+}
+
+void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, uint serial)
+{
+ QWaylandWindow *parent_wayland_window = parent;
+ if (!parent_wayland_window) {
+ qCWarning(lcQpaWayland) << "setPopup called without a parent window";
+ return;
+ }
+ if (!device) {
+ qCWarning(lcQpaWayland) << "setPopup called without an input device";
+ return;
+ }
+
+ // set_popup expects a position relative to the parent
+ QPoint transientPos = m_window->geometry().topLeft(); // this is absolute
+ transientPos -= parent_wayland_window->geometry().topLeft();
+ if (parent_wayland_window->decoration()) {
+ transientPos.setX(transientPos.x() + parent_wayland_window->decoration()->margins().left());
+ transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
+ }
+
+ Q_ASSERT(parent_wayland_window->object());
+ set_popup(device->wl_seat(), serial, parent_wayland_window->object(),
+ transientPos.x(), transientPos.y(), 0);
+}
+
+void QWaylandWlShellSurface::setType(Qt::WindowType type, QWaylandWindow *transientParent)
+{
+ if (type == Qt::Popup && transientParent && transientParent->object())
+ setPopup(transientParent, m_window->display()->lastInputDevice(), m_window->display()->lastInputSerial());
+ else if (transientParent && transientParent->object())
+ updateTransientParent(transientParent->window());
+ else
+ setTopLevel();
+}
+
+void QWaylandWlShellSurface::shell_surface_ping(uint32_t serial)
+{
+ pong(serial);
+}
+
+void QWaylandWlShellSurface::shell_surface_configure(uint32_t edges, int32_t width, int32_t height)
+{
+ m_pending.size = QSize(width, height);
+ m_pending.edges = static_cast<enum resize>(edges);
+ if (m_pending.edges && !m_pending.size.isEmpty())
+ m_normalSize = m_pending.size;
+ m_window->applyConfigureWhenPossible();
+}
+
+void QWaylandWlShellSurface::shell_surface_popup_done()
+{
+ QCoreApplication::postEvent(m_window->window(), new QCloseEvent());
+}
+
+}
+
+QT_END_NAMESPACE