feat: globalmenu updates
This commit is contained in:
3 files changed
+93
-15
No files matched your search
@@ -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}")
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user