fix: context-menu

when a popup is created and a focus event is received, we shouldn't close the popups, because it may be a focus event for a popup
This commit is contained in:
Ashley Wulber 2026-02-22 23:32:38 -05:00
parent fb1a7d3640
commit 442ce6ad0c

View file

@ -13,7 +13,7 @@ use derive_setters::Setters;
use iced::touch::Finger;
use iced::{Event, Vector, keyboard, window};
use iced_core::widget::{Tree, Widget, tree};
use iced_core::{Length, Point, Size, event, mouse, touch};
use iced_core::{Length, Point, Size, mouse, touch};
use std::collections::HashSet;
use std::sync::Arc;
@ -85,6 +85,7 @@ impl<Message: Clone + 'static> ContextMenu<'_, Message> {
// close existing popups
state.menu_states.clear();
state.active_root.clear();
dbg!("closing existing popups");
shell.publish(self.on_surface_action.as_ref().unwrap()(destroy_popup(id)));
state.view_cursor = view_cursor;
(
@ -336,13 +337,12 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
.with_data(|d| !d.open && !d.active_root.is_empty());
let open = state.menu_bar_state.inner.with_data_mut(|state| {
if reset {
if let Some(popup_id) = state.popup_id.get(&self.window_id).copied() {
if let Some(handler) = self.on_surface_action.as_ref() {
shell.publish((handler)(crate::surface::Action::DestroyPopup(popup_id)));
state.reset();
}
}
if reset
&& let Some(popup_id) = state.popup_id.get(&self.window_id).copied()
&& let Some(handler) = self.on_surface_action.as_ref()
{
shell.publish((handler)(crate::surface::Action::DestroyPopup(popup_id)));
state.reset();
}
state.open
});
@ -356,7 +356,6 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
mouse::Button::Right | mouse::Button::Left,
))
| Event::Touch(touch::Event::FingerPressed { .. })
| Event::Window(window::Event::Focused)
if open )
{
state.menu_bar_state.inner.with_data_mut(|state| {
@ -366,15 +365,14 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
state.open = false;
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
if matches!(WINDOWING_SYSTEM.get(), Some(WindowingSystem::Wayland)) {
if let Some(id) = state.popup_id.remove(&self.window_id) {
{
let surface_action = self.on_surface_action.as_ref().unwrap();
shell
.publish(surface_action(crate::surface::action::destroy_popup(id)));
}
state.view_cursor = cursor;
if matches!(WINDOWING_SYSTEM.get(), Some(WindowingSystem::Wayland))
&& let Some(id) = state.popup_id.remove(&self.window_id)
{
{
let surface_action = self.on_surface_action.as_ref().unwrap();
shell.publish(surface_action(crate::surface::action::destroy_popup(id)));
}
state.view_cursor = cursor;
}
});
}
@ -388,7 +386,7 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
}
Event::Touch(touch::Event::FingerLifted { id, .. }) => {
state.fingers_pressed.remove(&id);
state.fingers_pressed.remove(id);
}
_ => (),
@ -397,7 +395,7 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
// Present a context menu on a right click event.
if !was_open
&& self.context_menu.is_some()
&& (right_button_released(&event) || (touch_lifted(&event) && fingers_pressed == 2))
&& (right_button_released(event) || (touch_lifted(event) && fingers_pressed == 2))
{
state.context_cursor = cursor.position().unwrap_or_default();
let state = tree.state.downcast_mut::<LocalState>();
@ -412,9 +410,9 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
shell.capture_event();
return;
} else if !was_open && right_button_released(&event)
|| (touch_lifted(&event))
|| left_button_released(&event)
} else if !was_open && right_button_released(event)
|| (touch_lifted(event))
|| left_button_released(event)
{
state.menu_bar_state.inner.with_data_mut(|state| {
was_open = true;
@ -427,16 +425,15 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
feature = "winit",
feature = "surface-message"
))]
if matches!(WINDOWING_SYSTEM.get(), Some(WindowingSystem::Wayland)) {
if let Some(id) = state.popup_id.remove(&self.window_id) {
{
let surface_action = self.on_surface_action.as_ref().unwrap();
shell.publish(surface_action(
crate::surface::action::destroy_popup(id),
));
}
state.view_cursor = cursor;
if matches!(WINDOWING_SYSTEM.get(), Some(WindowingSystem::Wayland))
&& let Some(id) = state.popup_id.remove(&self.window_id)
{
{
let surface_action = self.on_surface_action.as_ref().unwrap();
shell
.publish(surface_action(crate::surface::action::destroy_popup(id)));
}
state.view_cursor = cursor;
}
});
}
@ -450,7 +447,7 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
clipboard,
shell,
viewport,
)
);
}
fn overlay<'b>(
@ -458,7 +455,7 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
tree: &'b mut Tree,
layout: iced_core::Layout<'_>,
_renderer: &crate::Renderer,
viewport: &iced::Rectangle,
_viewport: &iced::Rectangle,
translation: Vector,
) -> Option<iced_core::overlay::Element<'b, Message, crate::Theme, crate::Renderer>> {
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]