Skip to content

Commit

Permalink
more updates stolen from upstream and other edits
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivy committed Aug 9, 2024
1 parent 184ab46 commit da67a52
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 60 deletions.
47 changes: 24 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,9 +656,11 @@ impl Plugin for EguiPlugin {
world.init_non_send_resource::<SubscribedEvents<web_sys::ClipboardEvent>>();
// virtual keyboard events for text_agent
#[cfg(target_arch = "wasm32")]
world.init_non_send_resource::<SubscribedEvents<web_sys::KeyboardEvent>>();
#[cfg(target_arch = "wasm32")]
world.init_non_send_resource::<SubscribedEvents<web_sys::InputEvent>>();
#[cfg(target_arch = "wasm32")]
world.init_non_send_resource::<SubscribedEvents<web_sys::KeyboardEvent>>();
world.init_non_send_resource::<SubscribedEvents<web_sys::TouchEvent>>();
#[cfg(feature = "render")]
world.init_resource::<EguiUserTextures>();
#[cfg(feature = "render")]
Expand Down Expand Up @@ -725,29 +727,28 @@ impl Plugin for EguiPlugin {

app.add_systems(
PreStartup,
|channel: Res<text_agent::TextAgentChannel>,
mut subscribed_input_events: NonSendMut<
(|channel: Res<text_agent::TextAgentChannel>,
mut subscribed_keyboard_events: NonSendMut<
SubscribedEvents<web_sys::KeyboardEvent>,
>,
mut subscribed_input_events: NonSendMut<
SubscribedEvents<web_sys::InputEvent>,
>,
mut subscribed_keyboard_events: NonSendMut<
SubscribedEvents<web_sys::KeyboardEvent>,
mut subscribed_touch_events: NonSendMut<
SubscribedEvents<web_sys::TouchEvent>,
>| {
text_agent::install_text_agent(
&mut subscribed_input_events,
&mut subscribed_keyboard_events,
&mut subscribed_input_events,
&mut subscribed_touch_events,
channel.sender.clone(),
)
.unwrap();
},
);

app.add_systems(
PreStartup,
text_agent::virtual_keyboard_handler
.in_set(EguiSet::ProcessInput)
.after(process_input_system)
.after(InputSystem)
.after(EguiSet::InitContexts),
})
.in_set(EguiSet::ProcessInput)
.after(process_input_system)
.after(InputSystem)
.after(EguiSet::InitContexts),
);

app.add_systems(
Expand Down Expand Up @@ -962,6 +963,13 @@ pub fn string_from_js_value(value: &JsValue) -> String {
value.as_string().unwrap_or_else(|| format!("{value:#?}"))
}

#[cfg(target_arch = "wasm32")]
struct EventClosure<T> {
target: web_sys::EventTarget,
event_name: String,
closure: wasm_bindgen::closure::Closure<dyn FnMut(T)>,
}

/// Stores event listeners.
#[cfg(target_arch = "wasm32")]
pub struct SubscribedEvents<T> {
Expand Down Expand Up @@ -1000,13 +1008,6 @@ impl<T> SubscribedEvents<T> {
}
}

#[cfg(target_arch = "wasm32")]
struct EventClosure<T> {
target: web_sys::EventTarget,
event_name: String,
closure: wasm_bindgen::closure::Closure<dyn FnMut(T)>,
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
24 changes: 14 additions & 10 deletions src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use bevy::{
use std::marker::PhantomData;

#[cfg(target_arch = "wasm32")]
use crate::text_agent::VIRTUAL_KEYBOARD_GLOBAL;
use crate::text_agent::{is_mobile_safari, update_text_agent, VIRTUAL_KEYBOARD_GLOBAL};

#[allow(missing_docs)]
#[derive(SystemParam)]
Expand Down Expand Up @@ -414,15 +414,6 @@ pub fn process_input_system(
.egui_input
.events
.push(egui::Event::PointerGone);
#[cfg(target_arch = "wasm32")]
match VIRTUAL_KEYBOARD_GLOBAL.lock() {
Ok(mut touch_info) => {
touch_info.editing_text = editing_text;
}
Err(poisoned) => {
let _unused = poisoned.into_inner();
}
};
}
bevy::input::touch::TouchPhase::Canceled => {
window_context.ctx.pointer_touch_id = None;
Expand All @@ -432,6 +423,19 @@ pub fn process_input_system(
.push(egui::Event::PointerGone);
}
}
#[cfg(target_arch = "wasm32")]
if is_mobile_safari() {
match VIRTUAL_KEYBOARD_GLOBAL.lock() {
Ok(mut touch_info) => {
touch_info.editing_text = editing_text;
}
Err(poisoned) => {
let _unused = poisoned.into_inner();
}
};
} else {
update_text_agent(editing_text);
}
}
}

Expand Down
69 changes: 42 additions & 27 deletions src/text_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ pub fn propagate_text(
}
}

// stolen from https://github.com/emilk/egui/pull/4855
pub fn is_mobile_safari() -> bool {
(|| {
let user_agent = web_sys::window()?.navigator().user_agent().ok()?;
let is_ios = user_agent.contains("iPhone")
|| user_agent.contains("iPad")
|| user_agent.contains("iPod");
let is_safari = user_agent.contains("Safari");
Some(is_ios && is_safari)
})()
.unwrap_or(false)
}

fn is_mobile() -> Option<bool> {
const MOBILE_DEVICE: [&str; 6] = ["Android", "iPhone", "iPad", "iPod", "webOS", "BlackBerry"];

Expand All @@ -68,8 +81,9 @@ fn is_mobile() -> Option<bool> {

/// Text event handler,
pub fn install_text_agent(
subscribed_input_events: &mut SubscribedEvents<web_sys::InputEvent>,
subscribed_keyboard_events: &mut SubscribedEvents<web_sys::KeyboardEvent>,
subscribed_input_events: &mut SubscribedEvents<web_sys::InputEvent>,
subscribed_touch_events: &mut SubscribedEvents<web_sys::TouchEvent>,
sender: Sender<egui::Event>,
) -> Result<(), JsValue> {
let window = web_sys::window().unwrap();
Expand Down Expand Up @@ -101,7 +115,7 @@ pub fn install_text_agent(
input.set_autofocus(true);
input.set_hidden(true);

{
if let Some(true) = is_mobile() {
let input_clone = input.clone();
let sender_clone = sender.clone();
let closure = Closure::wrap(Box::new(move |_event: web_sys::InputEvent| {
Expand All @@ -125,9 +139,32 @@ pub fn install_text_agent(
event_name: "virtual_keyboard_input".to_owned(),
closure,
});
}

if let Some(true) = is_mobile() {
// mobile safari doesn't let you set input focus outside of an event handler
if is_mobile_safari() {
let closure = Closure::wrap(Box::new(move |_event: web_sys::TouchEvent| {
match VIRTUAL_KEYBOARD_GLOBAL.lock() {
Ok(touch_info) => {
update_text_agent(touch_info.editing_text);
}
Err(poisoned) => {
let _unused = poisoned.into_inner();
}
};
}) as Box<dyn FnMut(_)>);
document
.add_event_listener_with_callback("touchend", closure.as_ref().unchecked_ref())
.unwrap();
subscribed_touch_events.event_closures.push(EventClosure {
target: <web_sys::Document as std::convert::AsRef<web_sys::EventTarget>>::as_ref(
&document,
)
.clone(),
event_name: "virtual_keyboard_touchend".to_owned(),
closure,
});
}

// keydown
let sender_clone = sender.clone();
let closure = Closure::wrap(Box::new(move |event: web_sys::KeyboardEvent| {
Expand Down Expand Up @@ -156,9 +193,7 @@ pub fn install_text_agent(
event_name: "virtual_keyboard_keydown".to_owned(),
closure,
});
}

if let Some(true) = is_mobile() {
// keyup
let input_clone = input.clone();
let sender_clone = sender.clone();
Expand Down Expand Up @@ -192,28 +227,8 @@ pub fn install_text_agent(
Ok(())
}

pub fn virtual_keyboard_handler() {
let document = web_sys::window().unwrap().document().unwrap();
{
let closure = Closure::wrap(Box::new(move |_event: web_sys::TouchEvent| {
match VIRTUAL_KEYBOARD_GLOBAL.lock() {
Ok(touch_info) => {
update_text_agent(touch_info.editing_text);
}
Err(poisoned) => {
let _unused = poisoned.into_inner();
}
};
}) as Box<dyn FnMut(_)>);
document
.add_event_listener_with_callback("touchstart", closure.as_ref().unchecked_ref())
.unwrap();
closure.forget();
}
}

/// Focus or blur text agent to toggle mobile keyboard.
fn update_text_agent(editing_text: bool) {
pub fn update_text_agent(editing_text: bool) {
use web_sys::HtmlInputElement;

let window = match web_sys::window() {
Expand Down

0 comments on commit da67a52

Please sign in to comment.