Warning, file /plasma/kwin/src/dbusinterface.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 // own 0011 #include "dbusinterface.h" 0012 #include "compositingadaptor.h" 0013 #include "pluginsadaptor.h" 0014 #include "virtualdesktopmanageradaptor.h" 0015 0016 // kwin 0017 #include "atoms.h" 0018 #include "composite.h" 0019 #include "core/output.h" 0020 #include "core/renderbackend.h" 0021 #include "debug_console.h" 0022 #include "kwinadaptor.h" 0023 #include "main.h" 0024 #include "placement.h" 0025 #include "pluginmanager.h" 0026 #include "unmanaged.h" 0027 #include "virtualdesktops.h" 0028 #include "window.h" 0029 #include "workspace.h" 0030 #if KWIN_BUILD_ACTIVITIES 0031 #include "activities.h" 0032 #endif 0033 0034 // Qt 0035 #include <QOpenGLContext> 0036 0037 namespace KWin 0038 { 0039 0040 DBusInterface::DBusInterface(QObject *parent) 0041 : QObject(parent) 0042 , m_serviceName(QStringLiteral("org.kde.KWin")) 0043 { 0044 (void)new KWinAdaptor(this); 0045 0046 QDBusConnection dbus = QDBusConnection::sessionBus(); 0047 dbus.registerObject(QStringLiteral("/KWin"), this); 0048 dbus.registerService(m_serviceName); 0049 dbus.connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"), 0050 Workspace::self(), SLOT(slotReloadConfig())); 0051 0052 connect(Workspace::self(), &Workspace::showingDesktopChanged, this, &DBusInterface::onShowingDesktopChanged); 0053 } 0054 0055 DBusInterface::~DBusInterface() 0056 { 0057 QDBusConnection::sessionBus().unregisterService(m_serviceName); 0058 } 0059 0060 bool DBusInterface::showingDesktop() const 0061 { 0062 return workspace()->showingDesktop(); 0063 } 0064 0065 void DBusInterface::reconfigure() 0066 { 0067 Workspace::self()->reconfigure(); 0068 } 0069 0070 void DBusInterface::killWindow() 0071 { 0072 Workspace::self()->slotKillWindow(); 0073 } 0074 0075 void DBusInterface::cascadeDesktop() 0076 { 0077 workspace()->placement()->cascadeDesktop(); 0078 } 0079 0080 void DBusInterface::unclutterDesktop() 0081 { 0082 workspace()->placement()->unclutterDesktop(); 0083 } 0084 0085 QString DBusInterface::supportInformation() 0086 { 0087 return Workspace::self()->supportInformation(); 0088 } 0089 0090 QString DBusInterface::activeOutputName() 0091 { 0092 return Workspace::self()->activeOutput()->name(); 0093 } 0094 0095 bool DBusInterface::startActivity(const QString &in0) 0096 { 0097 #if KWIN_BUILD_ACTIVITIES 0098 if (!Workspace::self()->activities()) { 0099 return false; 0100 } 0101 return Workspace::self()->activities()->start(in0); 0102 #else 0103 return false; 0104 #endif 0105 } 0106 0107 bool DBusInterface::stopActivity(const QString &in0) 0108 { 0109 #if KWIN_BUILD_ACTIVITIES 0110 if (!Workspace::self()->activities()) { 0111 return false; 0112 } 0113 return Workspace::self()->activities()->stop(in0); 0114 #else 0115 return false; 0116 #endif 0117 } 0118 0119 int DBusInterface::currentDesktop() 0120 { 0121 return VirtualDesktopManager::self()->current(); 0122 } 0123 0124 bool DBusInterface::setCurrentDesktop(int desktop) 0125 { 0126 return VirtualDesktopManager::self()->setCurrent(desktop); 0127 } 0128 0129 void DBusInterface::nextDesktop() 0130 { 0131 VirtualDesktopManager::self()->moveTo(VirtualDesktopManager::Direction::Next); 0132 } 0133 0134 void DBusInterface::previousDesktop() 0135 { 0136 VirtualDesktopManager::self()->moveTo(VirtualDesktopManager::Direction::Previous); 0137 } 0138 0139 void DBusInterface::showDebugConsole() 0140 { 0141 DebugConsole *console = new DebugConsole; 0142 console->show(); 0143 } 0144 0145 void DBusInterface::replace() 0146 { 0147 QCoreApplication::exit(133); 0148 } 0149 0150 namespace 0151 { 0152 QVariantMap clientToVariantMap(const Window *c) 0153 { 0154 return 0155 { 0156 {QStringLiteral("resourceClass"), c->resourceClass()}, 0157 {QStringLiteral("resourceName"), c->resourceName()}, 0158 {QStringLiteral("desktopFile"), c->desktopFileName()}, 0159 {QStringLiteral("role"), c->windowRole()}, 0160 {QStringLiteral("caption"), c->captionNormal()}, 0161 {QStringLiteral("clientMachine"), c->wmClientMachine(true)}, 0162 {QStringLiteral("localhost"), c->isLocalhost()}, 0163 {QStringLiteral("type"), c->windowType()}, 0164 {QStringLiteral("x"), c->x()}, 0165 {QStringLiteral("y"), c->y()}, 0166 {QStringLiteral("width"), c->width()}, 0167 {QStringLiteral("height"), c->height()}, 0168 {QStringLiteral("desktops"), c->desktopIds()}, 0169 {QStringLiteral("minimized"), c->isMinimized()}, 0170 {QStringLiteral("shaded"), c->isShade()}, 0171 {QStringLiteral("fullscreen"), c->isFullScreen()}, 0172 {QStringLiteral("keepAbove"), c->keepAbove()}, 0173 {QStringLiteral("keepBelow"), c->keepBelow()}, 0174 {QStringLiteral("noBorder"), c->noBorder()}, 0175 {QStringLiteral("skipTaskbar"), c->skipTaskbar()}, 0176 {QStringLiteral("skipPager"), c->skipPager()}, 0177 {QStringLiteral("skipSwitcher"), c->skipSwitcher()}, 0178 {QStringLiteral("maximizeHorizontal"), c->maximizeMode() & MaximizeHorizontal}, 0179 {QStringLiteral("maximizeVertical"), c->maximizeMode() & MaximizeVertical}, 0180 {QStringLiteral("uuid"), c->internalId().toString()}, 0181 #if KWIN_BUILD_ACTIVITIES 0182 {QStringLiteral("activities"), c->activities()}, 0183 #endif 0184 }; 0185 } 0186 } 0187 0188 QVariantMap DBusInterface::queryWindowInfo() 0189 { 0190 m_replyQueryWindowInfo = message(); 0191 setDelayedReply(true); 0192 kwinApp()->startInteractiveWindowSelection( 0193 [this](Window *t) { 0194 if (!t) { 0195 QDBusConnection::sessionBus().send(m_replyQueryWindowInfo.createErrorReply( 0196 QStringLiteral("org.kde.KWin.Error.UserCancel"), 0197 QStringLiteral("User cancelled the query"))); 0198 return; 0199 } 0200 if (t->isClient()) { 0201 QDBusConnection::sessionBus().send(m_replyQueryWindowInfo.createReply(clientToVariantMap(t))); 0202 } else { 0203 QDBusConnection::sessionBus().send(m_replyQueryWindowInfo.createErrorReply( 0204 QStringLiteral("org.kde.KWin.Error.InvalidWindow"), 0205 QStringLiteral("Tried to query information about an unmanaged window"))); 0206 } 0207 }); 0208 return QVariantMap{}; 0209 } 0210 0211 QVariantMap DBusInterface::getWindowInfo(const QString &uuid) 0212 { 0213 const auto id = QUuid::fromString(uuid); 0214 const auto client = workspace()->findAbstractClient([&id](const Window *c) { 0215 return c->internalId() == id; 0216 }); 0217 if (client) { 0218 return clientToVariantMap(client); 0219 } else { 0220 return {}; 0221 } 0222 } 0223 0224 void DBusInterface::showDesktop(bool show) 0225 { 0226 workspace()->setShowingDesktop(show, true); 0227 0228 auto m = message(); 0229 if (m.service().isEmpty()) { 0230 return; 0231 } 0232 0233 // Keep track of whatever D-Bus client asked to show the desktop. If 0234 // they disappear from the bus, cancel the show desktop state so we do 0235 // not end up in a state where we are stuck showing the desktop. 0236 static QPointer<QDBusServiceWatcher> watcher; 0237 0238 if (show) { 0239 if (watcher) { 0240 // If we get a second call to `showDesktop(true)`, drop the previous 0241 // watcher and watch the new client. That way, we simply always 0242 // track the last state. 0243 watcher->deleteLater(); 0244 } 0245 0246 watcher = new QDBusServiceWatcher(m.service(), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForUnregistration, this); 0247 connect(watcher, &QDBusServiceWatcher::serviceUnregistered, []() { 0248 workspace()->setShowingDesktop(false, true); 0249 watcher->deleteLater(); 0250 }); 0251 } else if (watcher) { 0252 // Someone cancelled showing the desktop, so there's no more need to 0253 // watch to cancel the show desktop state. 0254 watcher->deleteLater(); 0255 } 0256 } 0257 0258 void DBusInterface::onShowingDesktopChanged(bool show, bool /*animated*/) 0259 { 0260 Q_EMIT showingDesktopChanged(show); 0261 } 0262 0263 CompositorDBusInterface::CompositorDBusInterface(Compositor *parent) 0264 : QObject(parent) 0265 , m_compositor(parent) 0266 { 0267 connect(m_compositor, &Compositor::compositingToggled, this, &CompositorDBusInterface::compositingToggled); 0268 new CompositingAdaptor(this); 0269 QDBusConnection dbus = QDBusConnection::sessionBus(); 0270 dbus.registerObject(QStringLiteral("/Compositor"), this); 0271 dbus.connect(QString(), QStringLiteral("/Compositor"), QStringLiteral("org.kde.kwin.Compositing"), 0272 QStringLiteral("reinit"), this, SLOT(reinitialize())); 0273 } 0274 0275 QString CompositorDBusInterface::compositingType() const 0276 { 0277 if (!m_compositor->compositing()) { 0278 return QStringLiteral("none"); 0279 } 0280 switch (m_compositor->backend()->compositingType()) { 0281 case OpenGLCompositing: 0282 if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) { 0283 return QStringLiteral("gles"); 0284 } else { 0285 return QStringLiteral("gl2"); 0286 } 0287 case QPainterCompositing: 0288 return QStringLiteral("qpainter"); 0289 case NoCompositing: 0290 default: 0291 return QStringLiteral("none"); 0292 } 0293 } 0294 0295 bool CompositorDBusInterface::isActive() const 0296 { 0297 return m_compositor->isActive(); 0298 } 0299 0300 bool CompositorDBusInterface::isCompositingPossible() const 0301 { 0302 return m_compositor->compositingPossible(); 0303 } 0304 0305 QString CompositorDBusInterface::compositingNotPossibleReason() const 0306 { 0307 return m_compositor->compositingNotPossibleReason(); 0308 } 0309 0310 bool CompositorDBusInterface::isOpenGLBroken() const 0311 { 0312 return m_compositor->openGLCompositingIsBroken(); 0313 } 0314 0315 bool CompositorDBusInterface::platformRequiresCompositing() const 0316 { 0317 return kwinApp()->operationMode() != Application::OperationModeX11; // TODO: Remove this property? 0318 } 0319 0320 void CompositorDBusInterface::resume() 0321 { 0322 if (kwinApp()->operationMode() == Application::OperationModeX11) { 0323 static_cast<X11Compositor *>(m_compositor)->resume(X11Compositor::ScriptSuspend); 0324 } 0325 } 0326 0327 void CompositorDBusInterface::suspend() 0328 { 0329 if (kwinApp()->operationMode() == Application::OperationModeX11) { 0330 static_cast<X11Compositor *>(m_compositor)->suspend(X11Compositor::ScriptSuspend); 0331 } 0332 } 0333 0334 void CompositorDBusInterface::reinitialize() 0335 { 0336 m_compositor->reinitialize(); 0337 } 0338 0339 QStringList CompositorDBusInterface::supportedOpenGLPlatformInterfaces() const 0340 { 0341 QStringList interfaces; 0342 bool supportsGlx = false; 0343 #if HAVE_EPOXY_GLX 0344 supportsGlx = (kwinApp()->operationMode() == Application::OperationModeX11); 0345 #endif 0346 if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) { 0347 supportsGlx = false; 0348 } 0349 if (supportsGlx) { 0350 interfaces << QStringLiteral("glx"); 0351 } 0352 interfaces << QStringLiteral("egl"); 0353 return interfaces; 0354 } 0355 0356 VirtualDesktopManagerDBusInterface::VirtualDesktopManagerDBusInterface(VirtualDesktopManager *parent) 0357 : QObject(parent) 0358 , m_manager(parent) 0359 { 0360 qDBusRegisterMetaType<KWin::DBusDesktopDataStruct>(); 0361 qDBusRegisterMetaType<KWin::DBusDesktopDataVector>(); 0362 0363 new VirtualDesktopManagerAdaptor(this); 0364 QDBusConnection::sessionBus().registerObject(QStringLiteral("/VirtualDesktopManager"), 0365 QStringLiteral("org.kde.KWin.VirtualDesktopManager"), 0366 this); 0367 0368 connect(m_manager, &VirtualDesktopManager::currentChanged, this, [this](uint previousDesktop, uint newDesktop) { 0369 Q_EMIT currentChanged(m_manager->currentDesktop()->id()); 0370 }); 0371 0372 connect(m_manager, &VirtualDesktopManager::countChanged, this, [this](uint previousCount, uint newCount) { 0373 Q_EMIT countChanged(newCount); 0374 Q_EMIT desktopsChanged(desktops()); 0375 }); 0376 0377 connect(m_manager, &VirtualDesktopManager::navigationWrappingAroundChanged, this, [this]() { 0378 Q_EMIT navigationWrappingAroundChanged(isNavigationWrappingAround()); 0379 }); 0380 0381 connect(m_manager, &VirtualDesktopManager::rowsChanged, this, &VirtualDesktopManagerDBusInterface::rowsChanged); 0382 0383 const QVector<VirtualDesktop *> allDesks = m_manager->desktops(); 0384 for (auto *vd : allDesks) { 0385 connect(vd, &VirtualDesktop::x11DesktopNumberChanged, this, [this, vd]() { 0386 DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()}; 0387 Q_EMIT desktopDataChanged(vd->id(), data); 0388 Q_EMIT desktopsChanged(desktops()); 0389 }); 0390 connect(vd, &VirtualDesktop::nameChanged, this, [this, vd]() { 0391 DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()}; 0392 Q_EMIT desktopDataChanged(vd->id(), data); 0393 Q_EMIT desktopsChanged(desktops()); 0394 }); 0395 } 0396 connect(m_manager, &VirtualDesktopManager::desktopCreated, this, [this](VirtualDesktop *vd) { 0397 connect(vd, &VirtualDesktop::x11DesktopNumberChanged, this, [this, vd]() { 0398 DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()}; 0399 Q_EMIT desktopDataChanged(vd->id(), data); 0400 Q_EMIT desktopsChanged(desktops()); 0401 }); 0402 connect(vd, &VirtualDesktop::nameChanged, this, [this, vd]() { 0403 DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()}; 0404 Q_EMIT desktopDataChanged(vd->id(), data); 0405 Q_EMIT desktopsChanged(desktops()); 0406 }); 0407 DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()}; 0408 Q_EMIT desktopCreated(vd->id(), data); 0409 Q_EMIT desktopsChanged(desktops()); 0410 }); 0411 connect(m_manager, &VirtualDesktopManager::desktopRemoved, this, [this](VirtualDesktop *vd) { 0412 Q_EMIT desktopRemoved(vd->id()); 0413 Q_EMIT desktopsChanged(desktops()); 0414 }); 0415 } 0416 0417 uint VirtualDesktopManagerDBusInterface::count() const 0418 { 0419 return m_manager->count(); 0420 } 0421 0422 void VirtualDesktopManagerDBusInterface::setRows(uint rows) 0423 { 0424 if (static_cast<uint>(m_manager->grid().height()) == rows) { 0425 return; 0426 } 0427 0428 m_manager->setRows(rows); 0429 m_manager->save(); 0430 } 0431 0432 uint VirtualDesktopManagerDBusInterface::rows() const 0433 { 0434 return m_manager->rows(); 0435 } 0436 0437 void VirtualDesktopManagerDBusInterface::setCurrent(const QString &id) 0438 { 0439 if (m_manager->currentDesktop()->id() == id) { 0440 return; 0441 } 0442 0443 auto *vd = m_manager->desktopForId(id); 0444 if (vd) { 0445 m_manager->setCurrent(vd); 0446 } 0447 } 0448 0449 QString VirtualDesktopManagerDBusInterface::current() const 0450 { 0451 return m_manager->currentDesktop()->id(); 0452 } 0453 0454 void VirtualDesktopManagerDBusInterface::setNavigationWrappingAround(bool wraps) 0455 { 0456 if (m_manager->isNavigationWrappingAround() == wraps) { 0457 return; 0458 } 0459 0460 m_manager->setNavigationWrappingAround(wraps); 0461 } 0462 0463 bool VirtualDesktopManagerDBusInterface::isNavigationWrappingAround() const 0464 { 0465 return m_manager->isNavigationWrappingAround(); 0466 } 0467 0468 DBusDesktopDataVector VirtualDesktopManagerDBusInterface::desktops() const 0469 { 0470 const auto desks = m_manager->desktops(); 0471 DBusDesktopDataVector desktopVect; 0472 desktopVect.reserve(m_manager->count()); 0473 0474 std::transform(desks.constBegin(), desks.constEnd(), 0475 std::back_inserter(desktopVect), 0476 [](const VirtualDesktop *vd) { 0477 return DBusDesktopDataStruct{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()}; 0478 }); 0479 0480 return desktopVect; 0481 } 0482 0483 void VirtualDesktopManagerDBusInterface::createDesktop(uint position, const QString &name) 0484 { 0485 m_manager->createVirtualDesktop(position, name); 0486 } 0487 0488 void VirtualDesktopManagerDBusInterface::setDesktopName(const QString &id, const QString &name) 0489 { 0490 VirtualDesktop *vd = m_manager->desktopForId(id); 0491 if (!vd) { 0492 return; 0493 } 0494 if (vd->name() == name) { 0495 return; 0496 } 0497 0498 vd->setName(name); 0499 m_manager->save(); 0500 } 0501 0502 void VirtualDesktopManagerDBusInterface::removeDesktop(const QString &id) 0503 { 0504 m_manager->removeVirtualDesktop(id); 0505 } 0506 0507 PluginManagerDBusInterface::PluginManagerDBusInterface(PluginManager *manager) 0508 : QObject(manager) 0509 , m_manager(manager) 0510 { 0511 new PluginsAdaptor(this); 0512 0513 QDBusConnection::sessionBus().registerObject(QStringLiteral("/Plugins"), 0514 QStringLiteral("org.kde.KWin.Plugins"), 0515 this); 0516 } 0517 0518 QStringList PluginManagerDBusInterface::loadedPlugins() const 0519 { 0520 return m_manager->loadedPlugins(); 0521 } 0522 0523 QStringList PluginManagerDBusInterface::availablePlugins() const 0524 { 0525 return m_manager->availablePlugins(); 0526 } 0527 0528 bool PluginManagerDBusInterface::LoadPlugin(const QString &name) 0529 { 0530 return m_manager->loadPlugin(name); 0531 } 0532 0533 void PluginManagerDBusInterface::UnloadPlugin(const QString &name) 0534 { 0535 m_manager->unloadPlugin(name); 0536 } 0537 0538 } // namespace