File indexing completed on 2025-03-16 11:21:24
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2010 Rohan Prabhu <rohan@rohanprabhu.com> 0006 SPDX-FileCopyrightText: 2011, 2012 Martin Gräßlin <mgraesslin@kde.org> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "workspace_wrapper.h" 0012 #include "core/output.h" 0013 #include "core/outputbackend.h" 0014 #include "cursor.h" 0015 #include "outline.h" 0016 #include "tiles/tilemanager.h" 0017 #include "virtualdesktops.h" 0018 #include "workspace.h" 0019 #include "x11window.h" 0020 #if KWIN_BUILD_ACTIVITIES 0021 #include "activities.h" 0022 #endif 0023 0024 #include <QApplication> 0025 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0026 #include <QDesktopWidget> 0027 #endif 0028 0029 namespace KWin 0030 { 0031 0032 WorkspaceWrapper::WorkspaceWrapper(QObject *parent) 0033 : QObject(parent) 0034 { 0035 KWin::Workspace *ws = KWin::Workspace::self(); 0036 KWin::VirtualDesktopManager *vds = KWin::VirtualDesktopManager::self(); 0037 connect(ws, &Workspace::desktopPresenceChanged, this, &WorkspaceWrapper::desktopPresenceChanged); 0038 connect(ws, &Workspace::currentDesktopChanged, this, &WorkspaceWrapper::currentDesktopChanged); 0039 connect(ws, &Workspace::windowAdded, this, &WorkspaceWrapper::clientAdded); 0040 connect(ws, &Workspace::windowAdded, this, &WorkspaceWrapper::setupClientConnections); 0041 connect(ws, &Workspace::windowRemoved, this, &WorkspaceWrapper::clientRemoved); 0042 connect(ws, &Workspace::windowActivated, this, &WorkspaceWrapper::clientActivated); 0043 connect(vds, &VirtualDesktopManager::countChanged, this, &WorkspaceWrapper::numberDesktopsChanged); 0044 connect(vds, &VirtualDesktopManager::layoutChanged, this, &WorkspaceWrapper::desktopLayoutChanged); 0045 connect(vds, &VirtualDesktopManager::currentChanged, this, &WorkspaceWrapper::currentVirtualDesktopChanged); 0046 connect(ws, &Workspace::windowDemandsAttentionChanged, this, &WorkspaceWrapper::clientDemandsAttentionChanged); 0047 #if KWIN_BUILD_ACTIVITIES 0048 if (KWin::Activities *activities = ws->activities()) { 0049 connect(activities, &Activities::currentChanged, this, &WorkspaceWrapper::currentActivityChanged); 0050 connect(activities, &Activities::added, this, &WorkspaceWrapper::activitiesChanged); 0051 connect(activities, &Activities::added, this, &WorkspaceWrapper::activityAdded); 0052 connect(activities, &Activities::removed, this, &WorkspaceWrapper::activitiesChanged); 0053 connect(activities, &Activities::removed, this, &WorkspaceWrapper::activityRemoved); 0054 } 0055 #endif 0056 connect(ws, &Workspace::geometryChanged, this, &WorkspaceWrapper::virtualScreenSizeChanged); 0057 connect(ws, &Workspace::geometryChanged, this, &WorkspaceWrapper::virtualScreenGeometryChanged); 0058 connect(ws, &Workspace::outputAdded, this, [this]() { 0059 Q_EMIT numberScreensChanged(numScreens()); 0060 }); 0061 connect(ws, &Workspace::outputRemoved, this, [this]() { 0062 Q_EMIT numberScreensChanged(numScreens()); 0063 }); 0064 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0065 connect(QApplication::desktop(), &QDesktopWidget::resized, this, &WorkspaceWrapper::screenResized); 0066 #endif 0067 connect(Cursors::self()->mouse(), &Cursor::posChanged, this, &WorkspaceWrapper::cursorPosChanged); 0068 0069 const QList<Window *> clients = ws->allClientList(); 0070 for (Window *client : clients) { 0071 setupClientConnections(client); 0072 } 0073 } 0074 0075 int WorkspaceWrapper::currentDesktop() const 0076 { 0077 return VirtualDesktopManager::self()->current(); 0078 } 0079 0080 VirtualDesktop *WorkspaceWrapper::currentVirtualDesktop() const 0081 { 0082 return VirtualDesktopManager::self()->currentDesktop(); 0083 } 0084 0085 int WorkspaceWrapper::numberOfDesktops() const 0086 { 0087 return VirtualDesktopManager::self()->count(); 0088 } 0089 0090 void WorkspaceWrapper::setCurrentDesktop(int desktop) 0091 { 0092 VirtualDesktopManager::self()->setCurrent(desktop); 0093 } 0094 0095 void WorkspaceWrapper::setCurrentVirtualDesktop(VirtualDesktop *desktop) 0096 { 0097 VirtualDesktopManager::self()->setCurrent(desktop); 0098 } 0099 0100 void WorkspaceWrapper::setNumberOfDesktops(int count) 0101 { 0102 VirtualDesktopManager::self()->setCount(count); 0103 } 0104 0105 Window *WorkspaceWrapper::activeClient() const 0106 { 0107 return workspace()->activeWindow(); 0108 } 0109 0110 QString WorkspaceWrapper::currentActivity() const 0111 { 0112 #if KWIN_BUILD_ACTIVITIES 0113 if (!Workspace::self()->activities()) { 0114 return QString(); 0115 } 0116 return Workspace::self()->activities()->current(); 0117 #else 0118 return QString(); 0119 #endif 0120 } 0121 0122 void WorkspaceWrapper::setCurrentActivity(QString activity) 0123 { 0124 #if KWIN_BUILD_ACTIVITIES 0125 if (Workspace::self()->activities()) { 0126 Workspace::self()->activities()->setCurrent(activity); 0127 } 0128 #endif 0129 } 0130 0131 QStringList WorkspaceWrapper::activityList() const 0132 { 0133 #if KWIN_BUILD_ACTIVITIES 0134 if (!Workspace::self()->activities()) { 0135 return QStringList(); 0136 } 0137 return Workspace::self()->activities()->all(); 0138 #else 0139 return QStringList(); 0140 #endif 0141 } 0142 0143 QPoint WorkspaceWrapper::cursorPos() const 0144 { 0145 return Cursors::self()->mouse()->pos(); 0146 } 0147 0148 #define SLOTWRAPPER(name) \ 0149 void WorkspaceWrapper::name() \ 0150 { \ 0151 Workspace::self()->name(); \ 0152 } 0153 0154 SLOTWRAPPER(slotToggleShowDesktop) 0155 0156 SLOTWRAPPER(slotWindowMaximize) 0157 SLOTWRAPPER(slotWindowMaximizeVertical) 0158 SLOTWRAPPER(slotWindowMaximizeHorizontal) 0159 SLOTWRAPPER(slotWindowMinimize) 0160 SLOTWRAPPER(slotWindowShade) 0161 SLOTWRAPPER(slotWindowRaise) 0162 SLOTWRAPPER(slotWindowLower) 0163 SLOTWRAPPER(slotWindowRaiseOrLower) 0164 SLOTWRAPPER(slotActivateAttentionWindow) 0165 SLOTWRAPPER(slotWindowMoveLeft) 0166 SLOTWRAPPER(slotWindowMoveRight) 0167 SLOTWRAPPER(slotWindowMoveUp) 0168 SLOTWRAPPER(slotWindowMoveDown) 0169 SLOTWRAPPER(slotWindowExpandHorizontal) 0170 SLOTWRAPPER(slotWindowExpandVertical) 0171 SLOTWRAPPER(slotWindowShrinkHorizontal) 0172 SLOTWRAPPER(slotWindowShrinkVertical) 0173 0174 SLOTWRAPPER(slotIncreaseWindowOpacity) 0175 SLOTWRAPPER(slotLowerWindowOpacity) 0176 0177 SLOTWRAPPER(slotWindowOperations) 0178 SLOTWRAPPER(slotWindowClose) 0179 SLOTWRAPPER(slotWindowMove) 0180 SLOTWRAPPER(slotWindowResize) 0181 SLOTWRAPPER(slotWindowAbove) 0182 SLOTWRAPPER(slotWindowBelow) 0183 SLOTWRAPPER(slotWindowOnAllDesktops) 0184 SLOTWRAPPER(slotWindowFullScreen) 0185 SLOTWRAPPER(slotWindowNoBorder) 0186 0187 SLOTWRAPPER(slotWindowToNextDesktop) 0188 SLOTWRAPPER(slotWindowToPreviousDesktop) 0189 SLOTWRAPPER(slotWindowToDesktopRight) 0190 SLOTWRAPPER(slotWindowToDesktopLeft) 0191 SLOTWRAPPER(slotWindowToDesktopUp) 0192 SLOTWRAPPER(slotWindowToDesktopDown) 0193 0194 SLOTWRAPPER(slotWindowToPrevScreen) 0195 SLOTWRAPPER(slotWindowToNextScreen) 0196 SLOTWRAPPER(slotWindowToLeftScreen) 0197 SLOTWRAPPER(slotWindowToRightScreen) 0198 SLOTWRAPPER(slotWindowToAboveScreen) 0199 SLOTWRAPPER(slotWindowToBelowScreen) 0200 0201 SLOTWRAPPER(slotSwitchToPrevScreen) 0202 SLOTWRAPPER(slotSwitchToNextScreen) 0203 SLOTWRAPPER(slotSwitchToLeftScreen) 0204 SLOTWRAPPER(slotSwitchToRightScreen) 0205 SLOTWRAPPER(slotSwitchToAboveScreen) 0206 SLOTWRAPPER(slotSwitchToBelowScreen) 0207 0208 #undef SLOTWRAPPER 0209 0210 #define SLOTWRAPPER(name, modes) \ 0211 void WorkspaceWrapper::name() \ 0212 { \ 0213 Workspace::self()->quickTileWindow(modes); \ 0214 } 0215 0216 SLOTWRAPPER(slotWindowQuickTileLeft, QuickTileFlag::Left) 0217 SLOTWRAPPER(slotWindowQuickTileRight, QuickTileFlag::Right) 0218 SLOTWRAPPER(slotWindowQuickTileTop, QuickTileFlag::Top) 0219 SLOTWRAPPER(slotWindowQuickTileBottom, QuickTileFlag::Bottom) 0220 SLOTWRAPPER(slotWindowQuickTileTopLeft, QuickTileFlag::Top | QuickTileFlag::Left) 0221 SLOTWRAPPER(slotWindowQuickTileTopRight, QuickTileFlag::Top | QuickTileFlag::Right) 0222 SLOTWRAPPER(slotWindowQuickTileBottomLeft, QuickTileFlag::Bottom | QuickTileFlag::Left) 0223 SLOTWRAPPER(slotWindowQuickTileBottomRight, QuickTileFlag::Bottom | QuickTileFlag::Right) 0224 0225 #undef SLOTWRAPPER 0226 0227 #define SLOTWRAPPER(name, direction) \ 0228 void WorkspaceWrapper::name() \ 0229 { \ 0230 Workspace::self()->switchWindow(Workspace::direction); \ 0231 } 0232 0233 SLOTWRAPPER(slotSwitchWindowUp, DirectionNorth) 0234 SLOTWRAPPER(slotSwitchWindowDown, DirectionSouth) 0235 SLOTWRAPPER(slotSwitchWindowRight, DirectionEast) 0236 SLOTWRAPPER(slotSwitchWindowLeft, DirectionWest) 0237 0238 #undef SLOTWRAPPER 0239 0240 #define SLOTWRAPPER(name, direction) \ 0241 void WorkspaceWrapper::name() \ 0242 { \ 0243 VirtualDesktopManager::self()->moveTo(VirtualDesktopManager::Direction::direction, options->isRollOverDesktops()); \ 0244 } 0245 0246 SLOTWRAPPER(slotSwitchDesktopNext, Next) 0247 SLOTWRAPPER(slotSwitchDesktopPrevious, Previous) 0248 SLOTWRAPPER(slotSwitchDesktopRight, Right) 0249 SLOTWRAPPER(slotSwitchDesktopLeft, Left) 0250 SLOTWRAPPER(slotSwitchDesktopUp, Up) 0251 SLOTWRAPPER(slotSwitchDesktopDown, Down) 0252 0253 #undef SLOTWRAPPER 0254 0255 void WorkspaceWrapper::setActiveClient(KWin::Window *client) 0256 { 0257 KWin::Workspace::self()->activateWindow(client); 0258 } 0259 0260 QSize WorkspaceWrapper::workspaceSize() const 0261 { 0262 return QSize(workspaceWidth(), workspaceHeight()); 0263 } 0264 0265 QSize WorkspaceWrapper::displaySize() const 0266 { 0267 return workspace()->geometry().size(); 0268 } 0269 0270 int WorkspaceWrapper::displayWidth() const 0271 { 0272 return displaySize().width(); 0273 } 0274 0275 int WorkspaceWrapper::displayHeight() const 0276 { 0277 return displaySize().height(); 0278 } 0279 0280 static VirtualDesktop *resolveVirtualDesktop(int desktopId) 0281 { 0282 if (desktopId == 0 || desktopId == -1) { 0283 return VirtualDesktopManager::self()->currentDesktop(); 0284 } else { 0285 return VirtualDesktopManager::self()->desktopForX11Id(desktopId); 0286 } 0287 } 0288 0289 QRectF WorkspaceWrapper::clientArea(ClientAreaOption option, const QPoint &p, int desktop) const 0290 { 0291 const Output *output = Workspace::self()->outputAt(p); 0292 const VirtualDesktop *virtualDesktop = resolveVirtualDesktop(desktop); 0293 return Workspace::self()->clientArea(static_cast<clientAreaOption>(option), output, virtualDesktop); 0294 } 0295 0296 QRectF WorkspaceWrapper::clientArea(ClientAreaOption option, const QPoint &p, VirtualDesktop *desktop) const 0297 { 0298 return workspace()->clientArea(static_cast<clientAreaOption>(option), workspace()->outputAt(p), desktop); 0299 } 0300 0301 QRectF WorkspaceWrapper::clientArea(ClientAreaOption option, const KWin::Window *c) const 0302 { 0303 if (!c) { 0304 return QRectF(); 0305 } 0306 return Workspace::self()->clientArea(static_cast<clientAreaOption>(option), c); 0307 } 0308 0309 QRectF WorkspaceWrapper::clientArea(ClientAreaOption option, KWin::Window *c) const 0310 { 0311 if (!c) { 0312 return QRectF(); 0313 } 0314 return Workspace::self()->clientArea(static_cast<clientAreaOption>(option), c); 0315 } 0316 0317 static VirtualDesktop *resolveDesktop(int desktopId) 0318 { 0319 auto vdm = VirtualDesktopManager::self(); 0320 if (desktopId == NETWinInfo::OnAllDesktops || desktopId == 0) { 0321 return vdm->currentDesktop(); 0322 } 0323 return vdm->desktopForX11Id(desktopId); 0324 } 0325 0326 static Output *resolveOutput(int outputId) 0327 { 0328 if (outputId == -1) { 0329 return workspace()->activeOutput(); 0330 } 0331 return workspace()->outputs().value(outputId); 0332 } 0333 0334 QRectF WorkspaceWrapper::clientArea(ClientAreaOption option, int outputId, int desktopId) const 0335 { 0336 VirtualDesktop *desktop = resolveDesktop(desktopId); 0337 if (Q_UNLIKELY(!desktop)) { 0338 return QRect(); 0339 } 0340 0341 Output *output = resolveOutput(outputId); 0342 if (Q_UNLIKELY(!output)) { 0343 return QRect(); 0344 } 0345 0346 return workspace()->clientArea(static_cast<clientAreaOption>(option), output, desktop); 0347 } 0348 0349 QRectF WorkspaceWrapper::clientArea(ClientAreaOption option, Output *output, VirtualDesktop *desktop) const 0350 { 0351 return workspace()->clientArea(static_cast<clientAreaOption>(option), output, desktop); 0352 } 0353 0354 QString WorkspaceWrapper::desktopName(int desktop) const 0355 { 0356 const VirtualDesktop *vd = VirtualDesktopManager::self()->desktopForX11Id(desktop); 0357 return vd ? vd->name() : QString(); 0358 } 0359 0360 void WorkspaceWrapper::createDesktop(int position, const QString &name) const 0361 { 0362 VirtualDesktopManager::self()->createVirtualDesktop(position, name); 0363 } 0364 0365 void WorkspaceWrapper::removeDesktop(int position) const 0366 { 0367 VirtualDesktop *vd = VirtualDesktopManager::self()->desktopForX11Id(position + 1); 0368 if (!vd) { 0369 return; 0370 } 0371 0372 VirtualDesktopManager::self()->removeVirtualDesktop(vd->id()); 0373 } 0374 0375 QString WorkspaceWrapper::supportInformation() const 0376 { 0377 return Workspace::self()->supportInformation(); 0378 } 0379 0380 void WorkspaceWrapper::setupClientConnections(Window *client) 0381 { 0382 connect(client, &Window::clientMinimized, this, &WorkspaceWrapper::clientMinimized); 0383 connect(client, &Window::clientUnminimized, this, &WorkspaceWrapper::clientUnminimized); 0384 connect(client, qOverload<Window *, bool, bool>(&Window::clientMaximizedStateChanged), 0385 this, &WorkspaceWrapper::clientMaximizeSet); 0386 0387 X11Window *x11Client = qobject_cast<X11Window *>(client); // TODO: Drop X11-specific signals. 0388 if (!x11Client) { 0389 return; 0390 } 0391 0392 connect(x11Client, &X11Window::clientManaging, this, &WorkspaceWrapper::clientManaging); 0393 connect(x11Client, &X11Window::clientFullScreenSet, this, &WorkspaceWrapper::clientFullScreenSet); 0394 } 0395 0396 void WorkspaceWrapper::showOutline(const QRect &geometry) 0397 { 0398 workspace()->outline()->show(geometry); 0399 } 0400 0401 void WorkspaceWrapper::showOutline(int x, int y, int width, int height) 0402 { 0403 workspace()->outline()->show(QRect(x, y, width, height)); 0404 } 0405 0406 void WorkspaceWrapper::hideOutline() 0407 { 0408 workspace()->outline()->hide(); 0409 } 0410 0411 X11Window *WorkspaceWrapper::getClient(qulonglong windowId) 0412 { 0413 return Workspace::self()->findClient(Predicate::WindowMatch, windowId); 0414 } 0415 0416 QSize WorkspaceWrapper::desktopGridSize() const 0417 { 0418 return VirtualDesktopManager::self()->grid().size(); 0419 } 0420 0421 int WorkspaceWrapper::desktopGridWidth() const 0422 { 0423 return desktopGridSize().width(); 0424 } 0425 0426 int WorkspaceWrapper::desktopGridHeight() const 0427 { 0428 return desktopGridSize().height(); 0429 } 0430 0431 int WorkspaceWrapper::workspaceHeight() const 0432 { 0433 return desktopGridHeight() * displayHeight(); 0434 } 0435 0436 int WorkspaceWrapper::workspaceWidth() const 0437 { 0438 return desktopGridWidth() * displayWidth(); 0439 } 0440 0441 int WorkspaceWrapper::numScreens() const 0442 { 0443 return workspace()->outputs().count(); 0444 } 0445 0446 int WorkspaceWrapper::screenAt(const QPointF &pos) const 0447 { 0448 return workspace()->outputs().indexOf(workspace()->outputAt(pos)); 0449 } 0450 0451 int WorkspaceWrapper::activeScreen() const 0452 { 0453 return workspace()->outputs().indexOf(workspace()->activeOutput()); 0454 } 0455 0456 QRect WorkspaceWrapper::virtualScreenGeometry() const 0457 { 0458 return workspace()->geometry(); 0459 } 0460 0461 QSize WorkspaceWrapper::virtualScreenSize() const 0462 { 0463 return workspace()->geometry().size(); 0464 } 0465 0466 void WorkspaceWrapper::sendClientToScreen(Window *client, int screen) 0467 { 0468 Output *output = workspace()->outputs().value(screen); 0469 if (output) { 0470 workspace()->sendWindowToOutput(client, output); 0471 } 0472 } 0473 0474 KWin::TileManager *WorkspaceWrapper::tilingForScreen(const QString &screenName) const 0475 { 0476 Output *output = kwinApp()->outputBackend()->findOutput(screenName); 0477 if (output) { 0478 return workspace()->tileManager(output); 0479 } 0480 return nullptr; 0481 } 0482 0483 KWin::TileManager *WorkspaceWrapper::tilingForScreen(int screen) const 0484 { 0485 Output *output = workspace()->outputs().value(screen); 0486 if (output) { 0487 return workspace()->tileManager(output); 0488 } 0489 return nullptr; 0490 } 0491 0492 QtScriptWorkspaceWrapper::QtScriptWorkspaceWrapper(QObject *parent) 0493 : WorkspaceWrapper(parent) 0494 { 0495 } 0496 0497 QList<KWin::Window *> QtScriptWorkspaceWrapper::clientList() const 0498 { 0499 return workspace()->allClientList(); 0500 } 0501 0502 QQmlListProperty<KWin::Window> DeclarativeScriptWorkspaceWrapper::clients() 0503 { 0504 return QQmlListProperty<KWin::Window>(this, nullptr, &DeclarativeScriptWorkspaceWrapper::countClientList, &DeclarativeScriptWorkspaceWrapper::atClientList); 0505 } 0506 0507 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0508 int DeclarativeScriptWorkspaceWrapper::countClientList(QQmlListProperty<KWin::Window> *clients) 0509 #else 0510 qsizetype DeclarativeScriptWorkspaceWrapper::countClientList(QQmlListProperty<KWin::Window> *clients) 0511 #endif 0512 { 0513 return workspace()->allClientList().size(); 0514 } 0515 0516 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0517 KWin::Window *DeclarativeScriptWorkspaceWrapper::atClientList(QQmlListProperty<KWin::Window> *clients, int index) 0518 #else 0519 KWin::Window *DeclarativeScriptWorkspaceWrapper::atClientList(QQmlListProperty<KWin::Window> *clients, qsizetype index) 0520 #endif 0521 { 0522 return workspace()->allClientList().at(index); 0523 } 0524 0525 DeclarativeScriptWorkspaceWrapper::DeclarativeScriptWorkspaceWrapper(QObject *parent) 0526 : WorkspaceWrapper(parent) 0527 { 0528 } 0529 0530 } // KWin 0531 0532 #include "moc_workspace_wrapper.cpp"