kwin/autotests/integration/kwin_wayland_test.cpp
Xaver Hugl ae84480fbf outputconfigurationstore: add new config system
Instead of an external service (like KScreen) storing and restoring output configurations,
with this commit KWin takes over that responsibility. This allows it to, among other things,
generate appropriate configs for new sets of outputs immediately, and take KWin-internal information
about outputs into account when generating them.

CCBUG: 474021
CCBUG: 469653
CCBUG: 466342
CCBUG: 470863
CCBUG: 466556
BUG: 466208
BUG: 455082
BUG: 457430
2023-10-05 20:29:04 +02:00

240 lines
6.9 KiB
C++

/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "kwin_wayland_test.h"
#include "backends/virtual/virtual_backend.h"
#include "compositor_wayland.h"
#include "core/session.h"
#include "effects.h"
#include "inputmethod.h"
#include "placement.h"
#include "pluginmanager.h"
#include "utils/xcbutils.h"
#include "wayland_server.h"
#include "workspace.h"
#include "xwayland/xwayland.h"
#include "xwayland/xwaylandlauncher.h"
#include <KPluginMetaData>
#include <QAbstractEventDispatcher>
#include <QPluginLoader>
#include <QSocketNotifier>
#include <QThread>
#include <QtConcurrentRun>
// system
#include <iostream>
#include <sys/socket.h>
#include <unistd.h>
Q_IMPORT_PLUGIN(KWinIntegrationPlugin)
Q_IMPORT_PLUGIN(KGlobalAccelImpl)
Q_IMPORT_PLUGIN(KWindowSystemKWinPlugin)
Q_IMPORT_PLUGIN(KWinIdleTimePoller)
namespace KWin
{
WaylandTestApplication::WaylandTestApplication(OperationMode mode, int &argc, char **argv)
: Application(mode, argc, argv)
{
QStandardPaths::setTestModeEnabled(true);
// TODO: add a test move to kglobalaccel instead?
QFile{QStandardPaths::locate(QStandardPaths::ConfigLocation, QStringLiteral("kglobalshortcutsrc"))}.remove();
QIcon::setThemeName(QStringLiteral("breeze"));
#if KWIN_BUILD_ACTIVITIES
setUseKActivities(false);
#endif
qputenv("KWIN_COMPOSE", QByteArrayLiteral("Q"));
qputenv("XDG_CURRENT_DESKTOP", QByteArrayLiteral("KDE"));
qunsetenv("XKB_DEFAULT_RULES");
qunsetenv("XKB_DEFAULT_MODEL");
qunsetenv("XKB_DEFAULT_LAYOUT");
qunsetenv("XKB_DEFAULT_VARIANT");
qunsetenv("XKB_DEFAULT_OPTIONS");
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
KConfigGroup windowsGroup = config->group("Windows");
windowsGroup.writeEntry("Placement", Placement::policyToString(PlacementSmart));
windowsGroup.sync();
setConfig(config);
const auto ownPath = libraryPaths().last();
removeLibraryPath(ownPath);
addLibraryPath(ownPath);
setSession(Session::create(Session::Type::Noop));
setOutputBackend(std::make_unique<VirtualBackend>());
WaylandServer::create(this);
setProcessStartupEnvironment(QProcessEnvironment::systemEnvironment());
}
WaylandTestApplication::~WaylandTestApplication()
{
setTerminating();
// need to unload all effects prior to destroying X connection as they might do X calls
// also before destroy Workspace, as effects might call into Workspace
if (effects) {
static_cast<EffectsHandlerImpl *>(effects)->unloadAllEffects();
}
m_xwayland.reset();
destroyVirtualInputDevices();
destroyColorManager();
destroyWorkspace();
destroyInputMethod();
destroyCompositor();
destroyInput();
}
void WaylandTestApplication::createVirtualInputDevices()
{
m_virtualKeyboard = std::make_unique<Test::VirtualInputDevice>();
m_virtualKeyboard->setName(QStringLiteral("Virtual Keyboard 1"));
m_virtualKeyboard->setKeyboard(true);
m_virtualPointer = std::make_unique<Test::VirtualInputDevice>();
m_virtualPointer->setName(QStringLiteral("Virtual Pointer 1"));
m_virtualPointer->setPointer(true);
m_virtualTouch = std::make_unique<Test::VirtualInputDevice>();
m_virtualTouch->setName(QStringLiteral("Virtual Touch 1"));
m_virtualTouch->setTouch(true);
input()->addInputDevice(m_virtualPointer.get());
input()->addInputDevice(m_virtualTouch.get());
input()->addInputDevice(m_virtualKeyboard.get());
}
void WaylandTestApplication::destroyVirtualInputDevices()
{
if (m_virtualPointer) {
input()->removeInputDevice(m_virtualPointer.get());
}
if (m_virtualTouch) {
input()->removeInputDevice(m_virtualTouch.get());
}
if (m_virtualKeyboard) {
input()->removeInputDevice(m_virtualKeyboard.get());
}
}
void WaylandTestApplication::performStartup()
{
if (!m_inputMethodServerToStart.isEmpty()) {
createInputMethod();
if (m_inputMethodServerToStart != QStringLiteral("internal")) {
inputMethod()->setInputMethodCommand(m_inputMethodServerToStart);
inputMethod()->setEnabled(true);
}
}
// first load options - done internally by a different thread
createOptions();
if (!outputBackend()->initialize()) {
std::exit(1);
}
// try creating the Wayland Backend
createInput();
createVirtualInputDevices();
createTabletModeManager();
WaylandCompositor::create();
createWorkspace();
createColorManager();
createPlugins();
connect(Compositor::self(), &Compositor::sceneCreated, this, &WaylandTestApplication::continueStartupWithScene);
}
void WaylandTestApplication::continueStartupWithScene()
{
disconnect(Compositor::self(), &Compositor::sceneCreated, this, &WaylandTestApplication::continueStartupWithScene);
waylandServer()->initWorkspace();
if (!waylandServer()->start()) {
qFatal("Failed to initialize the Wayland server, exiting now");
}
if (operationMode() == OperationModeXwayland) {
m_xwayland = std::make_unique<Xwl::Xwayland>(this);
m_xwayland->init();
}
notifyStarted();
}
Test::VirtualInputDevice *WaylandTestApplication::virtualPointer() const
{
return m_virtualPointer.get();
}
Test::VirtualInputDevice *WaylandTestApplication::virtualKeyboard() const
{
return m_virtualKeyboard.get();
}
Test::VirtualInputDevice *WaylandTestApplication::virtualTouch() const
{
return m_virtualTouch.get();
}
XwaylandInterface *WaylandTestApplication::xwayland() const
{
return m_xwayland.get();
}
Test::FractionalScaleManagerV1::~FractionalScaleManagerV1()
{
destroy();
}
Test::FractionalScaleV1::~FractionalScaleV1()
{
destroy();
}
int Test::FractionalScaleV1::preferredScale()
{
return m_preferredScale;
}
void Test::FractionalScaleV1::wp_fractional_scale_v1_preferred_scale(uint32_t scale)
{
m_preferredScale = scale;
}
void Test::setOutputConfig(const QVector<QRect> &geometries)
{
QVector<VirtualBackend::OutputInfo> converted;
std::transform(geometries.begin(), geometries.end(), std::back_inserter(converted), [](const auto &geometry) {
return VirtualBackend::OutputInfo{
.geometry = geometry,
};
});
static_cast<VirtualBackend *>(kwinApp()->outputBackend())->setVirtualOutputs(converted);
}
void Test::setOutputConfig(const QVector<OutputInfo> &infos)
{
QVector<VirtualBackend::OutputInfo> converted;
std::transform(infos.begin(), infos.end(), std::back_inserter(converted), [](const auto &info) {
return VirtualBackend::OutputInfo{
.geometry = info.geometry,
.scale = info.scale,
.internal = info.internal,
};
});
static_cast<VirtualBackend *>(kwinApp()->outputBackend())->setVirtualOutputs(converted);
}
}
#include "moc_kwin_wayland_test.cpp"