File indexing completed on 2024-05-05 17:43:31
0001 /* 0002 SPDX-FileCopyrightText: 2011 Lionel Chauvin <megabigbug@yahoo.fr> 0003 SPDX-FileCopyrightText: 2011, 2012 Cédric Bellegarde <gnumdk@gmail.com> 0004 SPDX-FileCopyrightText: 2016 Kai Uwe Broulik <kde@privat.broulik.de> 0005 0006 SPDX-License-Identifier: MIT 0007 */ 0008 0009 #include "menuimporter.h" 0010 #include "dbusmenutypes_p.h" 0011 #include "menuimporteradaptor.h" 0012 0013 #include <QDBusMessage> 0014 #include <QDBusServiceWatcher> 0015 0016 #include <KWindowInfo> 0017 #include <KWindowSystem> 0018 0019 static const char *DBUS_SERVICE = "com.canonical.AppMenu.Registrar"; 0020 static const char *DBUS_OBJECT_PATH = "/com/canonical/AppMenu/Registrar"; 0021 0022 MenuImporter::MenuImporter(QObject *parent) 0023 : QObject(parent) 0024 , m_serviceWatcher(new QDBusServiceWatcher(this)) 0025 { 0026 qDBusRegisterMetaType<DBusMenuLayoutItem>(); 0027 m_serviceWatcher->setConnection(QDBusConnection::sessionBus()); 0028 m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); 0029 connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &MenuImporter::slotServiceUnregistered); 0030 } 0031 0032 MenuImporter::~MenuImporter() 0033 { 0034 QDBusConnection::sessionBus().unregisterService(DBUS_SERVICE); 0035 } 0036 0037 bool MenuImporter::connectToBus() 0038 { 0039 if (!QDBusConnection::sessionBus().registerService(DBUS_SERVICE)) { 0040 return false; 0041 } 0042 new MenuImporterAdaptor(this); 0043 QDBusConnection::sessionBus().registerObject(DBUS_OBJECT_PATH, this); 0044 0045 return true; 0046 } 0047 0048 void MenuImporter::RegisterWindow(WId id, const QDBusObjectPath &path) 0049 { 0050 KWindowInfo info(id, NET::WMWindowType, NET::WM2WindowClass); 0051 NET::WindowTypes mask = NET::AllTypesMask; 0052 auto type = info.windowType(mask); 0053 0054 // Menu can try to register, right click in gimp for example 0055 if (type != NET::Unknown && (type & (NET::Menu | NET::DropdownMenu | NET::PopupMenu))) { 0056 return; 0057 } 0058 0059 if (path.path().isEmpty()) // prevent bad dbusmenu usage 0060 return; 0061 0062 QString service = message().service(); 0063 0064 QString classClass = info.windowClassClass(); 0065 m_windowClasses.insert(id, classClass); 0066 m_menuServices.insert(id, service); 0067 m_menuPaths.insert(id, path); 0068 0069 if (!m_serviceWatcher->watchedServices().contains(service)) { 0070 m_serviceWatcher->addWatchedService(service); 0071 } 0072 0073 Q_EMIT WindowRegistered(id, service, path); 0074 } 0075 0076 void MenuImporter::UnregisterWindow(WId id) 0077 { 0078 m_menuServices.remove(id); 0079 m_menuPaths.remove(id); 0080 m_windowClasses.remove(id); 0081 0082 Q_EMIT WindowUnregistered(id); 0083 } 0084 0085 QString MenuImporter::GetMenuForWindow(WId id, QDBusObjectPath &path) 0086 { 0087 path = m_menuPaths.value(id); 0088 return m_menuServices.value(id); 0089 } 0090 0091 void MenuImporter::slotServiceUnregistered(const QString &service) 0092 { 0093 WId id = m_menuServices.key(service); 0094 m_menuServices.remove(id); 0095 m_menuPaths.remove(id); 0096 m_windowClasses.remove(id); 0097 Q_EMIT WindowUnregistered(id); 0098 m_serviceWatcher->removeWatchedService(service); 0099 }