Add `Area::sense` and improve hit-testing of buttons in menus (#4234)

Previously, putting the cursor in the gap between two menu buttons would
not hover any of the buttons, but the click-sensitive menu itself. Now
the menu is no longer click-sensitive.
This commit is contained in:
Emil Ernerfeldt 2024-03-26 11:12:49 +01:00 committed by GitHub
parent 9cfaf8b961
commit 8a880d6d0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 9 deletions

View File

@ -61,6 +61,7 @@ impl State {
#[derive(Clone, Copy, Debug)]
pub struct Area {
pub(crate) id: Id,
sense: Option<Sense>,
movable: bool,
interactable: bool,
enabled: bool,
@ -78,6 +79,7 @@ impl Area {
pub fn new(id: Id) -> Self {
Self {
id,
sense: None,
movable: true,
interactable: true,
constrain: false,
@ -114,7 +116,7 @@ impl Area {
self
}
/// moveable by dragging the area?
/// Moveable by dragging the area?
#[inline]
pub fn movable(mut self, movable: bool) -> Self {
self.movable = movable;
@ -139,6 +141,15 @@ impl Area {
self
}
/// Explicitly set a sense.
///
/// If not set, this will default to `Sense::drag()` if movable, `Sense::click()` if interactable, and `Sense::hover()` otherwise.
#[inline]
pub fn sense(mut self, sense: Sense) -> Self {
self.sense = Some(sense);
self
}
/// `order(Order::Foreground)` for an Area that should always be on top
#[inline]
pub fn order(mut self, order: Order) -> Self {
@ -255,6 +266,7 @@ impl Area {
pub(crate) fn begin(self, ctx: &Context) -> Prepared {
let Self {
id,
sense,
movable,
order,
interactable,
@ -299,13 +311,15 @@ impl Area {
// interact right away to prevent frame-delay
let mut move_response = {
let interact_id = layer_id.id.with("move");
let sense = if movable {
Sense::drag()
} else if interactable {
Sense::click() // allow clicks to bring to front
} else {
Sense::hover()
};
let sense = sense.unwrap_or_else(|| {
if movable {
Sense::drag()
} else if interactable {
Sense::click() // allow clicks to bring to front
} else {
Sense::hover()
}
});
let move_response = ctx.create_widget(WidgetRect {
id: interact_id,

View File

@ -149,7 +149,8 @@ pub(crate) fn menu_ui<'c, R>(
.order(Order::Foreground)
.fixed_pos(pos)
.constrain_to(ctx.screen_rect())
.interactable(true);
.interactable(true)
.sense(Sense::hover());
let area_response = area.show(ctx, |ui| {
set_menu_style(ui.style_mut());