File indexing completed on 2024-05-12 17:00:19
0001 /* 0002 SPDX-FileCopyrightText: 2015 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 "windowsystem.h" 0007 #include "logging.h" 0008 #include "waylandintegration.h" 0009 #include "waylandxdgactivationv1_p.h" 0010 0011 #include <KWindowSystem> 0012 0013 #include <KWayland/Client/connection_thread.h> 0014 #include <KWayland/Client/plasmashell.h> 0015 #include <KWayland/Client/plasmawindowmanagement.h> 0016 #include <KWayland/Client/registry.h> 0017 #include <KWayland/Client/seat.h> 0018 #include <KWayland/Client/surface.h> 0019 0020 #include <QGuiApplication> 0021 #include <QPixmap> 0022 #include <QPoint> 0023 #include <QString> 0024 #include <QWindow> 0025 #include <private/qwaylanddisplay_p.h> 0026 #include <private/qwaylandinputdevice_p.h> 0027 #include <private/qwaylandwindow_p.h> 0028 #include <qpa/qplatformnativeinterface.h> 0029 0030 using namespace KWayland::Client; 0031 0032 WindowSystem::WindowSystem() 0033 : QObject() 0034 , KWindowSystemPrivateV2() 0035 , m_lastToken(qEnvironmentVariable("XDG_ACTIVATION_TOKEN")) 0036 { 0037 } 0038 0039 void WindowSystem::activateWindow(WId win, long int time) 0040 { 0041 Q_UNUSED(time); 0042 Surface *s = Surface::fromQtWinId(win); 0043 if (!s) { 0044 return; 0045 } 0046 WaylandXdgActivationV1 *activation = WaylandIntegration::self()->activation(); 0047 if (!activation) { 0048 return; 0049 } 0050 activation->activate(m_lastToken, *s); 0051 } 0052 0053 void WindowSystem::forceActiveWindow(WId win, long int time) 0054 { 0055 activateWindow(win, time); 0056 } 0057 0058 void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString &app_id) 0059 { 0060 wl_surface *wlSurface = [](QWindow *window) -> wl_surface * { 0061 if (!window) { 0062 return nullptr; 0063 } 0064 0065 QPlatformNativeInterface *native = qGuiApp->platformNativeInterface(); 0066 if (!native) { 0067 return nullptr; 0068 } 0069 window->create(); 0070 return reinterpret_cast<wl_surface *>(native->nativeResourceForWindow(QByteArrayLiteral("surface"), window)); 0071 }(window); 0072 0073 WaylandXdgActivationV1 *activation = WaylandIntegration::self()->activation(); 0074 if (!activation) { 0075 // Ensure that xdgActivationTokenArrived is always emitted asynchronously 0076 QTimer::singleShot(0, [serial] { 0077 Q_EMIT KWindowSystem::self()->xdgActivationTokenArrived(serial, {}); 0078 }); 0079 return; 0080 } 0081 0082 auto waylandWindow = window ? dynamic_cast<QtWaylandClient::QWaylandWindow *>(window->handle()) : nullptr; 0083 auto seat = waylandWindow ? waylandWindow->display()->defaultInputDevice()->wl_seat() : nullptr; 0084 auto tokenReq = activation->requestXdgActivationToken(seat, wlSurface, serial, app_id); 0085 connect(tokenReq, &WaylandXdgActivationTokenV1::failed, KWindowSystem::self(), [serial, app_id]() { 0086 Q_EMIT KWindowSystem::self()->xdgActivationTokenArrived(serial, {}); 0087 }); 0088 connect(tokenReq, &WaylandXdgActivationTokenV1::done, KWindowSystem::self(), [serial](const QString &token) { 0089 Q_EMIT KWindowSystem::self()->xdgActivationTokenArrived(serial, token); 0090 }); 0091 } 0092 0093 void WindowSystem::setCurrentToken(const QString &token) 0094 { 0095 m_lastToken = token; 0096 } 0097 0098 quint32 WindowSystem::lastInputSerial(QWindow *window) 0099 { 0100 auto waylandWindow = window ? dynamic_cast<QtWaylandClient::QWaylandWindow *>(window->handle()) : nullptr; 0101 if (!waylandWindow) { 0102 // Should never get here 0103 return 0; 0104 } 0105 return waylandWindow->display()->lastInputSerial(); 0106 } 0107 0108 WId WindowSystem::activeWindow() 0109 { 0110 qCDebug(KWAYLAND_KWS) << "This plugin does not support querying the active window"; 0111 return 0; 0112 } 0113 0114 bool WindowSystem::allowedActionsSupported() 0115 { 0116 return false; 0117 } 0118 0119 void WindowSystem::allowExternalProcessWindowActivation(int pid) 0120 { 0121 Q_UNUSED(pid) 0122 } 0123 0124 bool WindowSystem::compositingActive() 0125 { 0126 // wayland is always composited 0127 return true; 0128 } 0129 0130 void WindowSystem::connectNotify(const QMetaMethod &signal) 0131 { 0132 Q_UNUSED(signal) 0133 } 0134 0135 QPoint WindowSystem::constrainViewportRelativePosition(const QPoint &pos) 0136 { 0137 Q_UNUSED(pos) 0138 qCDebug(KWAYLAND_KWS) << "This plugin does not support viewport positions"; 0139 return QPoint(); 0140 } 0141 0142 int WindowSystem::currentDesktop() 0143 { 0144 qCDebug(KWAYLAND_KWS) << "This plugin does not support virtual desktops"; 0145 return 0; 0146 } 0147 0148 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 101) 0149 void WindowSystem::demandAttention(WId win, bool set) 0150 { 0151 Q_UNUSED(win) 0152 Q_UNUSED(set) 0153 qCDebug(KWAYLAND_KWS) << "This plugin does not support demanding attention"; 0154 } 0155 #endif 0156 0157 QString WindowSystem::desktopName(int desktop) 0158 { 0159 Q_UNUSED(desktop) 0160 qCDebug(KWAYLAND_KWS) << "This plugin does not support virtual desktops"; 0161 return QString(); 0162 } 0163 0164 QPoint WindowSystem::desktopToViewport(int desktop, bool absolute) 0165 { 0166 Q_UNUSED(desktop) 0167 Q_UNUSED(absolute) 0168 qCDebug(KWAYLAND_KWS) << "This plugin does not support viewport positions"; 0169 return QPoint(); 0170 } 0171 0172 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 0) 0173 WId WindowSystem::groupLeader(WId window) 0174 { 0175 Q_UNUSED(window) 0176 qCDebug(KWAYLAND_KWS) << "This plugin does not support group leader"; 0177 return 0; 0178 } 0179 #endif 0180 0181 bool WindowSystem::icccmCompliantMappingState() 0182 { 0183 return false; 0184 } 0185 0186 QPixmap WindowSystem::icon(WId win, int width, int height, bool scale, int flags) 0187 { 0188 Q_UNUSED(win) 0189 Q_UNUSED(width) 0190 Q_UNUSED(height) 0191 Q_UNUSED(scale) 0192 Q_UNUSED(flags) 0193 qCDebug(KWAYLAND_KWS) << "This plugin does not support getting window icons"; 0194 return QPixmap(); 0195 } 0196 0197 void WindowSystem::lowerWindow(WId win) 0198 { 0199 Q_UNUSED(win) 0200 qCDebug(KWAYLAND_KWS) << "This plugin does not support lower window"; 0201 } 0202 0203 bool WindowSystem::mapViewport() 0204 { 0205 qCDebug(KWAYLAND_KWS) << "This plugin does not support viewport positions"; 0206 return false; 0207 } 0208 0209 void WindowSystem::minimizeWindow(WId win) 0210 { 0211 Q_UNUSED(win) 0212 qCDebug(KWAYLAND_KWS) << "This plugin does not support minimizing windows"; 0213 } 0214 0215 void WindowSystem::unminimizeWindow(WId win) 0216 { 0217 Q_UNUSED(win) 0218 qCDebug(KWAYLAND_KWS) << "This plugin does not support unminimizing windows"; 0219 } 0220 0221 int WindowSystem::numberOfDesktops() 0222 { 0223 qCDebug(KWAYLAND_KWS) << "This plugin does not support virtual desktops"; 0224 return 1; 0225 } 0226 0227 void WindowSystem::raiseWindow(WId win) 0228 { 0229 Q_UNUSED(win) 0230 qCDebug(KWAYLAND_KWS) << "This plugin does not support raising windows"; 0231 } 0232 0233 QString WindowSystem::readNameProperty(WId window, long unsigned int atom) 0234 { 0235 Q_UNUSED(window) 0236 Q_UNUSED(atom) 0237 qCDebug(KWAYLAND_KWS) << "This plugin does not support reading X11 properties"; 0238 return QString(); 0239 } 0240 0241 void WindowSystem::setBlockingCompositing(WId window, bool active) 0242 { 0243 Q_UNUSED(window) 0244 Q_UNUSED(active) 0245 qCDebug(KWAYLAND_KWS) << "This plugin does not support blocking compositing"; 0246 } 0247 0248 void WindowSystem::setCurrentDesktop(int desktop) 0249 { 0250 Q_UNUSED(desktop) 0251 qCDebug(KWAYLAND_KWS) << "This plugin does not support virtual desktops"; 0252 } 0253 0254 void WindowSystem::setDesktopName(int desktop, const QString &name) 0255 { 0256 Q_UNUSED(desktop) 0257 Q_UNUSED(name) 0258 qCDebug(KWAYLAND_KWS) << "This plugin does not support virtual desktops"; 0259 } 0260 0261 void WindowSystem::setExtendedStrut(WId win, 0262 int left_width, 0263 int left_start, 0264 int left_end, 0265 int right_width, 0266 int right_start, 0267 int right_end, 0268 int top_width, 0269 int top_start, 0270 int top_end, 0271 int bottom_width, 0272 int bottom_start, 0273 int bottom_end) 0274 { 0275 Q_UNUSED(win) 0276 Q_UNUSED(left_width) 0277 Q_UNUSED(left_start) 0278 Q_UNUSED(left_end) 0279 Q_UNUSED(right_width) 0280 Q_UNUSED(right_start) 0281 Q_UNUSED(right_end) 0282 Q_UNUSED(top_width) 0283 Q_UNUSED(top_start) 0284 Q_UNUSED(top_end) 0285 Q_UNUSED(bottom_width) 0286 Q_UNUSED(bottom_start) 0287 Q_UNUSED(bottom_end) 0288 qCDebug(KWAYLAND_KWS) << "This plugin does not support window struts"; 0289 } 0290 0291 void WindowSystem::setStrut(WId win, int left, int right, int top, int bottom) 0292 { 0293 Q_UNUSED(win) 0294 Q_UNUSED(left) 0295 Q_UNUSED(right) 0296 Q_UNUSED(top) 0297 Q_UNUSED(bottom) 0298 qCDebug(KWAYLAND_KWS) << "This plugin does not support window struts"; 0299 } 0300 0301 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 101) 0302 void WindowSystem::setIcons(WId win, const QPixmap &icon, const QPixmap &miniIcon) 0303 { 0304 Q_UNUSED(win) 0305 Q_UNUSED(icon) 0306 Q_UNUSED(miniIcon) 0307 qCDebug(KWAYLAND_KWS) << "This plugin does not support setting window icons"; 0308 } 0309 #endif 0310 0311 void WindowSystem::setOnActivities(WId win, const QStringList &activities) 0312 { 0313 Q_UNUSED(win) 0314 Q_UNUSED(activities) 0315 qCDebug(KWAYLAND_KWS) << "This plugin does not support activities"; 0316 } 0317 0318 void WindowSystem::setOnAllDesktops(WId win, bool b) 0319 { 0320 Q_UNUSED(win) 0321 Q_UNUSED(b) 0322 qCDebug(KWAYLAND_KWS) << "This plugin does not support setting window on all desktops"; 0323 } 0324 0325 void WindowSystem::setOnDesktop(WId win, int desktop) 0326 { 0327 Q_UNUSED(win) 0328 Q_UNUSED(desktop) 0329 qCDebug(KWAYLAND_KWS) << "This plugin does not support setting window on a specific desktop"; 0330 } 0331 0332 void WindowSystem::setShowingDesktop(bool showing) 0333 { 0334 if (!WaylandIntegration::self()->plasmaWindowManagement()) { 0335 return; 0336 } 0337 WaylandIntegration::self()->plasmaWindowManagement()->setShowingDesktop(showing); 0338 } 0339 0340 void WindowSystem::clearState(WId win, NET::States state) 0341 { 0342 Surface *s = Surface::fromQtWinId(win); 0343 if (!s) { 0344 return; 0345 } 0346 0347 KWayland::Client::PlasmaShellSurface *plasmaShellSurface = nullptr; 0348 0349 if (state & NET::SkipTaskbar || state & NET::SkipSwitcher) { 0350 if (!WaylandIntegration::self()->waylandPlasmaShell()) { 0351 return; 0352 } 0353 plasmaShellSurface = PlasmaShellSurface::get(s); 0354 if (!plasmaShellSurface) { 0355 plasmaShellSurface = WaylandIntegration::self()->waylandPlasmaShell()->createSurface(s, this); 0356 } 0357 if (!plasmaShellSurface) { 0358 return; 0359 } 0360 } 0361 0362 if (state & NET::SkipTaskbar) { 0363 plasmaShellSurface->setSkipTaskbar(false); 0364 } 0365 0366 if (state & NET::SkipSwitcher) { 0367 plasmaShellSurface->setSkipSwitcher(false); 0368 } 0369 0370 if (state & NET::Max) { 0371 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Max window state"; 0372 } 0373 if (state & NET::FullScreen) { 0374 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing FullScreen window state"; 0375 } 0376 if (state & NET::Modal) { 0377 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Modal window state"; 0378 } 0379 if (state & NET::Sticky) { 0380 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Sticky window state"; 0381 } 0382 if (state & NET::Shaded) { 0383 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Shaded window state"; 0384 } 0385 if (state & NET::KeepAbove) { 0386 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing KeepAbove window state"; 0387 } 0388 if (state & NET::KeepAbove) { 0389 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing StaysOnTop window state"; 0390 } 0391 if (state & NET::SkipPager) { 0392 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing SkipPager window state"; 0393 } 0394 if (state & NET::Hidden) { 0395 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Hidden window state"; 0396 } 0397 if (state & NET::KeepBelow) { 0398 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing KeepBelow window state"; 0399 } 0400 if (state & NET::DemandsAttention) { 0401 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing DemandsAttention window state"; 0402 } 0403 } 0404 0405 void WindowSystem::setState(WId win, NET::States state) 0406 { 0407 Surface *s = Surface::fromQtWinId(win); 0408 if (!s) { 0409 return; 0410 } 0411 0412 KWayland::Client::PlasmaShellSurface *plasmaShellSurface = nullptr; 0413 0414 if (state & NET::SkipTaskbar || state & NET::SkipSwitcher) { 0415 if (!WaylandIntegration::self()->waylandPlasmaShell()) { 0416 return; 0417 } 0418 plasmaShellSurface = PlasmaShellSurface::get(s); 0419 if (!plasmaShellSurface) { 0420 plasmaShellSurface = WaylandIntegration::self()->waylandPlasmaShell()->createSurface(s, this); 0421 } 0422 if (!plasmaShellSurface) { 0423 return; 0424 } 0425 } 0426 0427 if (state & NET::SkipTaskbar) { 0428 plasmaShellSurface->setSkipTaskbar(true); 0429 } 0430 0431 if (state & NET::SkipSwitcher) { 0432 plasmaShellSurface->setSkipSwitcher(true); 0433 } 0434 0435 if (state & NET::Max) { 0436 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Max window state"; 0437 } 0438 if (state & NET::FullScreen) { 0439 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing FullScreen window state"; 0440 } 0441 if (state & NET::Modal) { 0442 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Modal window state"; 0443 } 0444 if (state & NET::Sticky) { 0445 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Sticky window state"; 0446 } 0447 if (state & NET::Shaded) { 0448 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Shaded window state"; 0449 } 0450 if (state & NET::KeepAbove) { 0451 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing KeepAbove window state"; 0452 } 0453 if (state & NET::KeepAbove) { 0454 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing StaysOnTop window state"; 0455 } 0456 if (state & NET::SkipPager) { 0457 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing SkipPager window state"; 0458 } 0459 if (state & NET::Hidden) { 0460 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing Hidden window state"; 0461 } 0462 if (state & NET::KeepBelow) { 0463 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing KeepBelow window state"; 0464 } 0465 if (state & NET::DemandsAttention) { 0466 qCDebug(KWAYLAND_KWS) << "This plugin does not support changing DemandsAttention window state"; 0467 } 0468 } 0469 0470 void WindowSystem::setType(WId win, NET::WindowType windowType) 0471 { 0472 if (!WaylandIntegration::self()->waylandPlasmaShell()) { 0473 return; 0474 } 0475 KWayland::Client::PlasmaShellSurface::Role role; 0476 0477 switch (windowType) { 0478 case NET::Normal: 0479 role = KWayland::Client::PlasmaShellSurface::Role::Normal; 0480 break; 0481 case NET::Desktop: 0482 role = KWayland::Client::PlasmaShellSurface::Role::Desktop; 0483 break; 0484 case NET::Dock: 0485 role = KWayland::Client::PlasmaShellSurface::Role::Panel; 0486 break; 0487 case NET::OnScreenDisplay: 0488 role = KWayland::Client::PlasmaShellSurface::Role::OnScreenDisplay; 0489 break; 0490 case NET::Notification: 0491 role = KWayland::Client::PlasmaShellSurface::Role::Notification; 0492 break; 0493 case NET::Tooltip: 0494 case NET::PopupMenu: 0495 role = KWayland::Client::PlasmaShellSurface::Role::ToolTip; 0496 break; 0497 case NET::CriticalNotification: 0498 role = KWayland::Client::PlasmaShellSurface::Role::CriticalNotification; 0499 break; 0500 default: 0501 return; 0502 } 0503 Surface *s = Surface::fromQtWinId(win); 0504 if (!s) { 0505 return; 0506 } 0507 KWayland::Client::PlasmaShellSurface *shellSurface = WaylandIntegration::self()->waylandPlasmaShell()->createSurface(s, this); 0508 0509 shellSurface->setRole(role); 0510 } 0511 0512 void WindowSystem::setUserTime(WId win, long int time) 0513 { 0514 Q_UNUSED(win) 0515 Q_UNUSED(time) 0516 qCDebug(KWAYLAND_KWS) << "This plugin does not support setting user type"; 0517 } 0518 0519 bool WindowSystem::showingDesktop() 0520 { 0521 if (!WaylandIntegration::self()->plasmaWindowManagement()) { 0522 return false; 0523 } 0524 return WaylandIntegration::self()->plasmaWindowManagement()->isShowingDesktop(); 0525 } 0526 0527 QList<WId> WindowSystem::stackingOrder() 0528 { 0529 qCDebug(KWAYLAND_KWS) << "This plugin does not support getting windows"; 0530 return QList<WId>(); 0531 } 0532 0533 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 0) 0534 WId WindowSystem::transientFor(WId window) 0535 { 0536 Q_UNUSED(window) 0537 qCDebug(KWAYLAND_KWS) << "This plugin does not support transient for windows"; 0538 return 0; 0539 } 0540 #endif 0541 0542 int WindowSystem::viewportToDesktop(const QPoint &pos) 0543 { 0544 Q_UNUSED(pos) 0545 qCDebug(KWAYLAND_KWS) << "This plugin does not support viewports"; 0546 return 0; 0547 } 0548 0549 int WindowSystem::viewportWindowToDesktop(const QRect &r) 0550 { 0551 Q_UNUSED(r) 0552 qCDebug(KWAYLAND_KWS) << "This plugin does not support viewports"; 0553 return 0; 0554 } 0555 0556 QList<WId> WindowSystem::windows() 0557 { 0558 return stackingOrder(); 0559 } 0560 0561 QRect WindowSystem::workArea(const QList<WId> &excludes, int desktop) 0562 { 0563 Q_UNUSED(excludes) 0564 Q_UNUSED(desktop) 0565 qCDebug(KWAYLAND_KWS) << "This plugin does not support work area"; 0566 return QRect(); 0567 } 0568 0569 QRect WindowSystem::workArea(int desktop) 0570 { 0571 Q_UNUSED(desktop) 0572 qCDebug(KWAYLAND_KWS) << "This plugin does not support work area"; 0573 return QRect(); 0574 }