Skip to content

Commit

Permalink
eframe web: ignore keyboard events unless canvas has focus (emilk#4718)
Browse files Browse the repository at this point in the history
* Fixes rerun-io/rerun#6638
* Related? emilk#4563

This improves how an eframe canvas works inside of a larger web page,
and how it works when there are multiple eframe apps in the same page.

`eframe` will set `tabindex="0"` on the canvas automatically, making it
focusable.
It will also set `outline: none` on the CSS, so the focused canvas won't
have an ugly outline.


## Breaking changes
You may wanna add this to your `index.html` to give the canvas focus on
startup:
```js
document.getElementById("the_canvas_id").focus();
```

## Test setup
```sh
./scripts/build_demo_web.sh
./scripts/start_server.sh
open http://localhost:8888/multiple_apps.html
```
Then open the "Input Event History" and "Text Edit" windows

## Tested
* Chromium
	* [x] drag-and-drop of files
	* Test both when a `TextEdit` is focused and when it is not:
	  * [x] `Event::Key`
	  * [x] `Event::Text`
	  * [x] copy-cut-paste
	  * [x] Wheel scroll
	* [x] `Event::PointerGone`
	* [x] Mouse drag
	* [x] Mouse click
	* [x] Mouse right-click
	* [x] Defocus all eframe canvas, and then start typing text
* [x] Firefox (all of the above)
* [x] Desktop Safari (all of the above)
* [x] Mobile Safari


## Future work (pre-existing issues)
* emilk#4723
* emilk#4724
* emilk#4725
* emilk#4726
  • Loading branch information
emilk authored Jun 28, 2024
1 parent 779312a commit 3b9f964
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 137 deletions.
4 changes: 4 additions & 0 deletions crates/eframe/src/web/app_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ impl AppRunner {
///
/// The result can be painted later with a call to [`Self::run_and_paint`] or [`Self::paint`].
pub fn logic(&mut self) {
// We sometimes miss blur/focus events due to the text agent, so let's just poll each frame:
self.input
.set_focus(super::has_focus(self.canvas()) || self.text_agent.has_focus());

let canvas_size = super::canvas_size_in_points(self.canvas(), self.egui_ctx());
let mut raw_input = self.input.new_frame(canvas_size);

Expand Down
8 changes: 6 additions & 2 deletions crates/eframe/src/web/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ impl WebInput {
raw_input
}

/// On alt-tab and similar.
pub fn on_web_page_focus_change(&mut self, focused: bool) {
/// On alt-tab, or user clicking another HTML element.
pub fn set_focus(&mut self, focused: bool) {
if self.raw.focused == focused {
return;
}

// log::debug!("on_web_page_focus_change: {focused}");
self.raw.modifiers = egui::Modifiers::default(); // Avoid sticky modifier keys on alt-tab:
self.raw.focused = focused;
Expand Down
Loading

0 comments on commit 3b9f964

Please sign in to comment.