Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.0:Update
plasmoid-active-window-control
plasma-512.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File plasma-512.patch of Package plasmoid-active-window-control
From 41cf4067b90ef1e47e9a7f744009a6dd9516910f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kostoln=C3=BD?= <clearmartin@zoho.com> Date: Wed, 10 Jan 2018 22:50:29 +0100 Subject: [PATCH] C++ plugin along with copied dbusmenuqt and appmenumodel updated added INSTALL file with install instructions --- INSTALL | 7 ++ lib/CMakeLists.txt | 6 +- lib/TODO | 0 ...vewindowcontrolapplet.cpp => appmenuapplet.cpp} | 137 +++++++++++++-------- ...activewindowcontrolapplet.h => appmenuapplet.h} | 16 +-- plugin/CMakeLists.txt | 32 ++--- plugin/appmenumodel.cpp | 76 ++++++++++-- plugin/appmenumodel.h | 19 ++- ...vewindowcontrolplugin.cpp => appmenuplugin.cpp} | 4 +- ...activewindowcontrolplugin.h => appmenuplugin.h} | 6 +- plugin/libdbusmenuqt/CMakeLists.txt | 2 - plugin/libdbusmenuqt/dbusmenuimporter.cpp | 18 ++- plugin/libdbusmenuqt/dbusmenuimporter.h | 3 + plugin/libdbusmenuqt/test/CMakeLists.txt | 3 - plugin/libdbusmenuqt/test/README | 2 - plugin/libdbusmenuqt/test/main.cpp | 84 ------------- plugin/qmldir | 2 +- 17 files changed, 218 insertions(+), 199 deletions(-) create mode 100644 INSTALL delete mode 100644 lib/TODO rename lib/{activewindowcontrolapplet.cpp => appmenuapplet.cpp} (58%) rename lib/{activewindowcontrolapplet.h => appmenuapplet.h} (83%) rename plugin/{activewindowcontrolplugin.cpp => appmenuplugin.cpp} (92%) rename plugin/{activewindowcontrolplugin.h => appmenuplugin.h} (90%) delete mode 100644 plugin/libdbusmenuqt/test/CMakeLists.txt delete mode 100644 plugin/libdbusmenuqt/test/README delete mode 100644 plugin/libdbusmenuqt/test/main.cpp diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..f991263 --- /dev/null +++ b/INSTALL @@ -0,0 +1,7 @@ +INSTALATION INSTRUCTIONS + +$ mkdir build +$ cd build +$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr +$ make +$ make install diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index fd02426..48e9f27 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,8 +1,8 @@ -set(activewindowcontrolapplet_SRCS - activewindowcontrolapplet.cpp +set(appmenuapplet_SRCS + appmenuapplet.cpp ) -add_library(plasma_applet_activewindowcontrol MODULE ${activewindowcontrolapplet_SRCS}) +add_library(plasma_applet_activewindowcontrol MODULE ${appmenuapplet_SRCS}) kcoreaddons_desktop_to_json(plasma_applet_activewindowcontrol ../package/metadata.desktop) diff --git a/lib/TODO b/lib/TODO deleted file mode 100644 index e69de29..0000000 diff --git a/lib/activewindowcontrolapplet.cpp b/lib/appmenuapplet.cpp similarity index 58% rename from lib/activewindowcontrolapplet.cpp rename to lib/appmenuapplet.cpp index 005a385..082ead3 100644 --- a/lib/activewindowcontrolapplet.cpp +++ b/lib/appmenuapplet.cpp @@ -19,7 +19,7 @@ * */ -#include "activewindowcontrolapplet.h" +#include "appmenuapplet.h" #include "../plugin/appmenumodel.h" #include <QAction> @@ -30,31 +30,61 @@ #include <QQuickWindow> #include <QScreen> #include <QDBusConnection> +#include <QDBusMessage> +#include <QDBusPendingCall> +#include <QDBusConnectionInterface> +#include <QTimer> -ActiveWindowControlApplet::ActiveWindowControlApplet(QObject *parent, const QVariantList &data) +int AppMenuApplet::s_refs = 0; + +static const QString s_viewService(QStringLiteral("org.kde.kappmenuview")); + +AppMenuApplet::AppMenuApplet(QObject *parent, const QVariantList &data) : Plasma::Applet(parent, data) { + ++s_refs; + //if we're the first, regster the service + if (s_refs == 1) { + QDBusConnection::sessionBus().interface()->registerService(s_viewService, + QDBusConnectionInterface::QueueService, + QDBusConnectionInterface::DontAllowReplacement); + } + /*it registers or unregisters the service when the destroyed value of the applet change, + and not in the dtor, because: + when we "delete" an applet, it just hides it for about a minute setting its status + to destroyed, in order to be able to do a clean undo: if we undo, there will be + another destroyedchanged and destroyed will be false. + When this happens, if we are the only appmenu applet existing, the dbus interface + will have to be registered again*/ + connect(this, &Applet::destroyedChanged, this, [this](bool destroyed) { + if (destroyed) { + //if we were the last, unregister + if (--s_refs == 0) { + QDBusConnection::sessionBus().interface()->unregisterService(s_viewService); + } + } else { + //if we're the first, regster the service + if (++s_refs == 1) { + QDBusConnection::sessionBus().interface()->registerService(s_viewService, + QDBusConnectionInterface::QueueService, + QDBusConnectionInterface::DontAllowReplacement); + } + } + }); } -ActiveWindowControlApplet::~ActiveWindowControlApplet() = default; +AppMenuApplet::~AppMenuApplet() = default; -void ActiveWindowControlApplet::init() +void AppMenuApplet::init() { - // TODO Wayland PlasmaShellSurface stuff - QDBusConnection::sessionBus().connect(QStringLiteral("org.kde.kappmenu"), - QStringLiteral("/KAppMenu"), - QStringLiteral("org.kde.kappmenu"), - QStringLiteral("reconfigured"), - this, SLOT(updateAppletEnabled())); - updateAppletEnabled(); } -AppMenuModel *ActiveWindowControlApplet::model() const +AppMenuModel *AppMenuApplet::model() const { return m_model; } -void ActiveWindowControlApplet::setModel(AppMenuModel *model) +void AppMenuApplet::setModel(AppMenuModel *model) { if (m_model != model) { m_model = model; @@ -62,12 +92,12 @@ void ActiveWindowControlApplet::setModel(AppMenuModel *model) } } -int ActiveWindowControlApplet::view() const +int AppMenuApplet::view() const { return m_viewType; } -void ActiveWindowControlApplet::setView(int type) +void AppMenuApplet::setView(int type) { if (m_viewType != type) { m_viewType = type; @@ -75,12 +105,12 @@ void ActiveWindowControlApplet::setView(int type) } } -int ActiveWindowControlApplet::currentIndex() const +int AppMenuApplet::currentIndex() const { return m_currentIndex; } -void ActiveWindowControlApplet::setCurrentIndex(int currentIndex) +void AppMenuApplet::setCurrentIndex(int currentIndex) { if (m_currentIndex != currentIndex) { m_currentIndex = currentIndex; @@ -88,12 +118,12 @@ void ActiveWindowControlApplet::setCurrentIndex(int currentIndex) } } -QQuickItem *ActiveWindowControlApplet::buttonGrid() const +QQuickItem *AppMenuApplet::buttonGrid() const { return m_buttonGrid; } -void ActiveWindowControlApplet::setButtonGrid(QQuickItem *buttonGrid) +void AppMenuApplet::setButtonGrid(QQuickItem *buttonGrid) { if (m_buttonGrid != buttonGrid) { m_buttonGrid = buttonGrid; @@ -101,34 +131,11 @@ void ActiveWindowControlApplet::setButtonGrid(QQuickItem *buttonGrid) } } -bool ActiveWindowControlApplet::appletEnabled() const -{ - return m_appletEnabled; -} - -void ActiveWindowControlApplet::updateAppletEnabled() -{ - KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("Appmenu Style")); - const QString &menuStyle = config.readEntry(QStringLiteral("Style")); - - const bool enabled = (menuStyle == QLatin1String("Widget")); - - if (m_appletEnabled != enabled) { - m_appletEnabled = enabled; - emit appletEnabledChanged(); - } -} - -QMenu *ActiveWindowControlApplet::createMenu(int idx) const +QMenu *AppMenuApplet::createMenu(int idx) const { QMenu *menu = nullptr; QAction *action = nullptr; - if (!m_model) { - qDebug() << "model not available"; - return menu; - } - if (view() == CompactView) { menu = new QMenu(); for (int i=0; i<m_model->rowCount(); i++) { @@ -150,24 +157,40 @@ QMenu *ActiveWindowControlApplet::createMenu(int idx) const return menu; } -void ActiveWindowControlApplet::onMenuAboutToHide() +void AppMenuApplet::onMenuAboutToHide() { setCurrentIndex(-1); } -void ActiveWindowControlApplet::trigger(QQuickItem *ctx, int idx) +void AppMenuApplet::trigger(QQuickItem *ctx, int idx) { if (m_currentIndex == idx) { return; } + if (!ctx || !ctx->window() || !ctx->window()->screen()) { + return; + } + QMenu *actionMenu = createMenu(idx); if (actionMenu) { - if (ctx && ctx->window() && ctx->window()->mouseGrabberItem()) { - // FIXME event forge thing enters press and hold move mode :/ - ctx->window()->mouseGrabberItem()->ungrabMouse(); - } + //this is a workaround where Qt will fail to realise a mouse has been released + // this happens if a window which does not accept focus spawns a new window that takes focus and X grab + // whilst the mouse is depressed + // https://bugreports.qt.io/browse/QTBUG-59044 + // this causes the next click to go missing + + //by releasing manually we avoid that situation + auto ungrabMouseHack = [ctx]() { + if (ctx && ctx->window() && ctx->window()->mouseGrabberItem()) { + // FIXME event forge thing enters press and hold move mode :/ + ctx->window()->mouseGrabberItem()->ungrabMouse(); + } + }; + + QTimer::singleShot(0, ctx, ungrabMouseHack); + //end workaround const auto &geo = ctx->window()->screen()->availableVirtualGeometry(); @@ -185,8 +208,16 @@ void ActiveWindowControlApplet::trigger(QQuickItem *ctx, int idx) actionMenu->installEventFilter(this); } + setStatus(Plasma::Types::AcceptingInputStatus); + actionMenu->winId();//create window handle + actionMenu->windowHandle()->setTransientParent(ctx->window()); + actionMenu->popup(pos); + //we can return to passive immediately, an autohide panel will stay open whilst + //any transient window is showing + setStatus(Plasma::Types::PassiveStatus); + if (view() == FullView) { // hide the old menu only after showing the new one to avoid brief flickering // in other windows as they briefly re-gain focus @@ -200,13 +231,13 @@ void ActiveWindowControlApplet::trigger(QQuickItem *ctx, int idx) setCurrentIndex(idx); // FIXME TODO connect only once - connect(actionMenu, &QMenu::aboutToHide, this, &ActiveWindowControlApplet::onMenuAboutToHide, Qt::UniqueConnection); + connect(actionMenu, &QMenu::aboutToHide, this, &AppMenuApplet::onMenuAboutToHide, Qt::UniqueConnection); return; } } // FIXME TODO doesn't work on submenu -bool ActiveWindowControlApplet::eventFilter(QObject *watched, QEvent *event) +bool AppMenuApplet::eventFilter(QObject *watched, QEvent *event) { auto *menu = qobject_cast<QMenu *>(watched); if (!menu) { @@ -258,6 +289,6 @@ bool ActiveWindowControlApplet::eventFilter(QObject *watched, QEvent *event) return false; } -K_EXPORT_PLASMA_APPLET_WITH_JSON(activewindowcontrol, ActiveWindowControlApplet, "metadata.json") +K_EXPORT_PLASMA_APPLET_WITH_JSON(appmenu, AppMenuApplet, "metadata.json") -#include "activewindowcontrolapplet.moc" +#include "appmenuapplet.moc" diff --git a/lib/activewindowcontrolapplet.h b/lib/appmenuapplet.h similarity index 83% rename from lib/activewindowcontrolapplet.h rename to lib/appmenuapplet.h index 8f8c2df..0633c32 100644 --- a/lib/activewindowcontrolapplet.h +++ b/lib/appmenuapplet.h @@ -29,12 +29,10 @@ class QQuickItem; class QMenu; class AppMenuModel; -class ActiveWindowControlApplet : public Plasma::Applet +class AppMenuApplet : public Plasma::Applet { Q_OBJECT - Q_PROPERTY(bool appletEnabled READ appletEnabled NOTIFY appletEnabledChanged) - Q_PROPERTY(AppMenuModel* model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(int view READ view WRITE setView NOTIFY viewChanged) @@ -49,8 +47,8 @@ class ActiveWindowControlApplet : public Plasma::Applet CompactView }; - explicit ActiveWindowControlApplet(QObject *parent, const QVariantList &data); - ~ActiveWindowControlApplet() override; + explicit AppMenuApplet(QObject *parent, const QVariantList &data); + ~AppMenuApplet() override; void init() override; @@ -65,22 +63,18 @@ class ActiveWindowControlApplet : public Plasma::Applet int view() const; void setView(int type); - bool appletEnabled() const; - signals: void modelChanged(); void viewChanged(); void currentIndexChanged(); void buttonGridChanged(); - void appletEnabledChanged(); void requestActivateIndex(int index); public slots: - void updateAppletEnabled(); void trigger(QQuickItem *ctx, int idx); protected: - bool eventFilter(QObject *watched, QEvent *event); + bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE; private: QMenu *createMenu(int idx) const; @@ -90,8 +84,8 @@ public slots: int m_currentIndex = -1; int m_viewType = FullView; - bool m_appletEnabled = true; QPointer<QMenu> m_currentMenu; QPointer<QQuickItem> m_buttonGrid; QPointer<AppMenuModel> m_model; + static int s_refs; }; diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 8f855ac..1a4efb9 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -1,27 +1,24 @@ -set(activewindowcontrolplugin_SRCS +set(appmenuapplet_SRCS appmenumodel.cpp - activewindowcontrolplugin.cpp - ) + appmenuplugin.cpp +) -add_library(activewindowcontrolplugin SHARED ${activewindowcontrolplugin_SRCS}) - -cmake_policy(SET CMP0053 NEW) -cmake_policy(SET CMP0063 NEW) +add_library(appmenuplugin SHARED ${appmenuapplet_SRCS}) +# load dbusmenuqt find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Widgets DBus) - +cmake_policy(SET CMP0063 NEW) add_subdirectory(libdbusmenuqt) -target_link_libraries(activewindowcontrolplugin +target_link_libraries(appmenuplugin Qt5::Core Qt5::Widgets Qt5::Quick - Qt5::DBus KF5::Plasma KF5::WindowSystem - dbusmenuqt - ) + dbusmenuqt) +# load X11 libraries find_package(X11) set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries" URL "http://www.x.org" @@ -45,15 +42,12 @@ endif() configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h) if(HAVE_X11) - find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED X11Extras) - find_package(XCB MODULE REQUIRED COMPONENTS XCB RANDR) + find_package(XCB MODULE REQUIRED COMPONENTS XCB) set_package_properties(XCB PROPERTIES TYPE REQUIRED) - target_link_libraries(activewindowcontrolplugin - Qt5::X11Extras - XCB::XCB - ) + target_link_libraries(appmenuplugin Qt5::X11Extras XCB::XCB) endif() -install(TARGETS activewindowcontrolplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/private/activeWindowControl) +# install plugin +install(TARGETS appmenuplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/private/activeWindowControl) install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/private/activeWindowControl) diff --git a/plugin/appmenumodel.cpp b/plugin/appmenumodel.cpp index 9d7d5e8..3b41ec6 100644 --- a/plugin/appmenumodel.cpp +++ b/plugin/appmenumodel.cpp @@ -25,22 +25,28 @@ #include <config-X11.h> -#ifdef HAVE_X11 +#if HAVE_X11 #include <QX11Info> #include <xcb/xcb.h> #endif #include <QAction> +#include <QGuiApplication> #include <QMenu> #include <QDebug> #include <QDBusConnection> #include <QDBusConnectionInterface> +#include <QDBusServiceWatcher> #include <dbusmenuimporter.h> static const QByteArray s_x11AppMenuServiceNamePropertyName = QByteArrayLiteral("_KDE_NET_WM_APPMENU_SERVICE_NAME"); static const QByteArray s_x11AppMenuObjectPathPropertyName = QByteArrayLiteral("_KDE_NET_WM_APPMENU_OBJECT_PATH"); +#if HAVE_X11 +static QHash<QByteArray, xcb_atom_t> s_atoms; +#endif + class KDBusMenuImporter : public DBusMenuImporter { @@ -60,17 +66,19 @@ class KDBusMenuImporter : public DBusMenuImporter }; AppMenuModel::AppMenuModel(QObject *parent) - : QAbstractListModel(parent) + : QAbstractListModel(parent), + m_serviceWatcher(new QDBusServiceWatcher(this)) { connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, this, &AppMenuModel::onActiveWindowChanged); connect(this, &AppMenuModel::modelNeedsUpdate, this, &AppMenuModel::update, Qt::UniqueConnection); onActiveWindowChanged(KWindowSystem::activeWindow()); + m_serviceWatcher->setConnection(QDBusConnection::sessionBus()); //if our current DBus connection gets lost, close the menu //we'll select the new menu when the focus changes - connect(QDBusConnection::sessionBus().interface(), &QDBusConnectionInterface::serviceOwnerChanged, this, [this](const QString &serviceName, const QString &oldOwner, const QString &newOwner) + connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [this](const QString &serviceName) { - if (serviceName == m_serviceName && newOwner.isEmpty()) { + if (serviceName == m_serviceName) { setMenuAvailable(false); emit modelNeedsUpdate(); } @@ -120,12 +128,18 @@ void AppMenuModel::update() void AppMenuModel::onActiveWindowChanged(WId id) { -#ifdef HAVE_X11 + qApp->removeNativeEventFilter(this); + + if (!id) { + setMenuAvailable(false); + emit modelNeedsUpdate(); + return; + } + +#if HAVE_X11 if (KWindowSystem::isPlatformX11()) { auto *c = QX11Info::connection(); - static QHash<QByteArray, xcb_atom_t> s_atoms; - auto getWindowPropertyString = [c, this](WId id, const QByteArray &name) -> QByteArray { QByteArray value; if (!s_atoms.contains(name)) { @@ -190,6 +204,11 @@ void AppMenuModel::onActiveWindowChanged(WId id) return; } + // monitor whether an app menu becomes available later + // this can happen when an app starts, shows its window, and only later announces global menu (e.g. Firefox) + qApp->installNativeEventFilter(this); + m_currentWindowId = id; + //no menu found, set it to unavailable setMenuAvailable(false); emit modelNeedsUpdate(); @@ -234,6 +253,8 @@ void AppMenuModel::updateApplicationMenu(const QString &serviceName, const QStri } m_serviceName = serviceName; + m_serviceWatcher->setWatchedServices(QStringList({m_serviceName})); + m_menuObjectPath = menuObjectPath; if (m_importer) { @@ -259,5 +280,46 @@ void AppMenuModel::updateApplicationMenu(const QString &serviceName, const QStri setMenuAvailable(true); emit modelNeedsUpdate(); }); + + connect(m_importer.data(), &DBusMenuImporter::actionActivationRequested, this, [this](QAction *action) { + // TODO submenus + auto it = std::find(m_activeActions.constBegin(), m_activeActions.constEnd(), action); + if (it != m_activeActions.constEnd()) { + requestActivateIndex(it - m_activeActions.constBegin()); + } + }); +} + +bool AppMenuModel::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +{ + Q_UNUSED(result); + + if (!KWindowSystem::isPlatformX11() || eventType != "xcb_generic_event_t") { + return false; + } + +#if HAVE_X11 + auto e = static_cast<xcb_generic_event_t *>(message); + const uint8_t type = e->response_type & ~0x80; + if (type == XCB_PROPERTY_NOTIFY) { + auto *event = reinterpret_cast<xcb_property_notify_event_t *>(e); + if (event->window == m_currentWindowId) { + + auto serviceNameAtom = s_atoms.value(s_x11AppMenuServiceNamePropertyName); + auto objectPathAtom = s_atoms.value(s_x11AppMenuObjectPathPropertyName); + + if (serviceNameAtom != XCB_ATOM_NONE && objectPathAtom != XCB_ATOM_NONE) { // shouldn't happen + if (event->atom == serviceNameAtom || event->atom == objectPathAtom) { + // see if we now have a menu + onActiveWindowChanged(KWindowSystem::activeWindow()); + } + } + } + } +#else + Q_UNUSED(message); +#endif + + return false; } diff --git a/plugin/appmenumodel.h b/plugin/appmenumodel.h index 77ad5e9..8d7ef92 100644 --- a/plugin/appmenumodel.h +++ b/plugin/appmenumodel.h @@ -20,6 +20,7 @@ ******************************************************************/ #include <QAbstractListModel> +#include <QAbstractNativeEventFilter> #include <QStringList> #include <KWindowSystem> #include <QPointer> @@ -27,9 +28,10 @@ class QMenu; class QAction; class QModelIndex; +class QDBusServiceWatcher; class KDBusMenuImporter; -class AppMenuModel : public QAbstractListModel +class AppMenuModel : public QAbstractListModel, public QAbstractNativeEventFilter { Q_OBJECT @@ -44,15 +46,21 @@ class AppMenuModel : public QAbstractListModel ActionRole }; - QVariant data(const QModelIndex &index, int role) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QHash<int, QByteArray> roleNames() const; + QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; void updateApplicationMenu(const QString &serviceName, const QString &menuObjectPath); bool menuAvailable() const; void setMenuAvailable(bool set); +signals: + void requestActivateIndex(int index); + +protected: + bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override; + private Q_SLOTS: void onActiveWindowChanged(WId id); void update(); @@ -64,10 +72,13 @@ private Q_SLOTS: private: bool m_menuAvailable; + WId m_currentWindowId = 0; + QPointer<QMenu> m_menu; QStringList m_activeMenu; QList<QAction *> m_activeActions; + QDBusServiceWatcher *m_serviceWatcher; QString m_serviceName; QString m_menuObjectPath; diff --git a/plugin/activewindowcontrolplugin.cpp b/plugin/appmenuplugin.cpp similarity index 92% rename from plugin/activewindowcontrolplugin.cpp rename to plugin/appmenuplugin.cpp index a5fe7de..76535cb 100644 --- a/plugin/activewindowcontrolplugin.cpp +++ b/plugin/appmenuplugin.cpp @@ -19,13 +19,13 @@ * ******************************************************************/ -#include "activewindowcontrolplugin.h" +#include "appmenuplugin.h" #include "appmenumodel.h" #include <QtQml> #include <QQmlEngine> -void ActiveWindowControlPlugin::registerTypes(const char *uri) +void AppmenuPlugin::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("org.kde.private.activeWindowControl")); qmlRegisterType<AppMenuModel>(uri, 1, 0, "AppMenuModel"); diff --git a/plugin/activewindowcontrolplugin.h b/plugin/appmenuplugin.h similarity index 90% rename from plugin/activewindowcontrolplugin.h rename to plugin/appmenuplugin.h index 6c587e0..583cec8 100644 --- a/plugin/activewindowcontrolplugin.h +++ b/plugin/appmenuplugin.h @@ -19,12 +19,12 @@ * ******************************************************************/ -#ifndef ACTIVEWINDOWCONTROLPLUGIN_H -#define ACTIVEWINDOWCONTROLPLUGIN_H +#ifndef APPMENUPLUGIN_H +#define APPMENUPLUGIN_H #include <QQmlExtensionPlugin> -class ActiveWindowControlPlugin : public QQmlExtensionPlugin +class AppmenuPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") diff --git a/plugin/libdbusmenuqt/CMakeLists.txt b/plugin/libdbusmenuqt/CMakeLists.txt index 49d3420..b92e5d6 100644 --- a/plugin/libdbusmenuqt/CMakeLists.txt +++ b/plugin/libdbusmenuqt/CMakeLists.txt @@ -18,5 +18,3 @@ target_link_libraries(dbusmenuqt Qt5::DBus Qt5::Widgets ) - -add_subdirectory(test) diff --git a/plugin/libdbusmenuqt/dbusmenuimporter.cpp b/plugin/libdbusmenuqt/dbusmenuimporter.cpp index 2aac5cd..707764f 100644 --- a/plugin/libdbusmenuqt/dbusmenuimporter.cpp +++ b/plugin/libdbusmenuqt/dbusmenuimporter.cpp @@ -362,6 +362,11 @@ void DBusMenuImporterPrivate::slotItemsPropertiesUpdated(const DBusMenuItemList } } +QAction *DBusMenuImporter::actionForId(int id) const +{ + return d->m_actionForId.value(id); +} + void DBusMenuImporter::slotItemActivationRequested(int id, uint /*timestamp*/) { QAction *action = d->m_actionForId.value(id); @@ -426,12 +431,10 @@ void DBusMenuImporter::slotGetLayoutFinished(QDBusPendingCallWatcher *watcher) sendClickedEvent(id); }); - if (action->menu()) { - auto menu = action->menu(); - connect(menu, &QMenu::aboutToShow, this, [menu, this]() { - updateMenu(menu); - }); + if (QMenu *menuAction = action->menu()) { + connect(menuAction, &QMenu::aboutToShow, this, &DBusMenuImporter::slotMenuAboutToShow, Qt::UniqueConnection); } + connect(menu, &QMenu::aboutToHide, this, &DBusMenuImporter::slotMenuAboutToHide, Qt::UniqueConnection); menu->addAction(action); } else { @@ -441,6 +444,9 @@ void DBusMenuImporter::slotGetLayoutFinished(QDBusPendingCallWatcher *watcher) filteredKeys.removeOne("toggle-type"); filteredKeys.removeOne("children-display"); d->updateAction(*it, dbusMenuItem.properties, filteredKeys); + // Move the action to the tail so we can keep the order same as the dbus request. + menu->removeAction(action); + menu->addAction(action); } } @@ -518,6 +524,8 @@ void DBusMenuImporter::slotMenuAboutToShow() QMenu *menu = qobject_cast<QMenu*>(sender()); Q_ASSERT(menu); + updateMenu(menu); + QAction *action = menu->menuAction(); Q_ASSERT(action); diff --git a/plugin/libdbusmenuqt/dbusmenuimporter.h b/plugin/libdbusmenuqt/dbusmenuimporter.h index 6d3fd4f..6f91ee9 100644 --- a/plugin/libdbusmenuqt/dbusmenuimporter.h +++ b/plugin/libdbusmenuqt/dbusmenuimporter.h @@ -47,6 +47,9 @@ class DBusMenuImporter : public QObject ~DBusMenuImporter() override; + + QAction *actionForId(int id) const; + /** * The menu created from listening to the DBusMenuExporter over DBus */ diff --git a/plugin/libdbusmenuqt/test/CMakeLists.txt b/plugin/libdbusmenuqt/test/CMakeLists.txt deleted file mode 100644 index a950a6f..0000000 --- a/plugin/libdbusmenuqt/test/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_executable(appmenutest main.cpp) -target_link_libraries(appmenutest - Qt5::Widgets) diff --git a/plugin/libdbusmenuqt/test/README b/plugin/libdbusmenuqt/test/README deleted file mode 100644 index 99dd020..0000000 --- a/plugin/libdbusmenuqt/test/README +++ /dev/null @@ -1,2 +0,0 @@ -App with a menu, designed for use testing appmenu QPTs/applets/kded modules -small enough that we can attach debuggers and breakpoints without drowning in data diff --git a/plugin/libdbusmenuqt/test/main.cpp b/plugin/libdbusmenuqt/test/main.cpp deleted file mode 100644 index 74a0e05..0000000 --- a/plugin/libdbusmenuqt/test/main.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2017 David Edmundson <davidedmundson@kde.org> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details - * - * You should have received a copy of the GNU Library General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <QApplication> - -#include <QMainWindow> -#include <QMenuBar> -#include <QDateTime> -#include <QIcon> -#include <QDebug> - -class MainWindow : public QMainWindow -{ -public: - MainWindow(); -}; - -MainWindow::MainWindow() : - QMainWindow() -{ - /*set an initial menu with the following - Menu A - - Item - - Checkable Item - - Item With Icon - - A separator - - Menu B - - Item B1 - Menu C - - DynamicItem ${timestamp} - - TopLevelItem - */ - - QAction *t; - auto menuA = new QMenu("Menu A", this); - menuA->addAction("Item"); - - t = menuA->addAction("Checkable Item"); - t->setCheckable(true); - - t = menuA->addAction(QIcon::fromTheme("document-edit"), "Item with icon"); - - menuA->addSeparator(); - - auto menuB = new QMenu("Menu B", this); - menuB->addAction("Item B1"); - menuA->addMenu(menuB); - - menuBar()->addMenu(menuA); - - auto menuC = new QMenu("Menu C", this); - connect(menuC, &QMenu::aboutToShow, this, [menuC]() { - menuC->clear(); - menuC->addAction("Dynamic Item " + QDateTime::currentDateTime().toString()); - }); - - menuBar()->addMenu(menuC); - - menuBar()->addAction("Top Level Item"); -} - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - MainWindow mw; - mw.show(); - return app.exec(); -} diff --git a/plugin/qmldir b/plugin/qmldir index e09e45e..e85fbc8 100644 --- a/plugin/qmldir +++ b/plugin/qmldir @@ -1,3 +1,3 @@ module org.kde.private.activeWindowControl -plugin activewindowcontrolplugin +plugin appmenuplugin
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor