diff --git a/src/platformtheme/qdbusmenubar.cpp b/src/platformtheme/qdbusmenubar.cpp index 6b70021..b0cb7fb 100644 --- a/src/platformtheme/qdbusmenubar.cpp +++ b/src/platformtheme/qdbusmenubar.cpp @@ -1,192 +1,197 @@ /**************************************************************************** ** ** Copyright (C) 2016 Dmitry Shachnev ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qdbusmenubar_p.h" QT_BEGIN_NAMESPACE /* note: do not change these to QStringLiteral; we are unloaded before QtDBus is done using the strings. */ #define REGISTRAR_SERVICE QLatin1String("com.canonical.AppMenu.Registrar") #define REGISTRAR_PATH QLatin1String("/com/canonical/AppMenu/Registrar") QDBusMenuBar::QDBusMenuBar() : QPlatformMenuBar() , m_menu(new QDBusPlatformMenu()) , m_menuAdaptor(new QDBusMenuAdaptor(m_menu)) { QDBusMenuItem::registerDBusTypes(); connect(m_menu, &QDBusPlatformMenu::propertiesUpdated, m_menuAdaptor, &QDBusMenuAdaptor::ItemsPropertiesUpdated); connect(m_menu, &QDBusPlatformMenu::updated, m_menuAdaptor, &QDBusMenuAdaptor::LayoutUpdated); // This signal is new in Qt 5.8 but distros might have backported it, hence a runtime look-up if (m_menu->metaObject()->indexOfSignal("popupRequested(int,uint)") != -1) { connect(m_menu, SIGNAL(popupRequested(int,uint)), m_menuAdaptor, SIGNAL(ItemActivationRequested(int,uint))); } } QDBusMenuBar::~QDBusMenuBar() { unregisterMenuBar(); delete m_menuAdaptor; delete m_menu; qDeleteAll(m_menuItems); } QDBusPlatformMenuItem *QDBusMenuBar::menuItemForMenu(QPlatformMenu *menu) { if (!menu) return nullptr; quintptr tag = menu->tag(); const auto it = m_menuItems.constFind(tag); if (it != m_menuItems.cend()) { return *it; } else { QDBusPlatformMenuItem *item = new QDBusPlatformMenuItem; updateMenuItem(item, menu); m_menuItems.insert(tag, item); return item; } } void QDBusMenuBar::updateMenuItem(QDBusPlatformMenuItem *item, QPlatformMenu *menu) { const QDBusPlatformMenu *ourMenu = qobject_cast(menu); item->setText(ourMenu->text()); item->setIcon(ourMenu->icon()); item->setEnabled(ourMenu->isEnabled()); item->setVisible(ourMenu->isVisible()); item->setMenu(menu); } void QDBusMenuBar::insertMenu(QPlatformMenu *menu, QPlatformMenu *before) { QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu); QDBusPlatformMenuItem *beforeItem = menuItemForMenu(before); m_menu->insertMenuItem(menuItem, beforeItem); m_menu->emitUpdated(); } void QDBusMenuBar::removeMenu(QPlatformMenu *menu) { QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu); m_menu->removeMenuItem(menuItem); m_menu->emitUpdated(); } void QDBusMenuBar::syncMenu(QPlatformMenu *menu) { QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu); updateMenuItem(menuItem, menu); } void QDBusMenuBar::handleReparent(QWindow *newParentWindow) { - if (newParentWindow && newParentWindow != m_window) { - QWindow *oldWindow = m_window; + if (newParentWindow == m_window) { + return; + } - unregisterMenuBar(); - m_window = newParentWindow; - registerMenuBar(); + QWindow *oldWindow = m_window; - emit windowChanged(newParentWindow, oldWindow); + unregisterMenuBar(); + m_window = newParentWindow; + + if (newParentWindow) { + registerMenuBar(); } + + emit windowChanged(newParentWindow, oldWindow); } QPlatformMenu *QDBusMenuBar::menuForTag(quintptr tag) const { QDBusPlatformMenuItem *menuItem = m_menuItems.value(tag); if (menuItem) return const_cast(menuItem->menu()); return nullptr; } QPlatformMenu *QDBusMenuBar::createMenu() const { return new QDBusPlatformMenu; } void QDBusMenuBar::registerMenuBar() { static uint menuBarId = 0; if (!m_window) { qWarning("Cannot register window menu without window"); return; } QDBusConnection connection = QDBusConnection::sessionBus(); m_objectPath = QStringLiteral("/MenuBar/%1").arg(++menuBarId); if (!connection.registerObject(m_objectPath, m_menu)) return; QDBusMenuRegistrarInterface registrar(REGISTRAR_SERVICE, REGISTRAR_PATH, connection, this); QDBusPendingReply<> r = registrar.RegisterWindow(static_cast(window()->winId()), QDBusObjectPath(m_objectPath)); r.waitForFinished(); if (r.isError()) { qWarning("Failed to register window menu, reason: %s (\"%s\")", qUtf8Printable(r.error().name()), qUtf8Printable(r.error().message())); connection.unregisterObject(m_objectPath); } } void QDBusMenuBar::unregisterMenuBar() { QDBusConnection connection = QDBusConnection::sessionBus(); if (m_window) { QDBusMenuRegistrarInterface registrar(REGISTRAR_SERVICE, REGISTRAR_PATH, connection, this); QDBusPendingReply<> r = registrar.UnregisterWindow(static_cast(window()->winId())); r.waitForFinished(); if (r.isError()) qWarning("Failed to unregister window menu, reason: %s (\"%s\")", qUtf8Printable(r.error().name()), qUtf8Printable(r.error().message())); } if (!m_objectPath.isEmpty()) connection.unregisterObject(m_objectPath); } #include "qdbusmenubar.moc" QT_END_NAMESPACE diff --git a/src/platformtheme/qdbusmenubar_p.h b/src/platformtheme/qdbusmenubar_p.h index 6a5a379..bfec005 100644 --- a/src/platformtheme/qdbusmenubar_p.h +++ b/src/platformtheme/qdbusmenubar_p.h @@ -1,101 +1,101 @@ /**************************************************************************** ** ** Copyright (C) 2016 Dmitry Shachnev ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QDBUSMENUBAR_P_H #define QDBUSMENUBAR_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QDBusMenuBar : public QPlatformMenuBar { Q_OBJECT public: QDBusMenuBar(); virtual ~QDBusMenuBar(); void insertMenu(QPlatformMenu *menu, QPlatformMenu *before) override; void removeMenu(QPlatformMenu *menu) override; void syncMenu(QPlatformMenu *menu) override; void handleReparent(QWindow *newParentWindow) override; QPlatformMenu *menuForTag(quintptr tag) const override; QPlatformMenu *createMenu() const override; QWindow *window() const { return m_window; } QString objectPath() const { return m_objectPath; } Q_SIGNALS: void windowChanged(QWindow *newWindow, QWindow *oldWindow); private: QDBusPlatformMenu *m_menu; QDBusMenuAdaptor *m_menuAdaptor; QHash m_menuItems; - QWindow *m_window = nullptr; + QPointer m_window; QString m_objectPath; QDBusPlatformMenuItem *menuItemForMenu(QPlatformMenu *menu); static void updateMenuItem(QDBusPlatformMenuItem *item, QPlatformMenu *menu); void registerMenuBar(); void unregisterMenuBar(); }; QT_END_NAMESPACE #endif // QDBUSMENUBAR_P_H