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