-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add WASM CustomEvent Example #2852
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
Closed
stevenhuyn
wants to merge
14
commits into
rust-windowing:master
from
stevenhuyn:stevenhuyn/wasm-custom-event
Closed
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
a072a6a
Add attempt
stevenhuyn e043943
Prepend button
stevenhuyn e89bc52
Use correct import
stevenhuyn ef16da9
Remove unecessary change
stevenhuyn eab2764
Create working example
stevenhuyn e0cb943
Revert config.toml to master
stevenhuyn 4c4d441
Add header doc
stevenhuyn d02c6d1
Update examples/wasm_custom_event.rs
stevenhuyn d060d4a
Use OnceCell
stevenhuyn b5337fb
Make HtmlScriptElement a dev-dependency of web_sys
stevenhuyn 2908f0b
Update examples/wasm_custom_event.rs
stevenhuyn 7acaf0b
Merge branch 'stevenhuyn/wasm-custom-event' of https://github.com/ste…
stevenhuyn 901cbc7
Remove unused dependency
stevenhuyn 427df2b
Unwrap result
stevenhuyn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| /// This example will show how to call a Rust function from JavaScript | ||
| /// You should see the number 42 appear in browser console output when you click the button | ||
|
|
||
| #[cfg(not(wasm_platform))] | ||
| pub fn main() { | ||
| panic!("This example is only meant to be compiled for wasm target") | ||
| } | ||
|
|
||
| #[cfg(wasm_platform)] | ||
| pub fn main() { | ||
| panic!("Please run `cargo run-wasm --example wasm_custom_event`") | ||
| } | ||
|
|
||
| #[cfg(wasm_platform)] | ||
| mod wasm { | ||
| use once_cell::unsync::OnceCell; | ||
| use wasm_bindgen::prelude::*; | ||
| use wasm_bindgen::JsCast; | ||
| use web_sys::HtmlScriptElement; | ||
| use winit::event::{Event, WindowEvent}; | ||
| use winit::event_loop::{EventLoop, EventLoopBuilder, EventLoopProxy}; | ||
| use winit::window::{Window, WindowBuilder}; | ||
|
|
||
|
|
||
| thread_local! { | ||
| pub static EVENT_LOOP_PROXY: OnceCell<EventLoopProxy<CustomEvent>> = OnceCell::new(); | ||
| } | ||
|
|
||
| // Function to be called from JS | ||
| fn wasm_call() -> u32 { | ||
| 42 | ||
| } | ||
|
|
||
| #[derive(Debug, Clone, Copy)] | ||
| pub enum CustomEvent { | ||
| WasmCall, | ||
| } | ||
|
|
||
| #[wasm_bindgen(start)] | ||
| pub fn run() { | ||
| console_log::init_with_level(log::Level::Debug).expect("error initializing logger"); | ||
|
|
||
| let event_loop: EventLoop<CustomEvent> = | ||
| EventLoopBuilder::<CustomEvent>::with_user_event().build(); | ||
|
|
||
| let event_loop_proxy = event_loop.create_proxy(); | ||
|
|
||
| // Initialize the thread_local EVENT_LOOP_PROXY value | ||
| EVENT_LOOP_PROXY.with(|cell| { | ||
| cell.set(event_loop_proxy).unwrap(); | ||
| }); | ||
|
|
||
| let window = WindowBuilder::new().build(&event_loop).unwrap(); | ||
|
|
||
| insert_canvas(&window); | ||
|
|
||
| event_loop.run(move |event, _, control_flow| { | ||
| control_flow.set_wait(); | ||
|
|
||
| match event { | ||
| Event::WindowEvent { | ||
| event: WindowEvent::CloseRequested, | ||
| window_id, | ||
| } if window_id == window.id() => control_flow.set_exit(), | ||
|
Comment on lines
+61
to
+64
Member
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. We can skip that here, it's not a thing in Wasm.
Author
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. Skip this match arm? Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.id() => control_flow.set_exit(), |
||
| Event::MainEventsCleared => { | ||
| window.request_redraw(); | ||
| } | ||
| // Handle custom events here | ||
| Event::UserEvent(CustomEvent::WasmCall) => { | ||
| // Send the result back to JS as proof that the custom event was handled | ||
| log::info!("{:?}", wasm_call()); | ||
| } | ||
| _ => (), | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| #[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = "handleWasmCall"))] | ||
| pub fn handle_wasm_call() { | ||
| EVENT_LOOP_PROXY.with(|cell| { | ||
| cell.get().unwrap().send_event(CustomEvent::WasmCall).ok(); | ||
| }); | ||
| } | ||
|
|
||
| pub fn insert_canvas(window: &Window) { | ||
| use winit::platform::web::WindowExtWebSys; | ||
|
|
||
| let canvas = window.canvas(); | ||
|
|
||
| let window = web_sys::window().unwrap(); | ||
| let document = window.document().unwrap(); | ||
| let body = document.body().unwrap(); | ||
|
|
||
| // Set a background color for the canvas to make it easier to tell where the canvas is for debugging purposes. | ||
| canvas.style().set_property("background-color", "crimson").unwrap(); | ||
| body.append_child(&canvas).unwrap(); | ||
|
|
||
| // Create script element | ||
| let script: HtmlScriptElement = document | ||
| .create_element("script") | ||
| .unwrap() | ||
| .dyn_into() | ||
| .unwrap(); | ||
| script.set_type("module"); | ||
|
|
||
| // Your JavaScript code here, including creating the button and attaching the event handler | ||
| script.set_inner_text( | ||
| r#" | ||
| import { handleWasmCall } from "./wasm_custom_event.js"; | ||
| let button = document.createElement("button"); | ||
| button.innerHTML = "Favourite Number?"; | ||
| button.onclick = handleWasmCall; | ||
| document.body.appendChild(button); | ||
| "#, | ||
| ); | ||
|
|
||
| let first_child = body.first_child(); | ||
| match first_child { | ||
| Some(node) => body.insert_before(&script, Some(&node)).unwrap(), | ||
| None => body.append_child(&script).unwrap(), | ||
| }; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,13 @@ | ||
| fn main() { | ||
| cargo_run_wasm::run_wasm_with_css("body { margin: 0px; }"); | ||
| cargo_run_wasm::run_wasm_with_css( | ||
| r#" | ||
| body { | ||
| margin: 0px; | ||
| display: flex; | ||
| flex-direction: column; | ||
| justify-content: center; | ||
| align-items: center; | ||
| } | ||
| "#, | ||
| ); | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Let's make a slightly more useful example. Instead of just printing 42 we could e.g. use
Window::set_inner_size(), which is a valid use-case and would also show how to pass parameters. This would require two input fields for width and height and a button to send.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.
Awaiting if the cargo-wasm-runner will go through first. rukai/cargo-run-wasm#36