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
This commit is contained in:
Martin Gräßlin 2016-10-10 16:42:05 +02:00
parent 721ebe1875
commit c291752819
3 changed files with 151 additions and 2 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);