Add support for wl_shell_surface::set_popup and popup_done
Summary: This extends the client side API to support creating popup ShellSurface windows and the server side API to send out the popup_done request. This is needed to properly support popup windows (e.g. context menus) in KWin. Reviewers: #plasma_on_wayland, #frameworks, #kwin Subscribers: plasma-devel Tags: #plasma_on_wayland, #frameworks Differential Revision: https://phabricator.kde.org/D5174
This commit is contained in:
parent
a1c8ea01d7
commit
bccb1f4cba
3 changed files with 90 additions and 0 deletions
|
@ -55,6 +55,7 @@ private Q_SLOTS:
|
|||
void testToplevel();
|
||||
void testTransient_data();
|
||||
void testTransient();
|
||||
void testTransientPopup();
|
||||
void testPing();
|
||||
void testTitle();
|
||||
void testWindowClass();
|
||||
|
@ -475,6 +476,72 @@ void TestWaylandShell::testTransient()
|
|||
QVERIFY(serverSurface2->acceptsKeyboardFocus());
|
||||
}
|
||||
|
||||
void TestWaylandShell::testTransientPopup()
|
||||
{
|
||||
using namespace KWayland::Server;
|
||||
using namespace KWayland::Client;
|
||||
QScopedPointer<Surface> s(m_compositor->createSurface());
|
||||
QVERIFY(!s.isNull());
|
||||
QVERIFY(s->isValid());
|
||||
ShellSurface *surface = m_shell->createSurface(s.data(), m_shell);
|
||||
|
||||
QSignalSpy serverSurfaceSpy(m_shellInterface, &ShellInterface::surfaceCreated);
|
||||
QVERIFY(serverSurfaceSpy.isValid());
|
||||
QVERIFY(serverSurfaceSpy.wait());
|
||||
ShellSurfaceInterface *serverSurface = serverSurfaceSpy.first().first().value<ShellSurfaceInterface*>();
|
||||
QVERIFY(serverSurface);
|
||||
QCOMPARE(serverSurface->isToplevel(), true);
|
||||
QCOMPARE(serverSurface->isPopup(), false);
|
||||
QCOMPARE(serverSurface->isTransient(), false);
|
||||
QCOMPARE(serverSurface->transientFor(), QPointer<SurfaceInterface>());
|
||||
QCOMPARE(serverSurface->transientOffset(), QPoint());
|
||||
QVERIFY(serverSurface->acceptsKeyboardFocus());
|
||||
|
||||
QSignalSpy transientSpy(serverSurface, &ShellSurfaceInterface::transientChanged);
|
||||
QVERIFY(transientSpy.isValid());
|
||||
QSignalSpy transientOffsetSpy(serverSurface, &ShellSurfaceInterface::transientOffsetChanged);
|
||||
QVERIFY(transientOffsetSpy.isValid());
|
||||
QSignalSpy transientForChangedSpy(serverSurface, &ShellSurfaceInterface::transientForChanged);
|
||||
QVERIFY(transientForChangedSpy.isValid());
|
||||
|
||||
QScopedPointer<Surface> s2(m_compositor->createSurface());
|
||||
m_shell->createSurface(s2.data(), m_shell);
|
||||
serverSurfaceSpy.clear();
|
||||
QVERIFY(serverSurfaceSpy.wait());
|
||||
ShellSurfaceInterface *serverSurface2 = serverSurfaceSpy.first().first().value<ShellSurfaceInterface*>();
|
||||
QVERIFY(serverSurface2 != serverSurface);
|
||||
QVERIFY(serverSurface2);
|
||||
QVERIFY(serverSurface2->acceptsKeyboardFocus());
|
||||
|
||||
// TODO: proper serial checking
|
||||
surface->setTransientPopup(s2.data(), m_seat, 1, QPoint(10, 20));
|
||||
QVERIFY(transientSpy.wait());
|
||||
QCOMPARE(transientSpy.count(), 1);
|
||||
QCOMPARE(transientSpy.first().first().toBool(), true);
|
||||
QCOMPARE(transientOffsetSpy.count(), 1);
|
||||
QCOMPARE(transientOffsetSpy.first().first().toPoint(), QPoint(10, 20));
|
||||
QCOMPARE(transientForChangedSpy.count(), 1);
|
||||
QCOMPARE(serverSurface->isToplevel(), false);
|
||||
QCOMPARE(serverSurface->isPopup(), true);
|
||||
QCOMPARE(serverSurface->isTransient(), true);
|
||||
QCOMPARE(serverSurface->transientFor(), QPointer<SurfaceInterface>(serverSurface2->surface()));
|
||||
QCOMPARE(serverSurface->transientOffset(), QPoint(10, 20));
|
||||
// TODO: honor the flag
|
||||
QCOMPARE(serverSurface->acceptsKeyboardFocus(), false);
|
||||
|
||||
QCOMPARE(serverSurface2->isToplevel(), true);
|
||||
QCOMPARE(serverSurface2->isPopup(), false);
|
||||
QCOMPARE(serverSurface2->isTransient(), false);
|
||||
QCOMPARE(serverSurface2->transientFor(), QPointer<SurfaceInterface>());
|
||||
QCOMPARE(serverSurface2->transientOffset(), QPoint());
|
||||
|
||||
// send popup done
|
||||
QSignalSpy popupDoneSpy(surface, &ShellSurface::popupDone);
|
||||
QVERIFY(popupDoneSpy.isValid());
|
||||
serverSurface->popupDone();
|
||||
QVERIFY(popupDoneSpy.wait());
|
||||
}
|
||||
|
||||
void TestWaylandShell::testPing()
|
||||
{
|
||||
using namespace KWayland::Server;
|
||||
|
|
|
@ -379,6 +379,9 @@ void ShellSurfaceInterface::Private::setPopupCallback(wl_client *client, wl_reso
|
|||
emit s->q_func()->transientChanged(!s->transientFor.isNull());
|
||||
emit s->q_func()->transientOffsetChanged(s->transientOffset);
|
||||
emit s->q_func()->transientForChanged();
|
||||
// we ignore the flags as Qt requests keyboard focus for popups
|
||||
// if we would honor the flag this could break compositors
|
||||
// compare QtWayland (5.6), file qwaylandwlshellsurface.cpp:208
|
||||
s->setAcceptsFocus(WL_SHELL_SURFACE_TRANSIENT_INACTIVE);
|
||||
}
|
||||
|
||||
|
@ -449,6 +452,14 @@ bool ShellSurfaceInterface::acceptsKeyboardFocus() const
|
|||
return d->acceptsKeyboardFocus;
|
||||
}
|
||||
|
||||
void ShellSurfaceInterface::popupDone()
|
||||
{
|
||||
Q_D();
|
||||
if (isPopup() && d->resource) {
|
||||
wl_shell_surface_send_popup_done(d->resource);
|
||||
}
|
||||
}
|
||||
|
||||
QPointer< SurfaceInterface > ShellSurfaceInterface::transientFor() const
|
||||
{
|
||||
Q_D();
|
||||
|
|
|
@ -231,6 +231,18 @@ public:
|
|||
**/
|
||||
bool acceptsKeyboardFocus() const;
|
||||
|
||||
/**
|
||||
* Sends a popup done event to the shell surface.
|
||||
* This is only relevant for popup windows. It indicates that the popup grab
|
||||
* got canceled. This happens when e.g. the user clicks outside of any surface
|
||||
* of the same client as this ShellSurfaceInterface. It is the task of the
|
||||
* compositor to send the popupDone event appropriately.
|
||||
*
|
||||
* @see isPopup
|
||||
* @since 5.33
|
||||
**/
|
||||
void popupDone();
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emitted whenever the title changes.
|
||||
|
|
Loading…
Reference in a new issue