File indexing completed on 2024-05-19 16:34:53

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"