From ad49e32de9ca6d64ef04f6edef2f53bd37c8b2df Mon Sep 17 00:00:00 2001 From: Nils Pukropp Date: Fri, 9 Oct 2026 02:44:00 +0200 Subject: [PATCH] fix(gui): context menus size to fit instead of scrolling A popover is sized and placed again when its parent's layout manager allocates it. Context menus were parented to the outermost list view, and the keyboard menu to the ScrolledWindow; neither has a layout manager, so a menu kept the size it was first given and often opened too short, with a scrollbar. The host is now the first widget from the list view up that has a layout manager, which still keeps menus out of list items and the theme rules that style their insides. --- crates/pdfs-gui/src/app/widgets/menu.rs | 32 ++++++++++++++++++------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/crates/pdfs-gui/src/app/widgets/menu.rs b/crates/pdfs-gui/src/app/widgets/menu.rs index 74dc19f..0e55a15 100644 --- a/crates/pdfs-gui/src/app/widgets/menu.rs +++ b/crates/pdfs-gui/src/app/widgets/menu.rs @@ -128,20 +128,34 @@ impl ActionMenu { } } -/// Where a menu opened over `anchor` should live in the widget tree: the -/// outermost grid or list view around it, or `anchor` itself. CSS descendant -/// selectors reach through a popover to its parent, and themes style the -/// insides of list items (`gridview > child box { margin: 12px }` in -/// Catppuccin); a menu parented to a tile picks those rules up and puts a wide -/// margin around every section. Under the view itself it is no item's child. +/// Where a menu opened over `anchor` should live in the widget tree. +/// +/// Not inside a list item: CSS descendant selectors reach through a popover to +/// its parent, and themes style the insides of list items (`gridview > child +/// box { margin: 12px }` in Catppuccin); a menu parented to a tile picks those +/// rules up and puts a wide margin around every section. So the search starts +/// at the outermost grid or list view around `anchor`. +/// +/// Not on a widget without a layout manager either: a popover is sized and +/// placed again when its parent's layout manager allocates it. The list views +/// and `ScrolledWindow` have none, so a menu parented there kept the size it was +/// first given, often too small, and opened scrolling. The host is the first +/// widget from there up that has one. fn popover_host(anchor: >k4::Widget) -> gtk4::Widget { - let mut host = anchor.clone(); + let mut start = anchor.clone(); let mut widget = anchor.parent(); while let Some(w) = widget { widget = w.parent(); if w.is::() || w.is::() || w.is::() { - host = w; + start = w; } } - host + let mut host = Some(start.clone()); + while let Some(w) = host { + if w.layout_manager().is_some() { + return w; + } + host = w.parent(); + } + start }