File indexing completed on 2024-11-10 04:57:41
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2011 Lionel Chauvin <megabigbug@yahoo.fr> 0006 SPDX-FileCopyrightText: 2011, 2012 Cédric Bellegarde <gnumdk@gmail.com> 0007 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 #include "appmenu.h" 0012 #include "workspace.h" 0013 #include "x11window.h" 0014 #include <appmenu_interface.h> 0015 0016 #include <QDBusObjectPath> 0017 #include <QDBusServiceWatcher> 0018 0019 #include "decorations/decorationbridge.h" 0020 #include <KDecoration2/DecorationSettings> 0021 0022 namespace KWin 0023 { 0024 0025 static const QString s_viewService(QStringLiteral("org.kde.kappmenuview")); 0026 0027 ApplicationMenu::ApplicationMenu() 0028 : m_appmenuInterface(new OrgKdeKappmenuInterface(QStringLiteral("org.kde.kappmenu"), QStringLiteral("/KAppMenu"), QDBusConnection::sessionBus(), this)) 0029 { 0030 connect(m_appmenuInterface, &OrgKdeKappmenuInterface::showRequest, this, &ApplicationMenu::slotShowRequest); 0031 connect(m_appmenuInterface, &OrgKdeKappmenuInterface::menuShown, this, &ApplicationMenu::slotMenuShown); 0032 connect(m_appmenuInterface, &OrgKdeKappmenuInterface::menuHidden, this, &ApplicationMenu::slotMenuHidden); 0033 0034 m_kappMenuWatcher = new QDBusServiceWatcher(QStringLiteral("org.kde.kappmenu"), QDBusConnection::sessionBus(), 0035 QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this); 0036 0037 connect(m_kappMenuWatcher, &QDBusServiceWatcher::serviceRegistered, this, [this]() { 0038 m_applicationMenuEnabled = true; 0039 Q_EMIT applicationMenuEnabledChanged(true); 0040 }); 0041 connect(m_kappMenuWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [this]() { 0042 m_applicationMenuEnabled = false; 0043 Q_EMIT applicationMenuEnabledChanged(false); 0044 }); 0045 0046 m_applicationMenuEnabled = QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.kappmenu")); 0047 } 0048 0049 bool ApplicationMenu::applicationMenuEnabled() const 0050 { 0051 return m_applicationMenuEnabled; 0052 } 0053 0054 void ApplicationMenu::setViewEnabled(bool enabled) 0055 { 0056 if (enabled) { 0057 QDBusConnection::sessionBus().interface()->registerService(s_viewService, 0058 QDBusConnectionInterface::QueueService, 0059 QDBusConnectionInterface::DontAllowReplacement); 0060 } else { 0061 QDBusConnection::sessionBus().interface()->unregisterService(s_viewService); 0062 } 0063 } 0064 0065 void ApplicationMenu::slotShowRequest(const QString &serviceName, const QDBusObjectPath &menuObjectPath, int actionId) 0066 { 0067 // Ignore show request when user has not configured the application menu title bar button 0068 auto decorationSettings = Workspace::self()->decorationBridge()->settings(); 0069 if (decorationSettings && !decorationSettings->decorationButtonsLeft().contains(KDecoration2::DecorationButtonType::ApplicationMenu) 0070 && !decorationSettings->decorationButtonsRight().contains(KDecoration2::DecorationButtonType::ApplicationMenu)) { 0071 return; 0072 } 0073 0074 if (Window *window = findWindowWithApplicationMenu(serviceName, menuObjectPath)) { 0075 window->showApplicationMenu(actionId); 0076 } 0077 } 0078 0079 void ApplicationMenu::slotMenuShown(const QString &serviceName, const QDBusObjectPath &menuObjectPath) 0080 { 0081 if (Window *window = findWindowWithApplicationMenu(serviceName, menuObjectPath)) { 0082 window->setApplicationMenuActive(true); 0083 } 0084 } 0085 0086 void ApplicationMenu::slotMenuHidden(const QString &serviceName, const QDBusObjectPath &menuObjectPath) 0087 { 0088 if (Window *window = findWindowWithApplicationMenu(serviceName, menuObjectPath)) { 0089 window->setApplicationMenuActive(false); 0090 } 0091 } 0092 0093 void ApplicationMenu::showApplicationMenu(const QPoint &p, Window *c, int actionId) 0094 { 0095 if (!c->hasApplicationMenu()) { 0096 return; 0097 } 0098 m_appmenuInterface->showMenu(p.x(), p.y(), c->applicationMenuServiceName(), QDBusObjectPath(c->applicationMenuObjectPath()), actionId); 0099 } 0100 0101 Window *ApplicationMenu::findWindowWithApplicationMenu(const QString &serviceName, const QDBusObjectPath &menuObjectPath) 0102 { 0103 if (serviceName.isEmpty() || menuObjectPath.path().isEmpty()) { 0104 return nullptr; 0105 } 0106 0107 return Workspace::self()->findWindow([&](const Window *window) { 0108 return window->applicationMenuServiceName() == serviceName 0109 && window->applicationMenuObjectPath() == menuObjectPath.path(); 0110 }); 0111 } 0112 0113 } // namespace KWin 0114 0115 #include "moc_appmenu.cpp"