Client xdg-shell: Add test for switching popups

Task-number: QTBUG-73524
Change-Id: Ie9a13aeae52a7576699147e5515e2ed32a3a4d1c
Reviewed-by: Giulio Camuffo <giulio.camuffo@kdab.com>
This commit is contained in:
Johan Klokkhammer Helsing 2019-02-05 10:07:56 +01:00 committed by Johan Helsing
parent 7fa16ebff6
commit c104decfdd
3 changed files with 94 additions and 1 deletions

View File

@ -236,6 +236,7 @@ void XdgPopup::xdg_popup_destroy(Resource *resource) {
}
m_xdgSurface->m_popup = nullptr;
m_parentXdgSurface->m_popups.removeAll(this);
emit destroyRequested();
}
} // namespace MockCompositor

View File

@ -130,8 +130,9 @@ protected:
void xdg_toplevel_set_min_size(Resource *resource, int32_t width, int32_t height) override;
};
class XdgPopup : public QtWaylandServer::xdg_popup
class XdgPopup : public QObject, public QtWaylandServer::xdg_popup
{
Q_OBJECT
public:
explicit XdgPopup(XdgSurface *xdgSurface, XdgSurface *parent, int id, int version = 1);
void sendConfigure(const QRect &geometry);
@ -141,6 +142,8 @@ public:
XdgSurface *m_parentXdgSurface = nullptr;
bool m_grabbed = false;
uint m_grabSerial = 0;
signals:
void destroyRequested();
protected:
void xdg_popup_grab(Resource *resource, ::wl_resource *seat, uint32_t serial) override;
void xdg_popup_destroy(Resource *resource) override;

View File

@ -43,6 +43,7 @@ private slots:
void configureStates();
void popup();
void tooltipOnPopup();
void switchPopups();
void pongs();
void minMaxSize();
void windowGeometry();
@ -332,6 +333,94 @@ void tst_xdgshell::tooltipOnPopup()
QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr);
}
// QTBUG-65680
void tst_xdgshell::switchPopups()
{
class Popup : public QRasterWindow {
public:
explicit Popup(QWindow *parent) {
setTransientParent(parent);
setFlags(Qt::Popup);
resize(10, 10);
show();
}
};
class Window : public QRasterWindow {
public:
void mousePressEvent(QMouseEvent *event) override {
QRasterWindow::mousePressEvent(event);
if (!m_popups.empty())
m_popups.last()->setVisible(false);
}
// The bug this checks for, is the case where there is a flushWindowSystemEvents() call
// somewhere within setVisible(false) before the grab has been released.
// This leads to the the release event below—including its show() call—to be handled
// At a time where there is still an active grab, making it illegal for the new popup to
// grab.
void mouseReleaseEvent(QMouseEvent *event) override {
QRasterWindow::mouseReleaseEvent(event);
m_popups << new Popup(this);
}
~Window() override { qDeleteAll(m_popups); }
QVector<Popup *> m_popups;
};
Window window;
window.resize(200, 200);
window.show();
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
exec([=] { xdgToplevel()->sendCompleteConfigure(); });
QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial);
exec([=] {
auto *surface = xdgToplevel()->surface();
auto *p = pointer();
p->sendEnter(surface, {100, 100});
// p->sendFrame(); //TODO: uncomment when we support seat v5
p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
// p->sendFrame();
p->sendLeave(surface);
// p->sendFrame();
});
QCOMPOSITOR_TRY_VERIFY(xdgPopup());
exec([=] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial);
QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_grabbed);
QSignalSpy firstDestroyed(exec([=] { return xdgPopup(); }), &XdgPopup::destroyRequested);
exec([=] {
auto *surface = xdgToplevel()->surface();
auto *p = pointer();
p->sendEnter(surface, {100, 100});
// p->sendFrame();
p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
// p->sendFrame();
});
// The client will now hide one popup and then show another
firstDestroyed.wait();
QCOMPOSITOR_TRY_VERIFY(xdgPopup());
QCOMPOSITOR_TRY_VERIFY(!xdgPopup(1));
// Verify we still grabbed in case the client has checks to avoid illegal grabs
QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_grabbed);
// Sometimes the popup will select another parent if one is illegal at the time it tries to
// grab. So we verify we got the intended parent on the compositor side.
QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_parentXdgSurface == xdgToplevel()->m_xdgSurface);
// For good measure just check that configuring works as usual
exec([=] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial);
}
void tst_xdgshell::pongs()
{
QSignalSpy pongSpy(exec([=] { return get<XdgWmBase>(); }), &XdgWmBase::pong);