File indexing completed on 2024-04-21 03:59:28
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 #include "kwindowsystem.h" 0007 #include "kwindowsystem_debug.h" 0008 #include "kwindowsystem_dummy_p.h" 0009 #include "pluginwrapper_p.h" 0010 0011 #include <config-kwindowsystem.h> 0012 0013 #if KWINDOWSYSTEM_HAVE_X11 0014 #include "kstartupinfo.h" 0015 #endif 0016 0017 #include <QGuiApplication> 0018 #include <QMetaMethod> 0019 #include <QPixmap> 0020 #include <QPluginLoader> 0021 #include <QTimer> 0022 #include <QWindow> 0023 #if KWINDOWSYSTEM_HAVE_X11 0024 #include <private/qtx11extras_p.h> 0025 #endif 0026 0027 // QPoint and QSize all have handy / operators which are useful for scaling, positions and sizes for high DPI support 0028 // QRect does not, so we create one for internal purposes within this class 0029 inline QRect operator/(const QRect &rectangle, qreal factor) 0030 { 0031 return QRect(rectangle.topLeft() / factor, rectangle.size() / factor); 0032 } 0033 0034 class KWindowSystemStaticContainer 0035 { 0036 public: 0037 KWindowSystemStaticContainer() 0038 { 0039 d.reset(KWindowSystemPluginWrapper::self().createWindowSystem()); 0040 0041 if (QCoreApplication::instance()) { 0042 kwm.moveToThread(QCoreApplication::instance()->thread()); 0043 } 0044 } 0045 KWindowSystem kwm; 0046 std::unique_ptr<KWindowSystemPrivate> d; 0047 }; 0048 0049 Q_GLOBAL_STATIC(KWindowSystemStaticContainer, g_kwmInstanceContainer) 0050 0051 KWindowSystemPrivate::~KWindowSystemPrivate() 0052 { 0053 } 0054 0055 void KWindowSystemPrivateDummy::activateWindow(QWindow *win, long time) 0056 { 0057 Q_UNUSED(win) 0058 Q_UNUSED(time) 0059 } 0060 0061 bool KWindowSystemPrivateDummy::showingDesktop() 0062 { 0063 return false; 0064 } 0065 0066 void KWindowSystemPrivateDummy::setShowingDesktop(bool showing) 0067 { 0068 Q_UNUSED(showing); 0069 } 0070 0071 KWindowSystem *KWindowSystem::self() 0072 { 0073 return &(g_kwmInstanceContainer()->kwm); 0074 } 0075 0076 KWindowSystemPrivate *KWindowSystem::d_func() 0077 { 0078 return g_kwmInstanceContainer()->d.get(); 0079 } 0080 0081 void KWindowSystem::activateWindow(QWindow *win, long time) 0082 { 0083 Q_D(KWindowSystem); 0084 d->activateWindow(win, time); 0085 } 0086 0087 void KWindowSystem::setMainWindow(QWindow *subWindow, WId mainWindowId) 0088 { 0089 QWindow *mainWindow = QWindow::fromWinId(mainWindowId); 0090 if (mainWindow) { // foreign windows not supported on all platforms 0091 subWindow->setTransientParent(mainWindow); 0092 0093 // mainWindow is not the child of any object, so make sure it gets deleted at some point 0094 connect(subWindow, &QObject::destroyed, mainWindow, &QObject::deleteLater); 0095 } 0096 } 0097 0098 void KWindowSystem::setMainWindow(QWindow *subWindow, const QString &mainWindowId) 0099 { 0100 Q_D(KWindowSystem); 0101 if (isPlatformWayland()) { 0102 if (auto dv2 = dynamic_cast<KWindowSystemPrivateV2 *>(d)) { 0103 dv2->setMainWindow(subWindow, mainWindowId); 0104 } 0105 } else { 0106 bool ok = false; 0107 // base 0 means "C style" parsing with 0x for base 16, 0b for base 2, etc. 0108 WId wid = mainWindowId.toULongLong(&ok, 0); 0109 if (ok) { 0110 setMainWindow(subWindow, wid); 0111 } else { 0112 qCWarning(LOG_KWINDOWSYSTEM) << "Failed to convert" << mainWindowId << "to WId"; 0113 } 0114 } 0115 } 0116 0117 bool KWindowSystem::showingDesktop() 0118 { 0119 Q_D(KWindowSystem); 0120 return d->showingDesktop(); 0121 } 0122 0123 void KWindowSystem::setShowingDesktop(bool showing) 0124 { 0125 Q_D(KWindowSystem); 0126 return d->setShowingDesktop(showing); 0127 } 0128 0129 static inline KWindowSystem::Platform initPlatform() 0130 { 0131 auto platformName = QGuiApplication::platformName(); 0132 if (platformName == QLatin1String("flatpak")) { 0133 // here we cannot know what is the actual windowing system, let's try it's env variable 0134 const auto flatpakPlatform = QString::fromLocal8Bit(qgetenv("QT_QPA_FLATPAK_PLATFORM")); 0135 if (!flatpakPlatform.isEmpty()) { 0136 platformName = flatpakPlatform; 0137 } 0138 } 0139 #if KWINDOWSYSTEM_HAVE_X11 0140 if (platformName == QLatin1String("xcb")) { 0141 return KWindowSystem::Platform::X11; 0142 } 0143 #endif 0144 if (platformName.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) { 0145 return KWindowSystem::Platform::Wayland; 0146 } 0147 return KWindowSystem::Platform::Unknown; 0148 } 0149 0150 KWindowSystem::Platform KWindowSystem::platform() 0151 { 0152 static Platform s_platform = initPlatform(); 0153 return s_platform; 0154 } 0155 0156 bool KWindowSystem::isPlatformX11() 0157 { 0158 return platform() == Platform::X11; 0159 } 0160 0161 bool KWindowSystem::isPlatformWayland() 0162 { 0163 return platform() == Platform::Wayland; 0164 } 0165 0166 void KWindowSystem::updateStartupId(QWindow *window) 0167 { 0168 // clang-format off 0169 // TODO: move to a new KWindowSystemPrivate interface 0170 #if KWINDOWSYSTEM_HAVE_X11 0171 if (isPlatformX11()) { 0172 const QByteArray startupId = QX11Info::nextStartupId(); 0173 if (!startupId.isEmpty()) { 0174 KStartupInfo::setNewStartupId(window, startupId); 0175 } 0176 } else 0177 #else 0178 Q_UNUSED(window); 0179 #endif 0180 if (isPlatformWayland()) { 0181 const QString token = qEnvironmentVariable("XDG_ACTIVATION_TOKEN"); 0182 if (!token.isEmpty()) { 0183 setCurrentXdgActivationToken(token); 0184 qunsetenv("XDG_ACTIVATION_TOKEN"); 0185 } 0186 } 0187 // clang-format on 0188 } 0189 0190 void KWindowSystem::setCurrentXdgActivationToken(const QString &token) 0191 { 0192 Q_D(KWindowSystem); 0193 auto dv2 = dynamic_cast<KWindowSystemPrivateV2 *>(d); 0194 if (!dv2) { 0195 return; 0196 } 0197 dv2->setCurrentToken(token); 0198 } 0199 0200 #include "moc_kwindowsystem.cpp"