File indexing completed on 2024-05-05 05:37:32

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     if (path.path().isEmpty()) // prevent bad dbusmenu usage
0051         return;
0052 
0053     if (KWindowSystem::isPlatformX11()) {
0054         KWindowInfo info(id, NET::WMWindowType, NET::WM2WindowClass);
0055         NET::WindowTypes mask = NET::AllTypesMask;
0056         auto type = info.windowType(mask);
0057 
0058         // Menu can try to register, right click in gimp for example
0059         if (type != NET::Unknown && (type & (NET::Menu | NET::DropdownMenu | NET::PopupMenu))) {
0060             return;
0061         }
0062         QString classClass = info.windowClassClass();
0063         m_windowClasses.insert(id, classClass);
0064     }
0065 
0066     QString service = message().service();
0067 
0068     m_menuServices.insert(id, service);
0069     m_menuPaths.insert(id, path);
0070 
0071     if (!m_serviceWatcher->watchedServices().contains(service)) {
0072         m_serviceWatcher->addWatchedService(service);
0073     }
0074 
0075     Q_EMIT WindowRegistered(id, service, path);
0076 }
0077 
0078 void MenuImporter::UnregisterWindow(WId id)
0079 {
0080     m_menuServices.remove(id);
0081     m_menuPaths.remove(id);
0082     m_windowClasses.remove(id);
0083 
0084     Q_EMIT WindowUnregistered(id);
0085 }
0086 
0087 QString MenuImporter::GetMenuForWindow(WId id, QDBusObjectPath &path)
0088 {
0089     path = m_menuPaths.value(id);
0090     return m_menuServices.value(id);
0091 }
0092 
0093 void MenuImporter::slotServiceUnregistered(const QString &service)
0094 {
0095     WId id = m_menuServices.key(service);
0096     m_menuServices.remove(id);
0097     m_menuPaths.remove(id);
0098     m_windowClasses.remove(id);
0099     Q_EMIT WindowUnregistered(id);
0100     m_serviceWatcher->removeWatchedService(service);
0101 }