From 8f7893b3854f3dbbb7da7c8e0fad1e5a49267590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 7 Oct 2015 19:02:48 +0200 Subject: [PATCH] [server] Add support for flags on transient ShellSurfaceInterface A transient surface can indicate through the flags that it does not want to accept keyboard focus. This is now exposed through a dedicated method. REVIEW: 125552 --- .../autotests/client/test_wayland_shell.cpp | 21 ++++++++++++++- src/wayland/server/shell_interface.cpp | 22 ++++++++++++++-- src/wayland/server/shell_interface.h | 26 +++++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/wayland/autotests/client/test_wayland_shell.cpp b/src/wayland/autotests/client/test_wayland_shell.cpp index d4cdde52c9..94cc03d34a 100644 --- a/src/wayland/autotests/client/test_wayland_shell.cpp +++ b/src/wayland/autotests/client/test_wayland_shell.cpp @@ -47,6 +47,7 @@ private Q_SLOTS: void testFullscreen(); void testMaximize(); void testToplevel(); + void testTransient_data(); void testTransient(); void testPing(); void testTitle(); @@ -335,6 +336,14 @@ void TestWaylandShell::testToplevel() QVERIFY(!toplevelSpy.first().first().toBool()); } +void TestWaylandShell::testTransient_data() +{ + QTest::addColumn("keyboardFocus"); + + QTest::newRow("focus") << true; + QTest::newRow("no focus") << false; +} + void TestWaylandShell::testTransient() { using namespace KWayland::Server; @@ -349,11 +358,15 @@ void TestWaylandShell::testTransient() QVERIFY(serverSurfaceSpy.wait()); ShellSurfaceInterface *serverSurface = serverSurfaceSpy.first().first().value(); QVERIFY(serverSurface); + QSignalSpy acceptsKeyboardFocusChangedSpy(serverSurface, &ShellSurfaceInterface::acceptsKeyboardFocusChanged); + QVERIFY(acceptsKeyboardFocusChangedSpy.isValid()); QCOMPARE(serverSurface->isToplevel(), true); QCOMPARE(serverSurface->isPopup(), false); QCOMPARE(serverSurface->isTransient(), false); QCOMPARE(serverSurface->transientFor(), QPointer()); QCOMPARE(serverSurface->transientOffset(), QPoint()); + QVERIFY(serverSurface->acceptsKeyboardFocus()); + QVERIFY(acceptsKeyboardFocusChangedSpy.isEmpty()); QSignalSpy transientSpy(serverSurface, &ShellSurfaceInterface::transientChanged); QVERIFY(transientSpy.isValid()); @@ -369,8 +382,10 @@ void TestWaylandShell::testTransient() ShellSurfaceInterface *serverSurface2 = serverSurfaceSpy.first().first().value(); QVERIFY(serverSurface2 != serverSurface); QVERIFY(serverSurface2); + QVERIFY(serverSurface2->acceptsKeyboardFocus()); - surface->setTransient(s2.data(), QPoint(10, 20)); + QFETCH(bool, keyboardFocus); + surface->setTransient(s2.data(), QPoint(10, 20), keyboardFocus ? ShellSurface::TransientFlag::Default : ShellSurface::TransientFlag::NoFocus); QVERIFY(transientSpy.wait()); QCOMPARE(transientSpy.count(), 1); QCOMPARE(transientSpy.first().first().toBool(), true); @@ -382,12 +397,16 @@ void TestWaylandShell::testTransient() QCOMPARE(serverSurface->isTransient(), true); QCOMPARE(serverSurface->transientFor(), QPointer(serverSurface2->surface())); QCOMPARE(serverSurface->transientOffset(), QPoint(10, 20)); + QCOMPARE(serverSurface->acceptsKeyboardFocus(), keyboardFocus); + QCOMPARE(acceptsKeyboardFocusChangedSpy.isEmpty(), keyboardFocus); + QCOMPARE(acceptsKeyboardFocusChangedSpy.count(), keyboardFocus ? 0 : 1); QCOMPARE(serverSurface2->isToplevel(), true); QCOMPARE(serverSurface2->isPopup(), false); QCOMPARE(serverSurface2->isTransient(), false); QCOMPARE(serverSurface2->transientFor(), QPointer()); QCOMPARE(serverSurface2->transientOffset(), QPoint()); + QVERIFY(serverSurface2->acceptsKeyboardFocus()); } void TestWaylandShell::testPing() diff --git a/src/wayland/server/shell_interface.cpp b/src/wayland/server/shell_interface.cpp index 17656f1de2..69e22e6de1 100644 --- a/src/wayland/server/shell_interface.cpp +++ b/src/wayland/server/shell_interface.cpp @@ -84,6 +84,7 @@ public: WindowMode windowMode = WindowMode::Toplevel; QPoint transientOffset; QPointer transientFor; + bool acceptsKeyboardFocus = true; void setWindowMode(WindowMode newWindowMode); private: @@ -106,6 +107,7 @@ private: void setTitle(const QString &title); void setWindowClass(const QByteArray &windowClass); void pong(quint32 serial); + void setAcceptsFocus(quint32 flags); ShellSurfaceInterface *q_func() { return reinterpret_cast(q); } @@ -283,9 +285,19 @@ void ShellSurfaceInterface::Private::setTransientCallback(wl_client *client, wl_ s->transientFor = QPointer(SurfaceInterface::get(parent)); s->transientOffset = QPoint(x, y); emit s->q_func()->transientChanged(!s->transientFor.isNull()); - // TODO: flags emit s->q_func()->transientOffsetChanged(s->transientOffset); emit s->q_func()->transientForChanged(); + s->setAcceptsFocus(flags); +} + +void ShellSurfaceInterface::Private::setAcceptsFocus(quint32 flags) +{ + const bool acceptsFocus = !(flags & WL_SHELL_SURFACE_TRANSIENT_INACTIVE); + if (acceptsFocus != acceptsKeyboardFocus) { + acceptsKeyboardFocus = acceptsFocus; + Q_Q(ShellSurfaceInterface); + emit q->acceptsKeyboardFocusChanged(); + } } void ShellSurfaceInterface::Private::setFullscreenCallback(wl_client *client, wl_resource *resource, uint32_t method, @@ -335,9 +347,9 @@ void ShellSurfaceInterface::Private::setPopupCallback(wl_client *client, wl_reso s->transientOffset = QPoint(x, y); s->setWindowMode(WindowMode::Popup); emit s->q_func()->transientChanged(!s->transientFor.isNull()); - // TODO: flags emit s->q_func()->transientOffsetChanged(s->transientOffset); emit s->q_func()->transientForChanged(); + s->setAcceptsFocus(WL_SHELL_SURFACE_TRANSIENT_INACTIVE); } void ShellSurfaceInterface::Private::setMaximizedCallback(wl_client *client, wl_resource *resource, wl_resource *output) @@ -435,6 +447,12 @@ QPoint ShellSurfaceInterface::transientOffset() const return d->transientOffset; } +bool ShellSurfaceInterface::acceptsKeyboardFocus() const +{ + Q_D(); + return d->acceptsKeyboardFocus; +} + QPointer< SurfaceInterface > ShellSurfaceInterface::transientFor() const { Q_D(); diff --git a/src/wayland/server/shell_interface.h b/src/wayland/server/shell_interface.h index 2bf0a61d3b..e0c5bd2ade 100644 --- a/src/wayland/server/shell_interface.h +++ b/src/wayland/server/shell_interface.h @@ -116,6 +116,15 @@ class KWAYLANDSERVER_EXPORT ShellSurfaceInterface : public Resource * @since 5.5 **/ Q_PROPERTY(QPoint transientOffset READ transientOffset NOTIFY transientOffsetChanged) + /** + * Whether the ShellSurfaceInterface can accept keyboard focus. + * + * By default ShellSurfaceInterface accepts keyboard focus, only transient surfaces + * might not want keyboard focus. + * + * @since 5.5 + **/ + Q_PROPERTY(bool acceptsKeyboardFocus READ acceptsKeyboardFocus NOTIFY acceptsKeyboardFocusChanged) public: virtual ~ShellSurfaceInterface(); @@ -205,6 +214,19 @@ public: **/ QPointer transientFor() const; + /** + * Whether the ShellSurfaceInterface can accept keyboard focus. + * + * This is only relevant for transient and popup windows. By default all ShellSurfaces + * accept keyboard focus. + * + * @returns Whether the ShellSurfaceInterface can accept keyboard focus. + * @see isTransient() + * @see acceptsKeyboardFocusChanged + * @since 5.5 + **/ + bool acceptsKeyboardFocus() const; + Q_SIGNALS: /** * Emitted whenever the title changes. @@ -244,6 +266,10 @@ Q_SIGNALS: * @since 5.5 **/ void transientForChanged(); + /** + * @since 5.5 + **/ + void acceptsKeyboardFocusChanged(); private: friend class ShellInterface;