diff --git a/egui/src/context.rs b/egui/src/context.rs index f9084f87..1507f6da 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -196,13 +196,13 @@ impl CtxRef { changed: false, // must be set by the widget itself }; - if !enabled || sense == Sense::hover() || !layer_id.allow_interaction() { + if !enabled || !sense.focusable || !layer_id.allow_interaction() { // Not interested or allowed input: self.memory().surrender_kb_focus(id); return response; } - if sense.click { + if sense.focusable { self.memory().interested_in_kb_focus(id); } diff --git a/egui/src/sense.rs b/egui/src/sense.rs index 42a83386..27ef9322 100644 --- a/egui/src/sense.rs +++ b/egui/src/sense.rs @@ -7,6 +7,11 @@ pub struct Sense { /// sliders, windows, scroll bars, scroll areas ... pub drag: bool, + + /// this widgets want focus. + /// Anything interactive + labels that can be focused + /// for the benefit of screen readers. + pub focusable: bool, } impl Sense { @@ -15,6 +20,17 @@ impl Sense { Self { click: false, drag: false, + focusable: false, + } + } + + /// Senses no clicks or drags, but can be focused with the keyboard. + /// Used for labels that can be focused for the benefit of screen readers. + pub fn focusable_noninteractive() -> Self { + Self { + click: false, + drag: false, + focusable: true, } } @@ -28,6 +44,7 @@ impl Sense { Self { click: true, drag: false, + focusable: true, } } @@ -36,6 +53,7 @@ impl Sense { Self { click: false, drag: true, + focusable: true, } } @@ -44,6 +62,7 @@ impl Sense { Self { click: true, drag: true, + focusable: true, } } @@ -53,6 +72,7 @@ impl Sense { Self { click: self.click | other.click, drag: self.drag | other.drag, + focusable: self.focusable | other.focusable, } } } diff --git a/egui/src/widgets/label.rs b/egui/src/widgets/label.rs index 58daa7f0..4fd7313d 100644 --- a/egui/src/widgets/label.rs +++ b/egui/src/widgets/label.rs @@ -159,6 +159,10 @@ impl Label { // This should be the easiest method of putting text anywhere. pub fn paint_galley(&self, ui: &mut Ui, pos: Pos2, galley: Galley) { + self.paint_galley_kb_focus(ui, pos, galley, false) + } + + fn paint_galley_kb_focus(&self, ui: &mut Ui, pos: Pos2, galley: Galley, kb_focus: bool) { let Self { mut background_color, code, @@ -170,6 +174,8 @@ impl Label { .. } = *self; + let underline = underline || kb_focus; + let text_color = if let Some(text_color) = self.text_color { text_color } else if strong { @@ -237,6 +243,8 @@ impl Label { impl Widget for Label { fn ui(self, ui: &mut Ui) -> Response { + let sense = Sense::focusable_noninteractive(); + if self.should_wrap(ui) && ui.layout().main_dir() == Direction::LeftToRight && ui.layout().main_wrap() @@ -260,7 +268,7 @@ impl Widget for Label { assert!(!galley.rows.is_empty(), "Galleys are never empty"); let rect = galley.rows[0].rect().translate(vec2(pos.x, pos.y)); let id = ui.advance_cursor_after_rect(rect); - let mut total_response = ui.interact(rect, id, Sense::hover()); + let mut response = ui.interact(rect, id, sense); let mut y_translation = 0.0; if let Some(row) = galley.rows.get(1) { @@ -276,15 +284,16 @@ impl Widget for Label { row.y_max += y_translation; let rect = row.rect().translate(vec2(pos.x, pos.y)); ui.advance_cursor_after_rect(rect); - total_response |= ui.interact(rect, id, Sense::hover()); + response |= ui.interact(rect, id, sense); } - - self.paint_galley(ui, pos, galley); - total_response + response.widget_info(|| WidgetInfo::labeled(WidgetType::Label, &galley.text)); + self.paint_galley_kb_focus(ui, pos, galley, response.has_kb_focus()); + response } else { let galley = self.layout(ui); - let (rect, response) = ui.allocate_exact_size(galley.size, Sense::hover()); - self.paint_galley(ui, rect.min, galley); + let (rect, response) = ui.allocate_exact_size(galley.size, sense); + response.widget_info(|| WidgetInfo::labeled(WidgetType::Label, &galley.text)); + self.paint_galley_kb_focus(ui, rect.min, galley, response.has_kb_focus()); response } }