Re-introduce Web examples (#3637)
This commit is contained in:
parent
24faacf497
commit
c15fa6e433
|
@ -1,6 +1,3 @@
|
|||
[alias]
|
||||
run-wasm = ["run", "--release", "--package", "run-wasm", "--"]
|
||||
|
||||
# Allow rust-analyzer and local `cargo doc` invocations to pick up unreleased changelog entries
|
||||
#
|
||||
# Note that these flags are (intentionally) not included when building from the downloaded crate.
|
||||
|
|
71
Cargo.toml
71
Cargo.toml
|
@ -1,7 +1,10 @@
|
|||
[package]
|
||||
name = "winit"
|
||||
version = "0.29.15"
|
||||
authors = ["The winit contributors", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||
authors = [
|
||||
"The winit contributors",
|
||||
"Pierre Krieger <pierre.krieger1708@gmail.com>",
|
||||
]
|
||||
description = "Cross-platform window creation library."
|
||||
keywords = ["windowing"]
|
||||
readme = "README.md"
|
||||
|
@ -45,7 +48,15 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||
[features]
|
||||
default = ["rwh_06", "x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
|
||||
x11 = ["x11-dl", "bytemuck", "percent-encoding", "xkbcommon-dl/x11", "x11rb"]
|
||||
wayland = ["wayland-client", "wayland-backend", "wayland-protocols", "wayland-protocols-plasma", "sctk", "ahash", "memmap2"]
|
||||
wayland = [
|
||||
"wayland-client",
|
||||
"wayland-backend",
|
||||
"wayland-protocols",
|
||||
"wayland-protocols-plasma",
|
||||
"sctk",
|
||||
"ahash",
|
||||
"memmap2",
|
||||
]
|
||||
wayland-dlopen = ["wayland-backend/dlopen"]
|
||||
wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/ab_glyph"]
|
||||
wayland-csd-adwaita-crossfont = ["sctk-adwaita", "sctk-adwaita/crossfont"]
|
||||
|
@ -66,8 +77,12 @@ bitflags = "2"
|
|||
cursor-icon = "1.1.0"
|
||||
dpi = { version = "0.1.1", path = "dpi" }
|
||||
rwh_04 = { package = "raw-window-handle", version = "0.4", optional = true }
|
||||
rwh_05 = { package = "raw-window-handle", version = "0.5.2", features = ["std"], optional = true }
|
||||
rwh_06 = { package = "raw-window-handle", version = "0.6", features = ["std"], optional = true }
|
||||
rwh_05 = { package = "raw-window-handle", version = "0.5.2", features = [
|
||||
"std",
|
||||
], optional = true }
|
||||
rwh_06 = { package = "raw-window-handle", version = "0.6", features = [
|
||||
"std",
|
||||
], optional = true }
|
||||
serde = { workspace = true, optional = true }
|
||||
smol_str = "0.2.0"
|
||||
tracing = { version = "0.1.40", default_features = false }
|
||||
|
@ -79,7 +94,12 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
|||
winit = { path = ".", features = ["rwh_05"] }
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dev-dependencies]
|
||||
softbuffer = { version = "0.3.0", default-features = false, features = ["x11", "x11-dlopen", "wayland", "wayland-dlopen"] }
|
||||
softbuffer = { version = "0.3.0", default-features = false, features = [
|
||||
"x11",
|
||||
"x11-dlopen",
|
||||
"wayland",
|
||||
"wayland-dlopen",
|
||||
] }
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
android-activity = "0.5.0"
|
||||
|
@ -194,15 +214,35 @@ calloop = "0.12.3"
|
|||
libc = "0.2.64"
|
||||
memmap2 = { version = "0.9.0", optional = true }
|
||||
percent-encoding = { version = "2.0", optional = true }
|
||||
rustix = { version = "0.38.4", default-features = false, features = ["std", "system", "thread", "process"] }
|
||||
sctk = { package = "smithay-client-toolkit", version = "0.18.0", default-features = false, features = ["calloop"], optional = true }
|
||||
rustix = { version = "0.38.4", default-features = false, features = [
|
||||
"std",
|
||||
"system",
|
||||
"thread",
|
||||
"process",
|
||||
] }
|
||||
sctk = { package = "smithay-client-toolkit", version = "0.18.0", default-features = false, features = [
|
||||
"calloop",
|
||||
], optional = true }
|
||||
sctk-adwaita = { version = "0.9.0", default_features = false, optional = true }
|
||||
wayland-backend = { version = "0.3.0", default_features = false, features = ["client_system"], optional = true }
|
||||
wayland-backend = { version = "0.3.0", default_features = false, features = [
|
||||
"client_system",
|
||||
], optional = true }
|
||||
wayland-client = { version = "0.31.1", optional = true }
|
||||
wayland-protocols = { version = "0.31.0", features = [ "staging"], optional = true }
|
||||
wayland-protocols-plasma = { version = "0.2.0", features = [ "client" ], optional = true }
|
||||
wayland-protocols = { version = "0.31.0", features = [
|
||||
"staging",
|
||||
], optional = true }
|
||||
wayland-protocols-plasma = { version = "0.2.0", features = [
|
||||
"client",
|
||||
], optional = true }
|
||||
x11-dl = { version = "2.19.1", optional = true }
|
||||
x11rb = { version = "0.13.0", default-features = false, features = ["allow-unsafe-code", "dl-libxcb", "randr", "resource_manager", "xinput", "xkb"], optional = true }
|
||||
x11rb = { version = "0.13.0", default-features = false, features = [
|
||||
"allow-unsafe-code",
|
||||
"dl-libxcb",
|
||||
"randr",
|
||||
"resource_manager",
|
||||
"xinput",
|
||||
"xkb",
|
||||
], optional = true }
|
||||
xkbcommon-dl = "0.4.2"
|
||||
|
||||
[target.'cfg(target_os = "redox")'.dependencies]
|
||||
|
@ -266,8 +306,8 @@ atomic-waker = "1"
|
|||
concurrent-queue = { version = "2", default-features = false }
|
||||
|
||||
[target.'cfg(target_family = "wasm")'.dev-dependencies]
|
||||
console_log = "1"
|
||||
web-sys = { version = "0.3.22", features = ['CanvasRenderingContext2d'] }
|
||||
console_error_panic_hook = "0.1"
|
||||
tracing-web = "0.1"
|
||||
|
||||
[[example]]
|
||||
doc-scrape-examples = true
|
||||
|
@ -275,10 +315,7 @@ name = "window"
|
|||
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"dpi",
|
||||
"run-wasm",
|
||||
]
|
||||
members = ["dpi"]
|
||||
|
||||
[workspace.package]
|
||||
rust-version = "1.70.0"
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::thread;
|
|||
#[cfg(not(web_platform))]
|
||||
use std::time;
|
||||
|
||||
use ::tracing::{info, warn};
|
||||
#[cfg(web_platform)]
|
||||
use web_time as time;
|
||||
|
||||
|
@ -15,6 +16,8 @@ use winit::window::{Window, WindowId};
|
|||
|
||||
#[path = "util/fill.rs"]
|
||||
mod fill;
|
||||
#[path = "util/tracing.rs"]
|
||||
mod tracing;
|
||||
|
||||
const WAIT_TIME: time::Duration = time::Duration::from_millis(100);
|
||||
const POLL_SLEEP_TIME: time::Duration = time::Duration::from_millis(100);
|
||||
|
@ -28,13 +31,16 @@ enum Mode {
|
|||
}
|
||||
|
||||
fn main() -> Result<(), impl std::error::Error> {
|
||||
tracing_subscriber::fmt::init();
|
||||
#[cfg(web_platform)]
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
println!("Press '1' to switch to Wait mode.");
|
||||
println!("Press '2' to switch to WaitUntil mode.");
|
||||
println!("Press '3' to switch to Poll mode.");
|
||||
println!("Press 'R' to toggle request_redraw() calls.");
|
||||
println!("Press 'Esc' to close the window.");
|
||||
tracing::init();
|
||||
|
||||
info!("Press '1' to switch to Wait mode.");
|
||||
info!("Press '2' to switch to WaitUntil mode.");
|
||||
info!("Press '3' to switch to Poll mode.");
|
||||
info!("Press 'R' to toggle request_redraw() calls.");
|
||||
info!("Press 'Esc' to close the window.");
|
||||
|
||||
let event_loop = EventLoop::new().unwrap();
|
||||
|
||||
|
@ -53,7 +59,7 @@ struct ControlFlowDemo {
|
|||
|
||||
impl ApplicationHandler for ControlFlowDemo {
|
||||
fn new_events(&mut self, _event_loop: &ActiveEventLoop, cause: StartCause) {
|
||||
println!("new_events: {cause:?}");
|
||||
info!("new_events: {cause:?}");
|
||||
|
||||
self.wait_cancelled = match cause {
|
||||
StartCause::WaitCancelled { .. } => self.mode == Mode::WaitUntil,
|
||||
|
@ -74,7 +80,7 @@ impl ApplicationHandler for ControlFlowDemo {
|
|||
_window_id: WindowId,
|
||||
event: WindowEvent,
|
||||
) {
|
||||
println!("{event:?}");
|
||||
info!("{event:?}");
|
||||
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
|
@ -93,19 +99,19 @@ impl ApplicationHandler for ControlFlowDemo {
|
|||
// See the `key_binding` example
|
||||
Key::Character("1") => {
|
||||
self.mode = Mode::Wait;
|
||||
println!("\nmode: {:?}\n", self.mode);
|
||||
warn!("mode: {:?}", self.mode);
|
||||
}
|
||||
Key::Character("2") => {
|
||||
self.mode = Mode::WaitUntil;
|
||||
println!("\nmode: {:?}\n", self.mode);
|
||||
warn!("mode: {:?}", self.mode);
|
||||
}
|
||||
Key::Character("3") => {
|
||||
self.mode = Mode::Poll;
|
||||
println!("\nmode: {:?}\n", self.mode);
|
||||
warn!("mode: {:?}", self.mode);
|
||||
}
|
||||
Key::Character("r") => {
|
||||
self.request_redraw = !self.request_redraw;
|
||||
println!("\nrequest_redraw: {}\n", self.request_redraw);
|
||||
warn!("request_redraw: {}", self.request_redraw);
|
||||
}
|
||||
Key::Named(NamedKey::Escape) => {
|
||||
self.close_requested = true;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#[cfg(not(web_platform))]
|
||||
pub fn init() {
|
||||
use tracing_subscriber::filter::{EnvFilter, LevelFilter};
|
||||
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
EnvFilter::builder()
|
||||
.with_default_directive(LevelFilter::INFO.into())
|
||||
.from_env_lossy(),
|
||||
)
|
||||
.init();
|
||||
}
|
||||
|
||||
#[cfg(web_platform)]
|
||||
pub fn init() {
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(
|
||||
tracing_subscriber::fmt::layer()
|
||||
.with_ansi(false)
|
||||
.without_time()
|
||||
.with_writer(tracing_web::MakeWebConsoleWriter::new()),
|
||||
)
|
||||
.init();
|
||||
}
|
|
@ -7,8 +7,8 @@ use std::fmt::Debug;
|
|||
use std::mem;
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
use std::num::NonZeroU32;
|
||||
use std::path::Path;
|
||||
|
||||
use ::tracing::{error, info};
|
||||
use cursor_icon::CursorIcon;
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
use rwh_05::HasRawDisplayHandle;
|
||||
|
@ -34,10 +34,18 @@ use winit::platform::startup_notify::{
|
|||
self, EventLoopExtStartupNotify, WindowAttributesExtStartupNotify, WindowExtStartupNotify,
|
||||
};
|
||||
|
||||
#[path = "util/tracing.rs"]
|
||||
mod tracing;
|
||||
|
||||
/// The amount of points to around the window for drag resize direction calculations.
|
||||
const BORDER_SIZE: f64 = 20.;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
#[cfg(web_platform)]
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
tracing::init();
|
||||
|
||||
let event_loop = EventLoop::<UserEvent>::with_user_event().build()?;
|
||||
let _event_loop_proxy = event_loop.create_proxy();
|
||||
|
||||
|
@ -46,7 +54,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
std::thread::spawn(move || {
|
||||
// Wake up the `event_loop` once every second and dispatch a custom event
|
||||
// from a different thread.
|
||||
println!("Starting to send user event every second");
|
||||
info!("Starting to send user event every second");
|
||||
loop {
|
||||
let _ = _event_loop_proxy.send_event(UserEvent::WakeUp);
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
|
@ -88,11 +96,9 @@ impl Application {
|
|||
// by WM, and on Windows, you still have to account for screen scaling. Here we use 32px,
|
||||
// since it seems to work well enough in most cases. Be careful about going too high, or
|
||||
// you'll be bitten by the low-quality downscaling built into the WM.
|
||||
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/data/icon.png");
|
||||
let icon = load_icon(include_bytes!("data/icon.png"));
|
||||
|
||||
let icon = load_icon(Path::new(path));
|
||||
|
||||
println!("Loading cursor assets");
|
||||
info!("Loading cursor assets");
|
||||
let custom_cursors = vec![
|
||||
event_loop.create_custom_cursor(decode_cursor(include_bytes!("data/cross.png"))),
|
||||
event_loop.create_custom_cursor(decode_cursor(include_bytes!("data/cross2.png"))),
|
||||
|
@ -124,7 +130,7 @@ impl Application {
|
|||
#[cfg(any(x11_platform, wayland_platform))]
|
||||
if let Some(token) = event_loop.read_token_from_env() {
|
||||
startup_notify::reset_activation_token_env();
|
||||
println!("Using token {:?} to activate a window", token);
|
||||
info!("Using token {:?} to activate a window", token);
|
||||
window_attributes = window_attributes.with_activation_token(token);
|
||||
}
|
||||
|
||||
|
@ -133,6 +139,12 @@ impl Application {
|
|||
window_attributes = window_attributes.with_tabbing_identifier(&tab_id);
|
||||
}
|
||||
|
||||
#[cfg(web_platform)]
|
||||
{
|
||||
use winit::platform::web::WindowAttributesExtWebSys;
|
||||
window_attributes = window_attributes.with_append(true);
|
||||
}
|
||||
|
||||
let window = event_loop.create_window(window_attributes)?;
|
||||
|
||||
#[cfg(ios_platform)]
|
||||
|
@ -145,7 +157,7 @@ impl Application {
|
|||
|
||||
let window_state = WindowState::new(self, window)?;
|
||||
let window_id = window_state.window.id();
|
||||
println!("Created new window with id={window_id:?}");
|
||||
info!("Created new window with id={window_id:?}");
|
||||
self.windows.insert(window_id, window_state);
|
||||
Ok(window_id)
|
||||
}
|
||||
|
@ -153,7 +165,7 @@ impl Application {
|
|||
fn handle_action(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, action: Action) {
|
||||
// let cursor_position = self.cursor_position;
|
||||
let window = self.windows.get_mut(&window_id).unwrap();
|
||||
println!("Executing action: {action:?}");
|
||||
info!("Executing action: {action:?}");
|
||||
match action {
|
||||
Action::CloseWindow => {
|
||||
let _ = self.windows.remove(&window_id);
|
||||
|
@ -161,13 +173,13 @@ impl Application {
|
|||
Action::CreateNewWindow => {
|
||||
#[cfg(any(x11_platform, wayland_platform))]
|
||||
if let Err(err) = window.window.request_activation_token() {
|
||||
println!("Failed to get activation token: {err}");
|
||||
info!("Failed to get activation token: {err}");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(err) = self.create_window(event_loop, None) {
|
||||
eprintln!("Error creating new window: {err}");
|
||||
error!("Error creating new window: {err}");
|
||||
}
|
||||
}
|
||||
Action::ToggleResizeIncrements => window.toggle_resize_increments(),
|
||||
|
@ -180,6 +192,12 @@ impl Application {
|
|||
Action::Minimize => window.minimize(),
|
||||
Action::NextCursor => window.next_cursor(),
|
||||
Action::NextCustomCursor => window.next_custom_cursor(&self.custom_cursors),
|
||||
#[cfg(web_platform)]
|
||||
Action::UrlCustomCursor => window.url_custom_cursor(event_loop),
|
||||
#[cfg(web_platform)]
|
||||
Action::AnimationCustomCursor => {
|
||||
window.animation_custom_cursor(event_loop, &self.custom_cursors)
|
||||
}
|
||||
Action::CycleCursorGrab => window.cycle_cursor_grab(),
|
||||
Action::DragWindow => window.drag_window(),
|
||||
Action::DragResizeWindow => window.drag_resize_window(),
|
||||
|
@ -191,7 +209,7 @@ impl Application {
|
|||
Action::CreateNewTab => {
|
||||
let tab_id = window.window.tabbing_identifier();
|
||||
if let Err(err) = self.create_window(event_loop, Some(tab_id)) {
|
||||
eprintln!("Error creating new window: {err}");
|
||||
error!("Error creating new window: {err}");
|
||||
}
|
||||
}
|
||||
Action::RequestResize => window.swap_dimensions(),
|
||||
|
@ -199,7 +217,7 @@ impl Application {
|
|||
}
|
||||
|
||||
fn dump_monitors(&self, event_loop: &ActiveEventLoop) {
|
||||
println!("Monitors information");
|
||||
info!("Monitors information");
|
||||
let primary_monitor = event_loop.primary_monitor();
|
||||
for monitor in event_loop.available_monitors() {
|
||||
let intro = if primary_monitor.as_ref() == Some(&monitor) {
|
||||
|
@ -209,30 +227,32 @@ impl Application {
|
|||
};
|
||||
|
||||
if let Some(name) = monitor.name() {
|
||||
println!("{intro}: {name}");
|
||||
info!("{intro}: {name}");
|
||||
} else {
|
||||
println!("{intro}: [no name]");
|
||||
info!("{intro}: [no name]");
|
||||
}
|
||||
|
||||
let PhysicalSize { width, height } = monitor.size();
|
||||
print!(" Current mode: {width}x{height}");
|
||||
if let Some(m_hz) = monitor.refresh_rate_millihertz() {
|
||||
println!(" @ {}.{} Hz", m_hz / 1000, m_hz % 1000);
|
||||
} else {
|
||||
println!();
|
||||
}
|
||||
info!(
|
||||
" Current mode: {width}x{height}{}",
|
||||
if let Some(m_hz) = monitor.refresh_rate_millihertz() {
|
||||
format!(" @ {}.{} Hz", m_hz / 1000, m_hz % 1000)
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
);
|
||||
|
||||
let PhysicalPosition { x, y } = monitor.position();
|
||||
println!(" Position: {x},{y}");
|
||||
info!(" Position: {x},{y}");
|
||||
|
||||
println!(" Scale factor: {}", monitor.scale_factor());
|
||||
info!(" Scale factor: {}", monitor.scale_factor());
|
||||
|
||||
println!(" Available modes (width x height x bit-depth):");
|
||||
info!(" Available modes (width x height x bit-depth):");
|
||||
for mode in monitor.video_modes() {
|
||||
let PhysicalSize { width, height } = mode.size();
|
||||
let bits = mode.bit_depth();
|
||||
let m_hz = mode.refresh_rate_millihertz();
|
||||
println!(
|
||||
info!(
|
||||
" {width}x{height}x{bits} @ {}.{} Hz",
|
||||
m_hz / 1000,
|
||||
m_hz % 1000
|
||||
|
@ -260,9 +280,9 @@ impl Application {
|
|||
}
|
||||
|
||||
fn print_help(&self) {
|
||||
println!("Keyboard bindings:");
|
||||
info!("Keyboard bindings:");
|
||||
for binding in KEY_BINDINGS {
|
||||
println!(
|
||||
info!(
|
||||
"{}{:<10} - {} ({})",
|
||||
modifiers_to_string(binding.mods),
|
||||
binding.trigger,
|
||||
|
@ -270,9 +290,9 @@ impl Application {
|
|||
binding.action.help(),
|
||||
);
|
||||
}
|
||||
println!("Mouse bindings:");
|
||||
info!("Mouse bindings:");
|
||||
for binding in MOUSE_BINDINGS {
|
||||
println!(
|
||||
info!(
|
||||
"{}{:<10} - {} ({})",
|
||||
modifiers_to_string(binding.mods),
|
||||
mouse_button_to_string(binding.trigger),
|
||||
|
@ -285,7 +305,7 @@ impl Application {
|
|||
|
||||
impl ApplicationHandler<UserEvent> for Application {
|
||||
fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: UserEvent) {
|
||||
println!("User event: {event:?}");
|
||||
info!("User event: {event:?}");
|
||||
}
|
||||
|
||||
fn window_event(
|
||||
|
@ -305,40 +325,40 @@ impl ApplicationHandler<UserEvent> for Application {
|
|||
}
|
||||
WindowEvent::Focused(focused) => {
|
||||
if focused {
|
||||
println!("Window={window_id:?} focused");
|
||||
info!("Window={window_id:?} focused");
|
||||
} else {
|
||||
println!("Window={window_id:?} unfocused");
|
||||
info!("Window={window_id:?} unfocused");
|
||||
}
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
|
||||
println!("Window={window_id:?} changed scale to {scale_factor}");
|
||||
info!("Window={window_id:?} changed scale to {scale_factor}");
|
||||
}
|
||||
WindowEvent::ThemeChanged(theme) => {
|
||||
println!("Theme changed to {theme:?}");
|
||||
info!("Theme changed to {theme:?}");
|
||||
window.set_theme(theme);
|
||||
}
|
||||
WindowEvent::RedrawRequested => {
|
||||
if let Err(err) = window.draw() {
|
||||
eprintln!("Error drawing window: {err}");
|
||||
error!("Error drawing window: {err}");
|
||||
}
|
||||
}
|
||||
WindowEvent::Occluded(occluded) => {
|
||||
window.set_occluded(occluded);
|
||||
}
|
||||
WindowEvent::CloseRequested => {
|
||||
println!("Closing Window={window_id:?}");
|
||||
info!("Closing Window={window_id:?}");
|
||||
self.windows.remove(&window_id);
|
||||
}
|
||||
WindowEvent::ModifiersChanged(modifiers) => {
|
||||
window.modifiers = modifiers.state();
|
||||
println!("Modifiers changed to {:?}", window.modifiers);
|
||||
info!("Modifiers changed to {:?}", window.modifiers);
|
||||
}
|
||||
WindowEvent::MouseWheel { delta, .. } => match delta {
|
||||
MouseScrollDelta::LineDelta(x, y) => {
|
||||
println!("Mouse wheel Line Delta: ({x},{y})");
|
||||
info!("Mouse wheel Line Delta: ({x},{y})");
|
||||
}
|
||||
MouseScrollDelta::PixelDelta(px) => {
|
||||
println!("Mouse wheel Pixel Delta: ({},{})", px.x, px.y);
|
||||
info!("Mouse wheel Pixel Delta: ({},{})", px.x, px.y);
|
||||
}
|
||||
},
|
||||
WindowEvent::KeyboardInput {
|
||||
|
@ -372,11 +392,11 @@ impl ApplicationHandler<UserEvent> for Application {
|
|||
}
|
||||
}
|
||||
WindowEvent::CursorLeft { .. } => {
|
||||
println!("Cursor left Window={window_id:?}");
|
||||
info!("Cursor left Window={window_id:?}");
|
||||
window.cursor_left();
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
println!("Moved cursor to {position:?}");
|
||||
info!("Moved cursor to {position:?}");
|
||||
window.cursor_moved(position);
|
||||
}
|
||||
WindowEvent::ActivationTokenDone { token: _token, .. } => {
|
||||
|
@ -384,40 +404,40 @@ impl ApplicationHandler<UserEvent> for Application {
|
|||
{
|
||||
startup_notify::set_activation_token_env(_token);
|
||||
if let Err(err) = self.create_window(event_loop, None) {
|
||||
eprintln!("Error creating new window: {err}");
|
||||
error!("Error creating new window: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowEvent::Ime(event) => match event {
|
||||
Ime::Enabled => println!("IME enabled for Window={window_id:?}"),
|
||||
Ime::Enabled => info!("IME enabled for Window={window_id:?}"),
|
||||
Ime::Preedit(text, caret_pos) => {
|
||||
println!("Preedit: {}, with caret at {:?}", text, caret_pos);
|
||||
info!("Preedit: {}, with caret at {:?}", text, caret_pos);
|
||||
}
|
||||
Ime::Commit(text) => {
|
||||
println!("Committed: {}", text);
|
||||
info!("Committed: {}", text);
|
||||
}
|
||||
Ime::Disabled => println!("IME disabled for Window={window_id:?}"),
|
||||
Ime::Disabled => info!("IME disabled for Window={window_id:?}"),
|
||||
},
|
||||
WindowEvent::PinchGesture { delta, .. } => {
|
||||
window.zoom += delta;
|
||||
let zoom = window.zoom;
|
||||
if delta > 0.0 {
|
||||
println!("Zoomed in {delta:.5} (now: {zoom:.5})");
|
||||
info!("Zoomed in {delta:.5} (now: {zoom:.5})");
|
||||
} else {
|
||||
println!("Zoomed out {delta:.5} (now: {zoom:.5})");
|
||||
info!("Zoomed out {delta:.5} (now: {zoom:.5})");
|
||||
}
|
||||
}
|
||||
WindowEvent::RotationGesture { delta, .. } => {
|
||||
window.rotated += delta;
|
||||
let rotated = window.rotated;
|
||||
if delta > 0.0 {
|
||||
println!("Rotated counterclockwise {delta:.5} (now: {rotated:.5})");
|
||||
info!("Rotated counterclockwise {delta:.5} (now: {rotated:.5})");
|
||||
} else {
|
||||
println!("Rotated clockwise {delta:.5} (now: {rotated:.5})");
|
||||
info!("Rotated clockwise {delta:.5} (now: {rotated:.5})");
|
||||
}
|
||||
}
|
||||
WindowEvent::DoubleTapGesture { .. } => {
|
||||
println!("Smart zoom");
|
||||
info!("Smart zoom");
|
||||
}
|
||||
WindowEvent::TouchpadPressure { .. }
|
||||
| WindowEvent::HoveredFileCancelled
|
||||
|
@ -438,11 +458,11 @@ impl ApplicationHandler<UserEvent> for Application {
|
|||
device_id: DeviceId,
|
||||
event: DeviceEvent,
|
||||
) {
|
||||
println!("Device {device_id:?} event: {event:?}");
|
||||
info!("Device {device_id:?} event: {event:?}");
|
||||
}
|
||||
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
println!("Resumed the event loop");
|
||||
info!("Resumed the event loop");
|
||||
self.dump_monitors(event_loop);
|
||||
|
||||
// Create initial window.
|
||||
|
@ -454,7 +474,7 @@ impl ApplicationHandler<UserEvent> for Application {
|
|||
|
||||
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if self.windows.is_empty() {
|
||||
println!("No windows left, exiting...");
|
||||
info!("No windows left, exiting...");
|
||||
event_loop.exit();
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +529,7 @@ impl WindowState {
|
|||
let surface = unsafe { Surface::new(app.context.as_ref().unwrap(), &window)? };
|
||||
|
||||
let theme = window.theme().unwrap_or(Theme::Dark);
|
||||
println!("Theme: {theme:?}");
|
||||
info!("Theme: {theme:?}");
|
||||
let named_idx = 0;
|
||||
window.set_cursor(CURSORS[named_idx]);
|
||||
|
||||
|
@ -596,7 +616,7 @@ impl WindowState {
|
|||
Some(_) => None,
|
||||
None => Some(LogicalSize::new(25.0, 25.0)),
|
||||
};
|
||||
println!("Had increments: {}", new_increments.is_none());
|
||||
info!("Had increments: {}", new_increments.is_none());
|
||||
self.window.set_resize_increments(new_increments);
|
||||
}
|
||||
|
||||
|
@ -618,9 +638,9 @@ impl WindowState {
|
|||
CursorGrabMode::Confined => CursorGrabMode::Locked,
|
||||
CursorGrabMode::Locked => CursorGrabMode::None,
|
||||
};
|
||||
println!("Changing cursor grab mode to {:?}", self.cursor_grab);
|
||||
info!("Changing cursor grab mode to {:?}", self.cursor_grab);
|
||||
if let Err(err) = self.window.set_cursor_grab(self.cursor_grab) {
|
||||
eprintln!("Error setting cursor grab: {err}");
|
||||
error!("Error setting cursor grab: {err}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -632,7 +652,7 @@ impl WindowState {
|
|||
OptionAsAlt::OnlyRight => OptionAsAlt::Both,
|
||||
OptionAsAlt::Both => OptionAsAlt::None,
|
||||
};
|
||||
println!("Setting option as alt {:?}", self.option_as_alt);
|
||||
info!("Setting option as alt {:?}", self.option_as_alt);
|
||||
self.window.set_option_as_alt(self.option_as_alt);
|
||||
}
|
||||
|
||||
|
@ -642,23 +662,23 @@ impl WindowState {
|
|||
let mut inner_size = old_inner_size;
|
||||
|
||||
mem::swap(&mut inner_size.width, &mut inner_size.height);
|
||||
println!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
|
||||
info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
|
||||
|
||||
if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
|
||||
if old_inner_size == new_inner_size {
|
||||
println!("Inner size change got ignored");
|
||||
info!("Inner size change got ignored");
|
||||
} else {
|
||||
self.resize(new_inner_size);
|
||||
}
|
||||
} else {
|
||||
println!("Request inner size is asynchronous");
|
||||
info!("Request inner size is asynchronous");
|
||||
}
|
||||
}
|
||||
|
||||
/// Pick the next cursor.
|
||||
fn next_cursor(&mut self) {
|
||||
self.named_idx = (self.named_idx + 1) % CURSORS.len();
|
||||
println!("Setting cursor to \"{:?}\"", CURSORS[self.named_idx]);
|
||||
info!("Setting cursor to \"{:?}\"", CURSORS[self.named_idx]);
|
||||
self.window
|
||||
.set_cursor(Cursor::Icon(CURSORS[self.named_idx]));
|
||||
}
|
||||
|
@ -670,9 +690,38 @@ impl WindowState {
|
|||
self.window.set_cursor(cursor);
|
||||
}
|
||||
|
||||
/// Custom cursor from an URL.
|
||||
#[cfg(web_platform)]
|
||||
fn url_custom_cursor(&mut self, event_loop: &ActiveEventLoop) {
|
||||
let cursor = event_loop.create_custom_cursor(url_custom_cursor());
|
||||
|
||||
self.window.set_cursor(cursor);
|
||||
}
|
||||
|
||||
/// Custom cursor from a URL.
|
||||
#[cfg(web_platform)]
|
||||
fn animation_custom_cursor(
|
||||
&mut self,
|
||||
event_loop: &ActiveEventLoop,
|
||||
custom_cursors: &[CustomCursor],
|
||||
) {
|
||||
use std::time::Duration;
|
||||
use winit::platform::web::CustomCursorExtWebSys;
|
||||
|
||||
let cursors = vec![
|
||||
custom_cursors[0].clone(),
|
||||
custom_cursors[1].clone(),
|
||||
event_loop.create_custom_cursor(url_custom_cursor()),
|
||||
];
|
||||
let cursor = CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap();
|
||||
let cursor = event_loop.create_custom_cursor(cursor);
|
||||
|
||||
self.window.set_cursor(cursor);
|
||||
}
|
||||
|
||||
/// Resize the window to the new size.
|
||||
fn resize(&mut self, size: PhysicalSize<u32>) {
|
||||
println!("Resized to {size:?}");
|
||||
info!("Resized to {size:?}");
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
{
|
||||
let (width, height) = match (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
|
||||
|
@ -703,9 +752,9 @@ impl WindowState {
|
|||
/// Drag the window.
|
||||
fn drag_window(&self) {
|
||||
if let Err(err) = self.window.drag_window() {
|
||||
println!("Error starting window drag: {err}");
|
||||
info!("Error starting window drag: {err}");
|
||||
} else {
|
||||
println!("Dragging window Window={:?}", self.window.id());
|
||||
info!("Dragging window Window={:?}", self.window.id());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -714,7 +763,7 @@ impl WindowState {
|
|||
let position = match self.cursor_position {
|
||||
Some(position) => position,
|
||||
None => {
|
||||
println!("Drag-resize requires cursor to be inside the window");
|
||||
info!("Drag-resize requires cursor to be inside the window");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -753,9 +802,9 @@ impl WindowState {
|
|||
};
|
||||
|
||||
if let Err(err) = self.window.drag_resize_window(direction) {
|
||||
println!("Error starting window drag-resize: {err}");
|
||||
info!("Error starting window drag-resize: {err}");
|
||||
} else {
|
||||
println!("Drag-resizing window Window={:?}", self.window.id());
|
||||
info!("Drag-resizing window Window={:?}", self.window.id());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -771,7 +820,7 @@ impl WindowState {
|
|||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
fn draw(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
if self.occluded {
|
||||
println!("Skipping drawing occluded window={:?}", self.window.id());
|
||||
info!("Skipping drawing occluded window={:?}", self.window.id());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -792,7 +841,7 @@ impl WindowState {
|
|||
|
||||
#[cfg(any(android_platform, ios_platform))]
|
||||
fn draw(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
println!("Drawing but without rendering...");
|
||||
info!("Drawing but without rendering...");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -831,6 +880,10 @@ enum Action {
|
|||
Minimize,
|
||||
NextCursor,
|
||||
NextCustomCursor,
|
||||
#[cfg(web_platform)]
|
||||
UrlCustomCursor,
|
||||
#[cfg(web_platform)]
|
||||
AnimationCustomCursor,
|
||||
CycleCursorGrab,
|
||||
PrintHelp,
|
||||
DragWindow,
|
||||
|
@ -858,6 +911,10 @@ impl Action {
|
|||
Action::ToggleResizeIncrements => "Use resize increments when resizing window",
|
||||
Action::NextCursor => "Advance the cursor to the next value",
|
||||
Action::NextCustomCursor => "Advance custom cursor to the next value",
|
||||
#[cfg(web_platform)]
|
||||
Action::UrlCustomCursor => "Custom cursor from an URL",
|
||||
#[cfg(web_platform)]
|
||||
Action::AnimationCustomCursor => "Custom cursor from an animation",
|
||||
Action::CycleCursorGrab => "Cycle through cursor grab mode",
|
||||
Action::PrintHelp => "Print help",
|
||||
Action::DragWindow => "Start window drag",
|
||||
|
@ -886,11 +943,27 @@ fn decode_cursor(bytes: &[u8]) -> CustomCursorSource {
|
|||
CustomCursor::from_rgba(samples.samples, w, h, w / 2, h / 2).unwrap()
|
||||
}
|
||||
|
||||
fn load_icon(path: &Path) -> Icon {
|
||||
#[cfg(web_platform)]
|
||||
fn url_custom_cursor() -> CustomCursorSource {
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use winit::platform::web::CustomCursorExtWebSys;
|
||||
|
||||
static URL_COUNTER: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
CustomCursor::from_url(
|
||||
format!(
|
||||
"https://picsum.photos/128?random={}",
|
||||
URL_COUNTER.fetch_add(1, Ordering::Relaxed)
|
||||
),
|
||||
64,
|
||||
64,
|
||||
)
|
||||
}
|
||||
|
||||
fn load_icon(bytes: &[u8]) -> Icon {
|
||||
let (icon_rgba, icon_width, icon_height) = {
|
||||
let image = image::open(path)
|
||||
.expect("Failed to open icon path")
|
||||
.into_rgba8();
|
||||
let image = image::load_from_memory(bytes).unwrap().into_rgba8();
|
||||
let (width, height) = image.dimensions();
|
||||
let rgba = image.into_raw();
|
||||
(rgba, width, height)
|
||||
|
@ -983,6 +1056,18 @@ const KEY_BINDINGS: &[Binding<&'static str>] = &[
|
|||
// C.
|
||||
Binding::new("C", ModifiersState::CONTROL, Action::NextCursor),
|
||||
Binding::new("C", ModifiersState::ALT, Action::NextCustomCursor),
|
||||
#[cfg(web_platform)]
|
||||
Binding::new(
|
||||
"C",
|
||||
ModifiersState::CONTROL.union(ModifiersState::SHIFT),
|
||||
Action::UrlCustomCursor,
|
||||
),
|
||||
#[cfg(web_platform)]
|
||||
Binding::new(
|
||||
"C",
|
||||
ModifiersState::ALT.union(ModifiersState::SHIFT),
|
||||
Action::AnimationCustomCursor,
|
||||
),
|
||||
Binding::new("Z", ModifiersState::CONTROL, Action::ToggleCursorVisibility),
|
||||
#[cfg(macos_platform)]
|
||||
Binding::new("T", ModifiersState::SUPER, Action::CreateNewTab),
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[package]
|
||||
name = "run-wasm"
|
||||
version = "0.1.0"
|
||||
rust-version.workspace = true
|
||||
repository.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
cargo-run-wasm = "0.2.0"
|
|
@ -1,3 +0,0 @@
|
|||
fn main() {
|
||||
cargo_run_wasm::run_wasm_with_css("body { margin: 0px; }");
|
||||
}
|
Loading…
Reference in New Issue