summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2018-08-03 12:53:38 +0200
committerPaul Olav Tvete <paul.tvete@qt.io>2018-08-17 15:22:12 +0000
commit192a8364a983ceff7a7d9f2a33161e1da738ed70 (patch)
treed12080fdf688bc21587c17048852d30dd49a4d3e
parent034c9f563d91fe646ab63675b7b951c5c0581f61 (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.cpp27
-rw-r--r--src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h8
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