Commit e772a3e9 authored by Martin Flöser's avatar Martin Flöser
Browse files

Add auto-hiding panel support to PlasmaShellSurface interface

Summary:
This change adds support for auto-hiding panels. A PlasmaShellSurface
with Role Panel and PanelBehavior AutoHide can request to get
auto-hidden at a screen edge. The compositor will then not show the
surface although it is still mapped and will show it again once the
screen edge gets triggered.

The interface is extended by one new request to allow the client to
request the hiding of the surface. In addition two events are added to
inform the client when the surface got hidden and when it got shown
again.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3007
parent 7d59e91f
......@@ -49,6 +49,7 @@ private Q_SLOTS:
void testSkipTaskbar();
void testPanelBehavior_data();
void testPanelBehavior();
void testAutoHidePanel();
void testDisconnect();
void testWhileDestroying();
......@@ -341,6 +342,60 @@ void TestPlasmaShell::testPanelBehavior()
QCOMPARE(sps->panelBehavior(), PlasmaShellSurfaceInterface::PanelBehavior::AlwaysVisible);
}
void TestPlasmaShell::testAutoHidePanel()
{
// this test verifies that auto-hiding panels work correctly
QSignalSpy plasmaSurfaceCreatedSpy(m_plasmaShellInterface, &PlasmaShellInterface::surfaceCreated);
QVERIFY(plasmaSurfaceCreatedSpy.isValid());
QScopedPointer<Surface> s(m_compositor->createSurface());
QScopedPointer<PlasmaShellSurface> ps(m_plasmaShell->createSurface(s.data()));
ps->setRole(PlasmaShellSurface::Role::Panel);
ps->setPanelBehavior(PlasmaShellSurface::PanelBehavior::AutoHide);
QVERIFY(plasmaSurfaceCreatedSpy.wait());
QCOMPARE(plasmaSurfaceCreatedSpy.count(), 1);
auto sps = plasmaSurfaceCreatedSpy.first().first().value<PlasmaShellSurfaceInterface*>();
QVERIFY(sps);
QCOMPARE(sps->panelBehavior(), PlasmaShellSurfaceInterface::PanelBehavior::AutoHide);
QSignalSpy autoHideRequestedSpy(sps, &PlasmaShellSurfaceInterface::panelAutoHideHideRequested);
QVERIFY(autoHideRequestedSpy.isValid());
QSignalSpy autoHideShowRequestedSpy(sps, &PlasmaShellSurfaceInterface::panelAutoHideShowRequested);
QVERIFY(autoHideShowRequestedSpy.isValid());
ps->requestHideAutoHidingPanel();
QVERIFY(autoHideRequestedSpy.wait());
QCOMPARE(autoHideRequestedSpy.count(), 1);
QCOMPARE(autoHideShowRequestedSpy.count(), 0);
QSignalSpy panelShownSpy(ps.data(), &PlasmaShellSurface::autoHidePanelShown);
QVERIFY(panelShownSpy.isValid());
QSignalSpy panelHiddenSpy(ps.data(), &PlasmaShellSurface::autoHidePanelHidden);
QVERIFY(panelHiddenSpy.isValid());
sps->hideAutoHidingPanel();
QVERIFY(panelHiddenSpy.wait());
QCOMPARE(panelHiddenSpy.count(), 1);
QCOMPARE(panelShownSpy.count(), 0);
ps->requestShowAutoHidingPanel();
QVERIFY(autoHideShowRequestedSpy.wait());
QCOMPARE(autoHideRequestedSpy.count(), 1);
QCOMPARE(autoHideShowRequestedSpy.count(), 1);
sps->showAutoHidingPanel();
QVERIFY(panelShownSpy.wait());
QCOMPARE(panelHiddenSpy.count(), 1);
QCOMPARE(panelShownSpy.count(), 1);
// change panel type
ps->setPanelBehavior(PlasmaShellSurface::PanelBehavior::AlwaysVisible);
// requesting auto hide should raise error
QSignalSpy errorSpy(m_connection, &ConnectionThread::errorOccurred);
QVERIFY(errorSpy.isValid());
ps->requestHideAutoHidingPanel();
QVERIFY(errorSpy.wait());
}
void TestPlasmaShell::testDisconnect()
{
// this test verifies that a disconnect cleans up
......
......@@ -52,8 +52,12 @@ public:
static PlasmaShellSurface *get(Surface *surface);
private:
static void autoHidingPanelHiddenCallback(void *data, org_kde_plasma_surface *org_kde_plasma_surface);
static void autoHidingPanelShownCallback(void *data, org_kde_plasma_surface *org_kde_plasma_surface);
PlasmaShellSurface *q;
static QVector<Private*> s_surfaces;
static const org_kde_plasma_surface_listener s_listener;
};
QVector<PlasmaShellSurface::Private*> PlasmaShellSurface::Private::s_surfaces;
......@@ -175,6 +179,26 @@ void PlasmaShellSurface::Private::setup(org_kde_plasma_surface *s)
Q_ASSERT(s);
Q_ASSERT(!surface);
surface.setup(s);
org_kde_plasma_surface_add_listener(surface, &s_listener, this);
}
const org_kde_plasma_surface_listener PlasmaShellSurface::Private::s_listener = {
autoHidingPanelHiddenCallback,
autoHidingPanelShownCallback
};
void PlasmaShellSurface::Private::autoHidingPanelHiddenCallback(void *data, org_kde_plasma_surface *org_kde_plasma_surface)
{
auto p = reinterpret_cast<PlasmaShellSurface::Private*>(data);
Q_ASSERT(p->surface == org_kde_plasma_surface);
emit p->q->autoHidePanelHidden();
}
void PlasmaShellSurface::Private::autoHidingPanelShownCallback(void *data, org_kde_plasma_surface *org_kde_plasma_surface)
{
auto p = reinterpret_cast<PlasmaShellSurface::Private*>(data);
Q_ASSERT(p->surface == org_kde_plasma_surface);
emit p->q->autoHidePanelShown();
}
PlasmaShellSurface::PlasmaShellSurface(QObject *parent)
......@@ -298,5 +322,15 @@ void PlasmaShellSurface::setSkipTaskbar(bool skip)
org_kde_plasma_surface_set_skip_taskbar(d->surface, skip);
}
void PlasmaShellSurface::requestHideAutoHidingPanel()
{
org_kde_plasma_surface_panel_auto_hide_hide(d->surface);
}
void PlasmaShellSurface::requestShowAutoHidingPanel()
{
org_kde_plasma_surface_panel_auto_hide_show(d->surface);
}
}
}
......@@ -289,6 +289,53 @@ public:
*/
void setSkipTaskbar(bool skip);
/**
* Requests to hide a surface with Role Panel and PanelBahvior AutoHide.
*
* Once the compositor has hidden the panel the signal @link{autoHidePanelHidden} gets
* emitted. Once it is shown again the signal @link{autoHidePanelShown} gets emitted.
*
* To show the surface again from client side use @link{requestShowAutoHidingPanel}.
*
* @see autoHidePanelHidden
* @see autoHidePanelShown
* @see requestShowAutoHidingPanel
* @since 5.28
**/
void requestHideAutoHidingPanel();
/**
* Requests to show a surface with Role Panel and PanelBahvior AutoHide.
*
* This request allows the client to show a surface which it previously
* requested to be hidden with @link{requestHideAutoHidingPanel}.
*
* @see autoHidePanelHidden
* @see autoHidePanelShown
* @see requestHideAutoHidingPanel
* @since 5.28
**/
void requestShowAutoHidingPanel();
Q_SIGNALS:
/**
* Emitted when the compositor hided an auto hiding panel.
* @see requestHideAutoHidingPanel
* @see autoHidePanelShown
* @see requestShowAutoHidingPanel
* @since 5.28
**/
void autoHidePanelHidden();
/**
* Emitted when the compositor showed an auto hiding panel.
* @see requestHideAutoHidingPanel
* @see autoHidePanelHidden
* @see requestShowAutoHidingPanel
* @since 5.28
**/
void autoHidePanelShown();
private:
friend class PlasmaShell;
class Private;
......
......@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]></copyright>
<interface name="org_kde_plasma_shell" version="3">
<interface name="org_kde_plasma_shell" version="4">
<description summary="create shell windows and helpers">
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 @@
-->
</interface>
<interface name="org_kde_plasma_surface" version="3">
<interface name="org_kde_plasma_surface" version="4">
<description summary="metadata interface">
An interface that may be implemented by a wl_surface, for
implementations that provide the shell user interface.
......@@ -335,23 +335,43 @@
<arg name="skip" type="uint" summary="Boolean value that sets wther to skip the taskbar"/>
</request>
<!-- Screen edge -->
<!-- Will replace https://community.kde.org/KWin/Screen_Edges -->
<!--
<enum name="screen_edge">
<entry name="none" value="0"/>
<entry name="left" value="1"/>
<entry name="top" value="2"/>
<entry name="right" value="3"/>
<entry name="bottom" value="4"/>
<enum name="error" since="4">
<entry name="panel_not_auto_hide" value="0"
summary="Request panel_auto_hide performed on a surface which does not correspond to an auto-hide panel."/>
</enum>
<request name="set_screen_edge">
<description summary="set screen edge activation">
</description>
<arg name="screen_edge" type="uint"/>
<request name="panel_auto_hide_hide" since="4">
<description summary="Hide the auto-hiding panel">
A panel surface with panel_behavior auto_hide can perform this request to hide the panel
on a screen edge without unmapping it. The compositor informs the client about the panel
being hidden with the event auto_hidden_panel_hidden.
The compositor will restore the visibility state of the
surface when the pointer touches the screen edge the panel borders. Once the compositor restores
the visibility the event auto_hidden_panel_shown will be sent. This event will also be sent
if the compositor is unable to hide the panel.
The client can also request to show the panel again with the request panel_auto_hide_show.
</description>
</request>
-->
<request name="panel_auto_hide_show" since="4">
<description summary="Show the auto-hiding panel">
A panel surface with panel_behavior auto_hide can perform this request to show the panel
again which got hidden with panel_auto_hide_hide.
</description>
</request>
<event name="auto_hidden_panel_hidden" since="4">
<description summary="Auto-hiding panel is hidden">
An auto-hiding panel got hidden by the compositor.
</description>
</event>
<event name="auto_hidden_panel_shown" since="4">
<description summary="Auto-hiding panel is shown">
An auto-hiding panel got shown by the compositor.
</description>
</event>
</interface>
</protocol>
......@@ -146,7 +146,7 @@ static const QMap<Registry::Interface, SuppertedInterfaceData> s_interfaces = {
&Registry::subCompositorRemoved
}},
{Registry::Interface::PlasmaShell, {
3,
4,
QByteArrayLiteral("org_kde_plasma_shell"),
&org_kde_plasma_shell_interface,
&Registry::plasmaShellAnnounced,
......
......@@ -50,7 +50,7 @@ private:
static const quint32 s_version;
};
const quint32 PlasmaShellInterface::Private::s_version = 3;
const quint32 PlasmaShellInterface::Private::s_version = 4;
PlasmaShellInterface::Private::Private(PlasmaShellInterface *q, Display *d)
: Global::Private(d, &org_kde_plasma_shell_interface, s_version)
......@@ -84,6 +84,8 @@ private:
static void setRoleCallback(wl_client *client, wl_resource *resource, uint32_t role);
static void setPanelBehaviorCallback(wl_client *client, wl_resource *resource, uint32_t flag);
static void setSkipTaskbarCallback(wl_client *client, wl_resource *resource, uint32_t skip);
static void panelAutoHideHideCallback(wl_client *client, wl_resource *resource);
static void panelAutoHideShowCallback(wl_client *client, wl_resource *resource);
void setPosition(const QPoint &globalPos);
void setRole(uint32_t role);
......@@ -158,7 +160,9 @@ const struct org_kde_plasma_surface_interface PlasmaShellSurfaceInterface::Priva
setPositionCallback,
setRoleCallback,
setPanelBehaviorCallback,
setSkipTaskbarCallback
setSkipTaskbarCallback,
panelAutoHideHideCallback,
panelAutoHideShowCallback
};
#endif
......@@ -270,6 +274,28 @@ void PlasmaShellSurfaceInterface::Private::setSkipTaskbarCallback(wl_client *cli
emit s->q_func()->skipTaskbarChanged();
}
void PlasmaShellSurfaceInterface::Private::panelAutoHideHideCallback(wl_client *client, wl_resource *resource)
{
auto s = cast<Private>(resource);
Q_ASSERT(client == *s->client);
if (s->m_role != Role::Panel || s->m_panelBehavior != PanelBehavior::AutoHide) {
wl_resource_post_error(s->resource, ORG_KDE_PLASMA_SURFACE_ERROR_PANEL_NOT_AUTO_HIDE, "Not an auto hide panel");
return;
}
emit s->q_func()->panelAutoHideHideRequested();
}
void PlasmaShellSurfaceInterface::Private::panelAutoHideShowCallback(wl_client *client, wl_resource *resource)
{
auto s = cast<Private>(resource);
Q_ASSERT(client == *s->client);
if (s->m_role != Role::Panel || s->m_panelBehavior != PanelBehavior::AutoHide) {
wl_resource_post_error(s->resource, ORG_KDE_PLASMA_SURFACE_ERROR_PANEL_NOT_AUTO_HIDE, "Not an auto hide panel");
return;
}
emit s->q_func()->panelAutoHideShowRequested();
}
void PlasmaShellSurfaceInterface::Private::setPanelBehavior(org_kde_plasma_surface_panel_behavior behavior)
{
PanelBehavior newBehavior = PanelBehavior::AlwaysVisible;
......@@ -325,6 +351,24 @@ bool PlasmaShellSurfaceInterface::skipTaskbar() const
return d->m_skipTaskbar;
}
void PlasmaShellSurfaceInterface::hideAutoHidingPanel()
{
Q_D();
if (!d->resource) {
return;
}
org_kde_plasma_surface_send_auto_hidden_panel_hidden(d->resource);
}
void PlasmaShellSurfaceInterface::showAutoHidingPanel()
{
Q_D();
if (!d->resource) {
return;
}
org_kde_plasma_surface_send_auto_hidden_panel_shown(d->resource);
}
PlasmaShellSurfaceInterface *PlasmaShellSurfaceInterface::get(wl_resource *native)
{
return Private::get<PlasmaShellSurfaceInterface>(native);
......
......@@ -138,6 +138,27 @@ public:
*/
bool skipTaskbar() const;
/**
* Informs the PlasmaShellSurfaceInterface that the auto-hiding panel got hidden.
* Once it is shown again the method @link{showAutoHidingPanel} should be used.
*
* @see showAutoHidingPanel
* @see panelAutoHideHideRequested
* @see panelAutoHideShowRequested
* @since 5.28
**/
void hideAutoHidingPanel();
/**
* Informs the PlasmaShellSurfaceInterface that the auto-hiding panel got shown again.
*
* @see hideAutoHidingPanel
* @see panelAutoHideHideRequested
* @see panelAutoHideShowRequested
* @see 5.28
**/
void showAutoHidingPanel();
/**
* @returns The PlasmaShellSurfaceInterface for the @p native resource.
* @since 5.5
......@@ -162,6 +183,35 @@ Q_SIGNALS:
*/
void skipTaskbarChanged();
/**
* A surface with Role Panel and PanelBehavior AutoHide requested to be hidden.
*
* The compositor should inform the PlasmaShellSurfaceInterface about the actual change.
* Once the surface is hidden it should invoke @link{hideAutoHidingPanel}. If the compositor
* cannot hide the surface (e.g. because it doesn't border a screen edge) it should inform
* the surface through invoking @link{showAutoHidingPanel}. This method should also be invoked
* whenever the surface gets shown again due to triggering the screen edge.
*
* @see hideAutoHidingPanel
* @see showAutoHidingPanel
* @see panelAutoHideShowRequested
* @since 5.28
**/
void panelAutoHideHideRequested();
/**
* A surface with Role Panel and PanelBehavior AutoHide requested to be shown.
*
* The compositor should inform the PlasmaShellSurfaceInterface about the actual change.
* Once the surface is shown it should invoke @link{showAutoHidingPanel}.
*
* @see hideAutoHidingPanel
* @see showAutoHidingPanel
* @see panelAutoHideHideRequested
* @since 5.28
**/
void panelAutoHideShowRequested();
private:
friend class PlasmaShellInterface;
explicit PlasmaShellSurfaceInterface(PlasmaShellInterface *shell, SurfaceInterface *parent, wl_resource *parentResource);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment