Fix focus problems on web (#4745)
* Closes https://github.com/emilk/egui/issues/4743 * Related to https://github.com/emilk/egui/issues/4569
This commit is contained in:
parent
31716d787e
commit
d271718065
|
|
@ -181,13 +181,33 @@ impl AppRunner {
|
||||||
self.clipped_primitives.is_some()
|
self.clipped_primitives.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Does the eframe app have focus?
|
||||||
|
///
|
||||||
|
/// Technically: does either the canvas or the [`TextAgent`] have focus?
|
||||||
|
pub fn has_focus(&self) -> bool {
|
||||||
|
super::has_focus(self.canvas()) || self.text_agent.has_focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_focus(&mut self) {
|
||||||
|
let has_focus = self.has_focus();
|
||||||
|
if self.input.raw.focused != has_focus {
|
||||||
|
// log::debug!("{} Focus changed to {has_focus}", self.canvas().id());
|
||||||
|
self.input.set_focus(has_focus);
|
||||||
|
|
||||||
|
if !has_focus {
|
||||||
|
// We lost focus - good idea to save
|
||||||
|
self.save();
|
||||||
|
}
|
||||||
|
self.egui_ctx().request_repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Runs the logic, but doesn't paint the result.
|
/// Runs the logic, but doesn't paint the result.
|
||||||
///
|
///
|
||||||
/// The result can be painted later with a call to [`Self::run_and_paint`] or [`Self::paint`].
|
/// The result can be painted later with a call to [`Self::run_and_paint`] or [`Self::paint`].
|
||||||
pub fn logic(&mut self) {
|
pub fn logic(&mut self) {
|
||||||
// We sometimes miss blur/focus events due to the text agent, so let's just poll each frame:
|
// We sometimes miss blur/focus events due to the text agent, so let's just poll each frame:
|
||||||
self.input
|
self.update_focus();
|
||||||
.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 canvas_size = super::canvas_size_in_points(self.canvas(), self.egui_ctx());
|
||||||
let mut raw_input = self.input.new_frame(canvas_size);
|
let mut raw_input = self.input.new_frame(canvas_size);
|
||||||
|
|
@ -253,8 +273,8 @@ impl AppRunner {
|
||||||
cursor_icon,
|
cursor_icon,
|
||||||
open_url,
|
open_url,
|
||||||
copied_text,
|
copied_text,
|
||||||
events: _, // already handled
|
events: _, // already handled
|
||||||
mutable_text_under_cursor,
|
mutable_text_under_cursor: _, // TODO(#4569): https://github.com/emilk/egui/issues/4569
|
||||||
ime,
|
ime,
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
accesskit_update: _, // not currently implemented
|
accesskit_update: _, // not currently implemented
|
||||||
|
|
@ -273,7 +293,17 @@ impl AppRunner {
|
||||||
#[cfg(not(web_sys_unstable_apis))]
|
#[cfg(not(web_sys_unstable_apis))]
|
||||||
let _ = copied_text;
|
let _ = copied_text;
|
||||||
|
|
||||||
self.text_agent.set_focus(mutable_text_under_cursor);
|
if self.has_focus() {
|
||||||
|
// The eframe app has focus.
|
||||||
|
if ime.is_some() {
|
||||||
|
// We are editing text: give the focus to the text agent.
|
||||||
|
self.text_agent.focus();
|
||||||
|
} else {
|
||||||
|
// We are not editing text - give the focus to the canvas.
|
||||||
|
self.text_agent.blur();
|
||||||
|
self.canvas().focus().ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(err) = self.text_agent.move_to(ime, self.canvas()) {
|
if let Err(err) = self.text_agent.move_to(ime, self.canvas()) {
|
||||||
log::error!(
|
log::error!(
|
||||||
|
|
|
||||||
|
|
@ -103,17 +103,8 @@ fn install_blur_focus(runner_ref: &WebRunner, target: &EventTarget) -> Result<()
|
||||||
// so we also poll the focus state each frame in `AppRunner::logic`.
|
// so we also poll the focus state each frame in `AppRunner::logic`.
|
||||||
for event_name in ["blur", "focus"] {
|
for event_name in ["blur", "focus"] {
|
||||||
let closure = move |_event: web_sys::MouseEvent, runner: &mut AppRunner| {
|
let closure = move |_event: web_sys::MouseEvent, runner: &mut AppRunner| {
|
||||||
// log::debug!("{event_name:?}");
|
// log::debug!("{} {event_name:?}", runner.canvas().id());
|
||||||
|
runner.update_focus();
|
||||||
let has_focus = event_name == "focus";
|
|
||||||
|
|
||||||
if !has_focus {
|
|
||||||
// We lost focus - good idea to save
|
|
||||||
runner.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
runner.input.set_focus(has_focus);
|
|
||||||
runner.egui_ctx().request_repaint();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
runner_ref.add_event_listener(target, event_name, closure)?;
|
runner_ref.add_event_listener(target, event_name, closure)?;
|
||||||
|
|
|
||||||
|
|
@ -142,21 +142,25 @@ impl TextAgent {
|
||||||
super::has_focus(&self.input)
|
super::has_focus(&self.input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus(&self) {
|
pub fn focus(&self) {
|
||||||
if self.has_focus() {
|
if self.has_focus() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log::debug!("Focusing text agent");
|
||||||
|
|
||||||
if let Err(err) = self.input.focus() {
|
if let Err(err) = self.input.focus() {
|
||||||
log::error!("failed to set focus: {}", super::string_from_js_value(&err));
|
log::error!("failed to set focus: {}", super::string_from_js_value(&err));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blur(&self) {
|
pub fn blur(&self) {
|
||||||
if !self.has_focus() {
|
if !self.has_focus() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log::debug!("Blurring text agent");
|
||||||
|
|
||||||
if let Err(err) = self.input.blur() {
|
if let Err(err) = self.input.blur() {
|
||||||
log::error!("failed to set focus: {}", super::string_from_js_value(&err));
|
log::error!("failed to set focus: {}", super::string_from_js_value(&err));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue