Rename `should_propagate_event` & add `should_prevent_default` (#5779)
* [x] I have followed the instructions in the PR template Currently eframe [calls `prevent_default()`](962c7c7516/crates/eframe/src/web/events.rs (L307-L369)) for all copy / paste events on the [*document*](962c7c7516/crates/eframe/src/web/events.rs (L88)), making embedding an egui application in a page (e.g. an react application) hard (as all copy & paste functionality for other elements on the page is broken by this). I'm not sure what the motivation for this is, if any. This commit / PR adds a callback (`should_prevent_default`), similar to `should_propgate_event`, that an egui application can use to overwrite this behavior. It defaults to returning `true` for all events, to keep the existing behavior. I call `should_prevent_default` in every place that `should_propagate_event` is called (which is not all places that `prevent_default` is called!). I'm not sure for the motivation of not calling `should_propagate_event` everywhere that `stop_propagation` is called, but I kept that behavior for the `should_prevent_default` callback too. Please let me know if I'm missing some existing functionality that would allow me to do this, or if there's a reason that we don't want applications to be able to customize this (i.e. if there's a reason to always `prevent_default` for all copy / paste events on the whole document)
This commit is contained in:
parent
83254718a3
commit
ab0f0b7b64
|
|
@ -499,10 +499,16 @@ pub struct WebOptions {
|
|||
/// If the web event corresponding to an egui event should be propagated
|
||||
/// to the rest of the web page.
|
||||
///
|
||||
/// The default is `false`, meaning
|
||||
/// The default is `true`, meaning
|
||||
/// [`stopPropagation`](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation)
|
||||
/// is called on every event.
|
||||
pub should_propagate_event: Box<dyn Fn(&egui::Event) -> bool>,
|
||||
/// is called on every event, and the event is not propagated to the rest of the web page.
|
||||
pub should_stop_propagation: Box<dyn Fn(&egui::Event) -> bool>,
|
||||
|
||||
/// Whether the web event corresponding to an egui event should have `prevent_default` called
|
||||
/// on it or not.
|
||||
///
|
||||
/// Defaults to true.
|
||||
pub should_prevent_default: Box<dyn Fn(&egui::Event) -> bool>,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
|
|
@ -519,7 +525,8 @@ impl Default for WebOptions {
|
|||
|
||||
dithering: true,
|
||||
|
||||
should_propagate_event: Box::new(|_| false),
|
||||
should_stop_propagation: Box::new(|_| true),
|
||||
should_prevent_default: Box::new(|_| true),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,15 +139,20 @@ fn install_keydown(runner_ref: &WebRunner, target: &EventTarget) -> Result<(), J
|
|||
{
|
||||
if let Some(text) = text_from_keyboard_event(&event) {
|
||||
let egui_event = egui::Event::Text(text);
|
||||
let should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
let should_stop_propagation =
|
||||
(runner.web_options.should_stop_propagation)(&egui_event);
|
||||
let should_prevent_default =
|
||||
(runner.web_options.should_prevent_default)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
// If this is indeed text, then prevent any other action.
|
||||
event.prevent_default();
|
||||
if should_prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
|
||||
// Use web options to tell if the event should be propagated to parent elements.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
}
|
||||
|
|
@ -184,7 +189,7 @@ pub(crate) fn on_keydown(event: web_sys::KeyboardEvent, runner: &mut AppRunner)
|
|||
repeat: false, // egui will fill this in for us!
|
||||
modifiers,
|
||||
};
|
||||
let should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
let should_stop_propagation = (runner.web_options.should_stop_propagation)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
|
|
@ -201,7 +206,7 @@ pub(crate) fn on_keydown(event: web_sys::KeyboardEvent, runner: &mut AppRunner)
|
|||
}
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
}
|
||||
|
|
@ -261,7 +266,7 @@ pub(crate) fn on_keyup(event: web_sys::KeyboardEvent, runner: &mut AppRunner) {
|
|||
let modifiers = modifiers_from_kb_event(&event);
|
||||
runner.input.raw.modifiers = modifiers;
|
||||
|
||||
let mut propagate_event = false;
|
||||
let mut should_stop_propagation = true;
|
||||
|
||||
if let Some(key) = translate_key(&event.key()) {
|
||||
let egui_event = egui::Event::Key {
|
||||
|
|
@ -271,7 +276,7 @@ pub(crate) fn on_keyup(event: web_sys::KeyboardEvent, runner: &mut AppRunner) {
|
|||
repeat: false,
|
||||
modifiers,
|
||||
};
|
||||
propagate_event |= (runner.web_options.should_propagate_event)(&egui_event);
|
||||
should_stop_propagation &= (runner.web_options.should_stop_propagation)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
}
|
||||
|
||||
|
|
@ -290,7 +295,7 @@ pub(crate) fn on_keyup(event: web_sys::KeyboardEvent, runner: &mut AppRunner) {
|
|||
repeat: false,
|
||||
modifiers,
|
||||
};
|
||||
propagate_event |= (runner.web_options.should_propagate_event)(&egui_event);
|
||||
should_stop_propagation &= (runner.web_options.should_stop_propagation)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
}
|
||||
}
|
||||
|
|
@ -299,7 +304,7 @@ pub(crate) fn on_keyup(event: web_sys::KeyboardEvent, runner: &mut AppRunner) {
|
|||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
let has_focus = runner.input.raw.focused;
|
||||
if has_focus && !propagate_event {
|
||||
if has_focus && should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
}
|
||||
|
|
@ -310,19 +315,26 @@ fn install_copy_cut_paste(runner_ref: &WebRunner, target: &EventTarget) -> Resul
|
|||
if let Ok(text) = data.get_data("text") {
|
||||
let text = text.replace("\r\n", "\n");
|
||||
|
||||
let mut should_propagate = false;
|
||||
let mut should_stop_propagation = true;
|
||||
let mut should_prevent_default = true;
|
||||
if !text.is_empty() && runner.input.raw.focused {
|
||||
let egui_event = egui::Event::Paste(text);
|
||||
should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
should_stop_propagation =
|
||||
(runner.web_options.should_stop_propagation)(&egui_event);
|
||||
should_prevent_default =
|
||||
(runner.web_options.should_prevent_default)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
runner.needs_repaint.repaint_asap();
|
||||
}
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if should_prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
|
@ -340,10 +352,13 @@ fn install_copy_cut_paste(runner_ref: &WebRunner, target: &EventTarget) -> Resul
|
|||
}
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !(runner.web_options.should_propagate_event)(&egui::Event::Cut) {
|
||||
if (runner.web_options.should_stop_propagation)(&egui::Event::Cut) {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if (runner.web_options.should_prevent_default)(&egui::Event::Cut) {
|
||||
event.prevent_default();
|
||||
}
|
||||
})?;
|
||||
|
||||
runner_ref.add_event_listener(target, "copy", |event: web_sys::ClipboardEvent, runner| {
|
||||
|
|
@ -359,10 +374,13 @@ fn install_copy_cut_paste(runner_ref: &WebRunner, target: &EventTarget) -> Resul
|
|||
}
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !(runner.web_options.should_propagate_event)(&egui::Event::Copy) {
|
||||
if (runner.web_options.should_stop_propagation)(&egui::Event::Copy) {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if (runner.web_options.should_prevent_default)(&egui::Event::Copy) {
|
||||
event.prevent_default();
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
|
@ -484,7 +502,7 @@ fn install_pointerdown(runner_ref: &WebRunner, target: &EventTarget) -> Result<(
|
|||
|event: web_sys::PointerEvent, runner: &mut AppRunner| {
|
||||
let modifiers = modifiers_from_mouse_event(&event);
|
||||
runner.input.raw.modifiers = modifiers;
|
||||
let mut should_propagate = false;
|
||||
let mut should_stop_propagation = true;
|
||||
if let Some(button) = button_from_mouse_event(&event) {
|
||||
let pos = pos_from_mouse_event(runner.canvas(), &event, runner.egui_ctx());
|
||||
let modifiers = runner.input.raw.modifiers;
|
||||
|
|
@ -494,7 +512,7 @@ fn install_pointerdown(runner_ref: &WebRunner, target: &EventTarget) -> Result<(
|
|||
pressed: true,
|
||||
modifiers,
|
||||
};
|
||||
should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
should_stop_propagation = (runner.web_options.should_stop_propagation)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
|
||||
// In Safari we are only allowed to write to the clipboard during the
|
||||
|
|
@ -506,7 +524,7 @@ fn install_pointerdown(runner_ref: &WebRunner, target: &EventTarget) -> Result<(
|
|||
}
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
// Note: prevent_default breaks VSCode tab focusing, hence why we don't call it here.
|
||||
|
|
@ -536,7 +554,10 @@ fn install_pointerup(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||
pressed: false,
|
||||
modifiers,
|
||||
};
|
||||
let should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
let should_stop_propagation =
|
||||
(runner.web_options.should_stop_propagation)(&egui_event);
|
||||
let should_prevent_default =
|
||||
(runner.web_options.should_prevent_default)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
|
||||
// Previously on iOS, the canvas would not receive focus on
|
||||
|
|
@ -555,10 +576,12 @@ fn install_pointerup(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||
// Make sure we paint the output of the above logic call asap:
|
||||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
event.prevent_default();
|
||||
if should_prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
}
|
||||
|
|
@ -600,15 +623,19 @@ fn install_mousemove(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||
egui::pos2(event.client_x() as f32, event.client_y() as f32),
|
||||
) {
|
||||
let egui_event = egui::Event::PointerMoved(pos);
|
||||
let should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
let should_stop_propagation = (runner.web_options.should_stop_propagation)(&egui_event);
|
||||
let should_prevent_default = (runner.web_options.should_prevent_default)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if should_prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -622,10 +649,13 @@ fn install_mouseleave(runner_ref: &WebRunner, target: &EventTarget) -> Result<()
|
|||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !(runner.web_options.should_propagate_event)(&egui::Event::PointerGone) {
|
||||
if (runner.web_options.should_stop_propagation)(&egui::Event::PointerGone) {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if (runner.web_options.should_prevent_default)(&egui::Event::PointerGone) {
|
||||
event.prevent_default();
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -635,7 +665,8 @@ fn install_touchstart(runner_ref: &WebRunner, target: &EventTarget) -> Result<()
|
|||
target,
|
||||
"touchstart",
|
||||
|event: web_sys::TouchEvent, runner| {
|
||||
let mut should_propagate = false;
|
||||
let mut should_stop_propagation = true;
|
||||
let mut should_prevent_default = true;
|
||||
if let Some((pos, _)) = primary_touch_pos(runner, &event) {
|
||||
let egui_event = egui::Event::PointerButton {
|
||||
pos,
|
||||
|
|
@ -643,7 +674,8 @@ fn install_touchstart(runner_ref: &WebRunner, target: &EventTarget) -> Result<()
|
|||
pressed: true,
|
||||
modifiers: runner.input.raw.modifiers,
|
||||
};
|
||||
should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
should_stop_propagation = (runner.web_options.should_stop_propagation)(&egui_event);
|
||||
should_prevent_default = (runner.web_options.should_prevent_default)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
}
|
||||
|
||||
|
|
@ -651,10 +683,13 @@ fn install_touchstart(runner_ref: &WebRunner, target: &EventTarget) -> Result<()
|
|||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if should_prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -667,17 +702,23 @@ fn install_touchmove(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||
egui::pos2(touch.client_x() as f32, touch.client_y() as f32),
|
||||
) {
|
||||
let egui_event = egui::Event::PointerMoved(pos);
|
||||
let should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
let should_stop_propagation =
|
||||
(runner.web_options.should_stop_propagation)(&egui_event);
|
||||
let should_prevent_default =
|
||||
(runner.web_options.should_prevent_default)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
|
||||
push_touches(runner, egui::TouchPhase::Move, &event);
|
||||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if should_prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -691,18 +732,23 @@ fn install_touchend(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||
egui::pos2(touch.client_x() as f32, touch.client_y() as f32),
|
||||
) {
|
||||
// First release mouse to click:
|
||||
let mut should_propagate = false;
|
||||
let mut should_stop_propagation = true;
|
||||
let mut should_prevent_default = true;
|
||||
let egui_event = egui::Event::PointerButton {
|
||||
pos,
|
||||
button: egui::PointerButton::Primary,
|
||||
pressed: false,
|
||||
modifiers: runner.input.raw.modifiers,
|
||||
};
|
||||
should_propagate |= (runner.web_options.should_propagate_event)(&egui_event);
|
||||
should_stop_propagation &=
|
||||
(runner.web_options.should_stop_propagation)(&egui_event);
|
||||
should_prevent_default &= (runner.web_options.should_prevent_default)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
// Then remove hover effect:
|
||||
should_propagate |=
|
||||
(runner.web_options.should_propagate_event)(&egui::Event::PointerGone);
|
||||
should_stop_propagation &=
|
||||
(runner.web_options.should_stop_propagation)(&egui::Event::PointerGone);
|
||||
should_prevent_default &=
|
||||
(runner.web_options.should_prevent_default)(&egui::Event::PointerGone);
|
||||
runner.input.raw.events.push(egui::Event::PointerGone);
|
||||
|
||||
push_touches(runner, egui::TouchPhase::End, &event);
|
||||
|
|
@ -710,10 +756,13 @@ fn install_touchend(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if should_prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
|
||||
// Fix virtual keyboard IOS
|
||||
// Need call focus at the same time of event
|
||||
|
|
@ -769,16 +818,20 @@ fn install_wheel(runner_ref: &WebRunner, target: &EventTarget) -> Result<(), JsV
|
|||
modifiers,
|
||||
}
|
||||
};
|
||||
let should_propagate = (runner.web_options.should_propagate_event)(&egui_event);
|
||||
let should_stop_propagation = (runner.web_options.should_stop_propagation)(&egui_event);
|
||||
let should_prevent_default = (runner.web_options.should_prevent_default)(&egui_event);
|
||||
runner.input.raw.events.push(egui_event);
|
||||
|
||||
runner.needs_repaint.repaint_asap();
|
||||
|
||||
// Use web options to tell if the web event should be propagated to parent elements based on the egui event.
|
||||
if !should_propagate {
|
||||
if should_stop_propagation {
|
||||
event.stop_propagation();
|
||||
}
|
||||
event.prevent_default();
|
||||
|
||||
if should_prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue