Skip to content

Commit

Permalink
Track the global focus state of the UI
Browse files Browse the repository at this point in the history
  • Loading branch information
mwcampbell committed Jul 27, 2022
1 parent 0571bf6 commit 8dae3ff
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -17,6 +17,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui-w
* Added support for using `PaintCallback` shapes with the WGPU backend ([#1684](https://github.com/emilk/egui/pull/1684)).
* Added `Contex::request_repaint_after` ([#1694](https://github.com/emilk/egui/pull/1694)).
* `ctrl-h` now acts like backspace in `TextEdit` ([#1812](https://github.com/emilk/egui/pull/1812)).
* Added `RawInput::has_focus` which backends can set to indicate whether the UI as a whole has the keyboard focus.

### Changed
* MSRV (Minimum Supported Rust Version) is now `1.61.0` ([#1846](https://github.com/emilk/egui/pull/1846)).
Expand Down
1 change: 1 addition & 0 deletions egui-winit/CHANGELOG.md
Expand Up @@ -8,6 +8,7 @@ All notable changes to the `egui-winit` integration will be noted in this file.
* Allow deferred render + surface state initialization for Android ([#1634](https://github.com/emilk/egui/pull/1634)).
* Fixed window position persistence ([#1745](https://github.com/emilk/egui/pull/1745)).
* Fixed mouse cursor change on Linux ([#1747](https://github.com/emilk/egui/pull/1747)).
* Use the new `RawInput::has_focus` field to indicate whether the window has the keyboard focus.


## 0.18.0 - 2022-04-30
Expand Down
10 changes: 8 additions & 2 deletions egui-winit/src/lib.rs
Expand Up @@ -70,9 +70,14 @@ impl State {
}

pub fn new_with_wayland_display(wayland_display: Option<*mut c_void>) -> Self {
let egui_input = egui::RawInput {
has_focus: false, // winit will tell us when we have focus
..Default::default()
};

Self {
start_time: instant::Instant::now(),
egui_input: Default::default(),
egui_input,
pointer_pos_in_points: None,
any_pointer_button_down: false,
current_cursor_icon: egui::CursorIcon::Default,
Expand Down Expand Up @@ -214,7 +219,8 @@ impl State {
egui_ctx.wants_keyboard_input()
|| input.virtual_keycode == Some(winit::event::VirtualKeyCode::Tab)
}
WindowEvent::Focused(_) => {
WindowEvent::Focused(has_focus) => {
self.egui_input.has_focus = *has_focus;
// We will not be given a KeyboardInput event when the modifiers are released while
// the window does not have focus. Unset all modifier state to be safe.
self.egui_input.modifiers = egui::Modifiers::default();
Expand Down
9 changes: 9 additions & 0 deletions egui/src/data/input.rs
Expand Up @@ -62,6 +62,9 @@ pub struct RawInput {
/// Note: when using `eframe` on Windows you need to enable
/// drag-and-drop support using `eframe::NativeOptions`.
pub dropped_files: Vec<DroppedFile>,

/// The window has the keyboard focus (i.e. is receiving key presses).
pub has_focus: bool,
}

impl Default for RawInput {
Expand All @@ -76,6 +79,7 @@ impl Default for RawInput {
events: vec![],
hovered_files: Default::default(),
dropped_files: Default::default(),
has_focus: true, // integrations opt into global focus tracking
}
}
}
Expand All @@ -96,6 +100,7 @@ impl RawInput {
events: std::mem::take(&mut self.events),
hovered_files: self.hovered_files.clone(),
dropped_files: std::mem::take(&mut self.dropped_files),
has_focus: self.has_focus,
}
}

Expand All @@ -111,6 +116,7 @@ impl RawInput {
mut events,
mut hovered_files,
mut dropped_files,
has_focus,
} = newer;

self.screen_rect = screen_rect.or(self.screen_rect);
Expand All @@ -122,6 +128,7 @@ impl RawInput {
self.events.append(&mut events);
self.hovered_files.append(&mut hovered_files);
self.dropped_files.append(&mut dropped_files);
self.has_focus = has_focus;
}
}

Expand Down Expand Up @@ -541,6 +548,7 @@ impl RawInput {
events,
hovered_files,
dropped_files,
has_focus,
} = self;

ui.label(format!("screen_rect: {:?} points", screen_rect));
Expand All @@ -558,6 +566,7 @@ impl RawInput {
ui.label(format!("modifiers: {:#?}", modifiers));
ui.label(format!("hovered_files: {}", hovered_files.len()));
ui.label(format!("dropped_files: {}", dropped_files.len()));
ui.label(format!("has_focus: {}", has_focus));
ui.scope(|ui| {
ui.set_min_height(150.0);
ui.label(format!("events: {:#?}", events))
Expand Down
4 changes: 3 additions & 1 deletion egui/src/response.rs
Expand Up @@ -213,7 +213,9 @@ impl Response {

/// This widget has the keyboard focus (i.e. is receiving key presses).
pub fn has_focus(&self) -> bool {
self.ctx.memory().has_focus(self.id)
// Access input and memory in separate statements to prevent deadlock.
let has_global_focus = self.ctx.input().raw.has_focus;
has_global_focus && self.ctx.memory().has_focus(self.id)
}

/// True if this widget has keyboard focus this frame, but didn't last frame.
Expand Down

0 comments on commit 8dae3ff

Please sign in to comment.