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 2987de95, but for the stable version of xdg shell.

Change-Id: Ic998fb920a8b1b131e42833a61e663704c8663e4
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
Johan Klokkhammer Helsing 2018-08-03 12:53:38 +02:00 committed by Paul Olav Tvete
parent 4a6cf17488
commit 059debd75a
2 changed files with 32 additions and 3 deletions

View File

@ -182,6 +182,7 @@ QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurf
QtWayland::xdg_positioner *positioner) QtWayland::xdg_positioner *positioner)
: xdg_popup(xdgSurface->get_popup(parent->object(), positioner->object())) : xdg_popup(xdgSurface->get_popup(parent->object(), positioner->object()))
, m_xdgSurface(xdgSurface) , m_xdgSurface(xdgSurface)
, m_parent(parent)
{ {
} }
@ -189,6 +190,19 @@ QWaylandXdgSurface::Popup::~Popup()
{ {
if (isInitialized()) if (isInitialized())
destroy(); 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() void QWaylandXdgSurface::Popup::xdg_popup_popup_done()
@ -317,6 +331,14 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *d
Q_ASSERT(!m_toplevel && !m_popup); Q_ASSERT(!m_toplevel && !m_popup);
auto parentXdgSurface = static_cast<QWaylandXdgSurface *>(parent->shellSurface()); 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()); auto positioner = new QtWayland::xdg_positioner(m_shell->create_positioner());
// set_popup expects a position relative to the parent // set_popup expects a position relative to the parent
QPoint transientPos = m_window->geometry().topLeft(); // this is absolute 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); m_popup = new Popup(this, parentXdgSurface, positioner);
positioner->destroy(); positioner->destroy();
delete positioner; delete positioner;
if (grab) { if (grab)
m_popup->grab(device->wl_seat(), serial); m_popup->grab(device, serial);
}
} }
void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial) void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial)

View File

@ -129,9 +129,12 @@ private:
Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent, QtWayland::xdg_positioner *positioner); Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent, QtWayland::xdg_positioner *positioner);
~Popup() override; ~Popup() override;
void grab(QWaylandInputDevice *seat, uint serial);
void xdg_popup_popup_done() override; void xdg_popup_popup_done() override;
QWaylandXdgSurface *m_xdgSurface = nullptr; QWaylandXdgSurface *m_xdgSurface = nullptr;
QWaylandXdgSurface *m_parent = nullptr;
bool m_grabbing = false;
}; };
void setToplevel(); void setToplevel();
@ -144,6 +147,8 @@ private:
bool m_configured = false; bool m_configured = false;
QRegion m_exposeRegion; QRegion m_exposeRegion;
uint m_pendingConfigureSerial = 0; uint m_pendingConfigureSerial = 0;
friend class QWaylandXdgShell;
}; };
class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgShell : public QtWayland::xdg_wm_base class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgShell : public QtWayland::xdg_wm_base
@ -164,6 +169,9 @@ private:
QWaylandDisplay *m_display = nullptr; QWaylandDisplay *m_display = nullptr;
QScopedPointer<QWaylandXdgDecorationManagerV1> m_xdgDecorationManager; QScopedPointer<QWaylandXdgDecorationManagerV1> m_xdgDecorationManager;
QWaylandXdgSurface::Popup *m_topmostPopup = nullptr;
friend class QWaylandXdgSurface;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE