2016-06-30 11:32:54 +00:00
|
|
|
/********************************************************************
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*********************************************************************/
|
|
|
|
#include "kwin_wayland_test.h"
|
2016-07-01 07:54:44 +00:00
|
|
|
#include "shell_client.h"
|
2016-08-16 08:23:37 +00:00
|
|
|
#include "screenlockerwatcher.h"
|
2016-07-01 07:54:44 +00:00
|
|
|
#include "wayland_server.h"
|
2016-06-30 11:32:54 +00:00
|
|
|
|
|
|
|
#include <KWayland/Client/compositor.h>
|
|
|
|
#include <KWayland/Client/connection_thread.h>
|
|
|
|
#include <KWayland/Client/event_queue.h>
|
2017-11-16 20:48:19 +00:00
|
|
|
#include <KWayland/Client/idleinhibit.h>
|
2016-06-30 11:32:54 +00:00
|
|
|
#include <KWayland/Client/registry.h>
|
|
|
|
#include <KWayland/Client/plasmashell.h>
|
|
|
|
#include <KWayland/Client/plasmawindowmanagement.h>
|
2016-11-25 06:17:43 +00:00
|
|
|
#include <KWayland/Client/pointerconstraints.h>
|
2016-06-30 11:32:54 +00:00
|
|
|
#include <KWayland/Client/seat.h>
|
|
|
|
#include <KWayland/Client/server_decoration.h>
|
2018-06-07 09:08:15 +00:00
|
|
|
#include <KWayland/Client/shadow.h>
|
2016-06-30 11:32:54 +00:00
|
|
|
#include <KWayland/Client/shell.h>
|
|
|
|
#include <KWayland/Client/shm_pool.h>
|
2017-08-18 14:15:19 +00:00
|
|
|
#include <KWayland/Client/output.h>
|
2019-02-21 22:25:19 +00:00
|
|
|
#include <KWayland/Client/subcompositor.h>
|
|
|
|
#include <KWayland/Client/subsurface.h>
|
2016-06-30 11:32:54 +00:00
|
|
|
#include <KWayland/Client/surface.h>
|
2017-12-22 14:22:24 +00:00
|
|
|
#include <KWayland/Client/appmenu.h>
|
2016-04-22 12:13:37 +00:00
|
|
|
#include <KWayland/Client/xdgshell.h>
|
2019-01-01 17:37:18 +00:00
|
|
|
#include <KWayland/Client/xdgdecoration.h>
|
2016-12-03 13:31:14 +00:00
|
|
|
#include <KWayland/Server/display.h>
|
2016-06-30 11:32:54 +00:00
|
|
|
|
2016-08-16 06:19:45 +00:00
|
|
|
//screenlocker
|
|
|
|
#include <KScreenLocker/KsldApp>
|
|
|
|
|
2016-06-30 11:32:54 +00:00
|
|
|
#include <QThread>
|
|
|
|
|
2016-12-03 13:31:14 +00:00
|
|
|
// system
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2016-06-30 11:32:54 +00:00
|
|
|
using namespace KWayland::Client;
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
namespace Test
|
|
|
|
{
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
ConnectionThread *connection = nullptr;
|
|
|
|
EventQueue *queue = nullptr;
|
|
|
|
Compositor *compositor = nullptr;
|
2019-02-21 22:25:19 +00:00
|
|
|
SubCompositor *subCompositor = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
ServerSideDecorationManager *decoration = nullptr;
|
2018-06-07 09:08:15 +00:00
|
|
|
ShadowManager *shadowManager = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
Shell *shell = nullptr;
|
2016-04-22 12:13:37 +00:00
|
|
|
XdgShell *xdgShellV5 = nullptr;
|
XdgV6 - Kwin side
Summary:
Adds XDGV6 support for the kwin side.
Popup placement support is limited to the stuff v5 had,
a simple offset, rather than the awesome new positioner.
But Qt doesn't make use of it yet either.
Also ideally we should do all the positioning before sending the first
configure, but again Qt doesn't actually do anything with that anyway.
Also integrate pinging clients
Test Plan: gtk3-demo works nicely.
Reviewers: #plasma, graesslin, mart
Reviewed By: #plasma, graesslin
Subscribers: mart, graesslin, kwin, plasma-devel, #kwin
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6591
2017-09-25 15:37:59 +00:00
|
|
|
XdgShell *xdgShellV6 = nullptr;
|
2018-10-15 14:02:53 +00:00
|
|
|
XdgShell *xdgShellStable = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
ShmPool *shm = nullptr;
|
|
|
|
Seat *seat = nullptr;
|
|
|
|
PlasmaShell *plasmaShell = nullptr;
|
|
|
|
PlasmaWindowManagement *windowManagement = nullptr;
|
2016-11-25 06:17:43 +00:00
|
|
|
PointerConstraints *pointerConstraints = nullptr;
|
2017-08-18 14:15:19 +00:00
|
|
|
Registry *registry = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
QThread *thread = nullptr;
|
2017-08-18 14:15:19 +00:00
|
|
|
QVector<Output*> outputs;
|
2017-11-16 20:48:19 +00:00
|
|
|
IdleInhibitManager *idleInhibit = nullptr;
|
2017-12-22 14:22:24 +00:00
|
|
|
AppMenuManager *appMenu = nullptr;
|
2019-01-01 17:37:18 +00:00
|
|
|
XdgDecorationManager *xdgDecoration = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
} s_waylandConnection;
|
|
|
|
|
2016-12-03 13:31:14 +00:00
|
|
|
bool setupWaylandConnection(AdditionalWaylandInterfaces flags)
|
2016-06-30 11:32:54 +00:00
|
|
|
{
|
|
|
|
if (s_waylandConnection.connection) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-12-03 13:31:14 +00:00
|
|
|
|
|
|
|
int sx[2];
|
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
KWin::waylandServer()->display()->createClient(sx[0]);
|
2016-06-30 11:32:54 +00:00
|
|
|
// setup connection
|
|
|
|
s_waylandConnection.connection = new ConnectionThread;
|
|
|
|
QSignalSpy connectedSpy(s_waylandConnection.connection, &ConnectionThread::connected);
|
|
|
|
if (!connectedSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-12-03 13:31:14 +00:00
|
|
|
s_waylandConnection.connection->setSocketFd(sx[1]);
|
2016-06-30 11:32:54 +00:00
|
|
|
|
|
|
|
s_waylandConnection.thread = new QThread(kwinApp());
|
|
|
|
s_waylandConnection.connection->moveToThread(s_waylandConnection.thread);
|
|
|
|
s_waylandConnection.thread->start();
|
|
|
|
|
|
|
|
s_waylandConnection.connection->initConnection();
|
|
|
|
if (!connectedSpy.wait()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
s_waylandConnection.queue = new EventQueue;
|
|
|
|
s_waylandConnection.queue->setup(s_waylandConnection.connection);
|
|
|
|
if (!s_waylandConnection.queue->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-18 14:15:19 +00:00
|
|
|
Registry *registry = new Registry;
|
|
|
|
s_waylandConnection.registry = registry;
|
|
|
|
registry->setEventQueue(s_waylandConnection.queue);
|
|
|
|
|
|
|
|
QObject::connect(registry, &Registry::outputAnnounced, [=](quint32 name, quint32 version) {
|
|
|
|
auto output = registry->createOutput(name, version, s_waylandConnection.registry);
|
|
|
|
s_waylandConnection.outputs << output;
|
|
|
|
QObject::connect(output, &Output::removed, [=]() {
|
|
|
|
output->deleteLater();
|
|
|
|
s_waylandConnection.outputs.removeOne(output);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
QSignalSpy allAnnounced(registry, &Registry::interfacesAnnounced);
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!allAnnounced.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-18 14:15:19 +00:00
|
|
|
registry->create(s_waylandConnection.connection);
|
|
|
|
if (!registry->isValid()) {
|
2016-06-30 11:32:54 +00:00
|
|
|
return false;
|
|
|
|
}
|
2017-08-18 14:15:19 +00:00
|
|
|
registry->setup();
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!allAnnounced.wait()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.compositor = registry->createCompositor(registry->interface(Registry::Interface::Compositor).name, registry->interface(Registry::Interface::Compositor).version);
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!s_waylandConnection.compositor->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-02-21 22:25:19 +00:00
|
|
|
s_waylandConnection.subCompositor = registry->createSubCompositor(registry->interface(Registry::Interface::SubCompositor).name, registry->interface(Registry::Interface::SubCompositor).version);
|
|
|
|
if (!s_waylandConnection.subCompositor->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.shm = registry->createShmPool(registry->interface(Registry::Interface::Shm).name, registry->interface(Registry::Interface::Shm).version);
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!s_waylandConnection.shm->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.shell = registry->createShell(registry->interface(Registry::Interface::Shell).name, registry->interface(Registry::Interface::Shell).version);
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!s_waylandConnection.shell->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.xdgShellV5 = registry->createXdgShell(registry->interface(Registry::Interface::XdgShellUnstableV5).name, registry->interface(Registry::Interface::XdgShellUnstableV5).version);
|
2016-04-22 12:13:37 +00:00
|
|
|
if (!s_waylandConnection.xdgShellV5->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
XdgV6 - Kwin side
Summary:
Adds XDGV6 support for the kwin side.
Popup placement support is limited to the stuff v5 had,
a simple offset, rather than the awesome new positioner.
But Qt doesn't make use of it yet either.
Also ideally we should do all the positioning before sending the first
configure, but again Qt doesn't actually do anything with that anyway.
Also integrate pinging clients
Test Plan: gtk3-demo works nicely.
Reviewers: #plasma, graesslin, mart
Reviewed By: #plasma, graesslin
Subscribers: mart, graesslin, kwin, plasma-devel, #kwin
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6591
2017-09-25 15:37:59 +00:00
|
|
|
s_waylandConnection.xdgShellV6 = registry->createXdgShell(registry->interface(Registry::Interface::XdgShellUnstableV6).name, registry->interface(Registry::Interface::XdgShellUnstableV6).version);
|
|
|
|
if (!s_waylandConnection.xdgShellV6->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-10-15 14:02:53 +00:00
|
|
|
s_waylandConnection.xdgShellStable = registry->createXdgShell(registry->interface(Registry::Interface::XdgShellStable).name, registry->interface(Registry::Interface::XdgShellStable).version);
|
|
|
|
if (!s_waylandConnection.xdgShellStable->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-06-30 11:32:54 +00:00
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::Seat)) {
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.seat = registry->createSeat(registry->interface(Registry::Interface::Seat).name, registry->interface(Registry::Interface::Seat).version);
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!s_waylandConnection.seat->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2018-06-07 09:08:15 +00:00
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::ShadowManager)) {
|
|
|
|
s_waylandConnection.shadowManager = registry->createShadowManager(registry->interface(Registry::Interface::Shadow).name,
|
|
|
|
registry->interface(Registry::Interface::Shadow).version);
|
|
|
|
if (!s_waylandConnection.shadowManager->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2016-06-30 11:32:54 +00:00
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::Decoration)) {
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.decoration = registry->createServerSideDecorationManager(registry->interface(Registry::Interface::ServerSideDecorationManager).name,
|
|
|
|
registry->interface(Registry::Interface::ServerSideDecorationManager).version);
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!s_waylandConnection.decoration->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::PlasmaShell)) {
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.plasmaShell = registry->createPlasmaShell(registry->interface(Registry::Interface::PlasmaShell).name,
|
|
|
|
registry->interface(Registry::Interface::PlasmaShell).version);
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!s_waylandConnection.plasmaShell->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::WindowManagement)) {
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.windowManagement = registry->createPlasmaWindowManagement(registry->interface(Registry::Interface::PlasmaWindowManagement).name,
|
|
|
|
registry->interface(Registry::Interface::PlasmaWindowManagement).version);
|
2016-06-30 11:32:54 +00:00
|
|
|
if (!s_waylandConnection.windowManagement->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2016-11-25 06:17:43 +00:00
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::PointerConstraints)) {
|
2017-08-18 14:15:19 +00:00
|
|
|
s_waylandConnection.pointerConstraints = registry->createPointerConstraints(registry->interface(Registry::Interface::PointerConstraintsUnstableV1).name,
|
|
|
|
registry->interface(Registry::Interface::PointerConstraintsUnstableV1).version);
|
2016-11-25 06:17:43 +00:00
|
|
|
if (!s_waylandConnection.pointerConstraints->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2017-11-16 20:48:19 +00:00
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::IdleInhibition)) {
|
|
|
|
s_waylandConnection.idleInhibit = registry->createIdleInhibitManager(registry->interface(Registry::Interface::IdleInhibitManagerUnstableV1).name,
|
|
|
|
registry->interface(Registry::Interface::IdleInhibitManagerUnstableV1).version);
|
|
|
|
if (!s_waylandConnection.idleInhibit->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2017-12-22 14:22:24 +00:00
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::AppMenu)) {
|
|
|
|
s_waylandConnection.appMenu = registry->createAppMenuManager(registry->interface(Registry::Interface::AppMenu).name, registry->interface(Registry::Interface::AppMenu).version);
|
|
|
|
if (!s_waylandConnection.appMenu->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2019-01-01 17:37:18 +00:00
|
|
|
if (flags.testFlag(AdditionalWaylandInterface::XdgDecoration)) {
|
|
|
|
s_waylandConnection.xdgDecoration = registry->createXdgDecorationManager(registry->interface(Registry::Interface::XdgDecorationUnstableV1).name, registry->interface(Registry::Interface::XdgDecorationUnstableV1).version);
|
|
|
|
if (!s_waylandConnection.xdgDecoration->isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2016-06-30 11:32:54 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void destroyWaylandConnection()
|
|
|
|
{
|
|
|
|
delete s_waylandConnection.compositor;
|
|
|
|
s_waylandConnection.compositor = nullptr;
|
2019-02-21 22:25:19 +00:00
|
|
|
delete s_waylandConnection.subCompositor;
|
|
|
|
s_waylandConnection.subCompositor = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
delete s_waylandConnection.windowManagement;
|
|
|
|
s_waylandConnection.windowManagement = nullptr;
|
|
|
|
delete s_waylandConnection.plasmaShell;
|
|
|
|
s_waylandConnection.plasmaShell = nullptr;
|
|
|
|
delete s_waylandConnection.decoration;
|
|
|
|
s_waylandConnection.decoration = nullptr;
|
|
|
|
delete s_waylandConnection.decoration;
|
|
|
|
s_waylandConnection.decoration = nullptr;
|
|
|
|
delete s_waylandConnection.seat;
|
|
|
|
s_waylandConnection.seat = nullptr;
|
2016-11-25 06:17:43 +00:00
|
|
|
delete s_waylandConnection.pointerConstraints;
|
|
|
|
s_waylandConnection.pointerConstraints = nullptr;
|
2016-04-22 12:13:37 +00:00
|
|
|
delete s_waylandConnection.xdgShellV5;
|
|
|
|
s_waylandConnection.xdgShellV5 = nullptr;
|
XdgV6 - Kwin side
Summary:
Adds XDGV6 support for the kwin side.
Popup placement support is limited to the stuff v5 had,
a simple offset, rather than the awesome new positioner.
But Qt doesn't make use of it yet either.
Also ideally we should do all the positioning before sending the first
configure, but again Qt doesn't actually do anything with that anyway.
Also integrate pinging clients
Test Plan: gtk3-demo works nicely.
Reviewers: #plasma, graesslin, mart
Reviewed By: #plasma, graesslin
Subscribers: mart, graesslin, kwin, plasma-devel, #kwin
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6591
2017-09-25 15:37:59 +00:00
|
|
|
delete s_waylandConnection.xdgShellV6;
|
|
|
|
s_waylandConnection.xdgShellV6 = nullptr;
|
2018-10-15 14:02:53 +00:00
|
|
|
delete s_waylandConnection.xdgShellStable;
|
|
|
|
s_waylandConnection.xdgShellStable = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
delete s_waylandConnection.shell;
|
|
|
|
s_waylandConnection.shell = nullptr;
|
2018-06-07 09:08:15 +00:00
|
|
|
delete s_waylandConnection.shadowManager;
|
|
|
|
s_waylandConnection.shadowManager = nullptr;
|
2017-11-16 20:48:19 +00:00
|
|
|
delete s_waylandConnection.idleInhibit;
|
|
|
|
s_waylandConnection.idleInhibit = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
delete s_waylandConnection.shm;
|
|
|
|
s_waylandConnection.shm = nullptr;
|
|
|
|
delete s_waylandConnection.queue;
|
|
|
|
s_waylandConnection.queue = nullptr;
|
2017-08-18 14:15:19 +00:00
|
|
|
delete s_waylandConnection.registry;
|
|
|
|
s_waylandConnection.registry = nullptr;
|
2017-12-22 14:22:24 +00:00
|
|
|
delete s_waylandConnection.appMenu;
|
|
|
|
s_waylandConnection.appMenu = nullptr;
|
2019-01-01 17:37:18 +00:00
|
|
|
delete s_waylandConnection.xdgDecoration;
|
|
|
|
s_waylandConnection.xdgDecoration = nullptr;
|
2016-06-30 11:32:54 +00:00
|
|
|
if (s_waylandConnection.thread) {
|
|
|
|
QSignalSpy spy(s_waylandConnection.connection, &QObject::destroyed);
|
|
|
|
s_waylandConnection.connection->deleteLater();
|
2016-08-08 08:10:26 +00:00
|
|
|
if (spy.isEmpty()) {
|
|
|
|
QVERIFY(spy.wait());
|
|
|
|
}
|
2016-06-30 11:32:54 +00:00
|
|
|
s_waylandConnection.thread->quit();
|
|
|
|
s_waylandConnection.thread->wait();
|
|
|
|
delete s_waylandConnection.thread;
|
|
|
|
s_waylandConnection.thread = nullptr;
|
|
|
|
s_waylandConnection.connection = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ConnectionThread *waylandConnection()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.connection;
|
|
|
|
}
|
|
|
|
|
|
|
|
Compositor *waylandCompositor()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.compositor;
|
|
|
|
}
|
|
|
|
|
2019-02-21 22:25:19 +00:00
|
|
|
SubCompositor *waylandSubCompositor()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.subCompositor;
|
|
|
|
}
|
|
|
|
|
2018-06-07 09:08:15 +00:00
|
|
|
ShadowManager *waylandShadowManager()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.shadowManager;
|
|
|
|
}
|
|
|
|
|
2016-06-30 11:32:54 +00:00
|
|
|
Shell *waylandShell()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.shell;
|
|
|
|
}
|
|
|
|
|
|
|
|
ShmPool *waylandShmPool()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.shm;
|
|
|
|
}
|
|
|
|
|
|
|
|
Seat *waylandSeat()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.seat;
|
|
|
|
}
|
|
|
|
|
|
|
|
ServerSideDecorationManager *waylandServerSideDecoration()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.decoration;
|
|
|
|
}
|
|
|
|
|
|
|
|
PlasmaShell *waylandPlasmaShell()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.plasmaShell;
|
|
|
|
}
|
|
|
|
|
|
|
|
PlasmaWindowManagement *waylandWindowManagement()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.windowManagement;
|
|
|
|
}
|
|
|
|
|
2016-11-25 06:17:43 +00:00
|
|
|
PointerConstraints *waylandPointerConstraints()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.pointerConstraints;
|
|
|
|
}
|
|
|
|
|
2017-11-16 20:48:19 +00:00
|
|
|
IdleInhibitManager *waylandIdleInhibitManager()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.idleInhibit;
|
|
|
|
}
|
|
|
|
|
2017-12-22 14:22:24 +00:00
|
|
|
AppMenuManager* waylandAppMenuManager()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.appMenu;
|
|
|
|
}
|
|
|
|
|
2019-01-01 17:37:18 +00:00
|
|
|
XdgDecorationManager *xdgDecorationManager()
|
|
|
|
{
|
|
|
|
return s_waylandConnection.xdgDecoration;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-30 11:32:54 +00:00
|
|
|
bool waitForWaylandPointer()
|
|
|
|
{
|
|
|
|
if (!s_waylandConnection.seat) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QSignalSpy hasPointerSpy(s_waylandConnection.seat, &Seat::hasPointerChanged);
|
|
|
|
if (!hasPointerSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return hasPointerSpy.wait();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool waitForWaylandTouch()
|
|
|
|
{
|
|
|
|
if (!s_waylandConnection.seat) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QSignalSpy hasTouchSpy(s_waylandConnection.seat, &Seat::hasTouchChanged);
|
|
|
|
if (!hasTouchSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return hasTouchSpy.wait();
|
|
|
|
}
|
|
|
|
|
2016-08-11 09:17:09 +00:00
|
|
|
bool waitForWaylandKeyboard()
|
|
|
|
{
|
|
|
|
if (!s_waylandConnection.seat) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QSignalSpy hasKeyboardSpy(s_waylandConnection.seat, &Seat::hasKeyboardChanged);
|
|
|
|
if (!hasKeyboardSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return hasKeyboardSpy.wait();
|
|
|
|
}
|
|
|
|
|
2016-06-30 11:32:54 +00:00
|
|
|
void render(Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format)
|
|
|
|
{
|
|
|
|
QImage img(size, format);
|
|
|
|
img.fill(color);
|
2017-07-31 14:12:37 +00:00
|
|
|
render(surface, img);
|
|
|
|
}
|
|
|
|
|
|
|
|
void render(Surface *surface, const QImage &img)
|
|
|
|
{
|
2016-06-30 11:32:54 +00:00
|
|
|
surface->attachBuffer(s_waylandConnection.shm->createBuffer(img));
|
2017-07-31 14:12:37 +00:00
|
|
|
surface->damage(QRect(QPoint(0, 0), img.size()));
|
2016-06-30 11:32:54 +00:00
|
|
|
surface->commit(Surface::CommitFlag::None);
|
|
|
|
}
|
|
|
|
|
2016-07-01 07:54:44 +00:00
|
|
|
ShellClient *waitForWaylandWindowShown(int timeout)
|
|
|
|
{
|
|
|
|
QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
|
|
|
|
if (!clientAddedSpy.isValid()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (!clientAddedSpy.wait(timeout)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return clientAddedSpy.first().first().value<ShellClient*>();
|
|
|
|
}
|
|
|
|
|
|
|
|
ShellClient *renderAndWaitForShown(Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format, int timeout)
|
|
|
|
{
|
|
|
|
QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
|
|
|
|
if (!clientAddedSpy.isValid()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
render(surface, size, color, format);
|
|
|
|
flushWaylandConnection();
|
|
|
|
if (!clientAddedSpy.wait(timeout)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return clientAddedSpy.first().first().value<ShellClient*>();
|
|
|
|
}
|
|
|
|
|
2016-06-30 11:32:54 +00:00
|
|
|
void flushWaylandConnection()
|
|
|
|
{
|
|
|
|
if (s_waylandConnection.connection) {
|
|
|
|
s_waylandConnection.connection->flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Surface *createSurface(QObject *parent)
|
|
|
|
{
|
|
|
|
if (!s_waylandConnection.compositor) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto s = s_waylandConnection.compositor->createSurface(parent);
|
|
|
|
if (!s->isValid()) {
|
|
|
|
delete s;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2019-02-21 22:25:19 +00:00
|
|
|
SubSurface *createSubSurface(Surface *surface, Surface *parentSurface, QObject *parent)
|
|
|
|
{
|
|
|
|
if (!s_waylandConnection.subCompositor) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto s = s_waylandConnection.subCompositor->createSubSurface(surface, parentSurface, parent);
|
|
|
|
if (!s->isValid()) {
|
|
|
|
delete s;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2016-06-30 11:32:54 +00:00
|
|
|
ShellSurface *createShellSurface(Surface *surface, QObject *parent)
|
|
|
|
{
|
|
|
|
if (!s_waylandConnection.shell) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto s = s_waylandConnection.shell->createSurface(surface, parent);
|
|
|
|
if (!s->isValid()) {
|
|
|
|
delete s;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2019-02-26 13:41:07 +00:00
|
|
|
XdgShellSurface *createXdgShellV5Surface(Surface *surface, QObject *parent, CreationSetup creationSetup)
|
2016-04-22 12:13:37 +00:00
|
|
|
{
|
|
|
|
if (!s_waylandConnection.xdgShellV5) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto s = s_waylandConnection.xdgShellV5->createSurface(surface, parent);
|
|
|
|
if (!s->isValid()) {
|
|
|
|
delete s;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-02-26 13:41:07 +00:00
|
|
|
if (creationSetup == CreationSetup::CreateAndConfigure) {
|
|
|
|
initXdgShellSurface(surface, s);
|
|
|
|
}
|
2016-04-22 12:13:37 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2019-02-26 13:41:07 +00:00
|
|
|
XdgShellSurface *createXdgShellV6Surface(Surface *surface, QObject *parent, CreationSetup creationSetup)
|
XdgV6 - Kwin side
Summary:
Adds XDGV6 support for the kwin side.
Popup placement support is limited to the stuff v5 had,
a simple offset, rather than the awesome new positioner.
But Qt doesn't make use of it yet either.
Also ideally we should do all the positioning before sending the first
configure, but again Qt doesn't actually do anything with that anyway.
Also integrate pinging clients
Test Plan: gtk3-demo works nicely.
Reviewers: #plasma, graesslin, mart
Reviewed By: #plasma, graesslin
Subscribers: mart, graesslin, kwin, plasma-devel, #kwin
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6591
2017-09-25 15:37:59 +00:00
|
|
|
{
|
|
|
|
if (!s_waylandConnection.xdgShellV6) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto s = s_waylandConnection.xdgShellV6->createSurface(surface, parent);
|
|
|
|
if (!s->isValid()) {
|
|
|
|
delete s;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-02-26 13:41:07 +00:00
|
|
|
if (creationSetup == CreationSetup::CreateAndConfigure) {
|
|
|
|
initXdgShellSurface(surface, s);
|
|
|
|
}
|
XdgV6 - Kwin side
Summary:
Adds XDGV6 support for the kwin side.
Popup placement support is limited to the stuff v5 had,
a simple offset, rather than the awesome new positioner.
But Qt doesn't make use of it yet either.
Also ideally we should do all the positioning before sending the first
configure, but again Qt doesn't actually do anything with that anyway.
Also integrate pinging clients
Test Plan: gtk3-demo works nicely.
Reviewers: #plasma, graesslin, mart
Reviewed By: #plasma, graesslin
Subscribers: mart, graesslin, kwin, plasma-devel, #kwin
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6591
2017-09-25 15:37:59 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2019-02-26 13:41:07 +00:00
|
|
|
XdgShellSurface *createXdgShellStableSurface(Surface *surface, QObject *parent, CreationSetup creationSetup)
|
2018-10-15 14:02:53 +00:00
|
|
|
{
|
|
|
|
if (!s_waylandConnection.xdgShellStable) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto s = s_waylandConnection.xdgShellStable->createSurface(surface, parent);
|
|
|
|
if (!s->isValid()) {
|
|
|
|
delete s;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-02-26 13:41:07 +00:00
|
|
|
if (creationSetup == CreationSetup::CreateAndConfigure) {
|
|
|
|
initXdgShellSurface(surface, s);
|
|
|
|
}
|
2018-10-15 14:02:53 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2019-02-26 13:41:07 +00:00
|
|
|
XdgShellPopup *createXdgShellStablePopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent, CreationSetup creationSetup)
|
2018-10-19 22:21:54 +00:00
|
|
|
{
|
|
|
|
if (!s_waylandConnection.xdgShellStable) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto s = s_waylandConnection.xdgShellStable->createPopup(surface, parentSurface, positioner, parent);
|
|
|
|
if (!s->isValid()) {
|
|
|
|
delete s;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-02-26 13:41:07 +00:00
|
|
|
if (creationSetup == CreationSetup::CreateAndConfigure) {
|
|
|
|
initXdgShellPopup(surface, s);
|
|
|
|
}
|
2018-10-19 22:21:54 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2019-02-26 13:41:07 +00:00
|
|
|
void initXdgShellSurface(KWayland::Client::Surface *surface, KWayland::Client::XdgShellSurface *shellSurface)
|
|
|
|
{
|
|
|
|
//wait for configure
|
|
|
|
QSignalSpy configureRequestedSpy(shellSurface, &KWayland::Client::XdgShellSurface::configureRequested);
|
|
|
|
QVERIFY(configureRequestedSpy.isValid());
|
|
|
|
surface->commit(Surface::CommitFlag::None);
|
|
|
|
QVERIFY(configureRequestedSpy.wait());
|
|
|
|
shellSurface->ackConfigure(configureRequestedSpy.last()[2].toInt());
|
|
|
|
}
|
|
|
|
|
|
|
|
void initXdgShellPopup(KWayland::Client::Surface *surface, KWayland::Client::XdgShellPopup *shellPopup)
|
|
|
|
{
|
|
|
|
//wait for configure
|
|
|
|
QSignalSpy configureRequestedSpy(shellPopup, &KWayland::Client::XdgShellPopup::configureRequested);
|
|
|
|
QVERIFY(configureRequestedSpy.isValid());
|
|
|
|
surface->commit(Surface::CommitFlag::None);
|
|
|
|
QVERIFY(configureRequestedSpy.wait());
|
|
|
|
shellPopup->ackConfigure(configureRequestedSpy.last()[1].toInt());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-22 12:13:37 +00:00
|
|
|
QObject *createShellSurface(ShellSurfaceType type, KWayland::Client::Surface *surface, QObject *parent)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case ShellSurfaceType::WlShell:
|
|
|
|
return createShellSurface(surface, parent);
|
|
|
|
case ShellSurfaceType::XdgShellV5:
|
2019-02-26 13:41:07 +00:00
|
|
|
return createXdgShellV5Surface(surface, parent, CreationSetup::CreateAndConfigure);
|
XdgV6 - Kwin side
Summary:
Adds XDGV6 support for the kwin side.
Popup placement support is limited to the stuff v5 had,
a simple offset, rather than the awesome new positioner.
But Qt doesn't make use of it yet either.
Also ideally we should do all the positioning before sending the first
configure, but again Qt doesn't actually do anything with that anyway.
Also integrate pinging clients
Test Plan: gtk3-demo works nicely.
Reviewers: #plasma, graesslin, mart
Reviewed By: #plasma, graesslin
Subscribers: mart, graesslin, kwin, plasma-devel, #kwin
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6591
2017-09-25 15:37:59 +00:00
|
|
|
case ShellSurfaceType::XdgShellV6:
|
2019-02-26 13:41:07 +00:00
|
|
|
return createXdgShellV6Surface(surface, parent, CreationSetup::CreateAndConfigure);
|
2018-10-15 14:02:53 +00:00
|
|
|
case ShellSurfaceType::XdgShellStable:
|
2019-02-26 13:41:07 +00:00
|
|
|
return createXdgShellStableSurface(surface, parent, CreationSetup::CreateAndConfigure);
|
2016-04-22 12:13:37 +00:00
|
|
|
default:
|
|
|
|
Q_UNREACHABLE();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-26 13:41:07 +00:00
|
|
|
KWayland::Client::XdgShellSurface *createXdgShellSurface(ShellSurfaceType type, KWayland::Client::Surface *surface, QObject *parent, CreationSetup creationSetup)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case ShellSurfaceType::XdgShellV5:
|
|
|
|
return createXdgShellV5Surface(surface, parent, creationSetup);
|
|
|
|
case ShellSurfaceType::XdgShellV6:
|
|
|
|
return createXdgShellV6Surface(surface, parent, creationSetup);
|
|
|
|
case ShellSurfaceType::XdgShellStable:
|
|
|
|
return createXdgShellStableSurface(surface, parent, creationSetup);
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-01 10:37:09 +00:00
|
|
|
bool waitForWindowDestroyed(AbstractClient *client)
|
|
|
|
{
|
|
|
|
QSignalSpy destroyedSpy(client, &QObject::destroyed);
|
|
|
|
if (!destroyedSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return destroyedSpy.wait();
|
|
|
|
}
|
|
|
|
|
2016-08-16 06:19:45 +00:00
|
|
|
bool lockScreen()
|
|
|
|
{
|
|
|
|
if (waylandServer()->isScreenLocked()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QSignalSpy lockStateChangedSpy(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged);
|
|
|
|
if (!lockStateChangedSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ScreenLocker::KSldApp::self()->lock(ScreenLocker::EstablishLock::Immediate);
|
|
|
|
if (lockStateChangedSpy.count() != 1) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-08-16 08:23:37 +00:00
|
|
|
if (!waylandServer()->isScreenLocked()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!ScreenLockerWatcher::self()->isLocked()) {
|
|
|
|
QSignalSpy lockedSpy(ScreenLockerWatcher::self(), &ScreenLockerWatcher::locked);
|
|
|
|
if (!lockedSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!lockedSpy.wait()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!ScreenLockerWatcher::self()->isLocked()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2016-08-16 06:19:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool unlockScreen()
|
|
|
|
{
|
|
|
|
QSignalSpy lockStateChangedSpy(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged);
|
|
|
|
if (!lockStateChangedSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
using namespace ScreenLocker;
|
|
|
|
const auto children = KSldApp::self()->children();
|
|
|
|
for (auto it = children.begin(); it != children.end(); ++it) {
|
|
|
|
if (qstrcmp((*it)->metaObject()->className(), "LogindIntegration") != 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
QMetaObject::invokeMethod(*it, "requestUnlock");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (waylandServer()->isScreenLocked()) {
|
|
|
|
lockStateChangedSpy.wait();
|
|
|
|
}
|
2016-08-16 08:23:37 +00:00
|
|
|
if (waylandServer()->isScreenLocked()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (ScreenLockerWatcher::self()->isLocked()) {
|
|
|
|
QSignalSpy lockedSpy(ScreenLockerWatcher::self(), &ScreenLockerWatcher::locked);
|
|
|
|
if (!lockedSpy.isValid()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!lockedSpy.wait()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (ScreenLockerWatcher::self()->isLocked()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2016-08-16 06:19:45 +00:00
|
|
|
}
|
|
|
|
|
2016-06-30 11:32:54 +00:00
|
|
|
}
|
|
|
|
}
|