mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
fix(tray): open dbusmenu before layout fetch and show id-only rows
This commit is contained in:
@@ -275,10 +275,8 @@ namespace {
|
||||
if (entry.id <= 0 || !entry.visible) {
|
||||
return false;
|
||||
}
|
||||
if (entry.label.empty() && !entry.separator && !entry.hasSubmenu && entry.iconName.empty() &&
|
||||
entry.iconData.empty()) {
|
||||
return false;
|
||||
}
|
||||
// Keep rows whose labels (and icons) arrive only after ItemsPropertiesUpdated — the old Quickshell path
|
||||
// would still materialize these ids while the layout was filling in.
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -901,6 +899,20 @@ void TrayService::notifyMenuClosed(const std::string& itemId, std::int32_t entry
|
||||
sendMenuEvent(itemId, entryId, "closed");
|
||||
}
|
||||
|
||||
void TrayService::primeMenuForOpen(const std::string& itemId) {
|
||||
if (!ensureItemProxy(itemId)) {
|
||||
return;
|
||||
}
|
||||
const auto itemIt = m_items.find(itemId);
|
||||
if (itemIt == m_items.end()) {
|
||||
return;
|
||||
}
|
||||
if (itemIt->second.busName.empty() || itemIt->second.menuObjectPath.empty()) {
|
||||
return;
|
||||
}
|
||||
ensureMenuCache(itemId, itemIt->second.busName, itemIt->second.menuObjectPath);
|
||||
}
|
||||
|
||||
bool TrayService::activateMenuEntry(const std::string& itemId, std::int32_t entryId) {
|
||||
auto it = m_menuCache.find(itemId);
|
||||
if (it == m_menuCache.end() || it->second.proxy == nullptr) {
|
||||
|
||||
@@ -79,6 +79,8 @@ public:
|
||||
// open/close cycles.
|
||||
void notifyMenuOpened(const std::string& itemId, std::int32_t entryId = 0);
|
||||
void notifyMenuClosed(const std::string& itemId, std::int32_t entryId = 0);
|
||||
/// Ensures the dbusmenu proxy exists so notifyMenuOpened runs before the first menuEntries fetch.
|
||||
void primeMenuForOpen(const std::string& itemId);
|
||||
[[nodiscard]] std::vector<std::string> registeredItems() const;
|
||||
[[nodiscard]] bool activateItem(const std::string& itemId, std::int32_t x = 0, std::int32_t y = 0);
|
||||
[[nodiscard]] bool openContextMenu(const std::string& itemId, std::int32_t x = 0, std::int32_t y = 0);
|
||||
|
||||
@@ -323,6 +323,10 @@ void TrayMenu::toggleForItem(const std::string& itemId) {
|
||||
}
|
||||
|
||||
m_activeItemId = itemId;
|
||||
if (m_tray != nullptr) {
|
||||
m_tray->primeMenuForOpen(itemId);
|
||||
m_tray->notifyMenuOpened(m_activeItemId);
|
||||
}
|
||||
refreshEntries();
|
||||
|
||||
m_visible = true;
|
||||
@@ -332,14 +336,6 @@ void TrayMenu::toggleForItem(const std::string& itemId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify the dbusmenu server the root menu is being opened. Well-behaved
|
||||
// servers (including Electron) rely on paired opened/closed events to reset
|
||||
// internal state — skipping them causes their handlers to desync after many
|
||||
// open/close cycles, eventually returning errors on every GetLayout.
|
||||
if (m_tray != nullptr) {
|
||||
m_tray->notifyMenuOpened(m_activeItemId);
|
||||
}
|
||||
|
||||
rebuildScenes();
|
||||
}
|
||||
|
||||
@@ -977,6 +973,7 @@ void TrayMenu::openSubmenu(std::int32_t parentEntryId, float rowCenterY) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_tray->notifyMenuOpened(m_activeItemId, parentEntryId);
|
||||
m_submenuEntries = m_tray->menuEntriesForParent(m_activeItemId, parentEntryId);
|
||||
if (m_submenuEntries.empty()) {
|
||||
m_pendingSubmenuParentEntryId = parentEntryId;
|
||||
@@ -986,9 +983,6 @@ void TrayMenu::openSubmenu(std::int32_t parentEntryId, float rowCenterY) {
|
||||
m_pendingSubmenuParentEntryId = 0;
|
||||
m_pendingSubmenuRowCenterY = 0.0f;
|
||||
m_submenuParentEntryId = parentEntryId;
|
||||
// Signal the server that this submenu is being opened. Matches the opened/closed
|
||||
// pairing we do for the root menu.
|
||||
m_tray->notifyMenuOpened(m_activeItemId, parentEntryId);
|
||||
|
||||
// Anchor rect is in the main popup's coordinate space (0,0 = top-left of main popup surface)
|
||||
const auto mainWidth = static_cast<std::int32_t>(m_instance->surface->width());
|
||||
|
||||
Reference in New Issue
Block a user