Browse Source

[text] surrender keyboard focus by clicking outside text edit area

pull/15/head
Emil Ernerfeldt 4 years ago
parent
commit
2f161dd3d4
  1. 2
      egui/src/context.rs
  2. 47
      egui/src/memory.rs
  3. 8
      egui/src/ui.rs
  4. 11
      egui/src/widgets/text_edit.rs

2
egui/src/context.rs

@ -308,7 +308,7 @@ impl Context {
/// If true, Egui is currently listening on text input (e.g. typing text in a `TextEdit`).
pub fn wants_keyboard_input(&self) -> bool {
self.memory().kb_focus_id.is_some()
self.memory().interaction.kb_focus_id.is_some()
}
// ---------------------------------------------------------------------

47
egui/src/memory.rs

@ -18,10 +18,6 @@ pub struct Memory {
#[cfg_attr(feature = "with_serde", serde(skip))]
pub(crate) interaction: Interaction,
/// The widget with keyboard focus (i.e. a text input field).
#[cfg_attr(feature = "with_serde", serde(skip))]
pub(crate) kb_focus_id: Option<Id>,
// states of various types of widgets
pub(crate) collapsing_headers: HashMap<Id, collapsing_header::State>,
pub(crate) menu_bar: HashMap<Id, menu::BarState>,
@ -50,6 +46,9 @@ pub struct Interaction {
/// A widget interested in drags that has a mouse press on it.
pub drag_id: Option<Id>,
/// The widget with keyboard focus (i.e. a text input field).
pub kb_focus_id: Option<Id>,
/// HACK: windows have low priority on dragging.
/// This is so that if you drag a slider in a window,
/// the slider will steal the drag away from the window.
@ -70,6 +69,21 @@ impl Interaction {
pub fn is_using_mouse(&self) -> bool {
self.click_id.is_some() || self.drag_id.is_some()
}
fn begin_frame(&mut self, prev_input: &crate::input::InputState) {
self.click_interest = false;
self.drag_interest = false;
if !prev_input.mouse.could_be_click {
self.click_id = None;
}
if !prev_input.mouse.down || prev_input.mouse.pos.is_none() {
// mouse was not down last frame
self.click_id = None;
self.drag_id = None;
}
}
}
#[derive(Clone, Debug, Default)]
@ -92,17 +106,10 @@ pub struct Areas {
impl Memory {
pub(crate) fn begin_frame(&mut self, prev_input: &crate::input::InputState) {
self.interaction.click_interest = false;
self.interaction.drag_interest = false;
if !prev_input.mouse.could_be_click {
self.interaction.click_id = None;
}
self.interaction.begin_frame(prev_input);
if !prev_input.mouse.down || prev_input.mouse.pos.is_none() {
// mouse was not down last frame
self.interaction.click_id = None;
self.interaction.drag_id = None;
let window_interaction = self.window_interaction.take();
if let Some(window_interaction) = window_interaction {
@ -120,12 +127,26 @@ impl Memory {
}
pub(crate) fn end_frame(&mut self) {
self.areas.end_frame()
self.areas.end_frame();
}
pub fn layer_at(&self, pos: Pos2, resize_interact_radius_side: f32) -> Option<Layer> {
self.areas.layer_at(pos, resize_interact_radius_side)
}
pub fn has_kb_focus(&self, id: Id) -> bool {
self.interaction.kb_focus_id == Some(id)
}
pub fn request_kb_focus(&mut self, id: Id) {
self.interaction.kb_focus_id = Some(id);
}
pub fn surrender_kb_focus(&mut self, id: Id) {
if self.interaction.kb_focus_id == Some(id) {
self.interaction.kb_focus_id = None;
}
}
}
impl Areas {

8
egui/src/ui.rs

@ -259,14 +259,6 @@ impl Ui {
self.ctx()
.contains_mouse(self.layer(), self.clip_rect(), rect)
}
pub fn has_kb_focus(&self, id: Id) -> bool {
self.memory().kb_focus_id == Some(id)
}
pub fn request_kb_focus(&self, id: Id) {
self.memory().kb_focus_id = Some(id);
}
}
/// # `Id` creation

11
egui/src/widgets/text_edit.rs

@ -76,17 +76,20 @@ impl<'t> Widget for TextEdit<'t> {
let interact = ui.interact(rect, id, Sense::click_and_drag()); // TODO: implement drag-select
if interact.clicked {
ui.request_kb_focus(id);
ui.memory().request_kb_focus(id);
if let Some(mouse_pos) = ui.input().mouse.pos {
state.cursor = Some(galley.char_at(mouse_pos - interact.rect.min).char_idx);
}
} else if ui.input().mouse.click {
// User clicked somewhere else
ui.memory().surrender_kb_focus(id);
}
if interact.hovered {
ui.output().cursor_icon = CursorIcon::Text;
}
let has_kb_focus = ui.has_kb_focus(id);
if has_kb_focus {
if ui.memory().has_kb_focus(id) {
let mut cursor = state.cursor.unwrap_or_else(|| text.chars().count());
cursor = clamp(cursor, 0..=text.chars().count());
@ -141,7 +144,7 @@ impl<'t> Widget for TextEdit<'t> {
});
}
if has_kb_focus {
if ui.memory().has_kb_focus(id) {
let cursor_blink_hz = ui.style().cursor_blink_hz;
let show_cursor =
(ui.input().time * cursor_blink_hz as f64 * 3.0).floor() as i64 % 3 != 0;

Loading…
Cancel
Save