diff --git a/autotests/client/test_plasmashell.cpp b/autotests/client/test_plasmashell.cpp --- a/autotests/client/test_plasmashell.cpp +++ b/autotests/client/test_plasmashell.cpp @@ -54,6 +54,7 @@ void testPanelTakesFocus(); void testDisconnect(); void testWhileDestroying(); + void testPopupBehavior(); private: Display *m_display = nullptr; @@ -526,5 +527,39 @@ QVERIFY(clientErrorSpy.isEmpty()); } +void TestPlasmaShell::testPopupBehavior() +{ + // this test verifies that the popup behavior is properly passed to the server + QSignalSpy plasmaSurfaceCreatedSpy(m_plasmaShellInterface, &PlasmaShellInterface::surfaceCreated); + QVERIFY(plasmaSurfaceCreatedSpy.isValid()); + + QScopedPointer s(m_compositor->createSurface()); + QScopedPointer ps(m_plasmaShell->createSurface(s.data())); + QVERIFY(plasmaSurfaceCreatedSpy.wait()); + QCOMPARE(plasmaSurfaceCreatedSpy.count(), 1); + + // verify that we got a plasma shell surface + auto sps = plasmaSurfaceCreatedSpy.first().first().value(); + QVERIFY(sps); + QVERIFY(sps->surface()); + QCOMPARE(sps->popupBehavior(), 0); + + // now change the behavior + QSignalSpy behaviorChangedSpy(sps, &PlasmaShellSurfaceInterface::popupBehaviorChanged); + QVERIFY(behaviorChangedSpy.isValid()); + ps->setPopupBehavior(PlasmaShellSurface::PopupBehavior::AlwaysOnTop); + QVERIFY(behaviorChangedSpy.wait()); + QCOMPARE(sps->popupBehavior(), PlasmaShellSurfaceInterface::PopupBehavior::AlwaysOnTop); + + // changing to same should not trigger the signal + ps->setPopupBehavior(PlasmaShellSurface::PopupBehavior::AlwaysOnTop); + QVERIFY(!behaviorChangedSpy.wait(100)); + + // but changing back to Always Visible should work + ps->setPopupBehavior(PlasmaShellSurface::PopupBehaviorFlags()); + QVERIFY(behaviorChangedSpy.wait()); + QCOMPARE(sps->popupBehavior(), PlasmaShellSurfaceInterface::PopupBehaviorFlags()); +} + QTEST_GUILESS_MAIN(TestPlasmaShell) #include "test_plasmashell.moc" diff --git a/src/client/plasmashell.h b/src/client/plasmashell.h --- a/src/client/plasmashell.h +++ b/src/client/plasmashell.h @@ -333,6 +333,23 @@ **/ void setPanelTakesFocus(bool takesFocus); + /** + * Describes how a PlasmaShellSurface should behave. + * Applies to all roles except Panel + * Choosing to honor this is up to the compositor + * @since 5.FIXME + **/ + enum class PopupBehavior { + AlwaysOnTop = 1, + }; + Q_DECLARE_FLAGS(PopupBehaviorFlags, PopupBehavior) + + /** + * Sets the PopupBehavior for a PlasmaShellSurface + * @since 5.FIXME + **/ + void setPopupBehavior(PopupBehaviorFlags behavior); + Q_SIGNALS: /** * Emitted when the compositor hided an auto hiding panel. @@ -363,5 +380,5 @@ Q_DECLARE_METATYPE(KWayland::Client::PlasmaShellSurface::Role) Q_DECLARE_METATYPE(KWayland::Client::PlasmaShellSurface::PanelBehavior) - +Q_DECLARE_OPERATORS_FOR_FLAGS(KWayland::Client::PlasmaShellSurface::PopupBehaviorFlags) #endif diff --git a/src/client/plasmashell.cpp b/src/client/plasmashell.cpp --- a/src/client/plasmashell.cpp +++ b/src/client/plasmashell.cpp @@ -342,5 +342,19 @@ org_kde_plasma_surface_set_panel_takes_focus(d->surface, takesFocus); } +void PlasmaShellSurface::setPopupBehavior(PlasmaShellSurface::PopupBehaviorFlags behavior) +{ + Q_ASSERT(isValid()); + if (wl_proxy_get_version(d->surface) < ORG_KDE_PLASMA_SURFACE_SET_POPUP_BEHAVIOR_SINCE_VERSION) { + return; + } + uint32_t wlRole = 0; + if (behavior & PopupBehavior::AlwaysOnTop) { + wlRole |= ORG_KDE_PLASMA_SURFACE_POPUP_BEHAVIOR_ALWAYS_ON_TOP; + } + org_kde_plasma_surface_set_popup_behavior(d->surface, wlRole); +} + + } } diff --git a/src/client/protocols/plasma-shell.xml b/src/client/protocols/plasma-shell.xml --- a/src/client/protocols/plasma-shell.xml +++ b/src/client/protocols/plasma-shell.xml @@ -17,7 +17,7 @@ along with this program. If not, see . ]]> - + This interface is used by KF5 powered Wayland shells to communicate with the compositor and can only be bound one time. @@ -130,7 +130,7 @@ --> - + An interface that may be implemented by a wl_surface, for implementations that provide the shell user interface. @@ -319,7 +319,7 @@ - + Set flags bitmask as described by the flag enum. Pass 0 to unset any flag, the surface will adjust its behavior to the default. @@ -393,5 +393,21 @@ + + + + + The popup dialog remains above other windows + + + + + + Set flags bitmask as described by the flag enum. + Pass 0 to unset any flag, the surface will adjust its behavior to + the default. + + + diff --git a/src/client/registry.cpp b/src/client/registry.cpp --- a/src/client/registry.cpp +++ b/src/client/registry.cpp @@ -169,7 +169,7 @@ &Registry::subCompositorRemoved }}, {Registry::Interface::PlasmaShell, { - 5, + 6, QByteArrayLiteral("org_kde_plasma_shell"), &org_kde_plasma_shell_interface, &Registry::plasmaShellAnnounced, diff --git a/src/server/plasmashell_interface.h b/src/server/plasmashell_interface.h --- a/src/server/plasmashell_interface.h +++ b/src/server/plasmashell_interface.h @@ -176,6 +176,17 @@ **/ bool panelTakesFocus() const; + enum class PopupBehavior { + AlwaysOnTop = 1, ///< The popup should stay above other windows + }; + Q_DECLARE_FLAGS(PopupBehaviorFlags, PopupBehavior) + + /** + * @returns The PopupBehavior for a PlasmaShellSurfaceInterface + * @since 5.FIXME + **/ + PopupBehaviorFlags popupBehavior() const; + /** * @returns The PlasmaShellSurfaceInterface for the @p native resource. * @since 5.5 @@ -233,6 +244,12 @@ **/ void panelAutoHideShowRequested(); + /** + * A change of the popup behavior has been requested. + * @since 5.FIXME + **/ + void popupBehaviorChanged(); + private: friend class PlasmaShellInterface; explicit PlasmaShellSurfaceInterface(PlasmaShellInterface *shell, SurfaceInterface *parent, wl_resource *parentResource); @@ -245,5 +262,5 @@ Q_DECLARE_METATYPE(KWayland::Server::PlasmaShellSurfaceInterface::Role) Q_DECLARE_METATYPE(KWayland::Server::PlasmaShellSurfaceInterface::PanelBehavior) - +Q_DECLARE_OPERATORS_FOR_FLAGS(KWayland::Server::PlasmaShellSurfaceInterface::PopupBehaviorFlags) #endif diff --git a/src/server/plasmashell_interface.cpp b/src/server/plasmashell_interface.cpp --- a/src/server/plasmashell_interface.cpp +++ b/src/server/plasmashell_interface.cpp @@ -50,7 +50,7 @@ static const quint32 s_version; }; -const quint32 PlasmaShellInterface::Private::s_version = 5; +const quint32 PlasmaShellInterface::Private::s_version = 6; PlasmaShellInterface::Private::Private(PlasmaShellInterface *q, Display *d) : Global::Private(d, &org_kde_plasma_shell_interface, s_version) @@ -73,8 +73,9 @@ SurfaceInterface *surface; QPoint m_globalPos; Role m_role = Role::Normal; - bool m_positionSet = false; PanelBehavior m_panelBehavior = PanelBehavior::AlwaysVisible; + PopupBehaviorFlags m_popupBehavior; + bool m_positionSet = false; bool m_skipTaskbar = false; bool m_skipSwitcher = false; bool panelTakesFocus = false; @@ -90,10 +91,12 @@ static void panelAutoHideHideCallback(wl_client *client, wl_resource *resource); static void panelAutoHideShowCallback(wl_client *client, wl_resource *resource); static void panelTakesFocusCallback(wl_client *client, wl_resource *resource, uint32_t takesFocus); + static void setPopupBehaviorCallback(wl_client *client, wl_resource *resource, uint32_t flag); void setPosition(const QPoint &globalPos); void setRole(uint32_t role); void setPanelBehavior(org_kde_plasma_surface_panel_behavior behavior); + void setPopupBehavior(uint32_t behavior); PlasmaShellSurfaceInterface *q_func() { return reinterpret_cast(q); @@ -168,7 +171,8 @@ panelAutoHideHideCallback, panelAutoHideShowCallback, panelTakesFocusCallback, - setSkipSwitcherCallback + setSkipSwitcherCallback, + setPopupBehaviorCallback, }; #endif @@ -402,10 +406,39 @@ return d->panelTakesFocus; } +PlasmaShellSurfaceInterface::PopupBehaviorFlags PlasmaShellSurfaceInterface::popupBehavior() const +{ + Q_D(); + return d->m_popupBehavior; +} + PlasmaShellSurfaceInterface *PlasmaShellSurfaceInterface::get(wl_resource *native) { return Private::get(native); } +void PlasmaShellSurfaceInterface::Private::setPopupBehaviorCallback(wl_client *client, wl_resource *resource, uint32_t flag) +{ + auto s = cast(resource); + Q_ASSERT(client == *s->client); + s->setPopupBehavior(flag); +} + + +void PlasmaShellSurfaceInterface::Private::setPopupBehavior(uint32_t behavior) +{ + PopupBehaviorFlags newBehavior; + if (behavior & ORG_KDE_PLASMA_SURFACE_POPUP_BEHAVIOR_ALWAYS_ON_TOP) { + newBehavior |= PopupBehavior::AlwaysOnTop; + } + + if (m_popupBehavior == newBehavior) { + return; + } + m_popupBehavior = newBehavior; + Q_Q(PlasmaShellSurfaceInterface); + emit q->popupBehaviorChanged(); +} + } }