mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 14:49:06 -04:00
Don't focus Areas, Windows and ScrollAreas (#7827)
Currently, tabbing through egui demo app, there are a lot of widgets that have invisible focus. Tabbing into a window for example takes 10 (!) presses of the tab key before the first widget within the window is focused. Before that, the focus moves to each resize handle, the scroll area and the scroll bar. At that point a user might think the focus is entirely broken. This pr removes the focusable sense from all these elements. Anything that can be focused should somehow indicate that it currently has focus, or the user could get frustrated. It also adds a debug flag to always show the focused widget, so it's easier to debug these cases
This commit is contained in:
@@ -505,9 +505,9 @@ impl Area {
|
||||
let interact_id = layer_id.id.with("move");
|
||||
let sense = sense.unwrap_or_else(|| {
|
||||
if movable {
|
||||
Sense::drag()
|
||||
Sense::DRAG
|
||||
} else if interactable {
|
||||
Sense::click() // allow clicks to bring to front
|
||||
Sense::CLICK // allow clicks to bring to front
|
||||
} else {
|
||||
Sense::hover()
|
||||
}
|
||||
|
||||
@@ -810,7 +810,7 @@ impl ScrollArea {
|
||||
// or we will steal input from the widgets we contain.
|
||||
let content_response_option = state
|
||||
.interact_rect
|
||||
.map(|rect| ui.interact(rect, id.with("area"), Sense::drag()));
|
||||
.map(|rect| ui.interact(rect, id.with("area"), Sense::DRAG));
|
||||
|
||||
if content_response_option
|
||||
.as_ref()
|
||||
@@ -1276,7 +1276,7 @@ impl Prepared {
|
||||
};
|
||||
|
||||
let sense = if scroll_source.scroll_bar && ui.is_enabled() {
|
||||
Sense::click_and_drag()
|
||||
Sense::CLICK | Sense::DRAG
|
||||
} else {
|
||||
Sense::hover()
|
||||
};
|
||||
|
||||
@@ -937,7 +937,7 @@ fn move_and_resize_window(ctx: &Context, id: Id, interaction: &ResizeInteraction
|
||||
fn do_resize_interaction(
|
||||
ctx: &Context,
|
||||
possible: PossibleInteractions,
|
||||
_accessibility_parent: Id,
|
||||
accessibility_parent: Id,
|
||||
layer_id: LayerId,
|
||||
outer_rect: Rect,
|
||||
window_frame: Frame,
|
||||
@@ -957,14 +957,14 @@ fn do_resize_interaction(
|
||||
let rect = outer_rect.shrink(window_frame.stroke.width / 2.0);
|
||||
|
||||
let side_response = |rect, id| {
|
||||
ctx.register_accesskit_parent(id, _accessibility_parent);
|
||||
ctx.register_accesskit_parent(id, accessibility_parent);
|
||||
let response = ctx.create_widget(
|
||||
WidgetRect {
|
||||
layer_id,
|
||||
id,
|
||||
rect,
|
||||
interact_rect: rect,
|
||||
sense: Sense::drag(),
|
||||
sense: Sense::DRAG, // Don't use Sense::drag() since we don't want these to be focusable
|
||||
enabled: true,
|
||||
},
|
||||
true,
|
||||
@@ -1324,7 +1324,7 @@ impl TitleBar {
|
||||
let id = ui.unique_id().with("__window_title_bar");
|
||||
|
||||
if ui
|
||||
.interact(double_click_rect, id, Sense::click())
|
||||
.interact(double_click_rect, id, Sense::CLICK)
|
||||
.double_clicked()
|
||||
&& collapsible
|
||||
{
|
||||
|
||||
@@ -2432,7 +2432,8 @@ impl Context {
|
||||
if let Some(widget) =
|
||||
self.write(|ctx| ctx.viewport().this_pass.widgets.get(id).copied())
|
||||
{
|
||||
paint_widget(&widget, text, color);
|
||||
let text = format!("{text} - {id:?}");
|
||||
paint_widget(&widget, &text, color);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2541,6 +2542,12 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
if self.global_style().debug.show_focused_widget
|
||||
&& let Some(focused_id) = self.memory(|mem| mem.focused())
|
||||
{
|
||||
paint_widget_id(focused_id, "focused", Color32::PURPLE);
|
||||
}
|
||||
|
||||
if let Some(debug_rect) = self.pass_state_mut(|fs| fs.debug_rect.take()) {
|
||||
debug_rect.paint(&self.debug_painter());
|
||||
}
|
||||
|
||||
@@ -53,19 +53,23 @@ impl Sense {
|
||||
Self::FOCUSABLE
|
||||
}
|
||||
|
||||
/// Sense clicks and hover, but not drags.
|
||||
/// Sense clicks and hover, but not drags, and make the widget focusable.
|
||||
///
|
||||
/// Use [`Sense::CLICK`] if you don't want the widget to be focusable.
|
||||
#[inline]
|
||||
pub fn click() -> Self {
|
||||
Self::CLICK | Self::FOCUSABLE
|
||||
}
|
||||
|
||||
/// Sense drags and hover, but not clicks.
|
||||
/// Sense drags and hover, but not clicks. Make the widget focusable.
|
||||
///
|
||||
/// Use [`Sense::DRAG`] if you don't want the widget to be focusable
|
||||
#[inline]
|
||||
pub fn drag() -> Self {
|
||||
Self::DRAG | Self::FOCUSABLE
|
||||
}
|
||||
|
||||
/// Sense both clicks, drags and hover (e.g. a slider or window).
|
||||
/// Sense both clicks, drags and hover (e.g. a slider or window), and make the widget focusable.
|
||||
///
|
||||
/// Note that this will introduce a latency when dragging,
|
||||
/// because when the user starts a press egui can't know if this is the start
|
||||
|
||||
@@ -1303,6 +1303,13 @@ pub struct DebugOptions {
|
||||
///
|
||||
/// See [`emath::GuiRounding`] for more.
|
||||
pub show_unaligned: bool,
|
||||
|
||||
/// Highlight the currently focused widget.
|
||||
///
|
||||
/// This is useful when some widget has a invisible focus (e.g. when a widget is using
|
||||
/// `Sense::click()` when it should be using `Sense::CLICK`) and you need to find which one it
|
||||
/// is.
|
||||
pub show_focused_widget: bool,
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -1319,6 +1326,7 @@ impl Default for DebugOptions {
|
||||
show_interactive_widgets: false,
|
||||
show_widget_hits: false,
|
||||
show_unaligned: cfg!(debug_assertions),
|
||||
show_focused_widget: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2480,6 +2488,7 @@ impl DebugOptions {
|
||||
show_interactive_widgets,
|
||||
show_widget_hits,
|
||||
show_unaligned,
|
||||
show_focused_widget,
|
||||
} = self;
|
||||
|
||||
{
|
||||
@@ -2514,6 +2523,11 @@ impl DebugOptions {
|
||||
"Show rectangles not aligned to integer point coordinates",
|
||||
);
|
||||
|
||||
ui.checkbox(
|
||||
show_focused_widget,
|
||||
"Highlight which widget has keyboard focus",
|
||||
);
|
||||
|
||||
ui.vertical_centered(|ui| reset_button(ui, self, "Reset debug options"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user