diff --git a/applets/appmenu/package/contents/ui/main.qml b/applets/appmenu/package/contents/ui/main.qml --- a/applets/appmenu/package/contents/ui/main.qml +++ b/applets/appmenu/package/contents/ui/main.qml @@ -104,7 +104,7 @@ Repeater { id: buttonRepeater - model: appMenuModel + model: !appMenuModel.menuHidden ? appMenuModel : 0 PlasmaComponents.ToolButton { readonly property int buttonIndex: index diff --git a/applets/appmenu/plugin/appmenumodel.h b/applets/appmenu/plugin/appmenumodel.h --- a/applets/appmenu/plugin/appmenumodel.h +++ b/applets/appmenu/plugin/appmenumodel.h @@ -39,6 +39,7 @@ Q_OBJECT Q_PROPERTY(bool menuAvailable READ menuAvailable WRITE setMenuAvailable NOTIFY menuAvailableChanged) + Q_PROPERTY(bool menuHidden READ menuHidden NOTIFY menuHiddenChanged) public: explicit AppMenuModel(QObject *parent = nullptr); @@ -58,25 +59,34 @@ bool menuAvailable() const; void setMenuAvailable(bool set); + bool menuHidden() const; + 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 onWindowChanged(WId id); + void setMenuHidden(bool hide); void update(); signals: void menuAvailableChanged(); + void menuHiddenChanged(); void modelNeedsUpdate(); private: bool m_menuAvailable; + bool m_menuHidden = false; bool m_updatePending = false; + //! current active window used WId m_currentWindowId = 0; + //! window that its menu initialization may be delayed + WId m_delayedMenuWindowId = 0; QPointer m_menu; diff --git a/applets/appmenu/plugin/appmenumodel.cpp b/applets/appmenu/plugin/appmenumodel.cpp --- a/applets/appmenu/plugin/appmenumodel.cpp +++ b/applets/appmenu/plugin/appmenumodel.cpp @@ -69,12 +69,18 @@ m_serviceWatcher(new QDBusServiceWatcher(this)) { connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, this, &AppMenuModel::onActiveWindowChanged); + connect(KWindowSystem::self() + , static_cast(&KWindowSystem::windowChanged) + , this + , &AppMenuModel::onWindowChanged); + connect(this, &AppMenuModel::modelNeedsUpdate, this, [this] { if (!m_updatePending) { m_updatePending = true; QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); } }); + onActiveWindowChanged(KWindowSystem::activeWindow()); m_serviceWatcher->setConnection(QDBusConnection::sessionBus()); @@ -100,10 +106,24 @@ { if (m_menuAvailable != set) { m_menuAvailable = set; + setMenuHidden(false); emit menuAvailableChanged(); } } +bool AppMenuModel::menuHidden() const +{ + return m_menuHidden; +} + +void AppMenuModel::setMenuHidden(bool hide) +{ + if (m_menuHidden != hide) { + m_menuHidden = hide; + emit menuHiddenChanged(); + } +} + int AppMenuModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); @@ -187,23 +207,27 @@ return; } + m_currentWindowId = id; + WId transientId = info.transientFor(); // lok at transient windows first while (transientId) { if (updateMenuFromWindowIfHasMenu(transientId)) { + setMenuHidden(false); return; } transientId = KWindowInfo(transientId, nullptr, NET::WM2TransientFor).transientFor(); } if (updateMenuFromWindowIfHasMenu(id)) { + setMenuHidden(false); 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; + m_delayedMenuWindowId = id; //no menu found, set it to unavailable setMenuAvailable(false); @@ -213,6 +237,13 @@ } +void AppMenuModel::onWindowChanged(WId id) +{ + if (m_currentWindowId == id) { + KWindowInfo info(id, NET::WMState); + setMenuHidden(info.isMinimized()); + } +} QHash AppMenuModel::roleNames() const { @@ -321,7 +352,7 @@ const uint8_t type = e->response_type & ~0x80; if (type == XCB_PROPERTY_NOTIFY) { auto *event = reinterpret_cast(e); - if (event->window == m_currentWindowId) { + if (event->window == m_delayedMenuWindowId) { auto serviceNameAtom = s_atoms.value(s_x11AppMenuServiceNamePropertyName); auto objectPathAtom = s_atoms.value(s_x11AppMenuObjectPathPropertyName);