/* SPDX-FileCopyrightText: 2014 Martin Gräßlin 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 #if KWINDOWSYSTEM_HAVE_X11 #include "kstartupinfo.h" #endif #include #include #include #include #include #include #if KWINDOWSYSTEM_HAVE_X11 #include #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 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(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(d); if (!dv2) { return; } dv2->setCurrentToken(token); } #include "moc_kwindowsystem.cpp"