Skip to content

feat: improved dropdown menus - #328

Open
waltmck wants to merge 15 commits into
wayle-rs:masterfrom
waltmck:fix-systray-dropdowns
Open

feat: improved dropdown menus#328
waltmck wants to merge 15 commits into
wayle-rs:masterfrom
waltmck:fix-systray-dropdowns

Conversation

@waltmck

@waltmck waltmck commented Jul 12, 2026

Copy link
Copy Markdown

#285 was caused by GtkPopoverMenu not being able to scroll: so, a menu/submenu that was too tall would simply overflow the screen and become unusable. In the process of rewriting this, I ran into some issues with autohide popovers.

GTK's autohide popover is, on Wayland, a xdg_popup grab (captures pointer + keyboard). On Hyprland/wlroots that grab is inherently buggy in ways that seem to be unavoidable:

  • Input freezes until the next pointer motion after an outside-click dismissal (Mouse interactions wont repeat unless you move the cursor. #62).
  • The dismiss-click is swallowed by the protocol, so clicking another bar button dismisses but doesn't open it.
  • Nested autohide popovers (our cascading systray menu) deadlock the grab chain.

My solution is to introduce a scrim, a transparent full-screen window that intercepts mouse and keyboard input whenever a popover is open. This is similar to and inspired by the approach used by eww/AGS/Astal, which draw their popup menus as a child widget inside a transparent fullscreen window (for the same reasons, to avoid buggy autohide behavior). However, I wanted to allow users to quickly switch between dropdowns with a single click, similar to the behavior of the bar on MacOS. The eww/AGS/Astal approach would layer the scrim above the bar, making other bar buttons non-functional when a popup was open (clicking them would just close the currently open popup).

My approach keeps dropdowns as real GTK popovers parented to bar buttons (their own surfaces), and the scrim is only a dismiss catcher, never a content host. That gives GTK-native popover positioning/flip/scroll. and one-click dropdown switching is achieved by keeping the bar layered above the scrim.

Additionally, whenever a popup is open the bar (and popup) will now be layered above even full-screen applications (again matching the behavior of MacOS). This allows CLI dispatchers (keep reading) to function even when a full-screen app is open.

Finally, in implementing the scrim-based approach I ran into several focus-grabbing race conditions. The cleanest solution to these turned out to be centralizing dropdown dispatch into a single dropdown coordinator. This made it straightforward to implement a CLI to open/close/toggle dropdowns, which I also implemented. This can be used by:

wayle dropdown list

which lists available dropdown menus; these can be opened and closed with wayle dropdown open <name> or wayle dropdown toggle <name>. By default dropdowns are opened/closed on the currently active monitor (which is determined using compositor-specific features), but as a fallback they will open/close on all monitors. The monitor can be overridden by passing --monitor=<name> or --monitor=all. Similar CLI bindings can control systray icons (wayle systray open and wayle systray toggle), with the same --monitor semantics.

Closes #62, closes #285, closes #173.

Note the merge conflicts with my existing PRs; see merge commit here.

Extensively tested on Hyprland, but needs additional testing on other compositors (Sway, Niri, Mango, etc.).

@waltmck waltmck changed the title feat: scrollable systray menus, plus scrim-based approach for popovers feat: improved dropdown menus: scrim-based approach, centralized dropdown dispatch, CLI to open/close dropdowns, fixed systray Jul 14, 2026
@waltmck waltmck changed the title feat: improved dropdown menus: scrim-based approach, centralized dropdown dispatch, CLI to open/close dropdowns, fixed systray feat: improved dropdown menus Jul 14, 2026
@justjustie

Copy link
Copy Markdown
Contributor

Sounds like this would also close #173

@waltmck

waltmck commented Jul 14, 2026

Copy link
Copy Markdown
Author

Sounds like this would also close #173

Yep it does, I missed that one. Added it to the description.

@waltmck
waltmck force-pushed the fix-systray-dropdowns branch 2 times, most recently from 0b685db to 009a7f8 Compare July 25, 2026 22:49
# Conflicts:
#	crates/wayle-shell/src/shell/bar/modules/systray/item/methods.rs
#	crates/wayle-shell/src/shell/bar/modules/systray/item/mod.rs
@Jas-SinghFSU Jas-SinghFSU self-assigned this Jul 27, 2026
Comment thread crates/wayle-config/src/infrastructure/service.rs Outdated
@Jas-SinghFSU

Copy link
Copy Markdown
Collaborator

Still in the process of reviewing, this is quite a chonker so I need to understand the intent, architecture and code - may take a bit.

Though one regression I noticed is that, on multi-monitor setups previously, the dropdown would hide if we clicked somewhere on another monitor. Here's an example scenario in which you have 2 monitors DP-1, DP-2:

  1. You click the audio dropdown in DP-1 and it opens the dropdown
  2. You move your mouse to DP-2 and click somewhere
  3. The dropdown in DP-1 now closes due to that click

Now, that dropdown remains open unless you click somewhere on the monitor in which the dropdown is open. Which is a behavioral regression. Is there some way to tackle this, perhaps with cross monitor shims? We do have to be aware of not adding more complexity to satisfy this though. We'll have to make that tradeoff and whether this regression is worth the one click dropdown switching.

@waltmck

waltmck commented Jul 27, 2026

Copy link
Copy Markdown
Author

Still in the process of reviewing, this is quite a chonker so I need to understand the intent, architecture and code - may take a bit.

Of course, take your time! Thanks for the review.

Though one regression I noticed is that, on multi-monitor setups previously, the dropdown would hide if we clicked somewhere on another monitor. Here's an example scenario in which you have 2 monitors DP-1, DP-2:

1. You click the audio dropdown in DP-1 and it opens the dropdown

2. You move your mouse to DP-2 and click somewhere

3. The dropdown in DP-1 now closes due to that click

Now, that dropdown remains open unless you click somewhere on the monitor in which the dropdown is open. Which is a behavioral regression. Is there some way to tackle this, perhaps with cross monitor shims? We do have to be aware of not adding more complexity to satisfy this though. We'll have to make that tradeoff and whether this regression is worth the one click dropdown switching.

My choice to change this behavior was actually intentional. The things that made me lean toward the per-monitor dropdown design were

  1. The new behavior matches MacOS's dropdowns, which will likely be familiar to many people.
  2. Global click-to-dismiss would lead to strange behavior with remote desktops: opening a menu on the remote desktop's virtual monitor would also open the scrim on the physical monitor, which seems counterintuitive to me.
  3. The scrim prevents keyboard input to a visible window. If a dropdown were opened on monitor 1 and this opened a scrim on monitor 2, keyboard inputs intended for a visible window on monitor 2 would be lost. This is counterintuitive because there is not visual indication on monitor 2 that the keyboard inputs are being swallowed (since there is no dropdown open). This behavior was also a UI shortcoming of the old approach.

If you would like a global click-to-dismiss I do think it can be implemented without too much additional complexity. A few follow-up questions:

  1. Should opening a dropdown on monitor 1 close other dropdowns that are open on monitor 2?
  2. Should opening a dropdown on monitor 1 also open the same dropdown on monitor 2, or just the scrim?
  3. If no to (2): how should we visually indicate on monitor 2 that keyboard inputs are being swallowed?
  4. If no to (2): should keyboard inputs on monitor 2's scrim control monitor 1's dropdowns?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: no scrolling for systray dropdown menus Feat: Launch dropdowns from command line Mouse interactions wont repeat unless you move the cursor.

3 participants