Support docks which take input

Summary:
On X11 one needs to force activate a panel to pass it focus. This change
implements something similar for Wayland but a little bit more stateful
by using a request on the PlasmaShellSurface. If set KWin will activate
the panel.

Reviewers: #kwin, #plasma_on_wayland

Subscribers: plasma-devel, kwin

Tags: #plasma_on_wayland, #kwin

Differential Revision: https://phabricator.kde.org/D3037
This commit is contained in:
Martin Gräßlin 2016-10-12 15:09:52 +02:00
parent 01667cacea
commit 03d706150a
6 changed files with 68 additions and 2 deletions

View file

@ -1634,4 +1634,9 @@ QRect AbstractClient::inputGeometry() const
return Toplevel::inputGeometry();
}
bool AbstractClient::dockWantsInput() const
{
return false;
}
}

View file

@ -416,6 +416,18 @@ public:
virtual const WindowRules* rules() const = 0;
virtual void takeFocus() = 0;
virtual bool wantsInput() const = 0;
/**
* Whether a dock window wants input.
*
* By default KWin doesn't pass focus to a dock window unless a force activate
* request is provided.
*
* This method allows to have dock windows take focus also through flags set on
* the window.
*
* The default implementation returns @c false.
**/
virtual bool dockWantsInput() const;
void checkWorkspacePosition(QRect oldGeometry = QRect(), int oldDesktop = -2, QRect oldClientGeometry = QRect());
virtual xcb_timestamp_t userTime() const;
virtual void updateWindowRules(Rules::Types selection) = 0;

View file

@ -371,8 +371,13 @@ void Workspace::takeActivity(AbstractClient* c, ActivityFlags flags)
}
cancelDelayFocus();
}
if (!flags.testFlag(ActivityFocusForce) && (c->isDock() || c->isSplash()))
flags &= ~ActivityFocus; // toplevel menus and dock windows don't take focus if not forced
if (!flags.testFlag(ActivityFocusForce) && (c->isDock() || c->isSplash())) {
// toplevel menus and dock windows don't take focus if not forced
// and don't have a flag that they take focus
if (!c->dockWantsInput()) {
flags &= ~ActivityFocus;
}
}
if (c->isShade()) {
if (c->wantsInput() && (flags & ActivityFocus)) {
// client cannot accept focus, but at least the window should be active (window menu, et. al. )

View file

@ -59,6 +59,8 @@ private Q_SLOTS:
void testOSDPlacement();
void testPanelTypeHasStrut_data();
void testPanelTypeHasStrut();
void testPanelActivate_data();
void testPanelActivate();
private:
ConnectionThread *m_connection = nullptr;
@ -368,5 +370,36 @@ void PlasmaSurfaceTest::testPanelWindowsCanCover()
QCOMPARE(stackingOrder.last(), panel);
}
void PlasmaSurfaceTest::testPanelActivate_data()
{
QTest::addColumn<bool>("wantsFocus");
QTest::addColumn<bool>("active");
QTest::newRow("no focus") << false << false;
QTest::newRow("focus") << true << true;
}
void PlasmaSurfaceTest::testPanelActivate()
{
QScopedPointer<Surface> surface(Test::createSurface());
QVERIFY(!surface.isNull());
QScopedPointer<QObject> shellSurface(Test::createShellSurface(Test::ShellSurfaceType::WlShell, surface.data()));
QVERIFY(!shellSurface.isNull());
QScopedPointer<PlasmaShellSurface> plasmaSurface(m_plasmaShell->createSurface(surface.data()));
QVERIFY(!plasmaSurface.isNull());
plasmaSurface->setRole(PlasmaShellSurface::Role::Panel);
QFETCH(bool, wantsFocus);
plasmaSurface->setPanelTakesFocus(wantsFocus);
auto panel = Test::renderAndWaitForShown(surface.data(), QSize(100, 200), Qt::blue);
QVERIFY(panel);
QCOMPARE(panel->windowType(), NET::Dock);
QVERIFY(panel->isDock());
QFETCH(bool, active);
QCOMPARE(panel->dockWantsInput(), active);
QCOMPARE(panel->isActive(), active);
}
WAYLANDTEST_MAIN(PlasmaSurfaceTest)
#include "plasma_surface_test.moc"

View file

@ -1373,4 +1373,14 @@ void ShellClient::showOnScreenEdge()
}
}
bool ShellClient::dockWantsInput() const
{
if (m_plasmaShellSurface) {
if (m_plasmaShellSurface->role() == PlasmaShellSurfaceInterface::Role::Panel) {
return m_plasmaShellSurface->panelTakesFocus();
}
}
return false;
}
}

View file

@ -96,6 +96,7 @@ public:
bool userCanSetFullScreen() const override;
bool userCanSetNoBorder() const override;
bool wantsInput() const override;
bool dockWantsInput() const override;
using AbstractClient::resizeWithChecks;
void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet) override;
using AbstractClient::setGeometry;