cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
201 lines
5.2 KiB
C++
201 lines
5.2 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
|
*/
|
|
#include "kwindowsystem.h"
|
|
#include "kwindowsystem_debug.h"
|
|
#include "kwindowsystem_dummy_p.h"
|
|
#include "pluginwrapper_p.h"
|
|
|
|
#include <config-kwindowsystem.h>
|
|
|
|
#if KWINDOWSYSTEM_HAVE_X11
|
|
#include "kstartupinfo.h"
|
|
#endif
|
|
|
|
#include <QGuiApplication>
|
|
#include <QMetaMethod>
|
|
#include <QPixmap>
|
|
#include <QPluginLoader>
|
|
#include <QTimer>
|
|
#include <QWindow>
|
|
#if KWINDOWSYSTEM_HAVE_X11
|
|
#include <private/qtx11extras_p.h>
|
|
#endif
|
|
|
|
// QPoint and QSize all have handy / operators which are useful for scaling, positions and sizes for high DPI support
|
|
// QRect does not, so we create one for internal purposes within this class
|
|
inline QRect operator/(const QRect &rectangle, qreal factor)
|
|
{
|
|
return QRect(rectangle.topLeft() / factor, rectangle.size() / factor);
|
|
}
|
|
|
|
class KWindowSystemStaticContainer
|
|
{
|
|
public:
|
|
KWindowSystemStaticContainer()
|
|
{
|
|
d.reset(KWindowSystemPluginWrapper::self().createWindowSystem());
|
|
|
|
if (QCoreApplication::instance()) {
|
|
kwm.moveToThread(QCoreApplication::instance()->thread());
|
|
}
|
|
}
|
|
KWindowSystem kwm;
|
|
std::unique_ptr<KWindowSystemPrivate> d;
|
|
};
|
|
|
|
Q_GLOBAL_STATIC(KWindowSystemStaticContainer, g_kwmInstanceContainer)
|
|
|
|
KWindowSystemPrivate::~KWindowSystemPrivate()
|
|
{
|
|
}
|
|
|
|
void KWindowSystemPrivateDummy::activateWindow(QWindow *win, long time)
|
|
{
|
|
Q_UNUSED(win)
|
|
Q_UNUSED(time)
|
|
}
|
|
|
|
bool KWindowSystemPrivateDummy::showingDesktop()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void KWindowSystemPrivateDummy::setShowingDesktop(bool showing)
|
|
{
|
|
Q_UNUSED(showing);
|
|
}
|
|
|
|
KWindowSystem *KWindowSystem::self()
|
|
{
|
|
return &(g_kwmInstanceContainer()->kwm);
|
|
}
|
|
|
|
KWindowSystemPrivate *KWindowSystem::d_func()
|
|
{
|
|
return g_kwmInstanceContainer()->d.get();
|
|
}
|
|
|
|
void KWindowSystem::activateWindow(QWindow *win, long time)
|
|
{
|
|
Q_D(KWindowSystem);
|
|
d->activateWindow(win, time);
|
|
}
|
|
|
|
void KWindowSystem::setMainWindow(QWindow *subWindow, WId mainWindowId)
|
|
{
|
|
QWindow *mainWindow = QWindow::fromWinId(mainWindowId);
|
|
if (mainWindow) { // foreign windows not supported on all platforms
|
|
subWindow->setTransientParent(mainWindow);
|
|
|
|
// mainWindow is not the child of any object, so make sure it gets deleted at some point
|
|
connect(subWindow, &QObject::destroyed, mainWindow, &QObject::deleteLater);
|
|
}
|
|
}
|
|
|
|
void KWindowSystem::setMainWindow(QWindow *subWindow, const QString &mainWindowId)
|
|
{
|
|
Q_D(KWindowSystem);
|
|
if (isPlatformWayland()) {
|
|
if (auto dv2 = dynamic_cast<KWindowSystemPrivateV2 *>(d)) {
|
|
dv2->setMainWindow(subWindow, mainWindowId);
|
|
}
|
|
} else {
|
|
bool ok = false;
|
|
// base 0 means "C style" parsing with 0x for base 16, 0b for base 2, etc.
|
|
WId wid = mainWindowId.toULongLong(&ok, 0);
|
|
if (ok) {
|
|
setMainWindow(subWindow, wid);
|
|
} else {
|
|
qCWarning(LOG_KWINDOWSYSTEM) << "Failed to convert" << mainWindowId << "to WId";
|
|
}
|
|
}
|
|
}
|
|
|
|
bool KWindowSystem::showingDesktop()
|
|
{
|
|
Q_D(KWindowSystem);
|
|
return d->showingDesktop();
|
|
}
|
|
|
|
void KWindowSystem::setShowingDesktop(bool showing)
|
|
{
|
|
Q_D(KWindowSystem);
|
|
return d->setShowingDesktop(showing);
|
|
}
|
|
|
|
static inline KWindowSystem::Platform initPlatform()
|
|
{
|
|
auto platformName = QGuiApplication::platformName();
|
|
if (platformName == QLatin1String("flatpak")) {
|
|
// here we cannot know what is the actual windowing system, let's try it's env variable
|
|
const auto flatpakPlatform = QString::fromLocal8Bit(qgetenv("QT_QPA_FLATPAK_PLATFORM"));
|
|
if (!flatpakPlatform.isEmpty()) {
|
|
platformName = flatpakPlatform;
|
|
}
|
|
}
|
|
#if KWINDOWSYSTEM_HAVE_X11
|
|
if (platformName == QLatin1String("xcb")) {
|
|
return KWindowSystem::Platform::X11;
|
|
}
|
|
#endif
|
|
if (platformName.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) {
|
|
return KWindowSystem::Platform::Wayland;
|
|
}
|
|
return KWindowSystem::Platform::Unknown;
|
|
}
|
|
|
|
KWindowSystem::Platform KWindowSystem::platform()
|
|
{
|
|
static Platform s_platform = initPlatform();
|
|
return s_platform;
|
|
}
|
|
|
|
bool KWindowSystem::isPlatformX11()
|
|
{
|
|
return platform() == Platform::X11;
|
|
}
|
|
|
|
bool KWindowSystem::isPlatformWayland()
|
|
{
|
|
return platform() == Platform::Wayland;
|
|
}
|
|
|
|
void KWindowSystem::updateStartupId(QWindow *window)
|
|
{
|
|
// clang-format off
|
|
// TODO: move to a new KWindowSystemPrivate interface
|
|
#if KWINDOWSYSTEM_HAVE_X11
|
|
if (isPlatformX11()) {
|
|
const QByteArray startupId = QX11Info::nextStartupId();
|
|
if (!startupId.isEmpty()) {
|
|
KStartupInfo::setNewStartupId(window, startupId);
|
|
}
|
|
} else
|
|
#else
|
|
Q_UNUSED(window);
|
|
#endif
|
|
if (isPlatformWayland()) {
|
|
const QString token = qEnvironmentVariable("XDG_ACTIVATION_TOKEN");
|
|
if (!token.isEmpty()) {
|
|
setCurrentXdgActivationToken(token);
|
|
qunsetenv("XDG_ACTIVATION_TOKEN");
|
|
}
|
|
}
|
|
// clang-format on
|
|
}
|
|
|
|
void KWindowSystem::setCurrentXdgActivationToken(const QString &token)
|
|
{
|
|
Q_D(KWindowSystem);
|
|
auto dv2 = dynamic_cast<KWindowSystemPrivateV2 *>(d);
|
|
if (!dv2) {
|
|
return;
|
|
}
|
|
dv2->setCurrentToken(token);
|
|
}
|
|
|
|
#include "moc_kwindowsystem.cpp"
|