fix(context-menu): close menu if pressed out of bounds and open

This commit is contained in:
Ashley Wulber 2025-07-23 10:22:31 -04:00 committed by Ashley Wulber
parent 3c13669865
commit c40eb87611

View file

@ -346,14 +346,21 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
} }
state.open state.open
}); });
if matches!( let mut was_open = false;
event, if matches!(event,
Event::Keyboard(keyboard::Event::KeyPressed { Event::Keyboard(keyboard::Event::KeyPressed {
key: keyboard::Key::Named(keyboard::key::Named::Escape), key: keyboard::Key::Named(keyboard::key::Named::Escape),
.. ..
}) })
) { | Event::Mouse(mouse::Event::ButtonPressed(
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| { state.menu_bar_state.inner.with_data_mut(|state| {
was_open = true;
state.menu_states.clear(); state.menu_states.clear();
state.active_root.clear(); state.active_root.clear();
state.open = false; state.open = false;
@ -371,7 +378,8 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
} }
}); });
} }
if cursor.is_over(bounds) {
if !was_open && cursor.is_over(bounds) {
let fingers_pressed = state.fingers_pressed.len(); let fingers_pressed = state.fingers_pressed.len();
match event { match event {
@ -383,36 +391,12 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
state.fingers_pressed.remove(&id); state.fingers_pressed.remove(&id);
} }
Event::Window(window::Event::Focused) => {
#[cfg(all(
feature = "wayland",
feature = "winit",
feature = "surface-message"
))]
if matches!(WINDOWING_SYSTEM.get(), Some(WindowingSystem::Wayland)) {
state.menu_bar_state.inner.with_data_mut(|state| {
if let Some(id) = state.popup_id.remove(&self.window_id) {
state.menu_states.clear();
state.active_root.clear();
state.open = false;
{
let surface_action = self.on_surface_action.as_ref().unwrap();
shell.publish(surface_action(
crate::surface::action::destroy_popup(id),
));
}
state.view_cursor = cursor;
}
});
}
}
_ => (), _ => (),
} }
// Present a context menu on a right click event. // Present a context menu on a right click event.
if self.context_menu.is_some() 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(); state.context_cursor = cursor.position().unwrap_or_default();
@ -427,64 +411,35 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
} }
return event::Status::Captured; return event::Status::Captured;
} else if right_button_released(&event) } else if !was_open && right_button_released(&event)
|| (touch_lifted(&event)) || (touch_lifted(&event))
|| left_button_released(&event) || left_button_released(&event)
{ {
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))] state.menu_bar_state.inner.with_data_mut(|state| {
if matches!(WINDOWING_SYSTEM.get(), Some(WindowingSystem::Wayland)) { was_open = true;
state.menu_bar_state.inner.with_data_mut(|state| { state.menu_states.clear();
if let Some(id) = state.popup_id.remove(&self.window_id) { state.active_root.clear();
state.menu_states.clear(); state.open = false;
state.active_root.clear();
state.open = false;
{
let surface_action = self.on_surface_action.as_ref().unwrap();
shell.publish(surface_action(
crate::surface::action::destroy_popup(id),
));
}
state.view_cursor = cursor;
}
});
}
}
} else if open {
match event {
Event::Mouse(mouse::Event::ButtonReleased(
mouse::Button::Right | mouse::Button::Left,
))
| Event::Touch(touch::Event::FingerLifted { .. }) => {
#[cfg(all( #[cfg(all(
feature = "wayland", feature = "wayland",
feature = "winit", feature = "winit",
feature = "surface-message" feature = "surface-message"
))] ))]
if matches!(WINDOWING_SYSTEM.get(), Some(WindowingSystem::Wayland)) { if matches!(WINDOWING_SYSTEM.get(), Some(WindowingSystem::Wayland)) {
state.menu_bar_state.inner.with_data_mut(|state| { if let Some(id) = state.popup_id.remove(&self.window_id) {
if let Some(id) = state.popup_id.remove(&self.window_id) { {
state.menu_states.clear(); let surface_action = self.on_surface_action.as_ref().unwrap();
state.active_root.clear(); shell.publish(surface_action(
state.open = false; crate::surface::action::destroy_popup(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;
} }
}); state.view_cursor = cursor;
}
} }
} });
_ => (),
} }
} }
self.content.as_widget_mut().on_event( self.content.as_widget_mut().on_event(
&mut tree.children[0], &mut tree.children[0],
event, event,