-
Notifications
You must be signed in to change notification settings - Fork 249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
web clipboard handling #178
Changes from 14 commits
493a21f
205cdde
9e85a90
69c447d
0ec3ed9
9032a4e
ea933e7
b45bea2
070f108
0e7dd24
e3fa6e3
43af68a
9d743fd
8768a9c
5c4f550
fe877d7
f97ae8d
d6b726b
feb884c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[alias] | ||
run-wasm = ["run", "--release", "--package", "run-wasm", "--"] | ||
|
||
# Using unstable APIs is required for writing to clipboard | ||
[target.wasm32-unknown-unknown] | ||
rustflags = ["--cfg=web_sys_unstable_apis"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "run-wasm" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
cargo-run-wasm = "0.2.0" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fn main() { | ||
cargo_run_wasm::run_wasm_with_css("body { margin: 0px; }"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,7 +54,7 @@ impl<'w, 's> InputEvents<'w, 's> { | |
#[derive(SystemParam)] | ||
pub struct InputResources<'w, 's> { | ||
#[cfg(feature = "manage_clipboard")] | ||
pub egui_clipboard: Res<'w, crate::EguiClipboard>, | ||
pub egui_clipboard: ResMut<'w, crate::EguiClipboard>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see #178 (comment) ; to be noted we can have mut only for wasm if we want. |
||
pub keyboard_input: Res<'w, Input<KeyCode>>, | ||
#[system_param(ignore)] | ||
_marker: PhantomData<&'s ()>, | ||
|
@@ -72,12 +72,32 @@ pub struct ContextSystemParams<'w, 's> { | |
/// Processes Bevy input and feeds it to Egui. | ||
pub fn process_input_system( | ||
mut input_events: InputEvents, | ||
input_resources: InputResources, | ||
mut input_resources: InputResources, | ||
mut context_params: ContextSystemParams, | ||
egui_settings: Res<EguiSettings>, | ||
mut egui_mouse_position: ResMut<EguiMousePosition>, | ||
time: Res<Time>, | ||
mut is_mac: Local<bool>, | ||
) { | ||
use std::sync::Once; | ||
static START: Once = Once::new(); | ||
|
||
START.call_once(|| { | ||
// run initialization here | ||
*is_mac = cfg!(target_os = "macos"); | ||
#[cfg(target_arch = "wasm32")] | ||
{ | ||
let window = web_sys::window().expect("window"); | ||
|
||
let nav = window.navigator(); | ||
let user_agent = nav.user_agent(); | ||
if let Ok(user_agent) = user_agent { | ||
log::debug!("{:?}", user_agent); | ||
*is_mac = user_agent.contains("Macintosh;"); | ||
} | ||
} | ||
}); | ||
|
||
// This is a workaround for Windows. For some reason, `WindowFocused` event isn't fired | ||
// when a window is created. | ||
if let Some(event) = input_events.ev_window_created.iter().last() { | ||
|
@@ -101,12 +121,8 @@ pub fn process_input_system( | |
let win = input_resources.keyboard_input.pressed(KeyCode::LWin) | ||
|| input_resources.keyboard_input.pressed(KeyCode::RWin); | ||
|
||
let mac_cmd = if cfg!(target_os = "macos") { | ||
win | ||
} else { | ||
false | ||
}; | ||
let command = if cfg!(target_os = "macos") { win } else { ctrl }; | ||
let mac_cmd = if *is_mac { win } else { false }; | ||
let command = if *is_mac { win } else { ctrl }; | ||
|
||
let modifiers = egui::Modifiers { | ||
alt, | ||
|
@@ -250,20 +266,47 @@ pub fn process_input_system( | |
// We also check that it's an `ButtonState::Pressed` event, as we don't want to | ||
// copy, cut or paste on the key release. | ||
#[cfg(feature = "manage_clipboard")] | ||
if command && pressed { | ||
match key { | ||
egui::Key::C => { | ||
{ | ||
#[cfg(not(target_arch = "wasm32"))] | ||
if command && pressed { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (to be clear, this is not a but introduced in this PR) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, good catch. This makes me wonder how we can detect running on MacOS in wasm. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. eframe uses events for all those, deferring the responsibility to the browser: https://github.com/emilk/egui/blob/307565efa55158cfa6b82d2e8fdc4c4914b954ed/crates/eframe/src/web/events.rs#L184 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It feels like we should adopt the same approach. Let's keep the whole block enabled only for non-wasm targets, whereas for wasm we'll just read from channels (which in turn will get messages on web_sys events). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is important to fix, as atm on MacOS, users need to do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I feel like it means we would bypass winit/bevy key inputs in wasm :/ could this possibly fixed upstream 🤔 ? for the record, ctrl-A works (kinda) on wasm; on azerty it's mapped to In all hindsight, I'd suggest a simpler approach where we detect if we run on mac or not through https://docs.rs/web-sys/latest/web_sys/struct.Navigator.html#method.platform, and adapt our meta key from there in case of Is it ok for you? |
||
match key { | ||
egui::Key::C => { | ||
focused_input.events.push(egui::Event::Copy); | ||
} | ||
egui::Key::X => { | ||
focused_input.events.push(egui::Event::Cut); | ||
} | ||
egui::Key::V => { | ||
if let Some(contents) = | ||
input_resources.egui_clipboard.get_contents() | ||
{ | ||
focused_input.events.push(egui::Event::Text(contents)) | ||
} | ||
} | ||
_ => {} | ||
} | ||
} | ||
#[cfg(target_arch = "wasm32")] | ||
{ | ||
if input_resources | ||
.egui_clipboard | ||
.web_copy | ||
.try_read_clipboard_event() | ||
.is_some() | ||
{ | ||
focused_input.events.push(egui::Event::Copy); | ||
} | ||
egui::Key::X => { | ||
if input_resources | ||
.egui_clipboard | ||
.web_cut | ||
.try_read_clipboard_event() | ||
.is_some() | ||
{ | ||
focused_input.events.push(egui::Event::Cut); | ||
} | ||
egui::Key::V => { | ||
if let Some(contents) = input_resources.egui_clipboard.get_contents() { | ||
focused_input.events.push(egui::Event::Text(contents)) | ||
} | ||
if let Some(contents) = input_resources.egui_clipboard.get_contents() { | ||
focused_input.events.push(egui::Event::Text(contents)); | ||
} | ||
_ => {} | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think cargo run-wasm is quite handy to easily test a wasm version ; I can make another PR if interested