diff options
author | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2018-08-03 12:53:38 +0200 |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@qt.io> | 2018-08-17 15:22:12 +0000 |
commit | 192a8364a983ceff7a7d9f2a33161e1da738ed70 (patch) | |
tree | d12080fdf688bc21587c17048852d30dd49a4d3e | |
parent | 034c9f563d91fe646ab63675b7b951c5c0581f61 (diff) |
xdg-shell stable: Make sure popup parent is topmost popup when grabbing
Avoids protocol errors on Weston, gnome-shell and wlroots-based compositors.
This is the same fix as 75c996e7, but for the stable version of xdg shell.
Change-Id: Ic998fb920a8b1b131e42833a61e663704c8663e4
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
-rw-r--r-- | src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp | 27 | ||||
-rw-r--r-- | src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h | 8 |
2 files changed, 32 insertions, 3 deletions
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp index 7dabd96f2..8b3d07481 100644 --- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp @@ -182,6 +182,7 @@ QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurf QtWayland::xdg_positioner *positioner) : xdg_popup(xdgSurface->get_popup(parent->object(), positioner->object())) , m_xdgSurface(xdgSurface) + , m_parent(parent) { } @@ -189,6 +190,19 @@ QWaylandXdgSurface::Popup::~Popup() { if (isInitialized()) destroy(); + + if (m_grabbing) { + auto *shell = m_xdgSurface->m_shell; + Q_ASSERT(shell->m_topmostPopup == this); + shell->m_topmostPopup = m_parent->m_popup; + } +} + +void QWaylandXdgSurface::Popup::grab(QWaylandInputDevice *seat, uint serial) +{ + m_xdgSurface->m_shell->m_topmostPopup = this; + xdg_popup::grab(seat->wl_seat(), serial); + m_grabbing = true; } void QWaylandXdgSurface::Popup::xdg_popup_popup_done() @@ -317,6 +331,14 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *d Q_ASSERT(!m_toplevel && !m_popup); auto parentXdgSurface = static_cast<QWaylandXdgSurface *>(parent->shellSurface()); + + auto *top = m_shell->m_topmostPopup; + if (grab && top && top->m_xdgSurface != parentXdgSurface) { + qCWarning(lcQpaWayland) << "setPopup called for a surface that was not the topmost popup, positions might be off."; + parentXdgSurface = top->m_xdgSurface; + parent = top->m_xdgSurface->m_window; + } + 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 @@ -332,9 +354,8 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *d m_popup = new Popup(this, parentXdgSurface, positioner); positioner->destroy(); delete positioner; - if (grab) { - m_popup->grab(device->wl_seat(), serial); - } + if (grab) + m_popup->grab(device, serial); } void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial) diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h index 37a4a8a4c..45d7d4b0e 100644 --- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h @@ -129,9 +129,12 @@ private: Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent, QtWayland::xdg_positioner *positioner); ~Popup() override; + void grab(QWaylandInputDevice *seat, uint serial); void xdg_popup_popup_done() override; QWaylandXdgSurface *m_xdgSurface = nullptr; + QWaylandXdgSurface *m_parent = nullptr; + bool m_grabbing = false; }; void setToplevel(); @@ -144,6 +147,8 @@ private: bool m_configured = false; QRegion m_exposeRegion; uint m_pendingConfigureSerial = 0; + + friend class QWaylandXdgShell; }; class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgShell : public QtWayland::xdg_wm_base @@ -164,6 +169,9 @@ private: QWaylandDisplay *m_display = nullptr; QScopedPointer<QWaylandXdgDecorationManagerV1> m_xdgDecorationManager; + QWaylandXdgSurface::Popup *m_topmostPopup = nullptr; + + friend class QWaylandXdgSurface; }; QT_END_NAMESPACE |