fix: request redraw on dropdown open/close in the in-window overlay path

`Dropdown::new` (the plain constructor used by any non-applet consumer) leaves `window_id`/`on_surface_action` unset, which routes the widget's `overlay()` impl to the in-window overlay path rather than the surface-action-based popup path. On that path, `update()`'s `open` closure and its close counterparts only ever requested a redraw inside the `#[cfg(wayland_platform)] if let Some(...)` block gated on those fields being set — so for the common case, opening or closing a dropdown flipped `is_open` with no redraw requested at all. The stale frame stuck around until some unrelated later event (e.g. cursor motion landing on the now-open/closed menu's bounds) forced a repaint,
making the menu appear to not open until the mouse moved, and not close until the same thing happened again on the way out.

Add an unconditional `shell.request_redraw()` at each of the three `is_open` transitions that don't already publish a Message of their own (an actual option selection already triggers a normal Message-driven redraw through the app's own update cycle, so that path needed no change):

- `open`: right after `is_open` is set true, ahead of the wayland-only surface-action block.
- the `close_operation` branch of the open/close operation state machine (`Id`-based programmatic close).
- the click-outside-closes-it branch of the mouse/touch press handler.

Fixes #1395
This commit is contained in:
Paul 2026-08-17 18:51:29 -04:00 • committed by Michael Murphy
parent c1897c01aa
commit 75e9ee7e65

View file

@ -661,6 +661,7 @@ pub fn update<
state.close_operation = false;
state.is_open.store(false, Ordering::SeqCst);
if is_open {
shell.request_redraw();
#[cfg(wayland_platform)]
if let Some(ref on_close) = on_surface_action {
shell.publish(on_close(surface::action::destroy_popup(state.popup_id)));
@ -684,6 +685,7 @@ pub fn update<
// Event wasn't processed by overlay, so cursor was clicked either outside it's
// bounds or on the drop-down, either way we close the overlay.
state.is_open.store(false, Ordering::Relaxed);
shell.request_redraw();
#[cfg(wayland_platform)]
if let Some(on_close) = on_surface_action {
shell.publish(on_close(surface::action::destroy_popup(state.popup_id)));