feat: globalmenu updates

This commit is contained in:
sankalp committed 2026-07-29 09:31:05 +05:45
1 parent 47c413b374
commit 8980e90e39
3 files changed
+93 -15

No files matched your search

+35 -3
View File
@@ -233,9 +233,27 @@ class DBusMenuClient:
if item.has_submenu and not item.children:
try:
self.about_to_show(item.id)
child_params = GLib.Variant(
"(iias)", (item.id, self._revision, [])
)
child_res = self._call("GetLayout", child_params)
if child_res:
child_layout = child_res.get_child_value(1)
while child_layout.is_of_type(GLib.VariantType("v")):
child_layout = child_layout.get_variant()
children_variant = child_layout.get_child_value(2)
for i in range(children_variant.n_children()):
c = children_variant.get_child_value(i)
if c.is_of_type(GLib.VariantType("v")):
c = c.get_variant()
item.children.append(
self._parse_dbusmenu(
c, _depth + 1, item.id
)
)
except Exception as e:
logger.warning(
f"[dbusmenu] self.about_to_show(item.id) failed: {e}"
f"[dbusmenu] about_to_show/fetch children failed for {item.id}: {e}"
)
except Exception as e:
@@ -443,6 +461,17 @@ class DBusMenuClient:
logger.warning(f"[dbusmenu] bus.signal_unsubscribe(sid) failed: {e}")
self._signal_ids.clear()
def _find_and_update_children(self, items, parent_id, new_children):
for item in items:
if item.id == parent_id:
item.children = new_children
return True
if item.children and self._find_and_update_children(
item.children, parent_id, new_children
):
return True
return False
def update_layout(
self, parent_id: int, revision: int
) -> Optional[List[DBusMenuItem]]:
@@ -456,11 +485,14 @@ class DBusMenuClient:
while layout.is_of_type(GLib.VariantType("v")):
layout = layout.get_variant()
parsed = self._parse_dbusmenu(layout).children
if parent_id == 0:
with self._lock:
with self._lock:
if parent_id == 0:
self._hash_cache = self._hash(parsed)
self._cache = parsed
self._cache_valid = True
elif self._cache is not None:
self._find_and_update_children(self._cache, parent_id, parsed)
self._cache_valid = True
return parsed
except Exception as e:
logger.error(f"[Menu] update_layout error: {e}")
+14 -7
View File
@@ -438,14 +438,21 @@ class GlobalMenuService(Service):
subtree = entry.importer.update_layout(parent_id, revision)
if subtree is None:
return
if parent_id == 0:
with self._state_lock:
if entry.wm_class == self._current_wm_class:
with self._state_lock:
if entry.wm_class == self._current_wm_class:
full_menu = entry.importer.get_layout()
if full_menu is not None:
self._current_menu = full_menu
elif parent_id == 0:
self._current_menu = subtree
with self._seq_lock:
self._extraction_seq += 1
seq = self._extraction_seq
idle_add(self._emit_menu_changed, subtree, seq)
with self._seq_lock:
self._extraction_seq += 1
seq = self._extraction_seq
idle_add(
self._emit_menu_changed,
self._current_menu or subtree,
seq,
)
def _handle_items_updated(
self,
+44 -5
View File
@@ -95,7 +95,40 @@ def _clean_label(label):
return label.replace("_", "")
def _build_gtk_menu_from_children(children, click_handler):
def _on_item_select(item, svc, child, click_handler):
if getattr(item, "_lazy_loaded", False):
return
item._lazy_loaded = True
try:
logger.info(
f"[GlobalMenu] load submenu id={child.id} label={getattr(child, 'label', '')}"
)
svc.about_to_show(child.id)
entry, _ = svc._resolve_current_entry()
if entry and entry.importer and hasattr(entry.importer, "update_layout"):
new_children = entry.importer.update_layout(
child.id, getattr(entry, "revision", 0)
)
if new_children:
logger.info(
f"[GlobalMenu] got {len(new_children)} children for id={child.id}: "
f"{[getattr(c, 'label', '?') for c in new_children[:5]]}"
)
new_menu = _build_gtk_menu_from_children(
new_children, click_handler, svc
)
new_menu.show_all()
item.set_submenu(new_menu)
else:
logger.info(
f"[GlobalMenu] no children for id={child.id} "
f"(update_layout returned {new_children})"
)
except Exception as e:
logger.warning(f"[GlobalMenu] submenu load failed: {e}")
def _build_gtk_menu_from_children(children, click_handler, svc=None):
menu = Gtk.Menu()
for child in children:
@@ -116,11 +149,18 @@ def _build_gtk_menu_from_children(children, click_handler):
sub_children = child.children if child.children else []
has_sub = getattr(child, "has_submenu", False) or bool(sub_children)
if has_sub and sub_children:
if has_sub:
item = Gtk.MenuItem.new_with_label(f"{cleaned} \u25b8")
sub_menu = _build_gtk_menu_from_children(sub_children, click_handler)
sub_menu = _build_gtk_menu_from_children(
sub_children, click_handler, svc
)
sub_menu.show_all()
item.set_submenu(sub_menu)
if svc and getattr(child, "id", None) is not None:
item.connect(
"select", _on_item_select, svc, child, click_handler
)
else:
item = Gtk.MenuItem.new_with_label(cleaned)
if not enabled:
@@ -225,7 +265,6 @@ class GlobalMenuDropdowns:
except Exception:
logger.exception("[globalmenu] cleanup failed")
self._destroy_widgets(self._gtk_menu_buttons)
self._gtk_menu_buttons.clear()
self._destroy_widgets(self._gtk_menus)
@@ -260,7 +299,7 @@ class GlobalMenuDropdowns:
setup_cursor_hover(menu_btn, "pointer")
gtk_menu = _build_gtk_menu_from_children(
children, self._make_click_handler
children, self._make_click_handler, self._global_menu_svc
)
menu_btn.set_popup(gtk_menu)
menu_btn.show_all()