diff --git a/CHANGELOG.md b/CHANGELOG.md index a9d8e4f6ef4..ee848821609 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ Unreleased` header. # Unreleased +- **Breaking:** Rename `EventLoopWindowTarget` to `ActiveEventLoop`. +- **Breaking:** Remove `Deref` implementation for `EventLoop` that gave `EventLoopWindowTarget`. - On X11, fix swapped instance and general class names. - **Breaking:** Removed unnecessary generic parameter `T` from `EventLoopWindowTarget`. - On Windows, macOS, X11, Wayland and Web, implement setting images as cursors. See the `custom_cursors.rs` example. diff --git a/examples/child_window.rs b/examples/child_window.rs index b9e28313c29..02369b730d5 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -1,10 +1,3 @@ -#[cfg(all( - feature = "rwh_06", - any(x11_platform, macos_platform, windows_platform) -))] -#[path = "util/fill.rs"] -mod fill; - #[cfg(all( feature = "rwh_06", any(x11_platform, macos_platform, windows_platform) @@ -13,19 +6,18 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { use std::collections::HashMap; + #[path = "util/fill.rs"] + mod fill; + use winit::{ dpi::{LogicalPosition, LogicalSize, Position}, event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::{EventLoop, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop}, raw_window_handle::HasRawWindowHandle, window::{Window, WindowId}, }; - fn spawn_child_window( - parent: &Window, - event_loop: &EventLoopWindowTarget, - windows: &mut HashMap, - ) { + fn spawn_child_window(parent: &Window, event_loop: &ActiveEventLoop) -> Window { let parent = parent.raw_window_handle().unwrap(); let mut builder = Window::builder() .with_title("child window") @@ -34,31 +26,34 @@ fn main() -> Result<(), impl std::error::Error> { .with_visible(true); // `with_parent_window` is unsafe. Parent window must be a valid window. builder = unsafe { builder.with_parent_window(Some(parent)) }; - let child_window = builder.build(event_loop).unwrap(); - let id = child_window.id(); - windows.insert(id, child_window); - println!("child window created with id: {id:?}"); + builder.build(event_loop).unwrap() } let mut windows = HashMap::new(); let event_loop: EventLoop<()> = EventLoop::new().unwrap(); - let parent_window = Window::builder() - .with_title("parent window") - .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) - .with_inner_size(LogicalSize::new(640.0f32, 480.0f32)) - .build(&event_loop) - .unwrap(); + let mut parent_window_id = unsafe { WindowId::dummy() }; - println!("parent window: {parent_window:?})"); + event_loop.run(move |event: Event<()>, event_loop| { + match event { + Event::Resumed => { + let window = Window::builder() + .with_title("parent window") + .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) + .with_inner_size(LogicalSize::new(640.0f32, 480.0f32)) + .build(event_loop) + .unwrap(); - event_loop.run(move |event: Event<()>, elwt| { - if let Event::WindowEvent { event, window_id } = event { - match event { + parent_window_id = window.id(); + + println!("Parent window id: {parent_window_id:?})"); + windows.insert(parent_window_id, window); + } + Event::WindowEvent { window_id, event } => match event { WindowEvent::CloseRequested => { windows.clear(); - elwt.exit(); + event_loop.exit(); } WindowEvent::CursorEntered { device_id: _ } => { // On x11, println when the cursor entered in a window even if the child window is created @@ -75,7 +70,11 @@ fn main() -> Result<(), impl std::error::Error> { }, .. } => { - spawn_child_window(&parent_window, elwt, &mut windows); + let parent_window = windows.get(&parent_window_id).unwrap(); + let child_window = spawn_child_window(parent_window, event_loop); + let child_id = child_window.id(); + println!("Child window created with id: {child_id:?}"); + windows.insert(child_id, child_window); } WindowEvent::RedrawRequested => { if let Some(window) = windows.get(&window_id) { @@ -83,15 +82,16 @@ fn main() -> Result<(), impl std::error::Error> { } } _ => (), - } + }, + _ => (), } }) } -#[cfg(not(all( +#[cfg(all( feature = "rwh_06", - any(x11_platform, macos_platform, windows_platform) -)))] + not(any(x11_platform, macos_platform, windows_platform)) +))] fn main() { panic!("This example is supported only on x11, macOS, and Windows, with the `rwh_06` feature enabled."); } diff --git a/examples/control_flow.rs b/examples/control_flow.rs index 1154b33f6c9..cdfa2703f6a 100644 --- a/examples/control_flow.rs +++ b/examples/control_flow.rs @@ -37,17 +37,14 @@ fn main() -> Result<(), impl std::error::Error> { println!("Press 'Esc' to close the window."); let event_loop = EventLoop::new().unwrap(); - let window = Window::builder() - .with_title("Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.") - .build(&event_loop) - .unwrap(); let mut mode = Mode::Wait; let mut request_redraw = false; let mut wait_cancelled = false; let mut close_requested = false; - event_loop.run(move |event, elwt| { + let mut window = None; + event_loop.run(move |event, event_loop| { use winit::event::StartCause; println!("{event:?}"); match event { @@ -57,6 +54,12 @@ fn main() -> Result<(), impl std::error::Error> { _ => false, } } + Event::Resumed => { + window = Some(Window::builder() + .with_title("Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.") + .build(event_loop) + .unwrap()); + } Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => { close_requested = true; @@ -94,32 +97,34 @@ fn main() -> Result<(), impl std::error::Error> { _ => (), }, WindowEvent::RedrawRequested => { - fill::fill_window(&window); + let window = window.as_ref().unwrap(); + window.pre_present_notify(); + fill::fill_window(window); } _ => (), }, Event::AboutToWait => { if request_redraw && !wait_cancelled && !close_requested { - window.request_redraw(); + window.as_ref().unwrap().request_redraw(); } match mode { - Mode::Wait => elwt.set_control_flow(ControlFlow::Wait), + Mode::Wait => event_loop.set_control_flow(ControlFlow::Wait), Mode::WaitUntil => { if !wait_cancelled { - elwt.set_control_flow(ControlFlow::WaitUntil( + event_loop.set_control_flow(ControlFlow::WaitUntil( time::Instant::now() + WAIT_TIME, )); } } Mode::Poll => { thread::sleep(POLL_SLEEP_TIME); - elwt.set_control_flow(ControlFlow::Poll); + event_loop.set_control_flow(ControlFlow::Poll); } }; if close_requested { - elwt.exit(); + event_loop.exit(); } } _ => (), diff --git a/examples/cursor.rs b/examples/cursor.rs deleted file mode 100644 index b857c19a7db..00000000000 --- a/examples/cursor.rs +++ /dev/null @@ -1,88 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, - window::{CursorIcon, Window}, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder().build(&event_loop).unwrap(); - window.set_title("A fantastic window!"); - - let mut cursor_idx = 0; - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Pressed, - .. - }, - .. - } => { - println!("Setting cursor to \"{:?}\"", CURSORS[cursor_idx]); - window.set_cursor(CURSORS[cursor_idx]); - if cursor_idx < CURSORS.len() - 1 { - cursor_idx += 1; - } else { - cursor_idx = 0; - } - } - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - WindowEvent::CloseRequested => { - elwt.exit(); - } - _ => (), - } - } - }) -} - -const CURSORS: &[CursorIcon] = &[ - CursorIcon::Default, - CursorIcon::Crosshair, - CursorIcon::Pointer, - CursorIcon::Move, - CursorIcon::Text, - CursorIcon::Wait, - CursorIcon::Help, - CursorIcon::Progress, - CursorIcon::NotAllowed, - CursorIcon::ContextMenu, - CursorIcon::Cell, - CursorIcon::VerticalText, - CursorIcon::Alias, - CursorIcon::Copy, - CursorIcon::NoDrop, - CursorIcon::Grab, - CursorIcon::Grabbing, - CursorIcon::AllScroll, - CursorIcon::ZoomIn, - CursorIcon::ZoomOut, - CursorIcon::EResize, - CursorIcon::NResize, - CursorIcon::NeResize, - CursorIcon::NwResize, - CursorIcon::SResize, - CursorIcon::SeResize, - CursorIcon::SwResize, - CursorIcon::WResize, - CursorIcon::EwResize, - CursorIcon::NsResize, - CursorIcon::NeswResize, - CursorIcon::NwseResize, - CursorIcon::ColResize, - CursorIcon::RowResize, -]; diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs deleted file mode 100644 index ea08c495ff8..00000000000 --- a/examples/cursor_grab.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, - keyboard::{Key, ModifiersState, NamedKey}, - window::{CursorGrabMode, Window}, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("Super Cursor Grab'n'Hide Simulator 9000") - .build(&event_loop) - .unwrap(); - - let mut modifiers = ModifiersState::default(); - - event_loop.run(move |event, elwt| match event { - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: key, - state: ElementState::Released, - .. - }, - .. - } => { - let result = match key { - Key::Named(NamedKey::Escape) => { - elwt.exit(); - Ok(()) - } - Key::Character(ch) => match ch.to_lowercase().as_str() { - "g" => window.set_cursor_grab(CursorGrabMode::Confined), - "l" => window.set_cursor_grab(CursorGrabMode::Locked), - "a" => window.set_cursor_grab(CursorGrabMode::None), - "h" => { - window.set_cursor_visible(modifiers.shift_key()); - Ok(()) - } - _ => Ok(()), - }, - _ => Ok(()), - }; - - if let Err(err) = result { - println!("error: {err}"); - } - } - WindowEvent::ModifiersChanged(new) => modifiers = new.state(), - WindowEvent::RedrawRequested => fill::fill_window(&window), - _ => (), - }, - Event::DeviceEvent { event, .. } => match event { - DeviceEvent::MouseMotion { delta } => println!("mouse moved: {delta:?}"), - DeviceEvent::Button { button, state } => match state { - ElementState::Pressed => println!("mouse button {button} pressed"), - ElementState::Released => println!("mouse button {button} released"), - }, - _ => (), - }, - _ => (), - }) -} diff --git a/examples/custom_cursors.rs b/examples/custom_cursors.rs deleted file mode 100644 index 0d0fb4469f8..00000000000 --- a/examples/custom_cursors.rs +++ /dev/null @@ -1,143 +0,0 @@ -#![allow(clippy::single_match, clippy::disallowed_methods)] - -#[cfg(not(web_platform))] -use simple_logger::SimpleLogger; -use winit::{ - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::{EventLoop, EventLoopWindowTarget}, - keyboard::Key, - window::{CursorIcon, CustomCursor, Window}, -}; -#[cfg(web_platform)] -use { - std::sync::atomic::{AtomicU64, Ordering}, - std::time::Duration, - winit::platform::web::CustomCursorExtWebSys, -}; - -#[cfg(web_platform)] -static COUNTER: AtomicU64 = AtomicU64::new(0); - -fn decode_cursor(bytes: &[u8], window_target: &EventLoopWindowTarget) -> CustomCursor { - let img = image::load_from_memory(bytes).unwrap().to_rgba8(); - let samples = img.into_flat_samples(); - let (_, w, h) = samples.extents(); - let (w, h) = (w as u16, h as u16); - let builder = CustomCursor::from_rgba(samples.samples, w, h, w / 2, h / 2).unwrap(); - - builder.build(window_target) -} - -#[cfg(not(web_platform))] -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - #[cfg(not(web_platform))] - SimpleLogger::new() - .with_level(log::LevelFilter::Info) - .init() - .unwrap(); - #[cfg(web_platform)] - console_log::init_with_level(log::Level::Debug).unwrap(); - - let event_loop = EventLoop::new().unwrap(); - let builder = Window::builder().with_title("A fantastic window!"); - #[cfg(web_platform)] - let builder = { - use winit::platform::web::WindowBuilderExtWebSys; - builder.with_append(true) - }; - let window = builder.build(&event_loop).unwrap(); - - let mut cursor_idx = 0; - let mut cursor_visible = true; - - let custom_cursors = [ - decode_cursor(include_bytes!("data/cross.png"), &event_loop), - decode_cursor(include_bytes!("data/cross2.png"), &event_loop), - decode_cursor(include_bytes!("data/gradient.png"), &event_loop), - ]; - - event_loop.run(move |event, _elwt| match event { - Event::WindowEvent { event, .. } => match event { - WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Pressed, - logical_key: key, - .. - }, - .. - } => match key.as_ref() { - Key::Character("1") => { - log::debug!("Setting cursor to {:?}", cursor_idx); - window.set_cursor(custom_cursors[cursor_idx].clone()); - cursor_idx = (cursor_idx + 1) % 3; - } - Key::Character("2") => { - log::debug!("Setting cursor icon to default"); - window.set_cursor(CursorIcon::default()); - } - Key::Character("3") => { - cursor_visible = !cursor_visible; - log::debug!("Setting cursor visibility to {:?}", cursor_visible); - window.set_cursor_visible(cursor_visible); - } - #[cfg(web_platform)] - Key::Character("4") => { - log::debug!("Setting cursor to a random image from an URL"); - window.set_cursor( - CustomCursor::from_url( - format!( - "https://picsum.photos/128?random={}", - COUNTER.fetch_add(1, Ordering::Relaxed) - ), - 64, - 64, - ) - .build(_elwt), - ); - } - #[cfg(web_platform)] - Key::Character("5") => { - log::debug!("Setting cursor to an animation"); - window.set_cursor( - CustomCursor::from_animation( - Duration::from_secs(3), - vec![ - custom_cursors[0].clone(), - custom_cursors[1].clone(), - CustomCursor::from_url( - format!( - "https://picsum.photos/128?random={}", - COUNTER.fetch_add(1, Ordering::Relaxed) - ), - 64, - 64, - ) - .build(_elwt), - ], - ) - .unwrap() - .build(_elwt), - ); - } - _ => {} - }, - WindowEvent::RedrawRequested => { - #[cfg(not(web_platform))] - fill::fill_window(&window); - } - WindowEvent::CloseRequested => { - #[cfg(not(web_platform))] - _elwt.exit(); - } - _ => (), - }, - Event::AboutToWait => { - window.request_redraw(); - } - _ => {} - }) -} diff --git a/examples/custom_events.rs b/examples/custom_events.rs deleted file mode 100644 index 90e8e41d8f5..00000000000 --- a/examples/custom_events.rs +++ /dev/null @@ -1,60 +0,0 @@ -#![allow(clippy::single_match)] - -#[cfg(not(web_platform))] -fn main() -> Result<(), impl std::error::Error> { - use simple_logger::SimpleLogger; - use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::Window, - }; - - #[path = "util/fill.rs"] - mod fill; - - #[derive(Debug, Clone, Copy)] - enum CustomEvent { - Timer, - } - - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::::with_user_event().build().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); - - // `EventLoopProxy` allows you to dispatch custom events to the main Winit event - // loop from any thread. - let event_loop_proxy = event_loop.create_proxy(); - - std::thread::spawn(move || { - // Wake up the `event_loop` once every second and dispatch a custom event - // from a different thread. - loop { - std::thread::sleep(std::time::Duration::from_secs(1)); - event_loop_proxy.send_event(CustomEvent::Timer).ok(); - } - }); - - event_loop.run(move |event, elwt| match event { - Event::UserEvent(event) => println!("user event: {event:?}"), - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => elwt.exit(), - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - fill::fill_window(&window); - } - _ => (), - }) -} - -#[cfg(web_platform)] -fn main() { - panic!("This example is not supported on web."); -} diff --git a/examples/icon.png b/examples/data/icon.png similarity index 100% rename from examples/icon.png rename to examples/data/icon.png diff --git a/examples/drag_window.rs b/examples/drag_window.rs deleted file mode 100644 index 5f2b597cd91..00000000000 --- a/examples/drag_window.rs +++ /dev/null @@ -1,105 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - event::{ElementState, Event, KeyEvent, MouseButton, StartCause, WindowEvent}, - event_loop::EventLoop, - keyboard::Key, - window::{Window, WindowId}, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window_1 = Window::builder().build(&event_loop).unwrap(); - let window_2 = Window::builder().build(&event_loop).unwrap(); - - let mut switched = false; - let mut entered_id = window_2.id(); - let mut cursor_location = None; - - event_loop.run(move |event, elwt| match event { - Event::NewEvents(StartCause::Init) => { - eprintln!("Switch which window is to be dragged by pressing \"x\".") - } - Event::WindowEvent { event, window_id } => match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::CursorMoved { position, .. } => cursor_location = Some(position), - WindowEvent::MouseInput { state, button, .. } => { - let window = if (window_id == window_1.id() && switched) - || (window_id == window_2.id() && !switched) - { - &window_2 - } else { - &window_1 - }; - - match (button, state) { - (MouseButton::Left, ElementState::Pressed) => window.drag_window().unwrap(), - (MouseButton::Right, ElementState::Released) => { - if let Some(position) = cursor_location { - window.show_window_menu(position); - } - } - _ => (), - } - } - WindowEvent::CursorEntered { .. } => { - entered_id = window_id; - name_windows(entered_id, switched, &window_1, &window_2) - } - WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Released, - logical_key: Key::Character(c), - .. - }, - .. - } => match c.as_str() { - "x" => { - switched = !switched; - name_windows(entered_id, switched, &window_1, &window_2); - println!("Switched!") - } - "d" => { - let window = if (window_id == window_1.id() && switched) - || (window_id == window_2.id() && !switched) - { - &window_2 - } else { - &window_1 - }; - - window.set_decorations(!window.is_decorated()); - } - _ => (), - }, - WindowEvent::RedrawRequested => { - if window_id == window_1.id() { - fill::fill_window(&window_1); - } else if window_id == window_2.id() { - fill::fill_window(&window_2); - } - } - _ => (), - }, - - _ => (), - }) -} - -fn name_windows(window_id: WindowId, switched: bool, window_1: &Window, window_2: &Window) { - let (drag_target, other) = - if (window_id == window_1.id() && switched) || (window_id == window_2.id() && !switched) { - (&window_2, &window_1) - } else { - (&window_1, &window_2) - }; - drag_target.set_title("drag target"); - other.set_title("winit window"); -} diff --git a/examples/focus.rs b/examples/focus.rs deleted file mode 100644 index e70a68793d6..00000000000 --- a/examples/focus.rs +++ /dev/null @@ -1,56 +0,0 @@ -#![allow(clippy::single_match)] - -//! Example for focusing a window. - -use simple_logger::SimpleLogger; -#[cfg(not(web_platform))] -use std::time; -#[cfg(web_platform)] -use web_time as time; -use winit::{ - event::{Event, StartCause, WindowEvent}, - event_loop::EventLoop, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) - .build(&event_loop) - .unwrap(); - - let mut deadline = time::Instant::now() + time::Duration::from_secs(3); - event_loop.run(move |event, elwt| { - match event { - Event::NewEvents(StartCause::ResumeTimeReached { .. }) => { - // Timeout reached; focus the window. - println!("Re-focusing the window."); - deadline += time::Duration::from_secs(3); - window.focus_window(); - } - Event::WindowEvent { event, window_id } if window_id == window.id() => match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::RedrawRequested => { - // Notify the windowing system that we'll be presenting to the window. - window.pre_present_notify(); - fill::fill_window(&window); - } - _ => (), - }, - Event::AboutToWait => { - window.request_redraw(); - } - - _ => (), - } - - elwt.set_control_flow(winit::event_loop::ControlFlow::WaitUntil(deadline)); - }) -} diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs deleted file mode 100644 index 979b216f7d2..00000000000 --- a/examples/fullscreen.rs +++ /dev/null @@ -1,163 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::dpi::LogicalSize; -use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; -use winit::event_loop::EventLoop; -use winit::keyboard::{Key, NamedKey}; -use winit::window::{Fullscreen, Window}; - -#[cfg(target_os = "macos")] -use winit::platform::macos::WindowExtMacOS; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let mut decorations = true; - let mut minimized = false; - let mut with_min_size = false; - let mut with_max_size = false; - - let window = Window::builder() - .with_title("Hello world!") - .build(&event_loop) - .unwrap(); - - let mut monitor_index = 0; - let mut monitor = event_loop - .available_monitors() - .next() - .expect("no monitor found!"); - println!("Monitor: {:?}", monitor.name()); - - let mut mode_index = 0; - let mut mode = monitor.video_modes().next().expect("no mode found"); - println!("Mode: {mode}"); - - println!("Keys:"); - println!("- Esc\tExit"); - println!("- F\tToggle exclusive fullscreen mode"); - println!("- B\tToggle borderless mode"); - #[cfg(target_os = "macos")] - println!("- C\tToggle simple fullscreen mode"); - println!("- S\tNext screen"); - println!("- M\tNext mode for this screen"); - println!("- D\tToggle window decorations"); - println!("- X\tMaximize window"); - println!("- Z\tMinimize window"); - println!("- I\tToggle mIn size limit"); - println!("- A\tToggle mAx size limit"); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: key, - state: ElementState::Pressed, - .. - }, - .. - } => match key { - Key::Named(NamedKey::Escape) => elwt.exit(), - // WARNING: Consider using `key_without_modifers()` if available on your platform. - // See the `key_binding` example - Key::Character(ch) => match ch.to_lowercase().as_str() { - "f" | "b" if window.fullscreen().is_some() => { - window.set_fullscreen(None); - } - "f" => { - let fullscreen = Some(Fullscreen::Exclusive(mode.clone())); - println!("Setting mode: {fullscreen:?}"); - window.set_fullscreen(fullscreen); - } - "b" => { - let fullscreen = Some(Fullscreen::Borderless(Some(monitor.clone()))); - println!("Setting mode: {fullscreen:?}"); - window.set_fullscreen(fullscreen); - } - #[cfg(target_os = "macos")] - "c" => { - window.set_simple_fullscreen(!window.simple_fullscreen()); - } - "s" => { - monitor_index += 1; - if let Some(mon) = elwt.available_monitors().nth(monitor_index) { - monitor = mon; - } else { - monitor_index = 0; - monitor = - elwt.available_monitors().next().expect("no monitor found!"); - } - println!("Monitor: {:?}", monitor.name()); - - mode_index = 0; - mode = monitor.video_modes().next().expect("no mode found"); - println!("Mode: {mode}"); - } - "m" => { - mode_index += 1; - if let Some(m) = monitor.video_modes().nth(mode_index) { - mode = m; - } else { - mode_index = 0; - mode = monitor.video_modes().next().expect("no mode found"); - } - println!("Mode: {mode}"); - } - "d" => { - decorations = !decorations; - window.set_decorations(decorations); - } - "x" => { - let is_maximized = window.is_maximized(); - window.set_maximized(!is_maximized); - } - "z" => { - minimized = !minimized; - window.set_minimized(minimized); - } - "i" => { - with_min_size = !with_min_size; - let min_size = if with_min_size { - Some(LogicalSize::new(100, 100)) - } else { - None - }; - window.set_min_inner_size(min_size); - eprintln!( - "Min: {with_min_size}: {min_size:?} => {:?}", - window.inner_size() - ); - } - "a" => { - with_max_size = !with_max_size; - let max_size = if with_max_size { - Some(LogicalSize::new(200, 200)) - } else { - None - }; - window.set_max_inner_size(max_size); - eprintln!( - "Max: {with_max_size}: {max_size:?} => {:?}", - window.inner_size() - ); - } - _ => (), - }, - _ => (), - }, - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/handling_close.rs b/examples/handling_close.rs deleted file mode 100644 index da15d65752b..00000000000 --- a/examples/handling_close.rs +++ /dev/null @@ -1,86 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, - keyboard::Key, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("Your faithful window") - .build(&event_loop) - .unwrap(); - - let mut close_requested = false; - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => { - // `CloseRequested` is sent when the close button on the window is pressed (or - // through whatever other mechanisms the window manager provides for closing a - // window). If you don't handle this event, the close button won't actually do - // anything. - - // A common thing to do here is prompt the user if they have unsaved work. - // Creating a proper dialog box for that is far beyond the scope of this - // example, so here we'll just respond to the Y and N keys. - println!("Are you ready to bid your window farewell? [Y/N]"); - close_requested = true; - - // In applications where you can safely close the window without further - // action from the user, this is generally where you'd handle cleanup before - // closing the window. How to close the window is detailed in the handler for - // the Y key. - } - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: key, - state: ElementState::Released, - .. - }, - .. - } => { - // WARNING: Consider using `key_without_modifers()` if available on your platform. - // See the `key_binding` example - match key.as_ref() { - Key::Character("y") => { - if close_requested { - // This is where you'll want to do any cleanup you need. - println!("Buh-bye!"); - - // For a single-window application like this, you'd normally just - // break out of the event loop here. If you wanted to keep running the - // event loop (i.e. if it's a multi-window application), you need to - // drop the window. That closes it, and results in `Destroyed` being - // sent. - elwt.exit(); - } - } - Key::Character("n") => { - if close_requested { - println!("Your window will continue to stay by your side."); - close_requested = false; - } - } - _ => (), - } - } - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/ime.rs b/examples/ime.rs deleted file mode 100644 index f18d87cf6a8..00000000000 --- a/examples/ime.rs +++ /dev/null @@ -1,94 +0,0 @@ -#![allow(clippy::single_match)] - -use log::LevelFilter; -use simple_logger::SimpleLogger; -use winit::{ - dpi::{PhysicalPosition, PhysicalSize}, - event::{ElementState, Event, Ime, WindowEvent}, - event_loop::EventLoop, - keyboard::NamedKey, - window::{ImePurpose, Window}, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new() - .with_level(LevelFilter::Trace) - .init() - .unwrap(); - - println!("IME position will system default"); - println!("Click to set IME position to cursor's"); - println!("Press F2 to toggle IME. See the documentation of `set_ime_allowed` for more info"); - println!("Press F3 to cycle through IME purposes."); - - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_inner_size(winit::dpi::LogicalSize::new(256f64, 128f64)) - .build(&event_loop) - .unwrap(); - - let mut ime_purpose = ImePurpose::Normal; - let mut ime_allowed = true; - window.set_ime_allowed(ime_allowed); - - let mut may_show_ime = false; - let mut cursor_position = PhysicalPosition::new(0.0, 0.0); - let mut ime_pos = PhysicalPosition::new(0.0, 0.0); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::CursorMoved { position, .. } => { - cursor_position = position; - } - WindowEvent::MouseInput { - state: ElementState::Released, - .. - } => { - println!( - "Setting ime position to {}, {}", - cursor_position.x, cursor_position.y - ); - ime_pos = cursor_position; - if may_show_ime { - window.set_ime_cursor_area(ime_pos, PhysicalSize::new(10, 10)); - } - } - WindowEvent::Ime(event) => { - println!("{event:?}"); - may_show_ime = event != Ime::Disabled; - if may_show_ime { - window.set_ime_cursor_area(ime_pos, PhysicalSize::new(10, 10)); - } - } - WindowEvent::KeyboardInput { event, .. } => { - println!("key: {event:?}"); - - if event.state == ElementState::Pressed && event.logical_key == NamedKey::F2 { - ime_allowed = !ime_allowed; - window.set_ime_allowed(ime_allowed); - println!("\nIME allowed: {ime_allowed}\n"); - } - if event.state == ElementState::Pressed && event.logical_key == NamedKey::F3 { - ime_purpose = match ime_purpose { - ImePurpose::Normal => ImePurpose::Password, - ImePurpose::Password => ImePurpose::Terminal, - _ => ImePurpose::Normal, - }; - window.set_ime_purpose(ime_purpose); - println!("\nIME purpose: {ime_purpose:?}\n"); - } - } - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/key_binding.rs b/examples/key_binding.rs deleted file mode 100644 index dcf18909aac..00000000000 --- a/examples/key_binding.rs +++ /dev/null @@ -1,62 +0,0 @@ -#![allow(clippy::single_match)] - -#[cfg(any(target_os = "macos", target_os = "windows", target_os = "linux"))] -use winit::{ - dpi::LogicalSize, - event::{ElementState, Event, WindowEvent}, - event_loop::EventLoop, - keyboard::{Key, ModifiersState}, - // WARNING: This is not available on all platforms (for example on the web). - platform::modifier_supplement::KeyEventExtModifierSupplement, - window::Window, -}; - -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] -fn main() { - println!("This example is not supported on this platform"); -} - -#[cfg(any(target_os = "macos", target_os = "windows", target_os = "linux"))] -fn main() -> Result<(), impl std::error::Error> { - #[path = "util/fill.rs"] - mod fill; - - simple_logger::SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_inner_size(LogicalSize::new(400.0, 200.0)) - .build(&event_loop) - .unwrap(); - - let mut modifiers = ModifiersState::default(); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::ModifiersChanged(new) => { - modifiers = new.state(); - } - WindowEvent::KeyboardInput { event, .. } => { - if event.state == ElementState::Pressed && !event.repeat { - match event.key_without_modifiers().as_ref() { - Key::Character("1") => { - if modifiers.shift_key() { - println!("Shift + 1 | logical_key: {:?}", event.logical_key); - } else { - println!("1"); - } - } - _ => (), - } - } - } - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - }; - }) -} diff --git a/examples/monitor_list.rs b/examples/monitor_list.rs deleted file mode 100644 index 35fe11c8f52..00000000000 --- a/examples/monitor_list.rs +++ /dev/null @@ -1,58 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::dpi::{PhysicalPosition, PhysicalSize}; -use winit::monitor::MonitorHandle; -use winit::{event_loop::EventLoop, window::Window}; - -fn main() { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - let window = Window::builder().build(&event_loop).unwrap(); - - if let Some(mon) = window.primary_monitor() { - print_info("Primary output", mon); - } - - for mon in window.available_monitors() { - if Some(&mon) == window.primary_monitor().as_ref() { - continue; - } - - println!(); - print_info("Output", mon); - } -} - -fn print_info(intro: &str, monitor: MonitorHandle) { - if let Some(name) = monitor.name() { - println!("{intro}: {name}"); - } else { - println!("{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!(); - } - - let PhysicalPosition { x, y } = monitor.position(); - println!(" Position: {x},{y}"); - - println!(" Scale factor: {}", monitor.scale_factor()); - - println!(" 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!( - " {width}x{height}x{bits} @ {}.{} Hz", - m_hz / 1000, - m_hz % 1000 - ); - } -} diff --git a/examples/mouse_wheel.rs b/examples/mouse_wheel.rs deleted file mode 100644 index 1a5667c018e..00000000000 --- a/examples/mouse_wheel.rs +++ /dev/null @@ -1,65 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("Mouse Wheel events") - .build(&event_loop) - .unwrap(); - - println!( - r" -When using so called 'natural scrolling' (scrolling that acts like on a touch screen), this is what to expect: - -Moving your finger downwards on a scroll wheel should make the window move down, and you should see a positive Y scroll value. - -When moving fingers on a trackpad down and to the right, you should see positive X and Y deltas, and the window should move down and to the right. - -With reverse scrolling, you should see the inverse behavior. - -In both cases the example window should move like the content of a scroll area in any other application. - -In other words, the deltas indicate the direction in which to move the content (in this case the window)." - ); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::MouseWheel { delta, .. } => match delta { - winit::event::MouseScrollDelta::LineDelta(x, y) => { - println!("mouse wheel Line Delta: ({x},{y})"); - let pixels_per_line = 120.0; - let mut pos = window.outer_position().unwrap(); - pos.x += (x * pixels_per_line) as i32; - pos.y += (y * pixels_per_line) as i32; - window.set_outer_position(pos) - } - winit::event::MouseScrollDelta::PixelDelta(p) => { - println!("mouse wheel Pixel Delta: ({},{})", p.x, p.y); - let mut pos = window.outer_position().unwrap(); - pos.x += p.x as i32; - pos.y += p.y as i32; - window.set_outer_position(pos) - } - }, - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs deleted file mode 100644 index e38bb53ddd9..00000000000 --- a/examples/multithreaded.rs +++ /dev/null @@ -1,211 +0,0 @@ -#![allow(clippy::single_match)] - -#[cfg(not(web_platform))] -fn main() -> Result<(), impl std::error::Error> { - use std::{collections::HashMap, sync::mpsc, thread, time::Duration}; - - use simple_logger::SimpleLogger; - use winit::{ - dpi::{PhysicalPosition, PhysicalSize, Position, Size}, - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, - keyboard::{Key, ModifiersState, NamedKey}, - window::{CursorGrabMode, CursorIcon, Fullscreen, Window, WindowLevel}, - }; - - const WINDOW_COUNT: usize = 3; - const WINDOW_SIZE: PhysicalSize = PhysicalSize::new(600, 400); - - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - let mut window_senders = HashMap::with_capacity(WINDOW_COUNT); - for _ in 0..WINDOW_COUNT { - let window = Window::builder() - .with_inner_size(WINDOW_SIZE) - .build(&event_loop) - .unwrap(); - - let mut video_modes: Vec<_> = window.current_monitor().unwrap().video_modes().collect(); - let mut video_mode_id = 0usize; - - let (tx, rx) = mpsc::channel(); - window_senders.insert(window.id(), tx); - let mut modifiers = ModifiersState::default(); - thread::spawn(move || { - while let Ok(event) = rx.recv() { - match event { - WindowEvent::Moved { .. } => { - // We need to update our chosen video mode if the window - // was moved to an another monitor, so that the window - // appears on this monitor instead when we go fullscreen - let previous_video_mode = video_modes.get(video_mode_id).cloned(); - video_modes = window.current_monitor().unwrap().video_modes().collect(); - video_mode_id = video_mode_id.min(video_modes.len()); - let video_mode = video_modes.get(video_mode_id); - - // Different monitors may support different video modes, - // and the index we chose previously may now point to a - // completely different video mode, so notify the user - if video_mode != previous_video_mode.as_ref() { - println!( - "Window moved to another monitor, picked video mode: {}", - video_modes.get(video_mode_id).unwrap() - ); - } - } - WindowEvent::ModifiersChanged(new) => { - modifiers = new.state(); - } - WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Released, - logical_key: key, - .. - }, - .. - } => { - use NamedKey::{ArrowLeft, ArrowRight}; - window.set_title(&format!("{key:?}")); - let state = !modifiers.shift_key(); - match key { - // Cycle through video modes - Key::Named(ArrowRight) | Key::Named(ArrowLeft) => { - if key == ArrowLeft { - video_mode_id = video_mode_id.saturating_sub(1); - } else if key == ArrowRight { - video_mode_id = (video_modes.len() - 1).min(video_mode_id + 1); - } - println!("Picking video mode: {}", video_modes[video_mode_id]); - } - // WARNING: Consider using `key_without_modifers()` if available on your platform. - // See the `key_binding` example - Key::Character(ch) => match ch.to_lowercase().as_str() { - "1" => window.set_window_level(WindowLevel::AlwaysOnTop), - "2" => window.set_window_level(WindowLevel::AlwaysOnBottom), - "3" => window.set_window_level(WindowLevel::Normal), - "c" => window.set_cursor(match state { - true => CursorIcon::Progress, - false => CursorIcon::Default, - }), - "d" => window.set_decorations(!state), - "f" => window.set_fullscreen(match (state, modifiers.alt_key()) { - (true, false) => Some(Fullscreen::Borderless(None)), - (true, true) => Some(Fullscreen::Exclusive( - video_modes[video_mode_id].clone(), - )), - (false, _) => None, - }), - ch @ ("g" | "l") => { - let mode = match (ch, state) { - ("l", true) => CursorGrabMode::Locked, - ("g", true) => CursorGrabMode::Confined, - (_, _) => CursorGrabMode::None, - }; - if let Err(err) = window.set_cursor_grab(mode) { - println!("error: {err}"); - } - } - "h" => window.set_cursor_visible(!state), - "i" => { - println!("Info:"); - println!("-> outer_position : {:?}", window.outer_position()); - println!("-> inner_position : {:?}", window.inner_position()); - println!("-> outer_size : {:?}", window.outer_size()); - println!("-> inner_size : {:?}", window.inner_size()); - println!("-> fullscreen : {:?}", window.fullscreen()); - } - "m" => window.set_maximized(state), - "p" => window.set_outer_position({ - let mut position = window.outer_position().unwrap(); - let sign = if state { 1 } else { -1 }; - position.x += 10 * sign; - position.y += 10 * sign; - position - }), - "q" => window.request_redraw(), - "r" => window.set_resizable(state), - "s" => { - let _ = window.request_inner_size(match state { - true => PhysicalSize::new( - WINDOW_SIZE.width + 50, - WINDOW_SIZE.height + 50, - ), - false => WINDOW_SIZE, - }); - } - "k" => window.set_min_inner_size(match state { - true => Some(PhysicalSize::new( - WINDOW_SIZE.width - 100, - WINDOW_SIZE.height - 100, - )), - false => None, - }), - "o" => window.set_max_inner_size(match state { - true => Some(PhysicalSize::new( - WINDOW_SIZE.width + 100, - WINDOW_SIZE.height + 100, - )), - false => None, - }), - "w" => { - if let Size::Physical(size) = WINDOW_SIZE.into() { - window - .set_cursor_position(Position::Physical( - PhysicalPosition::new( - size.width as i32 / 2, - size.height as i32 / 2, - ), - )) - .unwrap() - } - } - "z" => { - window.set_visible(false); - thread::sleep(Duration::from_secs(1)); - window.set_visible(true); - } - _ => (), - }, - _ => (), - } - } - _ => (), - } - } - }); - } - event_loop.run(move |event, elwt| { - if window_senders.is_empty() { - elwt.exit() - } - match event { - Event::WindowEvent { event, window_id } => match event { - WindowEvent::CloseRequested - | WindowEvent::Destroyed - | WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Released, - logical_key: Key::Named(NamedKey::Escape), - .. - }, - .. - } => { - window_senders.remove(&window_id); - } - _ => { - if let Some(tx) = window_senders.get(&window_id) { - tx.send(event).unwrap(); - } - } - }, - _ => {} - } - }) -} - -#[cfg(web_platform)] -fn main() { - panic!("Example not supported on Web"); -} diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs deleted file mode 100644 index 07a9b84eefe..00000000000 --- a/examples/multiwindow.rs +++ /dev/null @@ -1,64 +0,0 @@ -#![allow(clippy::single_match)] - -use std::collections::HashMap; - -use simple_logger::SimpleLogger; -use winit::{ - event::{ElementState, Event, WindowEvent}, - event_loop::EventLoop, - keyboard::{Key, NamedKey}, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let mut windows = HashMap::new(); - for _ in 0..3 { - let window = Window::new(&event_loop).unwrap(); - println!("Opened a new window: {:?}", window.id()); - windows.insert(window.id(), window); - } - - println!("Press N to open a new window."); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, window_id } = event { - match event { - WindowEvent::CloseRequested => { - println!("Window {window_id:?} has received the signal to close"); - - // This drops the window, causing it to close. - windows.remove(&window_id); - - if windows.is_empty() { - elwt.exit(); - } - } - WindowEvent::KeyboardInput { - event, - is_synthetic: false, - .. - } if event.state == ElementState::Pressed => match event.logical_key { - Key::Named(NamedKey::Escape) => elwt.exit(), - Key::Character(c) if c == "n" || c == "N" => { - let window = Window::new(elwt).unwrap(); - println!("Opened a new window: {:?}", window.id()); - windows.insert(window.id(), window); - } - _ => (), - }, - WindowEvent::RedrawRequested => { - if let Some(window) = windows.get(&window_id) { - fill::fill_window(window); - } - } - _ => (), - } - } - }) -} diff --git a/examples/window_pump_events.rs b/examples/pump_events.rs similarity index 62% rename from examples/window_pump_events.rs rename to examples/pump_events.rs index f6f30dab181..b52812ae461 100644 --- a/examples/window_pump_events.rs +++ b/examples/pump_events.rs @@ -25,38 +25,43 @@ fn main() -> std::process::ExitCode { let mut event_loop = EventLoop::new().unwrap(); SimpleLogger::new().init().unwrap(); - let window = Window::builder() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); - 'main: loop { + let mut window = None; + + loop { let timeout = Some(Duration::ZERO); - let status = event_loop.pump_events(timeout, |event, elwt| { + let status = event_loop.pump_events(timeout, |event, event_loop| { if let Event::WindowEvent { event, .. } = &event { // Print only Window events to reduce noise println!("{event:?}"); } match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - window_id, - } if window_id == window.id() => elwt.exit(), - Event::AboutToWait => { - window.request_redraw(); + Event::Resumed => { + window = Some( + Window::builder() + .with_title("A fantastic window!") + .build(event_loop) + .unwrap(), + ); } - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - fill::fill_window(&window); + Event::WindowEvent { event, .. } => { + let window = window.as_ref().unwrap(); + match event { + WindowEvent::CloseRequested => event_loop.exit(), + WindowEvent::RedrawRequested => fill::fill_window(window), + _ => (), + } + } + Event::AboutToWait => { + window.as_ref().unwrap().request_redraw(); } _ => (), } }); + if let PumpStatus::Exit(exit_code) = status { - break 'main ExitCode::from(exit_code as u8); + break ExitCode::from(exit_code as u8); } // Sleep for 1/60 second to simulate application work diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs deleted file mode 100644 index 9b20511744e..00000000000 --- a/examples/request_redraw.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - event::{ElementState, Event, WindowEvent}, - event_loop::EventLoop, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); - - event_loop.run(move |event, elwt| { - println!("{event:?}"); - - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::MouseInput { - state: ElementState::Released, - .. - } => { - window.request_redraw(); - } - WindowEvent::RedrawRequested => { - println!("\nredrawing!\n"); - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/request_redraw_threaded.rs b/examples/request_redraw_threaded.rs deleted file mode 100644 index 9801ba059ad..00000000000 --- a/examples/request_redraw_threaded.rs +++ /dev/null @@ -1,59 +0,0 @@ -#![allow(clippy::single_match)] - -#[cfg(not(web_platform))] -fn main() -> Result<(), impl std::error::Error> { - use std::{sync::Arc, thread, time}; - - use simple_logger::SimpleLogger; - use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::Window, - }; - - #[path = "util/fill.rs"] - mod fill; - - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = { - let window = Window::builder() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); - Arc::new(window) - }; - - thread::spawn({ - let window = window.clone(); - move || loop { - thread::sleep(time::Duration::from_secs(1)); - window.request_redraw(); - } - }); - - event_loop.run(move |event, elwt| { - println!("{event:?}"); - - match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => elwt.exit(), - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - println!("\nredrawing!\n"); - fill::fill_window(&window); - } - _ => (), - } - }) -} - -#[cfg(web_platform)] -fn main() { - unimplemented!() // `Window` can't be sent between threads -} diff --git a/examples/resizable.rs b/examples/resizable.rs deleted file mode 100644 index 3bfc4b59ced..00000000000 --- a/examples/resizable.rs +++ /dev/null @@ -1,54 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - dpi::LogicalSize, - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, - keyboard::{KeyCode, PhysicalKey}, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let mut resizable = false; - - let window = Window::builder() - .with_title("Hit space to toggle resizability.") - .with_inner_size(LogicalSize::new(600.0, 300.0)) - .with_min_inner_size(LogicalSize::new(400.0, 200.0)) - .with_max_inner_size(LogicalSize::new(800.0, 400.0)) - .with_resizable(resizable) - .build(&event_loop) - .unwrap(); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::KeyboardInput { - event: - KeyEvent { - physical_key: PhysicalKey::Code(KeyCode::Space), - state: ElementState::Released, - .. - }, - .. - } => { - resizable = !resizable; - println!("Resizable: {resizable}"); - window.set_resizable(resizable); - } - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - }; - }) -} diff --git a/examples/window_on_demand.rs b/examples/run_on_demand.rs similarity index 100% rename from examples/window_on_demand.rs rename to examples/run_on_demand.rs diff --git a/examples/startup_notification.rs b/examples/startup_notification.rs deleted file mode 100644 index 2c3730edec9..00000000000 --- a/examples/startup_notification.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! Demonstrates the use of startup notifications on Linux. - -#[cfg(any(x11_platform, wayland_platform))] -#[path = "./util/fill.rs"] -mod fill; - -#[cfg(any(x11_platform, wayland_platform))] -mod example { - use std::collections::HashMap; - use std::rc::Rc; - - use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; - use winit::event_loop::EventLoop; - use winit::platform::startup_notify::{ - EventLoopExtStartupNotify, WindowBuilderExtStartupNotify, WindowExtStartupNotify, - }; - use winit::window::{Window, WindowId}; - - pub(super) fn main() -> Result<(), impl std::error::Error> { - // Create the event loop and get the activation token. - let event_loop = EventLoop::new().unwrap(); - let mut current_token = match event_loop.read_token_from_env() { - Some(token) => Some(token), - None => { - println!("No startup notification token found in environment."); - None - } - }; - - let mut windows: HashMap> = HashMap::new(); - let mut counter = 0; - let mut create_first_window = false; - - event_loop.run(move |event, elwt| { - match event { - Event::Resumed => create_first_window = true, - - Event::WindowEvent { window_id, event } => match event { - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key, - state: ElementState::Pressed, - .. - }, - .. - } => { - if logical_key == "n" { - if let Some(window) = windows.get(&window_id) { - // Request a new activation token on this window. - // Once we get it we will use it to create a window. - window - .request_activation_token() - .expect("Failed to request activation token."); - } - } - } - - WindowEvent::CloseRequested => { - // Remove the window from the map. - windows.remove(&window_id); - if windows.is_empty() { - elwt.exit(); - return; - } - } - - WindowEvent::ActivationTokenDone { token, .. } => { - current_token = Some(token); - } - - WindowEvent::RedrawRequested => { - if let Some(window) = windows.get(&window_id) { - super::fill::fill_window(window); - } - } - - _ => {} - }, - _ => (), - } - - // See if we've passed the deadline. - if current_token.is_some() || create_first_window { - // Create the initial window. - let window = { - let mut builder = Window::builder().with_title(format!("Window {}", counter)); - - if let Some(token) = current_token.take() { - println!("Creating a window with token {token:?}"); - builder = builder.with_activation_token(token); - } - - Rc::new(builder.build(elwt).unwrap()) - }; - - // Add the window to the map. - windows.insert(window.id(), window.clone()); - - counter += 1; - create_first_window = false; - } - }) - } -} - -#[cfg(any(x11_platform, wayland_platform))] -fn main() -> Result<(), impl std::error::Error> { - example::main() -} - -#[cfg(not(any(x11_platform, wayland_platform)))] -fn main() { - println!("This example is only supported on X11 and Wayland platforms."); -} diff --git a/examples/theme.rs b/examples/theme.rs deleted file mode 100644 index 1723949d722..00000000000 --- a/examples/theme.rs +++ /dev/null @@ -1,68 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, - keyboard::Key, - window::{Theme, Window}, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .with_theme(Some(Theme::Dark)) - .build(&event_loop) - .unwrap(); - - println!("Initial theme: {:?}", window.theme()); - println!("debugging keys:"); - println!(" (A) Automatic theme"); - println!(" (L) Light theme"); - println!(" (D) Dark theme"); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { window_id, event } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::ThemeChanged(theme) if window_id == window.id() => { - println!("Theme is changed: {theme:?}") - } - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: key, - state: ElementState::Pressed, - .. - }, - .. - } => match key.as_ref() { - Key::Character("A" | "a") => { - println!("Theme was: {:?}", window.theme()); - window.set_theme(None); - } - Key::Character("L" | "l") => { - println!("Theme was: {:?}", window.theme()); - window.set_theme(Some(Theme::Light)); - } - Key::Character("D" | "d") => { - println!("Theme was: {:?}", window.theme()); - window.set_theme(Some(Theme::Dark)); - } - _ => (), - }, - WindowEvent::RedrawRequested => { - println!("\nredrawing!\n"); - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/timer.rs b/examples/timer.rs deleted file mode 100644 index 76c386f0c7f..00000000000 --- a/examples/timer.rs +++ /dev/null @@ -1,54 +0,0 @@ -#![allow(clippy::single_match)] - -use std::time::Duration; -#[cfg(not(web_platform))] -use std::time::Instant; -#[cfg(web_platform)] -use web_time::Instant; - -use simple_logger::SimpleLogger; -use winit::{ - event::{Event, StartCause, WindowEvent}, - event_loop::{ControlFlow, EventLoop}, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); - - let timer_length = Duration::new(1, 0); - - event_loop.run(move |event, elwt| { - println!("{event:?}"); - - match event { - Event::NewEvents(StartCause::Init) => { - elwt.set_control_flow(ControlFlow::WaitUntil(Instant::now() + timer_length)); - } - Event::NewEvents(StartCause::ResumeTimeReached { .. }) => { - elwt.set_control_flow(ControlFlow::WaitUntil(Instant::now() + timer_length)); - println!("\nTimer\n"); - } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => elwt.exit(), - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - fill::fill_window(&window); - } - _ => (), - } - }) -} diff --git a/examples/touch_gestures.rs b/examples/touch_gestures.rs deleted file mode 100644 index 52c9a39a3db..00000000000 --- a/examples/touch_gestures.rs +++ /dev/null @@ -1,62 +0,0 @@ -use simple_logger::SimpleLogger; -use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("Touchpad gestures") - .build(&event_loop) - .unwrap(); - #[cfg(target_os = "ios")] - { - use winit::platform::ios::WindowExtIOS; - window.recognize_doubletap_gesture(true); - window.recognize_pinch_gesture(true); - window.recognize_rotation_gesture(true); - } - - println!("Only supported on macOS/iOS at the moment."); - - let mut zoom = 0.0; - let mut rotated = 0.0; - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::PinchGesture { delta, .. } => { - zoom += delta; - if delta > 0.0 { - println!("Zoomed in {delta:.5} (now: {zoom:.5})"); - } else { - println!("Zoomed out {delta:.5} (now: {zoom:.5})"); - } - } - WindowEvent::DoubleTapGesture { .. } => { - println!("Smart zoom"); - } - WindowEvent::RotationGesture { delta, .. } => { - rotated += delta; - if delta > 0.0 { - println!("Rotated counterclockwise {delta:.5} (now: {rotated:.5})"); - } else { - println!("Rotated clockwise {delta:.5} (now: {rotated:.5})"); - } - } - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/transparent.rs b/examples/transparent.rs deleted file mode 100644 index 388e7a828e8..00000000000 --- a/examples/transparent.rs +++ /dev/null @@ -1,38 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_decorations(false) - .with_transparent(true) - .build(&event_loop) - .unwrap(); - - window.set_title("A fantastic window!"); - - event_loop.run(move |event, elwt| { - println!("{event:?}"); - - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/video_modes.rs b/examples/video_modes.rs deleted file mode 100644 index 75acdbd45bd..00000000000 --- a/examples/video_modes.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![allow(clippy::single_match)] - -use simple_logger::SimpleLogger; -use winit::event_loop::EventLoop; - -fn main() { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - let monitor = match event_loop.primary_monitor() { - Some(monitor) => monitor, - None => { - println!("No primary monitor detected."); - return; - } - }; - - println!("Listing available video modes:"); - - for mode in monitor.video_modes() { - println!("{mode}"); - } -} diff --git a/examples/web.rs b/examples/web.rs deleted file mode 100644 index 8779f3fb108..00000000000 --- a/examples/web.rs +++ /dev/null @@ -1,147 +0,0 @@ -#![allow(clippy::disallowed_methods, clippy::single_match)] - -use winit::{ - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, - keyboard::Key, - window::{Fullscreen, Window}, -}; - -pub fn main() -> Result<(), impl std::error::Error> { - let event_loop = EventLoop::new().unwrap(); - - let builder = Window::builder().with_title("A fantastic window!"); - #[cfg(wasm_platform)] - let builder = { - use winit::platform::web::WindowBuilderExtWebSys; - builder.with_append(true) - }; - let window = builder.build(&event_loop).unwrap(); - - #[cfg(web_platform)] - let log_list = wasm::insert_canvas_and_create_log_list(&window); - - event_loop.run(move |event, elwt| { - #[cfg(web_platform)] - wasm::log_event(&log_list, &event); - - match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - window_id, - } if window_id == window.id() => elwt.exit(), - Event::AboutToWait => { - window.request_redraw(); - } - Event::WindowEvent { - window_id, - event: - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: Key::Character(c), - state: ElementState::Released, - .. - }, - .. - }, - } if window_id == window.id() && c == "f" => { - if window.fullscreen().is_some() { - window.set_fullscreen(None); - } else { - window.set_fullscreen(Some(Fullscreen::Borderless(None))); - } - } - _ => (), - } - }) -} - -#[cfg(web_platform)] -mod wasm { - use std::num::NonZeroU32; - - use softbuffer::{Surface, SurfaceExtWeb}; - use wasm_bindgen::prelude::*; - use winit::{ - event::{Event, WindowEvent}, - window::Window, - }; - - #[wasm_bindgen(start)] - pub fn run() { - console_log::init_with_level(log::Level::Debug).expect("error initializing logger"); - - #[allow(clippy::main_recursion)] - let _ = super::main(); - } - - pub fn insert_canvas_and_create_log_list(window: &Window) -> web_sys::Element { - use winit::platform::web::WindowExtWebSys; - - let canvas = window.canvas().unwrap(); - let mut surface = Surface::from_canvas(canvas.clone()).unwrap(); - surface - .resize( - NonZeroU32::new(canvas.width()).unwrap(), - NonZeroU32::new(canvas.height()).unwrap(), - ) - .unwrap(); - let mut buffer = surface.buffer_mut().unwrap(); - buffer.fill(0xFFF0000); - buffer.present().unwrap(); - - let window = web_sys::window().unwrap(); - let document = window.document().unwrap(); - let body = document.body().unwrap(); - - let style = &canvas.style(); - style.set_property("margin", "50px").unwrap(); - // Use to test interactions with border and padding. - //style.set_property("border", "50px solid black").unwrap(); - //style.set_property("padding", "50px").unwrap(); - - let log_header = document.create_element("h2").unwrap(); - log_header.set_text_content(Some("Event Log")); - body.append_child(&log_header).unwrap(); - - let log_list = document.create_element("ul").unwrap(); - body.append_child(&log_list).unwrap(); - log_list - } - - pub fn log_event(log_list: &web_sys::Element, event: &Event<()>) { - log::debug!("{:?}", event); - - // Getting access to browser logs requires a lot of setup on mobile devices. - // So we implement this basic logging system into the page to give developers an easy alternative. - // As a bonus its also kind of handy on desktop. - let event = match event { - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => None, - Event::WindowEvent { event, .. } => Some(format!("{event:?}")), - Event::Resumed | Event::Suspended => Some(format!("{event:?}")), - _ => None, - }; - if let Some(event) = event { - let window = web_sys::window().unwrap(); - let document = window.document().unwrap(); - let log = document.create_element("li").unwrap(); - - let date = js_sys::Date::new_0(); - log.set_text_content(Some(&format!( - "{:02}:{:02}:{:02}.{:03}: {event}", - date.get_hours(), - date.get_minutes(), - date.get_seconds(), - date.get_milliseconds(), - ))); - - log_list - .insert_before(&log, log_list.first_child().as_ref()) - .unwrap(); - } - } -} diff --git a/examples/web_aspect_ratio.rs b/examples/web_aspect_ratio.rs deleted file mode 100644 index da03d1b8a3f..00000000000 --- a/examples/web_aspect_ratio.rs +++ /dev/null @@ -1,102 +0,0 @@ -#![allow(clippy::disallowed_methods)] - -pub fn main() { - println!("This example must be run with cargo run-wasm --example web_aspect_ratio") -} - -#[cfg(web_platform)] -mod wasm { - use wasm_bindgen::prelude::*; - use wasm_bindgen::JsCast; - use web_sys::HtmlCanvasElement; - use winit::{ - dpi::PhysicalSize, - event::{Event, WindowEvent}, - event_loop::EventLoop, - platform::web::WindowBuilderExtWebSys, - window::Window, - }; - - const EXPLANATION: &str = " -This example draws a circle in the middle of a 4/1 aspect ratio canvas which acts as a useful demonstration of winit's resize handling on web. -Even when the browser window is resized or aspect-ratio of the canvas changed the circle should always: -* Fill the entire width or height of the canvas (whichever is smaller) without exceeding it. -* Be perfectly round -* Not be blurry or pixelated (there is no antialiasing so you may still see jagged edges depending on the DPI of your monitor) - -Currently winit does not handle resizes on web so the circle is rendered incorrectly. -This example demonstrates the desired future functionality which will possibly be provided by https://github.com/rust-windowing/winit/pull/2074 -"; - - #[wasm_bindgen(start)] - pub fn run() { - console_log::init_with_level(log::Level::Debug).expect("error initializing logger"); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - // When running in a non-wasm environment this would set the window size to 100x100. - // However in this example it just sets a default initial size of 100x100 that is immediately overwritten due to the layout + styling of the page. - .with_inner_size(PhysicalSize::new(100, 100)) - .with_append(true) - .build(&event_loop) - .unwrap(); - - let canvas = create_canvas(&window); - - // Render once with the size info we currently have - render_circle(&canvas, window.inner_size()); - - let _ = event_loop.run(move |event, _| match event { - Event::WindowEvent { - event: WindowEvent::Resized(resize), - window_id, - } if window_id == window.id() => { - render_circle(&canvas, resize); - } - _ => (), - }); - } - - pub fn create_canvas(window: &Window) -> HtmlCanvasElement { - use winit::platform::web::WindowExtWebSys; - - let web_window = web_sys::window().unwrap(); - let document = web_window.document().unwrap(); - let body = document.body().unwrap(); - - // Set a background color for the canvas to make it easier to tell the where the canvas is for debugging purposes. - let canvas = window.canvas().unwrap(); - canvas - .style() - .set_css_text("display: block; background-color: crimson; margin: auto; width: 50%; aspect-ratio: 4 / 1;"); - - let explanation = document.create_element("pre").unwrap(); - explanation.set_text_content(Some(EXPLANATION)); - body.append_child(&explanation).unwrap(); - - canvas - } - - pub fn render_circle(canvas: &HtmlCanvasElement, size: PhysicalSize) { - log::info!("rendering circle with canvas size: {:?}", size); - let context = canvas - .get_context("2d") - .unwrap() - .unwrap() - .dyn_into::() - .unwrap(); - - context.begin_path(); - context - .arc( - size.width as f64 / 2.0, - size.height as f64 / 2.0, - size.width.min(size.height) as f64 / 2.0, - 0.0, - std::f64::consts::PI * 2.0, - ) - .unwrap(); - context.fill(); - } -} diff --git a/examples/window.rs b/examples/window.rs index 55645edcb56..8a4ef08e283 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -1,43 +1,984 @@ -#![allow(clippy::single_match)] +//! Simple winit application. -use simple_logger::SimpleLogger; -use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::Window, +use std::collections::HashMap; +use std::error::Error; +use std::fmt; +use std::fmt::Debug; +#[cfg(not(any(android_platform, ios_platform)))] +use std::num::NonZeroU32; +use std::path::Path; + +use cursor_icon::CursorIcon; +#[cfg(not(any(android_platform, ios_platform)))] +use rwh_05::HasRawDisplayHandle; +#[cfg(not(any(android_platform, ios_platform)))] +use softbuffer::{Context, Surface}; + +use winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize}; +use winit::event::{DeviceEvent, DeviceId, Event, Ime, WindowEvent}; +use winit::event::{MouseButton, MouseScrollDelta}; +use winit::event_loop::{ActiveEventLoop, EventLoop}; +use winit::keyboard::{Key, ModifiersState}; +use winit::window::{ + Cursor, CursorGrabMode, CustomCursor, Fullscreen, Icon, ResizeDirection, Theme, +}; +use winit::window::{Window, WindowId}; + +#[cfg(macos_platform)] +use winit::platform::macos::{OptionAsAlt, WindowBuilderExtMacOS, WindowExtMacOS}; +#[cfg(any(x11_platform, wayland_platform))] +use winit::platform::startup_notify::{ + self, EventLoopExtStartupNotify, WindowBuilderExtStartupNotify, WindowExtStartupNotify, }; -#[path = "util/fill.rs"] -mod fill; +/// The amount of points to around the window for drag resize direction calculations. +const BORDER_SIZE: f64 = 20.; + +fn main() -> Result<(), Box> { + let event_loop = EventLoop::::with_user_event().build()?; + let _event_loop_proxy = event_loop.create_proxy(); + + // Wire the user event from another thread. + #[cfg(not(web_platform))] + 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"); + loop { + let _ = _event_loop_proxy.send_event(UserEvent::WakeUp); + std::thread::sleep(std::time::Duration::from_secs(1)); + } + }); + + let mut state = Application::new(&event_loop); + + event_loop.run(move |event, event_loop| match event { + Event::NewEvents(_) => (), + Event::Resumed => { + println!("Resumed the event loop"); + state.dump_monitors(event_loop); + state.load_custom_cursors(event_loop); + + // Create initial window. + state + .create_window(event_loop, None) + .expect("failed to create initial window"); + + state.print_help(); + } + Event::AboutToWait => { + if state.windows.is_empty() { + println!("No windows left, exiting..."); + event_loop.exit(); + } + } + Event::WindowEvent { window_id, event } => { + state.handle_window_event(event_loop, window_id, event) + } + Event::DeviceEvent { device_id, event } => { + state.handle_device_event(event_loop, device_id, event) + } + Event::UserEvent(event) => { + println!("User event: {event:?}"); + } + Event::Suspended | Event::LoopExiting | Event::MemoryWarning => (), + })?; + + Ok(()) +} + +#[allow(dead_code)] +#[derive(Debug, Clone, Copy)] +enum UserEvent { + WakeUp, +} + +/// Application state and event handling. +struct Application { + /// Custom cursors assets. + custom_cursors: Vec, + /// Application icon. + icon: Icon, + windows: HashMap, + /// Drawing context. + /// + /// With OpenGL it could be EGLDisplay. + #[cfg(not(any(android_platform, ios_platform)))] + context: Context, +} + +impl Application { + fn new(_event_loop: &EventLoop) -> Self { + // SAFETY: the context is dropped inside the loop, since the state we're using + // is moved inside the closure. + #[cfg(not(any(android_platform, ios_platform)))] + let context = unsafe { Context::from_raw(_event_loop.raw_display_handle()).unwrap() }; -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); + // You'll have to choose an icon size at your own discretion. On X11, the desired size varies + // 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(Path::new(path)); + + Self { + #[cfg(not(any(android_platform, ios_platform)))] + context, + icon, + windows: Default::default(), + custom_cursors: Vec::new(), + } + } - let window = Window::builder() - .with_title("A fantastic window!") - .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) - .build(&event_loop) - .unwrap(); + fn create_window( + &mut self, + event_loop: &ActiveEventLoop, + _tab_id: Option, + ) -> Result> { + // TODO read-out activation token. + + #[allow(unused_mut)] + let mut window_builder = Window::builder() + .with_title("Winit window") + .with_transparent(true) + .with_window_icon(Some(self.icon.clone())); + + #[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); + window_builder = window_builder.with_activation_token(token); + } + + #[cfg(macos_platform)] + if let Some(tab_id) = _tab_id { + window_builder = window_builder.with_tabbing_identifier(&tab_id); + } + + let window = window_builder.build(event_loop)?; + + #[cfg(ios_platform)] + { + use winit::platform::ios::WindowExtIOS; + window.recognize_doubletap_gesture(true); + window.recognize_pinch_gesture(true); + window.recognize_rotation_gesture(true); + } + + let window_state = WindowState::new(self, window)?; + let window_id = window_state.window.id(); + println!("Created new window with id={window_id:?}"); + self.windows.insert(window_id, window_state); + Ok(window_id) + } + + 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:?}"); + match action { + Action::CloseWindow => { + let _ = self.windows.remove(&window_id); + } + Action::CreateNewWindow => { + #[cfg(any(x11_platform, wayland_platform))] + if let Err(err) = window.window.request_activation_token() { + println!("Failed to get activation token: {err}"); + } else { + return; + } + + if let Err(err) = self.create_window(event_loop, None) { + eprintln!("Error creating new window: {err}"); + } + } + Action::ToggleResizeIncrements => window.toggle_resize_increments(), + Action::ToggleCursorVisibility => window.toggle_cursor_visibility(), + Action::ToggleResizable => window.toggle_resizable(), + Action::ToggleDecorations => window.toggle_decorations(), + Action::ToggleFullscreen => window.toggle_fullscreen(), + Action::ToggleMaximize => window.toggle_maximize(), + Action::ToggleImeInput => window.toggle_ime(), + Action::Minimize => window.minimize(), + Action::NextCursor => window.next_cursor(), + Action::NextCustomCursor => window.next_custom_cursor(&self.custom_cursors), + Action::CycleCursorGrab => window.cycle_cursor_grab(), + Action::DragWindow => window.drag_window(), + Action::DragResizeWindow => window.drag_resize_window(), + Action::ShowWindowMenu => window.show_menu(), + Action::PrintHelp => self.print_help(), + #[cfg(macos_platform)] + Action::CycleOptionAsAlt => window.cycle_option_as_alt(), + #[cfg(macos_platform)] + 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}"); + } + } + } + } - event_loop.run(move |event, elwt| { - println!("{event:?}"); + fn handle_window_event( + &mut self, + event_loop: &ActiveEventLoop, + window_id: WindowId, + event: WindowEvent, + ) { + let window = match self.windows.get_mut(&window_id) { + Some(window) => window, + None => return, + }; match event { - Event::WindowEvent { event, window_id } if window_id == window.id() => match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::RedrawRequested => { - // Notify the windowing system that we'll be presenting to the window. - window.pre_present_notify(); - fill::fill_window(&window); - } - _ => (), + WindowEvent::Resized(size) => { + window.resize(size); + } + WindowEvent::Focused(focused) => { + if focused { + println!("Window={window_id:?} fosused"); + } else { + println!("Window={window_id:?} unfosused"); + } + } + WindowEvent::ScaleFactorChanged { scale_factor, .. } => { + println!("Window={window_id:?} changed scale to {scale_factor}"); + } + WindowEvent::ThemeChanged(theme) => { + println!("Theme changed to {theme:?}"); + window.set_theme(theme); + } + WindowEvent::RedrawRequested => { + if let Err(err) = window.draw() { + eprintln!("Error drawing window: {err}"); + } + } + WindowEvent::Occluded(occluded) => { + window.set_occluded(occluded); + } + WindowEvent::CloseRequested => { + println!("Closing Window={window_id:?}"); + self.windows.remove(&window_id); + } + WindowEvent::ModifiersChanged(modifiers) => { + window.modifiers = modifiers.state(); + println!("Modifiers changed to {:?}", window.modifiers); + } + WindowEvent::MouseWheel { delta, .. } => match delta { + MouseScrollDelta::LineDelta(x, y) => { + println!("Mouse wheel Line Delta: ({x},{y})"); + } + MouseScrollDelta::PixelDelta(px) => { + println!("Mouse wheel Pixel Delta: ({},{})", px.x, px.y); + } + }, + WindowEvent::KeyboardInput { + event, + is_synthetic: false, + .. + } => { + let mods = window.modifiers; + + // Dispatch actions only on press. + if event.state.is_pressed() { + let action = if let Key::Character(ch) = event.logical_key.as_ref() { + Self::process_key_binding(&ch.to_uppercase(), &mods) + } else { + None + }; + + if let Some(action) = action { + self.handle_action(event_loop, window_id, action); + } + } + } + WindowEvent::MouseInput { button, state, .. } => { + let mods = window.modifiers; + if let Some(action) = state + .is_pressed() + .then(|| Self::process_mouse_binding(button, &mods)) + .flatten() + { + self.handle_action(event_loop, window_id, action); + } + } + WindowEvent::CursorLeft { .. } => { + println!("Cursor left Window={window_id:?}"); + window.cursor_left(); + } + WindowEvent::CursorMoved { position, .. } => { + println!("Moved cursor to {position:?}"); + window.cursor_moved(position); + } + WindowEvent::ActivationTokenDone { token: _token, .. } => { + #[cfg(any(x11_platform, wayland_platform))] + { + startup_notify::set_activation_token_env(_token); + if let Err(err) = self.create_window(event_loop, None) { + eprintln!("Error creating new window: {err}"); + } + } + } + WindowEvent::Ime(event) => match event { + Ime::Enabled => println!("IME enabled for Window={window_id:?}"), + Ime::Preedit(text, caret_pos) => { + println!("Preedit: {}, with caret at {:?}", text, caret_pos); + } + Ime::Commit(text) => { + println!("Commited: {}", text); + } + Ime::Disabled => println!("IME disabled for Window={window_id:?}"), }, - Event::AboutToWait => { - window.request_redraw(); + WindowEvent::PinchGesture { delta, .. } => { + window.zoom += delta; + let zoom = window.zoom; + if delta > 0.0 { + println!("Zoomed in {delta:.5} (now: {zoom:.5})"); + } else { + println!("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})"); + } else { + println!("Rotated clockwise {delta:.5} (now: {rotated:.5})"); + } + } + WindowEvent::DoubleTapGesture { .. } => { + println!("Smart zoom"); + } + WindowEvent::TouchpadPressure { .. } + | WindowEvent::HoveredFileCancelled + | WindowEvent::KeyboardInput { .. } + | WindowEvent::CursorEntered { .. } + | WindowEvent::AxisMotion { .. } + | WindowEvent::DroppedFile(_) + | WindowEvent::HoveredFile(_) + | WindowEvent::Destroyed + | WindowEvent::Touch(_) + | WindowEvent::Moved(_) => (), + } + } + + fn handle_device_event(&mut self, _: &ActiveEventLoop, _: DeviceId, event: DeviceEvent) { + println!("Device event: {event:?}"); + } + + fn dump_monitors(&self, event_loop: &ActiveEventLoop) { + println!("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) { + "Primary monitor" + } else { + "Monitor" + }; + + if let Some(name) = monitor.name() { + println!("{intro}: {name}"); + } else { + println!("{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!(); + } + + let PhysicalPosition { x, y } = monitor.position(); + println!(" Position: {x},{y}"); + + println!(" Scale factor: {}", monitor.scale_factor()); + + println!(" 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!( + " {width}x{height}x{bits} @ {}.{} Hz", + m_hz / 1000, + m_hz % 1000 + ); + } + } + } + + fn load_custom_cursors(&mut self, event_loop: &ActiveEventLoop) { + println!("Loading cursor assets"); + self.custom_cursors = vec![ + decode_cursor(include_bytes!("data/cross.png"), event_loop), + decode_cursor(include_bytes!("data/cross2.png"), event_loop), + decode_cursor(include_bytes!("data/gradient.png"), event_loop), + ]; + } + + /// Process the key binding. + fn process_key_binding(key: &str, mods: &ModifiersState) -> Option { + KEY_BINDINGS.iter().find_map(|binding| { + binding + .is_triggered_by(&key, mods) + .then_some(binding.action) + }) + } + + /// Process mouse binding. + fn process_mouse_binding(button: MouseButton, mods: &ModifiersState) -> Option { + MOUSE_BINDINGS.iter().find_map(|binding| { + binding + .is_triggered_by(&button, mods) + .then_some(binding.action) + }) + } + + fn print_help(&self) { + println!("Keyboard bindings:"); + for binding in KEY_BINDINGS { + println!( + "{}{:<10} - {} ({})", + modifiers_to_string(binding.mods), + binding.trigger, + binding.action, + binding.action.help(), + ); + } + println!("Mouse bindings:"); + for binding in MOUSE_BINDINGS { + println!( + "{}{:<10} - {} ({})", + modifiers_to_string(binding.mods), + mouse_button_to_string(binding.trigger), + binding.action, + binding.action.help(), + ); + } + } +} + +/// State of the window. +struct WindowState { + /// IME input. + ime: bool, + /// Render surface. + /// + /// NOTE: This surface must be dropped before the `Window`. + #[cfg(not(any(android_platform, ios_platform)))] + surface: Surface, + /// The actual winit Window. + window: Window, + /// The window theme we're drawing with. + theme: Theme, + /// Cursor position over the window. + cursor_position: Option>, + /// Window modifiers state. + modifiers: ModifiersState, + /// Occlusion state of the window. + occluded: bool, + /// Current cursor grab mode. + cursor_grab: CursorGrabMode, + /// The amount of zoom into window. + zoom: f64, + /// The amount of rotation of the window. + rotated: f32, + + #[cfg(macos_platform)] + option_as_alt: OptionAsAlt, + + // Cursor states. + named_idx: usize, + custom_idx: usize, + cursor_hidden: bool, +} + +impl WindowState { + fn new(application: &Application, window: Window) -> Result> { + // SAFETY: the surface is dropped before the `window` which provided it with handle, thus + // it doesn't outlive it. + #[cfg(not(any(android_platform, ios_platform)))] + let surface = unsafe { Surface::new(&application.context, &window)? }; + + let theme = window.theme().unwrap_or(Theme::Dark); + println!("Theme: {theme:?}"); + let named_idx = 0; + window.set_cursor(CURSORS[named_idx]); + + // Allow IME out of the box. + let ime = true; + window.set_ime_allowed(ime); + + let size = window.inner_size(); + let mut state = Self { + #[cfg(macos_platform)] + option_as_alt: window.option_as_alt(), + custom_idx: application.custom_cursors.len() - 1, + cursor_grab: CursorGrabMode::None, + named_idx, + #[cfg(not(any(android_platform, ios_platform)))] + surface, + window, + theme, + ime, + cursor_position: Default::default(), + cursor_hidden: Default::default(), + modifiers: Default::default(), + occluded: Default::default(), + rotated: Default::default(), + zoom: Default::default(), + }; + + state.resize(size); + Ok(state) + } + + pub fn toggle_ime(&mut self) { + self.ime = !self.ime; + self.window.set_ime_allowed(self.ime); + if let Some(position) = self.ime.then_some(self.cursor_position).flatten() { + self.window + .set_ime_cursor_area(position, PhysicalSize::new(20, 20)); + } + } + + pub fn minimize(&mut self) { + self.window.set_minimized(true); + } + + pub fn cursor_moved(&mut self, position: PhysicalPosition) { + self.cursor_position = Some(position); + if self.ime { + self.window + .set_ime_cursor_area(position, PhysicalSize::new(20, 20)); + } + } + + pub fn cursor_left(&mut self) { + self.cursor_position = None; + } + + /// Toggle maximized. + fn toggle_maximize(&self) { + let maximized = self.window.is_maximized(); + self.window.set_maximized(!maximized); + } + + /// Toggle window decorations. + fn toggle_decorations(&self) { + let decorated = self.window.is_decorated(); + self.window.set_decorations(!decorated); + } + + /// Toggle window resizable state. + fn toggle_resizable(&self) { + let resizable = self.window.is_resizable(); + self.window.set_resizable(!resizable); + } + + /// Toggle cursor visibility + fn toggle_cursor_visibility(&mut self) { + self.cursor_hidden = !self.cursor_hidden; + self.window.set_cursor_visible(!self.cursor_hidden); + } + + /// Toggle resize increments on a window. + fn toggle_resize_increments(&mut self) { + let new_increments = match self.window.resize_increments() { + Some(_) => None, + None => Some(LogicalSize::new(25.0, 25.0)), + }; + println!("Had increments: {}", new_increments.is_none()); + self.window.set_resize_increments(new_increments); + } + + /// Toggle fullscreen. + fn toggle_fullscreen(&self) { + let fullscreen = if self.window.fullscreen().is_some() { + None + } else { + Some(Fullscreen::Borderless(None)) + }; + + self.window.set_fullscreen(fullscreen); + } + + /// Cycle through the grab modes ignoring errors. + fn cycle_cursor_grab(&mut self) { + self.cursor_grab = match self.cursor_grab { + CursorGrabMode::None => CursorGrabMode::Confined, + CursorGrabMode::Confined => CursorGrabMode::Locked, + CursorGrabMode::Locked => CursorGrabMode::None, + }; + println!("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}"); + } + } + + #[cfg(macos_platform)] + fn cycle_option_as_alt(&mut self) { + self.option_as_alt = match self.option_as_alt { + OptionAsAlt::None => OptionAsAlt::OnlyLeft, + OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight, + OptionAsAlt::OnlyRight => OptionAsAlt::Both, + OptionAsAlt::Both => OptionAsAlt::None, + }; + println!("Setting option as alt {:?}", self.option_as_alt); + self.window.set_option_as_alt(self.option_as_alt); + } + + /// 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]); + self.window + .set_cursor(Cursor::Icon(CURSORS[self.named_idx])); + } + + /// Pick the next custom cursor. + fn next_custom_cursor(&mut self, custom_cursors: &[CustomCursor]) { + self.custom_idx = (self.custom_idx + 1) % custom_cursors.len(); + let cursor = Cursor::Custom(custom_cursors[self.custom_idx].clone()); + self.window.set_cursor(cursor); + } + + /// Resize the window to the new size. + fn resize(&mut self, _size: PhysicalSize) { + #[cfg(not(any(android_platform, ios_platform)))] + { + let (width, height) = + match (NonZeroU32::new(_size.width), NonZeroU32::new(_size.height)) { + (Some(width), Some(height)) => (width, height), + _ => return, + }; + self.surface + .resize(width, height) + .expect("failed to resize inner buffer"); + } + self.window.request_redraw(); + } + + /// Change the theme. + fn set_theme(&mut self, theme: Theme) { + self.theme = theme; + self.window.request_redraw(); + } + + /// Show window menu. + fn show_menu(&self) { + if let Some(position) = self.cursor_position { + self.window.show_window_menu(position); + } + } + + /// Drag the window. + fn drag_window(&self) { + if let Err(err) = self.window.drag_window() { + println!("Error starting window drag: {err}"); + } else { + println!("Dragging window Window={:?}", self.window.id()); + } + } + + /// Drag-resize the window. + fn drag_resize_window(&self) { + let position = match self.cursor_position { + Some(position) => position, + None => { + println!("Drag-resize requires cursor to be inside the window"); + return; } + }; + + let win_size = self.window.inner_size(); + let border_size = BORDER_SIZE * self.window.scale_factor(); + + let x_direction = if position.x < border_size { + ResizeDirection::West + } else if position.x > (win_size.width as f64 - border_size) { + ResizeDirection::East + } else { + // Use arbitrary direction instead of None for simplicity. + ResizeDirection::SouthEast + }; + + let y_direction = if position.y < border_size { + ResizeDirection::North + } else if position.y > (win_size.height as f64 - border_size) { + ResizeDirection::South + } else { + // Use arbitrary direction instead of None for simplicity. + ResizeDirection::SouthEast + }; + + let direction = match (x_direction, y_direction) { + (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest, + (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest, + (ResizeDirection::West, _) => ResizeDirection::West, + (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast, + (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast, + (ResizeDirection::East, _) => ResizeDirection::East, + (_, ResizeDirection::South) => ResizeDirection::South, + (_, ResizeDirection::North) => ResizeDirection::North, + _ => return, + }; + + if let Err(err) = self.window.drag_resize_window(direction) { + println!("Error starting window drag-resize: {err}"); + } else { + println!("Drag-resizing window Window={:?}", self.window.id()); + } + } + + /// Change window occlusion state. + fn set_occluded(&mut self, occluded: bool) { + self.occluded = occluded; + if !occluded { + self.window.request_redraw(); + } + } + + /// Draw the window contents. + #[cfg(not(any(android_platform, ios_platform)))] + fn draw(&mut self) -> Result<(), Box> { + if self.occluded { + println!("Skipping drawing occluded window={:?}", self.window.id()); + return Ok(()); + } + + const WHITE: u32 = 0xFFFFFFFF; + const DARK_GRAY: u32 = 0xFF181818; + + let color = match self.theme { + Theme::Light => WHITE, + Theme::Dark => DARK_GRAY, + }; + + let mut buffer = self.surface.buffer_mut()?; + buffer.fill(color); + self.window.pre_present_notify(); + buffer.present()?; + Ok(()) + } + + #[cfg(any(android_platform, ios_platform))] + fn draw(&mut self) -> Result<(), Box> { + println!("Drawing but without rendering..."); + Ok(()) + } +} + +struct Binding { + trigger: T, + mods: ModifiersState, + action: Action, +} + +impl Binding { + const fn new(trigger: T, mods: ModifiersState, action: Action) -> Self { + Self { + trigger, + mods, + action, + } + } + + fn is_triggered_by(&self, trigger: &T, mods: &ModifiersState) -> bool { + &self.trigger == trigger && &self.mods == mods + } +} - _ => (), +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Action { + CloseWindow, + ToggleCursorVisibility, + CreateNewWindow, + ToggleResizeIncrements, + ToggleImeInput, + ToggleDecorations, + ToggleResizable, + ToggleFullscreen, + ToggleMaximize, + Minimize, + NextCursor, + NextCustomCursor, + CycleCursorGrab, + PrintHelp, + DragWindow, + DragResizeWindow, + ShowWindowMenu, + #[cfg(macos_platform)] + CycleOptionAsAlt, + #[cfg(macos_platform)] + CreateNewTab, +} + +impl Action { + fn help(&self) -> &'static str { + match self { + Action::CloseWindow => "Close window", + Action::ToggleCursorVisibility => "Hide cursor", + Action::CreateNewWindow => "Create new window", + Action::ToggleImeInput => "Toggle IME input", + Action::ToggleDecorations => "Toggle decorations", + Action::ToggleResizable => "Toggle window resizable state", + Action::ToggleFullscreen => "Toggle fullscreen", + Action::ToggleMaximize => "Maximize", + Action::Minimize => "Minimize", + 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", + Action::CycleCursorGrab => "Cycle through cursor grab mode", + Action::PrintHelp => "Print help", + Action::DragWindow => "Start window drag", + Action::DragResizeWindow => "Start window drag-resize", + Action::ShowWindowMenu => "Show window menu", + #[cfg(macos_platform)] + Action::CycleOptionAsAlt => "Cycle option as alt mode", + #[cfg(macos_platform)] + Action::CreateNewTab => "Create new tab", } - }) + } } + +impl fmt::Display for Action { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self, f) + } +} + +fn decode_cursor(bytes: &[u8], window_target: &ActiveEventLoop) -> CustomCursor { + let img = image::load_from_memory(bytes).unwrap().to_rgba8(); + let samples = img.into_flat_samples(); + let (_, w, h) = samples.extents(); + let (w, h) = (w as u16, h as u16); + let builder = CustomCursor::from_rgba(samples.samples, w, h, w / 2, h / 2).unwrap(); + + builder.build(window_target) +} + +fn load_icon(path: &Path) -> Icon { + let (icon_rgba, icon_width, icon_height) = { + let image = image::open(path) + .expect("Failed to open icon path") + .into_rgba8(); + let (width, height) = image.dimensions(); + let rgba = image.into_raw(); + (rgba, width, height) + }; + Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon") +} + +fn modifiers_to_string(mods: ModifiersState) -> String { + let mut mods_line = String::new(); + // Always add + since it's printed as a part of the bindings. + for (modifier, desc) in [ + (ModifiersState::SUPER, "Super+"), + (ModifiersState::ALT, "Alt+"), + (ModifiersState::CONTROL, "Ctrl+"), + (ModifiersState::SHIFT, "Shift+"), + ] { + if !mods.contains(modifier) { + continue; + } + + mods_line.push_str(desc); + } + mods_line +} + +fn mouse_button_to_string(button: MouseButton) -> &'static str { + match button { + MouseButton::Left => "LMB", + MouseButton::Right => "RMB", + MouseButton::Middle => "MMB", + MouseButton::Back => "Back", + MouseButton::Forward => "Forward", + MouseButton::Other(_) => "", + } +} + +/// Cursor list to cycle through. +const CURSORS: &[CursorIcon] = &[ + CursorIcon::Default, + CursorIcon::Crosshair, + CursorIcon::Pointer, + CursorIcon::Move, + CursorIcon::Text, + CursorIcon::Wait, + CursorIcon::Help, + CursorIcon::Progress, + CursorIcon::NotAllowed, + CursorIcon::ContextMenu, + CursorIcon::Cell, + CursorIcon::VerticalText, + CursorIcon::Alias, + CursorIcon::Copy, + CursorIcon::NoDrop, + CursorIcon::Grab, + CursorIcon::Grabbing, + CursorIcon::AllScroll, + CursorIcon::ZoomIn, + CursorIcon::ZoomOut, + CursorIcon::EResize, + CursorIcon::NResize, + CursorIcon::NeResize, + CursorIcon::NwResize, + CursorIcon::SResize, + CursorIcon::SeResize, + CursorIcon::SwResize, + CursorIcon::WResize, + CursorIcon::EwResize, + CursorIcon::NsResize, + CursorIcon::NeswResize, + CursorIcon::NwseResize, + CursorIcon::ColResize, + CursorIcon::RowResize, +]; + +const KEY_BINDINGS: &[Binding<&'static str>] = &[ + Binding::new("Q", ModifiersState::CONTROL, Action::CloseWindow), + Binding::new("H", ModifiersState::CONTROL, Action::PrintHelp), + Binding::new("F", ModifiersState::CONTROL, Action::ToggleFullscreen), + Binding::new("D", ModifiersState::CONTROL, Action::ToggleDecorations), + Binding::new("I", ModifiersState::CONTROL, Action::ToggleImeInput), + Binding::new("L", ModifiersState::CONTROL, Action::CycleCursorGrab), + Binding::new("P", ModifiersState::CONTROL, Action::ToggleResizeIncrements), + Binding::new("R", ModifiersState::CONTROL, Action::ToggleResizable), + // M. + Binding::new("M", ModifiersState::CONTROL, Action::ToggleMaximize), + Binding::new("M", ModifiersState::ALT, Action::Minimize), + // N. + Binding::new("N", ModifiersState::CONTROL, Action::CreateNewWindow), + // C. + Binding::new("C", ModifiersState::CONTROL, Action::NextCursor), + Binding::new("C", ModifiersState::ALT, Action::NextCustomCursor), + Binding::new("Z", ModifiersState::CONTROL, Action::ToggleCursorVisibility), + #[cfg(macos_platform)] + Binding::new("T", ModifiersState::SUPER, Action::CreateNewTab), + #[cfg(macos_platform)] + Binding::new("O", ModifiersState::CONTROL, Action::CycleOptionAsAlt), +]; + +const MOUSE_BINDINGS: &[Binding] = &[ + Binding::new( + MouseButton::Left, + ModifiersState::ALT, + Action::DragResizeWindow, + ), + Binding::new( + MouseButton::Left, + ModifiersState::CONTROL, + Action::DragWindow, + ), + Binding::new( + MouseButton::Right, + ModifiersState::CONTROL, + Action::ShowWindowMenu, + ), +]; diff --git a/examples/window_buttons.rs b/examples/window_buttons.rs deleted file mode 100644 index e854b4681dd..00000000000 --- a/examples/window_buttons.rs +++ /dev/null @@ -1,68 +0,0 @@ -#![allow(clippy::single_match)] - -// This example is used by developers to test various window functions. - -use simple_logger::SimpleLogger; -use winit::{ - dpi::LogicalSize, - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::{DeviceEvents, EventLoop}, - keyboard::Key, - window::{Window, WindowButtons}, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .with_inner_size(LogicalSize::new(300.0, 300.0)) - .build(&event_loop) - .unwrap(); - - eprintln!("Window Button keys:"); - eprintln!(" (F) Toggle close button"); - eprintln!(" (G) Toggle maximize button"); - eprintln!(" (H) Toggle minimize button"); - - event_loop.listen_device_events(DeviceEvents::Always); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { window_id, event } = event { - match event { - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: key, - state: ElementState::Pressed, - .. - }, - .. - } => match key.as_ref() { - Key::Character("F" | "f") => { - let buttons = window.enabled_buttons(); - window.set_enabled_buttons(buttons ^ WindowButtons::CLOSE); - } - Key::Character("G" | "g") => { - let buttons = window.enabled_buttons(); - window.set_enabled_buttons(buttons ^ WindowButtons::MAXIMIZE); - } - Key::Character("H" | "h") => { - let buttons = window.enabled_buttons(); - window.set_enabled_buttons(buttons ^ WindowButtons::MINIMIZE); - } - _ => (), - }, - WindowEvent::CloseRequested if window_id == window.id() => elwt.exit(), - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - } - } - }) -} diff --git a/examples/window_debug.rs b/examples/window_debug.rs deleted file mode 100644 index 3f219d05818..00000000000 --- a/examples/window_debug.rs +++ /dev/null @@ -1,137 +0,0 @@ -#![allow(clippy::single_match)] - -// This example is used by developers to test various window functions. - -use simple_logger::SimpleLogger; -use winit::{ - dpi::{LogicalSize, PhysicalSize}, - event::{DeviceEvent, ElementState, Event, KeyEvent, RawKeyEvent, WindowEvent}, - event_loop::{DeviceEvents, EventLoop}, - keyboard::{Key, KeyCode, PhysicalKey}, - window::{Fullscreen, Window}, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .with_inner_size(LogicalSize::new(100.0, 100.0)) - .build(&event_loop) - .unwrap(); - - eprintln!("debugging keys:"); - eprintln!(" (E) Enter exclusive fullscreen"); - eprintln!(" (F) Toggle borderless fullscreen"); - eprintln!(" (P) Toggle borderless fullscreen on system's preffered monitor"); - eprintln!(" (M) Toggle minimized"); - eprintln!(" (Q) Quit event loop"); - eprintln!(" (V) Toggle visibility"); - eprintln!(" (X) Toggle maximized"); - - let mut minimized = false; - let mut visible = true; - - event_loop.listen_device_events(DeviceEvents::Always); - - event_loop.run(move |event, elwt| { - match event { - // This used to use the virtual key, but the new API - // only provides the `physical_key` (`Code`). - Event::DeviceEvent { - event: - DeviceEvent::Key(RawKeyEvent { - physical_key, - state: ElementState::Released, - .. - }), - .. - } => match physical_key { - PhysicalKey::Code(KeyCode::KeyM) => { - if minimized { - minimized = !minimized; - window.set_minimized(minimized); - window.focus_window(); - } - } - PhysicalKey::Code(KeyCode::KeyV) => { - if !visible { - visible = !visible; - window.set_visible(visible); - } - } - _ => (), - }, - Event::WindowEvent { window_id, event } => match event { - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: Key::Character(key_str), - state: ElementState::Pressed, - .. - }, - .. - } => match key_str.as_ref() { - // WARNING: Consider using `key_without_modifers()` if available on your platform. - // See the `key_binding` example - "e" => { - fn area(size: PhysicalSize) -> u32 { - size.width * size.height - } - - let monitor = window.current_monitor().unwrap(); - if let Some(mode) = monitor - .video_modes() - .max_by(|a, b| area(a.size()).cmp(&area(b.size()))) - { - window.set_fullscreen(Some(Fullscreen::Exclusive(mode))); - } else { - eprintln!("no video modes available"); - } - } - "f" => { - if window.fullscreen().is_some() { - window.set_fullscreen(None); - } else { - let monitor = window.current_monitor(); - window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); - } - } - "p" => { - if window.fullscreen().is_some() { - window.set_fullscreen(None); - } else { - window.set_fullscreen(Some(Fullscreen::Borderless(None))); - } - } - "m" => { - minimized = !minimized; - window.set_minimized(minimized); - } - "q" => { - elwt.exit(); - } - "v" => { - visible = !visible; - window.set_visible(visible); - } - "x" => { - let is_maximized = window.is_maximized(); - window.set_maximized(!is_maximized); - } - _ => (), - }, - WindowEvent::CloseRequested if window_id == window.id() => elwt.exit(), - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - }, - _ => (), - } - }) -} diff --git a/examples/window_drag_resize.rs b/examples/window_drag_resize.rs deleted file mode 100644 index ef59b4c9164..00000000000 --- a/examples/window_drag_resize.rs +++ /dev/null @@ -1,149 +0,0 @@ -//! Demonstrates capability to create in-app draggable regions for client-side decoration support. - -use simple_logger::SimpleLogger; -use winit::{ - event::{ElementState, Event, KeyEvent, MouseButton, StartCause, WindowEvent}, - event_loop::EventLoop, - keyboard::Key, - window::{CursorIcon, ResizeDirection, Window}, -}; - -const BORDER: f64 = 8.0; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_inner_size(winit::dpi::LogicalSize::new(600.0, 400.0)) - .with_min_inner_size(winit::dpi::LogicalSize::new(400.0, 200.0)) - .with_decorations(false) - .build(&event_loop) - .unwrap(); - - let mut border = false; - let mut cursor_location = None; - - event_loop.run(move |event, elwt| match event { - Event::NewEvents(StartCause::Init) => { - eprintln!("Press 'B' to toggle borderless") - } - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::CursorMoved { position, .. } => { - if !window.is_decorated() { - let new_location = - cursor_resize_direction(window.inner_size(), position, BORDER); - - if new_location != cursor_location { - cursor_location = new_location; - window.set_cursor(cursor_direction_icon(cursor_location)) - } - } - } - - WindowEvent::MouseInput { - state: ElementState::Pressed, - button: MouseButton::Left, - .. - } => { - if let Some(dir) = cursor_location { - let _res = window.drag_resize_window(dir); - } else if !window.is_decorated() { - let _res = window.drag_window(); - } - } - WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Released, - logical_key: Key::Character(c), - .. - }, - .. - } if matches!(c.as_ref(), "B" | "b") => { - border = !border; - window.set_decorations(border); - } - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - }, - - _ => (), - }) -} - -fn cursor_direction_icon(resize_direction: Option) -> CursorIcon { - match resize_direction { - Some(resize_direction) => match resize_direction { - ResizeDirection::East => CursorIcon::EResize, - ResizeDirection::North => CursorIcon::NResize, - ResizeDirection::NorthEast => CursorIcon::NeResize, - ResizeDirection::NorthWest => CursorIcon::NwResize, - ResizeDirection::South => CursorIcon::SResize, - ResizeDirection::SouthEast => CursorIcon::SeResize, - ResizeDirection::SouthWest => CursorIcon::SwResize, - ResizeDirection::West => CursorIcon::WResize, - }, - None => CursorIcon::Default, - } -} - -fn cursor_resize_direction( - win_size: winit::dpi::PhysicalSize, - position: winit::dpi::PhysicalPosition, - border_size: f64, -) -> Option { - enum XDirection { - West, - East, - Default, - } - - enum YDirection { - North, - South, - Default, - } - - let xdir = if position.x < border_size { - XDirection::West - } else if position.x > (win_size.width as f64 - border_size) { - XDirection::East - } else { - XDirection::Default - }; - - let ydir = if position.y < border_size { - YDirection::North - } else if position.y > (win_size.height as f64 - border_size) { - YDirection::South - } else { - YDirection::Default - }; - - Some(match xdir { - XDirection::West => match ydir { - YDirection::North => ResizeDirection::NorthWest, - YDirection::South => ResizeDirection::SouthWest, - YDirection::Default => ResizeDirection::West, - }, - - XDirection::East => match ydir { - YDirection::North => ResizeDirection::NorthEast, - YDirection::South => ResizeDirection::SouthEast, - YDirection::Default => ResizeDirection::East, - }, - - XDirection::Default => match ydir { - YDirection::North => ResizeDirection::North, - YDirection::South => ResizeDirection::South, - YDirection::Default => return None, - }, - }) -} diff --git a/examples/window_icon.rs b/examples/window_icon.rs deleted file mode 100644 index a5863b05cbd..00000000000 --- a/examples/window_icon.rs +++ /dev/null @@ -1,60 +0,0 @@ -#![allow(clippy::single_match)] - -use std::path::Path; - -use simple_logger::SimpleLogger; -use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::{Icon, Window}, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - - // You'll have to choose an icon size at your own discretion. On X11, the desired size varies - // 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/icon.png"); - - let icon = load_icon(Path::new(path)); - - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("An iconic window!") - // At present, this only does anything on Windows and X11, so if you want to save load - // time, you can put icon loading behind a function that returns `None` on other platforms. - .with_window_icon(Some(icon)) - .build(&event_loop) - .unwrap(); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, .. } = event { - match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::DroppedFile(path) => { - window.set_window_icon(Some(load_icon(&path))); - } - WindowEvent::RedrawRequested => fill::fill_window(&window), - _ => (), - } - } - }) -} - -fn load_icon(path: &Path) -> Icon { - let (icon_rgba, icon_width, icon_height) = { - let image = image::open(path) - .expect("Failed to open icon path") - .into_rgba8(); - let (width, height) = image.dimensions(); - let rgba = image.into_raw(); - (rgba, width, height) - }; - Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon") -} diff --git a/examples/window_option_as_alt.rs b/examples/window_option_as_alt.rs deleted file mode 100644 index 910221abe83..00000000000 --- a/examples/window_option_as_alt.rs +++ /dev/null @@ -1,72 +0,0 @@ -#![allow(clippy::single_match)] - -#[cfg(target_os = "macos")] -use winit::platform::macos::{OptionAsAlt, WindowExtMacOS}; - -#[cfg(target_os = "macos")] -use winit::{ - event::ElementState, - event::{Event, MouseButton, WindowEvent}, - event_loop::EventLoop, - window::Window, -}; - -#[cfg(target_os = "macos")] -#[path = "util/fill.rs"] -mod fill; - -/// Prints the keyboard events characters received when option_is_alt is true versus false. -/// A left mouse click will toggle option_is_alt. -#[cfg(target_os = "macos")] -fn main() -> Result<(), impl std::error::Error> { - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) - .build(&event_loop) - .unwrap(); - - window.set_ime_allowed(true); - - let mut option_as_alt = window.option_as_alt(); - - event_loop.run(move |event, elwt| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - window_id, - } if window_id == window.id() => elwt.exit(), - Event::WindowEvent { event, .. } => match event { - WindowEvent::MouseInput { - state: ElementState::Pressed, - button: MouseButton::Left, - .. - } => { - option_as_alt = match option_as_alt { - OptionAsAlt::None => OptionAsAlt::OnlyLeft, - OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight, - OptionAsAlt::OnlyRight => OptionAsAlt::Both, - OptionAsAlt::Both => OptionAsAlt::None, - }; - - println!("Received Mouse click, toggling option_as_alt to: {option_as_alt:?}"); - window.set_option_as_alt(option_as_alt); - } - WindowEvent::KeyboardInput { .. } => println!("KeyboardInput: {event:?}"), - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - }, - Event::AboutToWait => { - window.request_redraw(); - } - - _ => (), - }) -} - -#[cfg(not(target_os = "macos"))] -fn main() { - println!("This example is only supported on MacOS"); -} diff --git a/examples/window_resize_increments.rs b/examples/window_resize_increments.rs deleted file mode 100644 index 2326cfb28a6..00000000000 --- a/examples/window_resize_increments.rs +++ /dev/null @@ -1,52 +0,0 @@ -use log::debug; -use simple_logger::SimpleLogger; -use winit::{ - dpi::LogicalSize, - event::{ElementState, Event, WindowEvent}, - event_loop::EventLoop, - keyboard::NamedKey, - window::Window, -}; - -#[path = "util/fill.rs"] -mod fill; - -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let window = Window::builder() - .with_title("A fantastic window!") - .with_inner_size(LogicalSize::new(128.0, 128.0)) - .with_resize_increments(LogicalSize::new(25.0, 25.0)) - .build(&event_loop) - .unwrap(); - - let mut has_increments = true; - - event_loop.run(move |event, elwt| match event { - Event::WindowEvent { event, window_id } if window_id == window.id() => match event { - WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::KeyboardInput { event, .. } - if event.logical_key == NamedKey::Space - && event.state == ElementState::Released => - { - has_increments = !has_increments; - - let new_increments = match window.resize_increments() { - Some(_) => None, - None => Some(LogicalSize::new(25.0, 25.0)), - }; - debug!("Had increments: {}", new_increments.is_none()); - window.set_resize_increments(new_increments); - } - WindowEvent::RedrawRequested => { - fill::fill_window(&window); - } - _ => (), - }, - Event::AboutToWait => window.request_redraw(), - - _ => (), - }) -} diff --git a/examples/window_tabbing.rs b/examples/window_tabbing.rs deleted file mode 100644 index c0ff0a6787a..00000000000 --- a/examples/window_tabbing.rs +++ /dev/null @@ -1,107 +0,0 @@ -#![allow(clippy::single_match)] - -#[cfg(target_os = "macos")] -use std::{collections::HashMap, num::NonZeroUsize}; - -#[cfg(target_os = "macos")] -use simple_logger::SimpleLogger; -#[cfg(target_os = "macos")] -use winit::{ - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, - keyboard::{Key, NamedKey}, - platform::macos::{WindowBuilderExtMacOS, WindowExtMacOS}, - window::Window, -}; - -#[cfg(target_os = "macos")] -#[path = "util/fill.rs"] -mod fill; - -#[cfg(target_os = "macos")] -fn main() -> Result<(), impl std::error::Error> { - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new().unwrap(); - - let mut windows = HashMap::new(); - let window = Window::new(&event_loop).unwrap(); - println!("Opened a new window: {:?}", window.id()); - windows.insert(window.id(), window); - - println!("Press N to open a new window."); - - event_loop.run(move |event, elwt| { - if let Event::WindowEvent { event, window_id } = event { - match event { - WindowEvent::CloseRequested => { - println!("Window {window_id:?} has received the signal to close"); - - // This drops the window, causing it to close. - windows.remove(&window_id); - - if windows.is_empty() { - elwt.exit(); - } - } - WindowEvent::Resized(_) => { - if let Some(window) = windows.get(&window_id) { - window.request_redraw(); - } - } - WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Pressed, - logical_key, - .. - }, - is_synthetic: false, - .. - } => match logical_key.as_ref() { - Key::Character("t") => { - let tabbing_id = windows.get(&window_id).unwrap().tabbing_identifier(); - let window = Window::builder() - .with_tabbing_identifier(&tabbing_id) - .build(elwt) - .unwrap(); - println!("Added a new tab: {:?}", window.id()); - windows.insert(window.id(), window); - } - Key::Character("w") => { - let _ = windows.remove(&window_id); - } - Key::Named(NamedKey::ArrowRight) => { - windows.get(&window_id).unwrap().select_next_tab(); - } - Key::Named(NamedKey::ArrowLeft) => { - windows.get(&window_id).unwrap().select_previous_tab(); - } - Key::Character(ch) => { - if let Ok(index) = ch.parse::() { - let index = index.get(); - // Select the last tab when pressing `9`. - let window = windows.get(&window_id).unwrap(); - if index == 9 { - window.select_tab_at_index(window.num_tabs() - 1) - } else { - window.select_tab_at_index(index - 1); - } - } - } - _ => (), - }, - WindowEvent::RedrawRequested => { - if let Some(window) = windows.get(&window_id) { - fill::fill_window(window); - } - } - _ => (), - } - } - }) -} - -#[cfg(not(target_os = "macos"))] -fn main() { - println!("This example is only supported on MacOS"); -} diff --git a/examples/x11_embed.rs b/examples/x11_embed.rs index 6f96379ac7c..f4d6d9f54d1 100644 --- a/examples/x11_embed.rs +++ b/examples/x11_embed.rs @@ -1,13 +1,10 @@ //! A demonstration of embedding a winit window in an existing X11 application. +use std::error::Error; #[cfg(x11_platform)] -#[path = "util/fill.rs"] -mod fill; - -#[cfg(x11_platform)] -mod imple { - use super::fill; +fn main() -> Result<(), Box> { use simple_logger::SimpleLogger; + use winit::{ event::{Event, WindowEvent}, event_loop::EventLoop, @@ -15,56 +12,53 @@ mod imple { window::Window, }; - pub(super) fn entry() -> Result<(), Box> { - // First argument should be a 32-bit X11 window ID. - let parent_window_id = std::env::args() - .nth(1) - .ok_or("Expected a 32-bit X11 window ID as the first argument.")? - .parse::()?; + #[path = "util/fill.rs"] + mod fill; + + // First argument should be a 32-bit X11 window ID. + let parent_window_id = std::env::args() + .nth(1) + .ok_or("Expected a 32-bit X11 window ID as the first argument.")? + .parse::()?; - SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new()?; + SimpleLogger::new().init().unwrap(); + let event_loop = EventLoop::new()?; - let window = Window::builder() - .with_title("An embedded window!") - .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) - .with_embed_parent_window(parent_window_id) - .build(&event_loop) - .unwrap(); + let mut window = None; + event_loop.run(move |event, event_loop| match event { + Event::Resumed => { + window = Some( + Window::builder() + .with_title("An embedded window!") + .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) + .with_embed_parent_window(parent_window_id) + .build(event_loop) + .unwrap(), + ); + } + Event::WindowEvent { event, .. } => { + let window = window.as_ref().unwrap(); - event_loop.run(move |event, elwt| { match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - window_id, - } if window_id == window.id() => elwt.exit(), - Event::AboutToWait => { - window.request_redraw(); - } - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - // Notify the windowing system that we'll be presenting to the window. + WindowEvent::CloseRequested => event_loop.exit(), + WindowEvent::RedrawRequested => { window.pre_present_notify(); - fill::fill_window(&window); + fill::fill_window(window); } _ => (), } - })?; + } + Event::AboutToWait => { + window.as_ref().unwrap().request_redraw(); + } + _ => (), + })?; - Ok(()) - } + Ok(()) } #[cfg(not(x11_platform))] -mod imple { - pub(super) fn entry() -> Result<(), Box> { - println!("This example is only supported on X11 platforms."); - Ok(()) - } -} - -fn main() -> Result<(), Box> { - imple::entry() +fn main() -> Result<(), Box> { + println!("This example is only supported on X11 platforms."); + Ok(()) } diff --git a/src/cursor.rs b/src/cursor.rs index b519b579fb4..2e8da938a96 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -5,7 +5,7 @@ use std::{error::Error, hash::Hash}; use cursor_icon::CursorIcon; -use crate::event_loop::EventLoopWindowTarget; +use crate::event_loop::ActiveEventLoop; use crate::platform_impl::{self, PlatformCustomCursor, PlatformCustomCursorBuilder}; /// The maximum width and height for a cursor when using [`CustomCursor::from_rgba`]. @@ -49,13 +49,10 @@ impl From for Cursor { /// # Example /// /// ```no_run -/// use winit::{ -/// event::{Event, WindowEvent}, -/// event_loop::{ControlFlow, EventLoop}, -/// window::{CustomCursor, Window}, -/// }; -/// -/// let mut event_loop = EventLoop::new().unwrap(); +/// # use winit::event_loop::ActiveEventLoop; +/// # use winit::window::Window; +/// # fn scope(event_loop: &ActiveEventLoop, window: &Window) { +/// use winit::window::CustomCursor; /// /// let w = 10; /// let h = 10; @@ -72,8 +69,8 @@ impl From for Cursor { /// /// let custom_cursor = builder.build(&event_loop); /// -/// let window = Window::new(&event_loop).unwrap(); /// window.set_cursor(custom_cursor.clone()); +/// # } /// ``` #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct CustomCursor { @@ -113,7 +110,7 @@ pub struct CustomCursorBuilder { } impl CustomCursorBuilder { - pub fn build(self, window_target: &EventLoopWindowTarget) -> CustomCursor { + pub fn build(self, window_target: &ActiveEventLoop) -> CustomCursor { CustomCursor { inner: PlatformCustomCursor::build(self.inner, &window_target.p), } @@ -217,7 +214,7 @@ impl Eq for OnlyCursorImage {} impl OnlyCursorImage { pub(crate) fn build( builder: OnlyCursorImageBuilder, - _: &platform_impl::EventLoopWindowTarget, + _: &platform_impl::ActiveEventLoop, ) -> Self { Self(Arc::new(builder.0)) } @@ -298,7 +295,7 @@ impl NoCustomCursor { Ok(Self) } - fn build(self, _: &platform_impl::EventLoopWindowTarget) -> NoCustomCursor { + fn build(self, _: &platform_impl::ActiveEventLoop) -> NoCustomCursor { self } } diff --git a/src/event_loop.rs b/src/event_loop.rs index 7f16dbbabba..0cac6980078 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -8,7 +8,6 @@ //! See the root-level documentation for information on how to create and use an event loop to //! handle events. use std::marker::PhantomData; -use std::ops::Deref; #[cfg(any(x11_platform, wayland_platform))] use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; @@ -45,11 +44,9 @@ pub struct EventLoop { /// Target that associates windows with an [`EventLoop`]. /// /// This type exists to allow you to create new windows while Winit executes -/// your callback. [`EventLoop`] will coerce into this type (`impl Deref for -/// EventLoop`), so functions that take this as a parameter can also take -/// `&EventLoop`. -pub struct EventLoopWindowTarget { - pub(crate) p: platform_impl::EventLoopWindowTarget, +/// your callback. +pub struct ActiveEventLoop { + pub(crate) p: platform_impl::ActiveEventLoop, pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync } @@ -135,13 +132,13 @@ impl fmt::Debug for EventLoop { } } -impl fmt::Debug for EventLoopWindowTarget { +impl fmt::Debug for ActiveEventLoop { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("EventLoopWindowTarget { .. }") + f.pad("ActiveEventLoop { .. }") } } -/// Set through [`EventLoopWindowTarget::set_control_flow()`]. +/// Set through [`ActiveEventLoop::set_control_flow()`]. /// /// Indicates the desired behavior of the event loop after [`Event::AboutToWait`] is emitted. /// @@ -241,14 +238,14 @@ impl EventLoop { /// /// This function won't be available with `target_feature = "exception-handling"`. /// - /// [`set_control_flow()`]: EventLoopWindowTarget::set_control_flow() + /// [`set_control_flow()`]: ActiveEventLoop::set_control_flow() /// [`run()`]: Self::run() /// [^1]: `EventLoopExtWebSys::spawn()` is only available on Web. #[inline] #[cfg(not(all(web_platform, target_feature = "exception-handling")))] pub fn run(self, event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &EventLoopWindowTarget), + F: FnMut(Event, &ActiveEventLoop), { self.event_loop.run(event_handler) } @@ -259,12 +256,41 @@ impl EventLoop { event_loop_proxy: self.event_loop.create_proxy(), } } + + /// Gets a persistent reference to the underlying platform display. + /// + /// See the [`OwnedDisplayHandle`] type for more information. + pub fn owned_display_handle(&self) -> OwnedDisplayHandle { + OwnedDisplayHandle { + platform: self.event_loop.window_target().p.owned_display_handle(), + } + } + + /// Change if or when [`DeviceEvent`]s are captured. + /// + /// See [`ActiveEventLoop::listen_device_events`] for details. + /// + /// [`DeviceEvent`]: crate::event::DeviceEvent + pub fn listen_device_events(&self, allowed: DeviceEvents) { + self.event_loop + .window_target() + .p + .listen_device_events(allowed); + } + + /// Sets the [`ControlFlow`]. + pub fn set_control_flow(&self, control_flow: ControlFlow) { + self.event_loop + .window_target() + .p + .set_control_flow(control_flow) + } } #[cfg(feature = "rwh_06")] impl rwh_06::HasDisplayHandle for EventLoop { fn display_handle(&self) -> Result, rwh_06::HandleError> { - rwh_06::HasDisplayHandle::display_handle(&**self) + rwh_06::HasDisplayHandle::display_handle(self.event_loop.window_target()) } } @@ -272,7 +298,7 @@ impl rwh_06::HasDisplayHandle for EventLoop { unsafe impl rwh_05::HasRawDisplayHandle for EventLoop { /// Returns a [`rwh_05::RawDisplayHandle`] for the event loop. fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle { - rwh_05::HasRawDisplayHandle::raw_display_handle(&**self) + rwh_05::HasRawDisplayHandle::raw_display_handle(self.event_loop.window_target()) } } @@ -304,14 +330,7 @@ impl AsRawFd for EventLoop { } } -impl Deref for EventLoop { - type Target = EventLoopWindowTarget; - fn deref(&self) -> &EventLoopWindowTarget { - self.event_loop.window_target() - } -} - -impl EventLoopWindowTarget { +impl ActiveEventLoop { /// Returns the list of all the monitors available on the system. #[inline] pub fn available_monitors(&self) -> impl Iterator { @@ -386,7 +405,7 @@ impl EventLoopWindowTarget { } #[cfg(feature = "rwh_06")] -impl rwh_06::HasDisplayHandle for EventLoopWindowTarget { +impl rwh_06::HasDisplayHandle for ActiveEventLoop { fn display_handle(&self) -> Result, rwh_06::HandleError> { let raw = self.p.raw_display_handle_rwh_06()?; // SAFETY: The display will never be deallocated while the event loop is alive. @@ -395,7 +414,7 @@ impl rwh_06::HasDisplayHandle for EventLoopWindowTarget { } #[cfg(feature = "rwh_05")] -unsafe impl rwh_05::HasRawDisplayHandle for EventLoopWindowTarget { +unsafe impl rwh_05::HasRawDisplayHandle for ActiveEventLoop { /// Returns a [`rwh_05::RawDisplayHandle`] for the event loop. fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle { self.p.raw_display_handle_rwh_05() @@ -406,7 +425,7 @@ unsafe impl rwh_05::HasRawDisplayHandle for EventLoopWindowTarget { /// /// The purpose of this type is to provide a cheaply clonable handle to the underlying /// display handle. This is often used by graphics APIs to connect to the underlying APIs. -/// It is difficult to keep a handle to the [`EventLoop`] type or the [`EventLoopWindowTarget`] +/// It is difficult to keep a handle to the [`EventLoop`] type or the [`ActiveEventLoop`] /// type. In contrast, this type involves no lifetimes and can be persisted for as long as /// needed. /// diff --git a/src/lib.rs b/src/lib.rs index a746f3e5784..9aabc8941f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,7 +67,6 @@ //! }; //! //! let event_loop = EventLoop::new().unwrap(); -//! let window = Window::builder().build(&event_loop).unwrap(); //! //! // ControlFlow::Poll continuously runs the event loop, even if the OS hasn't //! // dispatched any events. This is ideal for games and similar applications. @@ -78,14 +77,19 @@ //! // input, and uses significantly less power/CPU time than ControlFlow::Poll. //! event_loop.set_control_flow(ControlFlow::Wait); //! -//! event_loop.run(move |event, elwt| { +//! let mut window = None; +//! +//! event_loop.run(move |event, event_loop| { //! match event { +//! Event::Resumed => { +//! window = Some(Window::builder().build(&event_loop).unwrap()); +//! } //! Event::WindowEvent { //! event: WindowEvent::CloseRequested, //! .. //! } => { //! println!("The close button was pressed; stopping"); -//! elwt.exit(); +//! event_loop.exit(); //! }, //! Event::AboutToWait => { //! // Application update code. @@ -95,7 +99,7 @@ //! // You only need to call this if you've determined that you need to redraw in //! // applications which do not always need to. Applications that redraw continuously //! // can render here instead. -//! window.request_redraw(); +//! window.as_ref().unwrap().request_redraw(); //! }, //! Event::WindowEvent { //! event: WindowEvent::RedrawRequested, @@ -132,7 +136,7 @@ //! [`EventLoop`]: event_loop::EventLoop //! [`EventLoop::new()`]: event_loop::EventLoop::new //! [`EventLoop::run()`]: event_loop::EventLoop::run -//! [`exit()`]: event_loop::EventLoopWindowTarget::exit +//! [`exit()`]: event_loop::ActiveEventLoop::exit //! [`Window`]: window::Window //! [`WindowId`]: window::WindowId //! [`WindowBuilder`]: window::WindowBuilder diff --git a/src/monitor.rs b/src/monitor.rs index 7fe7e234947..f1df3207d15 100644 --- a/src/monitor.rs +++ b/src/monitor.rs @@ -3,7 +3,7 @@ //! If you want to get basic information about a monitor, you can use the //! [`MonitorHandle`] type. This is retrieved from one of the following //! methods, which return an iterator of [`MonitorHandle`]: -//! - [`EventLoopWindowTarget::available_monitors`](crate::event_loop::EventLoopWindowTarget::available_monitors). +//! - [`ActiveEventLoop::available_monitors`](crate::event_loop::ActiveEventLoop::available_monitors). //! - [`Window::available_monitors`](crate::window::Window::available_monitors). use crate::{ dpi::{PhysicalPosition, PhysicalSize}, diff --git a/src/platform/android.rs b/src/platform/android.rs index 9bdcb03528a..9ffe68abebd 100644 --- a/src/platform/android.rs +++ b/src/platform/android.rs @@ -1,5 +1,5 @@ use crate::{ - event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder}, window::{Window, WindowBuilder}, }; @@ -10,8 +10,8 @@ pub trait EventLoopExtAndroid {} impl EventLoopExtAndroid for EventLoop {} -/// Additional methods on [`EventLoopWindowTarget`] that are specific to Android. -pub trait EventLoopWindowTargetExtAndroid {} +/// Additional methods on [`ActiveEventLoop`] that are specific to Android. +pub trait ActiveEventLoopExtAndroid {} /// Additional methods on [`Window`] that are specific to Android. pub trait WindowExtAndroid { @@ -30,7 +30,7 @@ impl WindowExtAndroid for Window { } } -impl EventLoopWindowTargetExtAndroid for EventLoopWindowTarget {} +impl ActiveEventLoopExtAndroid for ActiveEventLoop {} /// Additional methods on [`WindowBuilder`] that are specific to Android. pub trait WindowBuilderExtAndroid {} diff --git a/src/platform/macos.rs b/src/platform/macos.rs index bb93f700fe3..7646afb6fa5 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -4,7 +4,7 @@ use std::os::raw::c_void; use serde::{Deserialize, Serialize}; use crate::{ - event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoopBuilder}, monitor::MonitorHandle, window::{Window, WindowBuilder}, }; @@ -375,8 +375,8 @@ impl MonitorHandleExtMacOS for MonitorHandle { } } -/// Additional methods on [`EventLoopWindowTarget`] that are specific to macOS. -pub trait EventLoopWindowTargetExtMacOS { +/// Additional methods on [`ActiveEventLoop`] that are specific to macOS. +pub trait ActiveEventLoopExtMacOS { /// Hide the entire application. In most applications this is typically triggered with Command-H. fn hide_application(&self); /// Hide the other applications. In most applications this is typically triggered with Command+Option-H. @@ -389,7 +389,7 @@ pub trait EventLoopWindowTargetExtMacOS { fn allows_automatic_window_tabbing(&self) -> bool; } -impl EventLoopWindowTargetExtMacOS for EventLoopWindowTarget { +impl ActiveEventLoopExtMacOS for ActiveEventLoop { fn hide_application(&self) { self.p.hide_application() } diff --git a/src/platform/pump_events.rs b/src/platform/pump_events.rs index 51cb6056977..804723dcbfe 100644 --- a/src/platform/pump_events.rs +++ b/src/platform/pump_events.rs @@ -2,7 +2,7 @@ use std::time::Duration; use crate::{ event::Event, - event_loop::{EventLoop, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop}, }; /// The return status for `pump_events` @@ -32,68 +32,6 @@ pub trait EventLoopExtPumpEvents { /// Passing a `timeout` of `None` means that it may wait indefinitely for new /// events before returning control back to the external loop. /// - /// ## Example - /// - /// ```rust,no_run - /// # // Copied from examples/window_pump_events.rs - /// # #[cfg(any( - /// # windows_platform, - /// # macos_platform, - /// # x11_platform, - /// # wayland_platform, - /// # android_platform, - /// # ))] - /// fn main() -> std::process::ExitCode { - /// # use std::{process::ExitCode, thread::sleep, time::Duration}; - /// # - /// # use simple_logger::SimpleLogger; - /// # use winit::{ - /// # event::{Event, WindowEvent}, - /// # event_loop::EventLoop, - /// # platform::pump_events::{EventLoopExtPumpEvents, PumpStatus}, - /// # window::Window, - /// # }; - /// let mut event_loop = EventLoop::new().unwrap(); - /// # - /// # SimpleLogger::new().init().unwrap(); - /// let window = Window::builder() - /// .with_title("A fantastic window!") - /// .build(&event_loop) - /// .unwrap(); - /// - /// 'main: loop { - /// let timeout = Some(Duration::ZERO); - /// let status = event_loop.pump_events(timeout, |event, elwt| { - /// # if let Event::WindowEvent { event, .. } = &event { - /// # // Print only Window events to reduce noise - /// # println!("{event:?}"); - /// # } - /// # - /// match event { - /// Event::WindowEvent { - /// event: WindowEvent::CloseRequested, - /// window_id, - /// } if window_id == window.id() => elwt.exit(), - /// Event::AboutToWait => { - /// window.request_redraw(); - /// } - /// _ => (), - /// } - /// }); - /// if let PumpStatus::Exit(exit_code) = status { - /// break 'main ExitCode::from(exit_code as u8); - /// } - /// - /// // Sleep for 1/60 second to simulate application work - /// // - /// // Since `pump_events` doesn't block it will be important to - /// // throttle the loop in the app somehow. - /// println!("Update()"); - /// sleep(Duration::from_millis(16)); - /// } - /// } - /// ``` - /// /// **Note:** This is not a portable API, and its usage involves a number of /// caveats and trade offs that should be considered before using this API! /// @@ -137,12 +75,14 @@ pub trait EventLoopExtPumpEvents { /// other lifecycle events occur while the event is buffered. /// /// ## Supported Platforms + /// /// - Windows /// - Linux /// - MacOS /// - Android /// /// ## Unsupported Platforms + /// /// - **Web:** This API is fundamentally incompatible with the event-based way in which /// Web browsers work because it's not possible to have a long-running external /// loop that would block the browser and there is nothing that can be @@ -152,6 +92,7 @@ pub trait EventLoopExtPumpEvents { /// there's no way to support the same approach to polling as on MacOS. /// /// ## Platform-specific + /// /// - **Windows**: The implementation will use `PeekMessage` when checking for /// window messages to avoid blocking your external event loop. /// @@ -174,7 +115,7 @@ pub trait EventLoopExtPumpEvents { /// callback. fn pump_events(&mut self, timeout: Option, event_handler: F) -> PumpStatus where - F: FnMut(Event, &EventLoopWindowTarget); + F: FnMut(Event, &ActiveEventLoop); } impl EventLoopExtPumpEvents for EventLoop { @@ -182,7 +123,7 @@ impl EventLoopExtPumpEvents for EventLoop { fn pump_events(&mut self, timeout: Option, event_handler: F) -> PumpStatus where - F: FnMut(Event, &EventLoopWindowTarget), + F: FnMut(Event, &ActiveEventLoop), { self.event_loop.pump_events(timeout, event_handler) } diff --git a/src/platform/run_on_demand.rs b/src/platform/run_on_demand.rs index ea287ca52f3..0010eab8868 100644 --- a/src/platform/run_on_demand.rs +++ b/src/platform/run_on_demand.rs @@ -1,7 +1,7 @@ use crate::{ error::EventLoopError, event::Event, - event_loop::{EventLoop, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop}, }; #[cfg(doc)] @@ -62,11 +62,11 @@ pub trait EventLoopExtRunOnDemand { doc = "[^1]: `spawn()` is only available on `wasm` platforms." )] /// - /// [`exit()`]: EventLoopWindowTarget::exit() - /// [`set_control_flow()`]: EventLoopWindowTarget::set_control_flow() + /// [`exit()`]: ActiveEventLoop::exit() + /// [`set_control_flow()`]: ActiveEventLoop::set_control_flow() fn run_on_demand(&mut self, event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &EventLoopWindowTarget); + F: FnMut(Event, &ActiveEventLoop); } impl EventLoopExtRunOnDemand for EventLoop { @@ -74,14 +74,14 @@ impl EventLoopExtRunOnDemand for EventLoop { fn run_on_demand(&mut self, event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &EventLoopWindowTarget), + F: FnMut(Event, &ActiveEventLoop), { self.event_loop.window_target().clear_exit(); self.event_loop.run_on_demand(event_handler) } } -impl EventLoopWindowTarget { +impl ActiveEventLoop { /// Clear exit status. pub(crate) fn clear_exit(&self) { self.p.clear_exit() diff --git a/src/platform/startup_notify.rs b/src/platform/startup_notify.rs index 0fc71347546..ef3dd77f60a 100644 --- a/src/platform/startup_notify.rs +++ b/src/platform/startup_notify.rs @@ -24,7 +24,7 @@ use std::env; use crate::error::NotSupportedError; -use crate::event_loop::{AsyncRequestSerial, EventLoopWindowTarget}; +use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial}; use crate::window::{ActivationToken, Window, WindowBuilder}; /// The variable which is used mostly on X11. @@ -55,13 +55,13 @@ pub trait WindowBuilderExtStartupNotify { fn with_activation_token(self, token: ActivationToken) -> Self; } -impl EventLoopExtStartupNotify for EventLoopWindowTarget { +impl EventLoopExtStartupNotify for ActiveEventLoop { fn read_token_from_env(&self) -> Option { match self.p { #[cfg(wayland_platform)] - crate::platform_impl::EventLoopWindowTarget::Wayland(_) => env::var(WAYLAND_VAR), + crate::platform_impl::ActiveEventLoop::Wayland(_) => env::var(WAYLAND_VAR), #[cfg(x11_platform)] - crate::platform_impl::EventLoopWindowTarget::X(_) => env::var(X11_VAR), + crate::platform_impl::ActiveEventLoop::X(_) => env::var(X11_VAR), } .ok() .map(ActivationToken::_new) diff --git a/src/platform/wayland.rs b/src/platform/wayland.rs index e8f3fd5d90f..c493123a22c 100644 --- a/src/platform/wayland.rs +++ b/src/platform/wayland.rs @@ -1,18 +1,18 @@ use crate::{ - event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoopBuilder}, monitor::MonitorHandle, window::{Window, WindowBuilder}, }; pub use crate::window::Theme; -/// Additional methods on [`EventLoopWindowTarget`] that are specific to Wayland. -pub trait EventLoopWindowTargetExtWayland { - /// True if the [`EventLoopWindowTarget`] uses Wayland. +/// Additional methods on [`ActiveEventLoop`] that are specific to Wayland. +pub trait ActiveEventLoopExtWayland { + /// True if the [`ActiveEventLoop`] uses Wayland. fn is_wayland(&self) -> bool; } -impl EventLoopWindowTargetExtWayland for EventLoopWindowTarget { +impl ActiveEventLoopExtWayland for ActiveEventLoop { #[inline] fn is_wayland(&self) -> bool { self.p.is_wayland() diff --git a/src/platform/web.rs b/src/platform/web.rs index 9c0b5a29735..e0fb64298f4 100644 --- a/src/platform/web.rs +++ b/src/platform/web.rs @@ -39,7 +39,7 @@ use web_sys::HtmlCanvasElement; use crate::cursor::CustomCursorBuilder; use crate::event::Event; -use crate::event_loop::{EventLoop, EventLoopWindowTarget}; +use crate::event_loop::{ActiveEventLoop, EventLoop}; #[cfg(web_platform)] use crate::platform_impl::CustomCursorFuture as PlatformCustomCursorFuture; use crate::platform_impl::{PlatformCustomCursor, PlatformCustomCursorBuilder}; @@ -172,7 +172,7 @@ pub trait EventLoopExtWebSys { /// [^1]: `run()` is _not_ available on WASM when the target supports `exception-handling`. fn spawn(self, event_handler: F) where - F: 'static + FnMut(Event, &EventLoopWindowTarget); + F: 'static + FnMut(Event, &ActiveEventLoop); } impl EventLoopExtWebSys for EventLoop { @@ -180,13 +180,13 @@ impl EventLoopExtWebSys for EventLoop { fn spawn(self, event_handler: F) where - F: 'static + FnMut(Event, &EventLoopWindowTarget), + F: 'static + FnMut(Event, &ActiveEventLoop), { self.event_loop.spawn(event_handler) } } -pub trait EventLoopWindowTargetExtWebSys { +pub trait ActiveEventLoopExtWebSys { /// Sets the strategy for [`ControlFlow::Poll`]. /// /// See [`PollStrategy`]. @@ -202,7 +202,7 @@ pub trait EventLoopWindowTargetExtWebSys { fn poll_strategy(&self) -> PollStrategy; } -impl EventLoopWindowTargetExtWebSys for EventLoopWindowTarget { +impl ActiveEventLoopExtWebSys for ActiveEventLoop { #[inline] fn set_poll_strategy(&self, strategy: PollStrategy) { self.p.set_poll_strategy(strategy); @@ -315,11 +315,11 @@ impl Error for BadAnimation {} pub trait CustomCursorBuilderExtWebSys { /// Async version of [`CustomCursorBuilder::build()`] which waits until the /// cursor has completely finished loading. - fn build_async(self, window_target: &EventLoopWindowTarget) -> CustomCursorFuture; + fn build_async(self, window_target: &ActiveEventLoop) -> CustomCursorFuture; } impl CustomCursorBuilderExtWebSys for CustomCursorBuilder { - fn build_async(self, window_target: &EventLoopWindowTarget) -> CustomCursorFuture { + fn build_async(self, window_target: &ActiveEventLoop) -> CustomCursorFuture { CustomCursorFuture(PlatformCustomCursor::build_async( self.inner, &window_target.p, diff --git a/src/platform/x11.rs b/src/platform/x11.rs index 7dc3e8cde79..ccb63de3c68 100644 --- a/src/platform/x11.rs +++ b/src/platform/x11.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use crate::{ - event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoopBuilder}, monitor::MonitorHandle, window::{Window, WindowBuilder}, }; @@ -89,13 +89,13 @@ pub fn register_xlib_error_hook(hook: XlibErrorHook) { } } -/// Additional methods on [`EventLoopWindowTarget`] that are specific to X11. -pub trait EventLoopWindowTargetExtX11 { - /// True if the [`EventLoopWindowTarget`] uses X11. +/// Additional methods on [`ActiveEventLoop`] that are specific to X11. +pub trait ActiveEventLoopExtX11 { + /// True if the [`ActiveEventLoop`] uses X11. fn is_x11(&self) -> bool; } -impl EventLoopWindowTargetExtX11 for EventLoopWindowTarget { +impl ActiveEventLoopExtX11 for ActiveEventLoop { #[inline] fn is_x11(&self) -> bool { !self.p.is_wayland() @@ -175,9 +175,9 @@ pub trait WindowBuilderExtX11 { /// /// ```no_run /// use winit::window::Window; + /// use winit::event_loop::ActiveEventLoop; /// use winit::platform::x11::{XWindow, WindowBuilderExtX11}; - /// # fn main() -> Result<(), Box> { - /// let event_loop = winit::event_loop::EventLoop::new().unwrap(); + /// # fn create_window(event_loop: &ActiveEventLoop) -> Result<(), Box> { /// let parent_window_id = std::env::args().nth(1).unwrap().parse::()?; /// let window = Window::builder() /// .with_embed_parent_window(parent_window_id) diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index ad564385516..e8982f38ee1 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -24,7 +24,7 @@ use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error, event::{self, Force, InnerSizeWriter, StartCause}, - event_loop::{self, ControlFlow, DeviceEvents, EventLoopWindowTarget as RootELW}, + event_loop::{self, ActiveEventLoop as RootELW, ControlFlow, DeviceEvents}, platform::pump_events::PumpStatus, window::{ self, CursorGrabMode, ImePurpose, ResizeDirection, Theme, WindowButtons, WindowLevel, @@ -141,7 +141,7 @@ pub struct KeyEventExtra {} pub struct EventLoop { android_app: AndroidApp, - window_target: event_loop::EventLoopWindowTarget, + window_target: event_loop::ActiveEventLoop, redraw_flag: SharedFlag, user_events_sender: mpsc::Sender, user_events_receiver: PeekableReceiver, //must wake looper whenever something gets sent @@ -179,8 +179,8 @@ impl EventLoop { Ok(Self { android_app: android_app.clone(), - window_target: event_loop::EventLoopWindowTarget { - p: EventLoopWindowTarget { + window_target: event_loop::ActiveEventLoop { + p: ActiveEventLoop { app: android_app.clone(), control_flow: Cell::new(ControlFlow::default()), exit: Cell::new(false), @@ -482,14 +482,14 @@ impl EventLoop { pub fn run(mut self, event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(event::Event, &event_loop::EventLoopWindowTarget), + F: FnMut(event::Event, &event_loop::ActiveEventLoop), { self.run_on_demand(event_handler) } pub fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(event::Event, &event_loop::EventLoopWindowTarget), + F: FnMut(event::Event, &event_loop::ActiveEventLoop), { loop { match self.pump_events(None, &mut event_handler) { @@ -617,7 +617,7 @@ impl EventLoop { }); } - pub fn window_target(&self) -> &event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &event_loop::ActiveEventLoop { &self.window_target } @@ -661,14 +661,14 @@ impl EventLoopProxy { } } -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { app: AndroidApp, control_flow: Cell, exit: Cell, redraw_requester: RedrawRequester, } -impl EventLoopWindowTarget { +impl ActiveEventLoop { pub fn primary_monitor(&self) -> Option { Some(MonitorHandle::new(self.app.clone())) } @@ -782,7 +782,7 @@ pub(crate) struct Window { impl Window { pub(crate) fn new( - el: &EventLoopWindowTarget, + el: &ActiveEventLoop, _window_attrs: window::WindowAttributes, ) -> Result { // FIXME this ignores requested window attributes diff --git a/src/platform_impl/ios/app_state.rs b/src/platform_impl/ios/app_state.rs index eac89365f8d..272b6517e66 100644 --- a/src/platform_impl/ios/app_state.rs +++ b/src/platform_impl/ios/app_state.rs @@ -29,7 +29,7 @@ use super::view::WinitUIWindow; use crate::{ dpi::PhysicalSize, event::{Event, InnerSizeWriter, StartCause, WindowEvent}, - event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget}, + event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow}, window::WindowId as RootWindowId, }; @@ -50,8 +50,8 @@ pub(crate) struct HandlePendingUserEvents; pub(crate) struct EventLoopHandler { #[allow(clippy::type_complexity)] - pub(crate) handler: Box, &RootEventLoopWindowTarget)>, - pub(crate) event_loop: RootEventLoopWindowTarget, + pub(crate) handler: Box, &RootActiveEventLoop)>, + pub(crate) event_loop: RootActiveEventLoop, } impl fmt::Debug for EventLoopHandler { diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index cf69eec5a84..929c7efa660 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -20,8 +20,7 @@ use crate::{ error::EventLoopError, event::Event, event_loop::{ - ControlFlow, DeviceEvents, EventLoopClosed, - EventLoopWindowTarget as RootEventLoopWindowTarget, + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, EventLoopClosed, }, platform::ios::Idiom, platform_impl::platform::app_state::{EventLoopHandler, HandlePendingUserEvents}, @@ -34,11 +33,11 @@ use super::{ }; #[derive(Debug)] -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { pub(super) mtm: MainThreadMarker, } -impl EventLoopWindowTarget { +impl ActiveEventLoop { pub fn available_monitors(&self) -> VecDeque { monitor::uiscreens(self.mtm) } @@ -109,9 +108,9 @@ impl OwnedDisplayHandle { } fn map_user_event( - mut handler: impl FnMut(Event, &RootEventLoopWindowTarget), + mut handler: impl FnMut(Event, &RootActiveEventLoop), receiver: mpsc::Receiver, -) -> impl FnMut(Event, &RootEventLoopWindowTarget) { +) -> impl FnMut(Event, &RootActiveEventLoop) { move |event, window_target| match event.map_nonuser_event() { Ok(event) => (handler)(event, window_target), Err(_) => { @@ -126,7 +125,7 @@ pub struct EventLoop { mtm: MainThreadMarker, sender: Sender, receiver: Receiver, - window_target: RootEventLoopWindowTarget, + window_target: RootActiveEventLoop, } #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -158,8 +157,8 @@ impl EventLoop { mtm, sender, receiver, - window_target: RootEventLoopWindowTarget { - p: EventLoopWindowTarget { mtm }, + window_target: RootActiveEventLoop { + p: ActiveEventLoop { mtm }, _marker: PhantomData, }, }) @@ -167,7 +166,7 @@ impl EventLoop { pub fn run(self, handler: F) -> ! where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &RootActiveEventLoop), { let application = UIApplication::shared(self.mtm); assert!( @@ -181,8 +180,8 @@ impl EventLoop { let handler = unsafe { std::mem::transmute::< - Box, &RootEventLoopWindowTarget)>, - Box, &RootEventLoopWindowTarget)>, + Box, &RootActiveEventLoop)>, + Box, &RootActiveEventLoop)>, >(Box::new(handler)) }; @@ -211,7 +210,7 @@ impl EventLoop { EventLoopProxy::new(self.sender.clone()) } - pub fn window_target(&self) -> &RootEventLoopWindowTarget { + pub fn window_target(&self) -> &RootActiveEventLoop { &self.window_target } } diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index 7f8c23fc247..ad863624cd7 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -72,7 +72,7 @@ use crate::event::DeviceId as RootDeviceId; pub(crate) use self::{ event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }, monitor::{MonitorHandle, VideoModeHandle}, diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 5b22bd8268f..ed5e74782ba 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -18,9 +18,7 @@ use crate::{ event::{Event, WindowEvent}, icon::Icon, platform::ios::{ScreenEdge, StatusBarStyle, ValidOrientations}, - platform_impl::platform::{ - app_state, monitor, EventLoopWindowTarget, Fullscreen, MonitorHandle, - }, + platform_impl::platform::{app_state, monitor, ActiveEventLoop, Fullscreen, MonitorHandle}, window::{ CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowButtons, WindowId as RootWindowId, WindowLevel, @@ -399,7 +397,7 @@ pub struct Window { impl Window { pub(crate) fn new( - event_loop: &EventLoopWindowTarget, + event_loop: &ActiveEventLoop, window_attributes: WindowAttributes, ) -> Result { let mtm = event_loop.mtm; diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 4589eb4d67a..ff19c96d999 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -22,8 +22,7 @@ use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{EventLoopError, ExternalError, NotSupportedError, OsError as RootOsError}, event_loop::{ - AsyncRequestSerial, ControlFlow, DeviceEvents, EventLoopClosed, - EventLoopWindowTarget as RootELW, + ActiveEventLoop as RootELW, AsyncRequestSerial, ControlFlow, DeviceEvents, EventLoopClosed, }, icon::Icon, keyboard::Key, @@ -286,16 +285,16 @@ impl VideoModeHandle { impl Window { #[inline] pub(crate) fn new( - window_target: &EventLoopWindowTarget, + window_target: &ActiveEventLoop, attribs: WindowAttributes, ) -> Result { match *window_target { #[cfg(wayland_platform)] - EventLoopWindowTarget::Wayland(ref window_target) => { + ActiveEventLoop::Wayland(ref window_target) => { wayland::Window::new(window_target, attribs).map(Window::Wayland) } #[cfg(x11_platform)] - EventLoopWindowTarget::X(ref window_target) => { + ActiveEventLoop::X(ref window_target) => { x11::Window::new(window_target, attribs).map(Window::X) } } @@ -647,15 +646,13 @@ pub(crate) enum PlatformCustomCursor { impl PlatformCustomCursor { pub(crate) fn build( builder: PlatformCustomCursorBuilder, - p: &EventLoopWindowTarget, + p: &ActiveEventLoop, ) -> PlatformCustomCursor { match p { #[cfg(wayland_platform)] - EventLoopWindowTarget::Wayland(_) => { - Self::Wayland(wayland::CustomCursor::build(builder, p)) - } + ActiveEventLoop::Wayland(_) => Self::Wayland(wayland::CustomCursor::build(builder, p)), #[cfg(x11_platform)] - EventLoopWindowTarget::X(p) => Self::X(x11::CustomCursor::build(builder, p)), + ActiveEventLoop::X(p) => Self::X(x11::CustomCursor::build(builder, p)), } } } @@ -826,7 +823,7 @@ impl EventLoop { x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_events(timeout, callback)) } - pub fn window_target(&self) -> &crate::event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &crate::event_loop::ActiveEventLoop { x11_or_wayland!(match self; EventLoop(evlp) => evlp.window_target()) } } @@ -849,19 +846,19 @@ impl EventLoopProxy { } } -pub enum EventLoopWindowTarget { +pub enum ActiveEventLoop { #[cfg(wayland_platform)] - Wayland(wayland::EventLoopWindowTarget), + Wayland(wayland::ActiveEventLoop), #[cfg(x11_platform)] - X(x11::EventLoopWindowTarget), + X(x11::ActiveEventLoop), } -impl EventLoopWindowTarget { +impl ActiveEventLoop { #[inline] pub fn is_wayland(&self) -> bool { match *self { #[cfg(wayland_platform)] - EventLoopWindowTarget::Wayland(_) => true, + ActiveEventLoop::Wayland(_) => true, #[cfg(x11_platform)] _ => false, } @@ -871,12 +868,12 @@ impl EventLoopWindowTarget { pub fn available_monitors(&self) -> VecDeque { match *self { #[cfg(wayland_platform)] - EventLoopWindowTarget::Wayland(ref evlp) => evlp + ActiveEventLoop::Wayland(ref evlp) => evlp .available_monitors() .map(MonitorHandle::Wayland) .collect(), #[cfg(x11_platform)] - EventLoopWindowTarget::X(ref evlp) => { + ActiveEventLoop::X(ref evlp) => { evlp.available_monitors().map(MonitorHandle::X).collect() } } @@ -885,7 +882,7 @@ impl EventLoopWindowTarget { #[inline] pub fn primary_monitor(&self) -> Option { Some( - x11_or_wayland!(match self; EventLoopWindowTarget(evlp) => evlp.primary_monitor()?; as MonitorHandle), + x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.primary_monitor()?; as MonitorHandle), ) } diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index bbf61a2695b..f95e3d16c1d 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -19,12 +19,10 @@ use sctk::reexports::client::{Connection, QueueHandle}; use crate::dpi::LogicalSize; use crate::error::{EventLoopError, OsError as RootOsError}; use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent}; -use crate::event_loop::{ - ControlFlow, DeviceEvents, EventLoopWindowTarget as RootEventLoopWindowTarget, -}; +use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents}; use crate::platform::pump_events::PumpStatus; use crate::platform_impl::platform::min_timeout; -use crate::platform_impl::{EventLoopWindowTarget as PlatformEventLoopWindowTarget, OsError}; +use crate::platform_impl::{ActiveEventLoop as PlatformActiveEventLoop, OsError}; mod proxy; pub mod sink; @@ -63,7 +61,7 @@ pub struct EventLoop { connection: Connection, /// Event loop window target. - window_target: RootEventLoopWindowTarget, + window_target: RootActiveEventLoop, // XXX drop after everything else, just to be safe. /// Calloop's event loop. @@ -159,7 +157,7 @@ impl EventLoop { .map_err(|error| error.error); map_err!(result, WaylandError::Calloop)?; - let window_target = EventLoopWindowTarget { + let window_target = ActiveEventLoop { connection: connection.clone(), wayland_dispatcher: wayland_dispatcher.clone(), event_loop_awakener, @@ -179,8 +177,8 @@ impl EventLoop { user_events_sender, pending_user_events, event_loop, - window_target: RootEventLoopWindowTarget { - p: PlatformEventLoopWindowTarget::Wayland(window_target), + window_target: RootActiveEventLoop { + p: PlatformActiveEventLoop::Wayland(window_target), _marker: PhantomData, }, }; @@ -190,7 +188,7 @@ impl EventLoop { pub fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &RootActiveEventLoop), { let exit = loop { match self.pump_events(None, &mut event_handler) { @@ -217,7 +215,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &RootActiveEventLoop), { if !self.loop_running { self.loop_running = true; @@ -244,7 +242,7 @@ impl EventLoop { pub fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &RootActiveEventLoop), { let cause = loop { let start = Instant::now(); @@ -320,7 +318,7 @@ impl EventLoop { fn single_iteration(&mut self, callback: &mut F, cause: StartCause) where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &RootActiveEventLoop), { // NOTE currently just indented to simplify the diff @@ -525,13 +523,13 @@ impl EventLoop { } #[inline] - pub fn window_target(&self) -> &RootEventLoopWindowTarget { + pub fn window_target(&self) -> &RootActiveEventLoop { &self.window_target } fn with_state<'a, U: 'a, F: FnOnce(&'a mut WinitState) -> U>(&'a mut self, callback: F) -> U { let state = match &mut self.window_target.p { - PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), + PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(), #[cfg(x11_platform)] _ => unreachable!(), }; @@ -541,7 +539,7 @@ impl EventLoop { fn loop_dispatch>>(&mut self, timeout: D) -> IOResult<()> { let state = match &mut self.window_target.p { - PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), + PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(), #[cfg(feature = "x11")] _ => unreachable!(), }; @@ -554,7 +552,7 @@ impl EventLoop { fn roundtrip(&mut self) -> Result { let state = match &mut self.window_target.p { - PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), + PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(), #[cfg(feature = "x11")] _ => unreachable!(), }; @@ -597,7 +595,7 @@ impl AsRawFd for EventLoop { } } -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { /// The event loop wakeup source. pub event_loop_awakener: calloop::ping::Ping, @@ -621,7 +619,7 @@ pub struct EventLoopWindowTarget { pub connection: Connection, } -impl EventLoopWindowTarget { +impl ActiveEventLoop { pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { self.control_flow.set(control_flow) } diff --git a/src/platform_impl/linux/wayland/mod.rs b/src/platform_impl/linux/wayland/mod.rs index 2c0d6b5d3dd..3e5939f6dba 100644 --- a/src/platform_impl/linux/wayland/mod.rs +++ b/src/platform_impl/linux/wayland/mod.rs @@ -12,7 +12,7 @@ use sctk::reexports::client::{self, ConnectError, DispatchError, Proxy}; pub(super) use crate::cursor::OnlyCursorImage as CustomCursor; use crate::dpi::{LogicalSize, PhysicalSize}; pub use crate::platform_impl::platform::{OsError, WindowId}; -pub use event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}; +pub use event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy}; pub use output::{MonitorHandle, VideoModeHandle}; pub use window::Window; diff --git a/src/platform_impl/linux/wayland/output.rs b/src/platform_impl/linux/wayland/output.rs index d8a9303a332..666c1b38a3e 100644 --- a/src/platform_impl/linux/wayland/output.rs +++ b/src/platform_impl/linux/wayland/output.rs @@ -6,9 +6,9 @@ use sctk::output::OutputData; use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; use crate::platform_impl::platform::VideoModeHandle as PlatformVideoModeHandle; -use super::event_loop::EventLoopWindowTarget; +use super::event_loop::ActiveEventLoop; -impl EventLoopWindowTarget { +impl ActiveEventLoop { #[inline] pub fn available_monitors(&self) -> impl Iterator { self.state diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index c6578b6fb3c..ed585acedac 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -33,7 +33,7 @@ use super::event_loop::sink::EventSink; use super::output::MonitorHandle; use super::state::WinitState; use super::types::xdg_activation::XdgActivationTokenData; -use super::{EventLoopWindowTarget, WaylandError, WindowId}; +use super::{ActiveEventLoop, WaylandError, WindowId}; pub(crate) mod state; @@ -81,7 +81,7 @@ pub struct Window { impl Window { pub(crate) fn new( - event_loop_window_target: &EventLoopWindowTarget, + event_loop_window_target: &ActiveEventLoop, attributes: WindowAttributes, ) -> Result { let queue_handle = event_loop_window_target.queue_handle.clone(); diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 67dc65907d1..e0fc1fcd4f4 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -24,7 +24,7 @@ use super::{ use crate::{ dpi::{PhysicalPosition, PhysicalSize}, event::{DeviceEvent, ElementState, Event, Ime, RawKeyEvent, TouchPhase, WindowEvent}, - event_loop::EventLoopWindowTarget as RootELW, + event_loop::ActiveEventLoop as RootELW, keyboard::ModifiersState, platform_impl::platform::common::{keymap, xkb_state::KbdState}, }; @@ -1401,7 +1401,7 @@ impl EventProcessor { } fn handle_pressed_keys( - wt: &super::EventLoopWindowTarget, + wt: &super::ActiveEventLoop, window_id: crate::window::WindowId, state: ElementState, kb_state: &mut KbdState, diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 9a0ac9bd422..2b77d39079a 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -71,7 +71,7 @@ use super::{common::xkb_state::KbdState, ControlFlow, OsError}; use crate::{ error::{EventLoopError, OsError as RootOsError}, event::{Event, StartCause, WindowEvent}, - event_loop::{DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, + event_loop::{ActiveEventLoop as RootELW, DeviceEvents, EventLoopClosed}, platform::pump_events::PumpStatus, platform_impl::platform::{min_timeout, WindowId}, window::WindowAttributes, @@ -142,7 +142,7 @@ impl PeekableReceiver { } } -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { xconn: Arc, wm_delete_window: xproto::Atom, net_wm_ping: xproto::Atom, @@ -300,7 +300,7 @@ impl EventLoop { let kb_state = KbdState::from_x11_xkb(xconn.xcb_connection().get_raw_xcb_connection()).unwrap(); - let window_target = EventLoopWindowTarget { + let window_target = ActiveEventLoop { ime, root, control_flow: Cell::new(ControlFlow::default()), @@ -325,7 +325,7 @@ impl EventLoop { window_target.update_listen_device_events(true); let target = Rc::new(RootELW { - p: super::EventLoopWindowTarget::X(window_target), + p: super::ActiveEventLoop::X(window_target), _marker: PhantomData, }); @@ -667,15 +667,15 @@ impl AsRawFd for EventLoop { } } -pub(crate) fn get_xtarget(target: &RootELW) -> &EventLoopWindowTarget { +pub(crate) fn get_xtarget(target: &RootELW) -> &ActiveEventLoop { match target.p { - super::EventLoopWindowTarget::X(ref target) => target, + super::ActiveEventLoop::X(ref target) => target, #[cfg(wayland_platform)] _ => unreachable!(), } } -impl EventLoopWindowTarget { +impl ActiveEventLoop { /// Returns the `XConnection` of this events loop. #[inline] pub(crate) fn x_connection(&self) -> &Arc { @@ -835,7 +835,7 @@ impl Deref for Window { impl Window { pub(crate) fn new( - event_loop: &EventLoopWindowTarget, + event_loop: &ActiveEventLoop, attribs: WindowAttributes, ) -> Result { let window = Arc::new(UnownedWindow::new(event_loop, attribs)?); diff --git a/src/platform_impl/linux/x11/util/cursor.rs b/src/platform_impl/linux/x11/util/cursor.rs index 027d2364209..f85f6a7321e 100644 --- a/src/platform_impl/linux/x11/util/cursor.rs +++ b/src/platform_impl/linux/x11/util/cursor.rs @@ -9,7 +9,7 @@ use x11rb::connection::Connection; use crate::{platform_impl::PlatformCustomCursorBuilder, window::CursorIcon}; -use super::super::EventLoopWindowTarget; +use super::super::ActiveEventLoop; use super::*; impl XConnection { @@ -124,10 +124,7 @@ impl PartialEq for CustomCursor { impl Eq for CustomCursor {} impl CustomCursor { - pub(crate) fn build( - builder: PlatformCustomCursorBuilder, - p: &EventLoopWindowTarget, - ) -> CustomCursor { + pub(crate) fn build(builder: PlatformCustomCursorBuilder, p: &ActiveEventLoop) -> CustomCursor { unsafe { let ximage = (p.xconn.xcursor.XcursorImageCreate)( builder.0.width as i32, diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index ba417e3910e..d7001e98108 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -44,8 +44,7 @@ use crate::{ use super::{ ffi, util::{self, SelectedCursor}, - CookieResultExt, EventLoopWindowTarget, ImeRequest, ImeSender, VoidCookie, WindowId, - XConnection, + ActiveEventLoop, CookieResultExt, ImeRequest, ImeSender, VoidCookie, WindowId, XConnection, }; #[derive(Debug)] @@ -153,7 +152,7 @@ macro_rules! leap { impl UnownedWindow { #[allow(clippy::unnecessary_cast)] pub(crate) fn new( - event_loop: &EventLoopWindowTarget, + event_loop: &ActiveEventLoop, window_attrs: WindowAttributes, ) -> Result { let xconn = &event_loop.xconn; diff --git a/src/platform_impl/macos/app_delegate.rs b/src/platform_impl/macos/app_delegate.rs index ee3ac878d37..d01263d03b7 100644 --- a/src/platform_impl/macos/app_delegate.rs +++ b/src/platform_impl/macos/app_delegate.rs @@ -17,7 +17,7 @@ use super::window::WinitWindow; use super::{menu, WindowId, DEVICE_ID}; use crate::dpi::PhysicalSize; use crate::event::{DeviceEvent, Event, InnerSizeWriter, StartCause, WindowEvent}; -use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget}; +use crate::event_loop::{ActiveEventLoop as RootWindowTarget, ControlFlow}; use crate::window::WindowId as RootWindowId; #[derive(Debug, Default)] diff --git a/src/platform_impl/macos/cursor.rs b/src/platform_impl/macos/cursor.rs index 6ce9383a6a5..3d26da1d19c 100644 --- a/src/platform_impl/macos/cursor.rs +++ b/src/platform_impl/macos/cursor.rs @@ -10,7 +10,7 @@ use once_cell::sync::Lazy; use std::ffi::c_uchar; use std::slice; -use super::EventLoopWindowTarget; +use super::ActiveEventLoop; use crate::cursor::CursorImage; use crate::cursor::OnlyCursorImageBuilder; use crate::window::CursorIcon; @@ -24,7 +24,7 @@ unsafe impl Send for CustomCursor {} unsafe impl Sync for CustomCursor {} impl CustomCursor { - pub(crate) fn build(cursor: OnlyCursorImageBuilder, _: &EventLoopWindowTarget) -> CustomCursor { + pub(crate) fn build(cursor: OnlyCursorImageBuilder, _: &ActiveEventLoop) -> CustomCursor { Self(cursor_from_image(&cursor.0)) } } diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 32cc1990874..08aca4a502b 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -38,9 +38,7 @@ use super::{ use crate::{ error::EventLoopError, event::Event, - event_loop::{ - ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget, - }, + event_loop::{ActiveEventLoop as RootWindowTarget, ControlFlow, DeviceEvents, EventLoopClosed}, platform::{macos::ActivationPolicy, pump_events::PumpStatus}, }; @@ -73,12 +71,12 @@ impl PanicInfo { } #[derive(Debug)] -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { delegate: Id, pub(super) mtm: MainThreadMarker, } -impl EventLoopWindowTarget { +impl ActiveEventLoop { #[inline] pub fn available_monitors(&self) -> VecDeque { monitor::available_monitors() @@ -134,7 +132,7 @@ impl EventLoopWindowTarget { } } -impl EventLoopWindowTarget { +impl ActiveEventLoop { pub(crate) fn hide_application(&self) { NSApplication::sharedApplication(self.mtm).hide(None) } @@ -252,7 +250,7 @@ impl EventLoop { sender, receiver: Rc::new(receiver), window_target: Rc::new(RootWindowTarget { - p: EventLoopWindowTarget { delegate, mtm }, + p: ActiveEventLoop { delegate, mtm }, _marker: PhantomData, }), panic_info, diff --git a/src/platform_impl/macos/mod.rs b/src/platform_impl/macos/mod.rs index 39505074618..fef8060cda6 100644 --- a/src/platform_impl/macos/mod.rs +++ b/src/platform_impl/macos/mod.rs @@ -19,7 +19,7 @@ use std::fmt; pub(crate) use self::{ event::{physicalkey_to_scancode, scancode_to_physicalkey, KeyEventExtra}, event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }, monitor::{MonitorHandle, VideoModeHandle}, diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index c269fd7245a..a70deacd51a 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -5,7 +5,7 @@ use icrate::Foundation::{MainThreadBound, MainThreadMarker, NSObject}; use objc2::rc::{autoreleasepool, Id}; use objc2::{declare_class, mutability, ClassType, DeclaredClass}; -use super::event_loop::EventLoopWindowTarget; +use super::event_loop::ActiveEventLoop; use super::window_delegate::WindowDelegate; use crate::error::OsError as RootOsError; use crate::window::WindowAttributes; @@ -25,7 +25,7 @@ impl Drop for Window { impl Window { pub(crate) fn new( - window_target: &EventLoopWindowTarget, + window_target: &ActiveEventLoop, attributes: WindowAttributes, ) -> Result { let mtm = window_target.mtm; diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index aa7acb2a6f8..f2cac6c1a88 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -274,7 +274,7 @@ impl EventState { pub struct EventLoop { windows: Vec<(Arc, EventState)>, - window_target: event_loop::EventLoopWindowTarget, + window_target: event_loop::ActiveEventLoop, user_events_sender: mpsc::Sender, user_events_receiver: mpsc::Receiver, } @@ -306,8 +306,8 @@ impl EventLoop { Ok(Self { windows: Vec::new(), - window_target: event_loop::EventLoopWindowTarget { - p: EventLoopWindowTarget { + window_target: event_loop::ActiveEventLoop { + p: ActiveEventLoop { control_flow: Cell::new(ControlFlow::default()), exit: Cell::new(false), creates: Mutex::new(VecDeque::new()), @@ -466,10 +466,10 @@ impl EventLoop { pub fn run(mut self, mut event_handler_inner: F) -> Result<(), EventLoopError> where - F: FnMut(event::Event, &event_loop::EventLoopWindowTarget), + F: FnMut(event::Event, &event_loop::ActiveEventLoop), { let mut event_handler = - move |event: event::Event, window_target: &event_loop::EventLoopWindowTarget| { + move |event: event::Event, window_target: &event_loop::ActiveEventLoop| { event_handler_inner(event, window_target); }; @@ -676,7 +676,7 @@ impl EventLoop { Ok(()) } - pub fn window_target(&self) -> &event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &event_loop::ActiveEventLoop { &self.window_target } @@ -716,7 +716,7 @@ impl Clone for EventLoopProxy { impl Unpin for EventLoopProxy {} -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { control_flow: Cell, exit: Cell, pub(super) creates: Mutex>>, @@ -726,7 +726,7 @@ pub struct EventLoopWindowTarget { pub(super) wake_socket: Arc, } -impl EventLoopWindowTarget { +impl ActiveEventLoop { pub fn primary_monitor(&self) -> Option { Some(MonitorHandle) } diff --git a/src/platform_impl/orbital/mod.rs b/src/platform_impl/orbital/mod.rs index 4d54499871a..f9e26c53592 100644 --- a/src/platform_impl/orbital/mod.rs +++ b/src/platform_impl/orbital/mod.rs @@ -6,9 +6,7 @@ use std::sync::Arc; use crate::dpi::{PhysicalPosition, PhysicalSize}; -pub(crate) use self::event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, -}; +pub(crate) use self::event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle}; mod event_loop; pub use self::window::Window; diff --git a/src/platform_impl/orbital/window.rs b/src/platform_impl/orbital/window.rs index a019a8e6ede..6f85e2013a0 100644 --- a/src/platform_impl/orbital/window.rs +++ b/src/platform_impl/orbital/window.rs @@ -12,9 +12,7 @@ use crate::{ window::ImePurpose, }; -use super::{ - EventLoopWindowTarget, MonitorHandle, RedoxSocket, TimeSocket, WindowId, WindowProperties, -}; +use super::{ActiveEventLoop, MonitorHandle, RedoxSocket, TimeSocket, WindowId, WindowProperties}; // These values match the values uses in the `window_new` function in orbital: // https://gitlab.redox-os.org/redox-os/orbital/-/blob/master/src/scheme.rs @@ -34,7 +32,7 @@ pub struct Window { impl Window { pub(crate) fn new( - el: &EventLoopWindowTarget, + el: &ActiveEventLoop, attrs: window::WindowAttributes, ) -> Result { let scale = MonitorHandle.scale_factor(); diff --git a/src/platform_impl/web/cursor.rs b/src/platform_impl/web/cursor.rs index 1ff90ff2279..79c1d61b202 100644 --- a/src/platform_impl/web/cursor.rs +++ b/src/platform_impl/web/cursor.rs @@ -22,7 +22,7 @@ use web_sys::{ use super::backend::Style; use super::main_thread::{MainThreadMarker, MainThreadSafe}; use super::r#async::{AbortHandle, Abortable, DropAbortHandle, Notified, Notifier}; -use super::EventLoopWindowTarget; +use super::ActiveEventLoop; use crate::cursor::{BadImage, Cursor, CursorImage, CustomCursor as RootCustomCursor}; use crate::platform::web::CustomCursorError; @@ -75,10 +75,7 @@ impl PartialEq for CustomCursor { impl Eq for CustomCursor {} impl CustomCursor { - pub(crate) fn build( - builder: CustomCursorBuilder, - window_target: &EventLoopWindowTarget, - ) -> Self { + pub(crate) fn build(builder: CustomCursorBuilder, window_target: &ActiveEventLoop) -> Self { match builder { CustomCursorBuilder::Image(image) => Self::build_spawn( window_target, @@ -110,11 +107,7 @@ impl CustomCursor { } } - fn build_spawn( - window_target: &EventLoopWindowTarget, - task: F, - animation: bool, - ) -> CustomCursor + fn build_spawn(window_target: &ActiveEventLoop, task: F, animation: bool) -> CustomCursor where F: 'static + Future>, S: Into, @@ -172,7 +165,7 @@ impl CustomCursor { pub(crate) fn build_async( builder: CustomCursorBuilder, - window_target: &EventLoopWindowTarget, + window_target: &ActiveEventLoop, ) -> CustomCursorFuture { let CustomCursor { animation, state } = Self::build(builder, window_target); let binding = state.get(window_target.runner.main_thread()).borrow(); diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 2cc9d27d520..84cd1715599 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -3,7 +3,7 @@ use std::sync::mpsc::{self, Receiver, Sender}; use crate::error::EventLoopError; use crate::event::Event; -use crate::event_loop::EventLoopWindowTarget as RootEventLoopWindowTarget; +use crate::event_loop::ActiveEventLoop as RootActiveEventLoop; use super::{backend, device, window}; @@ -13,10 +13,10 @@ mod state; mod window_target; pub(crate) use proxy::EventLoopProxy; -pub(crate) use window_target::{EventLoopWindowTarget, OwnedDisplayHandle}; +pub(crate) use window_target::{ActiveEventLoop, OwnedDisplayHandle}; pub struct EventLoop { - elw: RootEventLoopWindowTarget, + elw: RootActiveEventLoop, user_event_sender: Sender, user_event_receiver: Receiver, } @@ -27,8 +27,8 @@ pub(crate) struct PlatformSpecificEventLoopAttributes {} impl EventLoop { pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result { let (user_event_sender, user_event_receiver) = mpsc::channel(); - let elw = RootEventLoopWindowTarget { - p: EventLoopWindowTarget::new(), + let elw = RootActiveEventLoop { + p: ActiveEventLoop::new(), _marker: PhantomData, }; Ok(EventLoop { @@ -40,9 +40,9 @@ impl EventLoop { pub fn run(self, mut event_handler: F) -> ! where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &RootActiveEventLoop), { - let target = RootEventLoopWindowTarget { + let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData, }; @@ -77,9 +77,9 @@ impl EventLoop { pub fn spawn(self, mut event_handler: F) where - F: 'static + FnMut(Event, &RootEventLoopWindowTarget), + F: 'static + FnMut(Event, &RootActiveEventLoop), { - let target = RootEventLoopWindowTarget { + let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData, }; @@ -105,7 +105,7 @@ impl EventLoop { EventLoopProxy::new(self.elw.p.waker(), self.user_event_sender.clone()) } - pub fn window_target(&self) -> &RootEventLoopWindowTarget { + pub fn window_target(&self) -> &RootActiveEventLoop { &self.elw } } diff --git a/src/platform_impl/web/event_loop/runner.rs b/src/platform_impl/web/event_loop/runner.rs index f7932ff76e2..a1ca8d421d5 100644 --- a/src/platform_impl/web/event_loop/runner.rs +++ b/src/platform_impl/web/event_loop/runner.rs @@ -215,7 +215,7 @@ impl Shared { // Set the event callback to use for the event loop runner // This the event callback is a fairly thin layer over the user-provided callback that closes - // over a RootEventLoopWindowTarget reference + // over a RootActiveEventLoop reference pub fn set_listener(&self, event_handler: Box) { { let mut runner = self.0.runner.borrow_mut(); @@ -736,7 +736,7 @@ impl Shared { // * `self`, i.e. the item which triggered this event loop wakeup, which // is usually a `wasm-bindgen` `Closure`, which will be dropped after // returning to the JS glue code. - // * The `EventLoopWindowTarget` leaked inside `EventLoop::run` due to the + // * The `ActiveEventLoop` leaked inside `EventLoop::run` due to the // JS exception thrown at the end. // * For each undropped `Window`: // * The `register_redraw_request` closure. diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index 3b290dd3c18..f5833278a13 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -43,12 +43,12 @@ impl Clone for ModifiersShared { } #[derive(Clone)] -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { pub(crate) runner: runner::Shared, modifiers: ModifiersShared, } -impl EventLoopWindowTarget { +impl ActiveEventLoop { pub fn new() -> Self { Self { runner: runner::Shared::new(), diff --git a/src/platform_impl/web/mod.rs b/src/platform_impl/web/mod.rs index a70dacd0486..860f950f0a3 100644 --- a/src/platform_impl/web/mod.rs +++ b/src/platform_impl/web/mod.rs @@ -12,7 +12,7 @@ // for winit's cross-platform structures. They are all relatively simple translations. // // The event_loop module handles listening for and processing events. 'Proxy' implements -// EventLoopProxy and 'WindowTarget' implements EventLoopWindowTarget. WindowTarget also handles +// EventLoopProxy and 'WindowTarget' implements ActiveEventLoop. WindowTarget also handles // registering the event handlers. The 'Execution' struct in the 'runner' module handles taking // incoming events (from the registered handlers) and ensuring they are passed to the user in a // compliant way. @@ -33,7 +33,7 @@ mod backend; pub use self::device::DeviceId; pub use self::error::OsError; pub(crate) use self::event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }; pub use self::monitor::{MonitorHandle, VideoModeHandle}; diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index 7f4239360c8..328565528d9 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -8,7 +8,7 @@ use crate::window::{ use super::main_thread::{MainThreadMarker, MainThreadSafe}; use super::r#async::Dispatcher; -use super::{backend, monitor::MonitorHandle, EventLoopWindowTarget, Fullscreen}; +use super::{backend, monitor::MonitorHandle, ActiveEventLoop, Fullscreen}; use web_sys::HtmlCanvasElement; use std::cell::RefCell; @@ -29,7 +29,7 @@ pub struct Inner { impl Window { pub(crate) fn new( - target: &EventLoopWindowTarget, + target: &ActiveEventLoop, mut attr: WindowAttributes, ) -> Result { let id = target.generate_id(); diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 21ca4c0325a..f09972bf707 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -74,7 +74,7 @@ use crate::{ DeviceEvent, Event, Force, Ime, InnerSizeWriter, RawKeyEvent, Touch, TouchPhase, WindowEvent, }, - event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, + event_loop::{ActiveEventLoop as RootELW, ControlFlow, DeviceEvents, EventLoopClosed}, keyboard::ModifiersState, platform::pump_events::PumpStatus, platform_impl::platform::{ @@ -176,7 +176,7 @@ impl Default for PlatformSpecificEventLoopAttributes { } } -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { thread_id: u32, thread_msg_target: HWND, pub(crate) runner_shared: EventLoopRunnerShared, @@ -216,7 +216,7 @@ impl EventLoop { user_event_sender, user_event_receiver, window_target: RootELW { - p: EventLoopWindowTarget { + p: ActiveEventLoop { thread_id, thread_msg_target, runner_shared, @@ -522,7 +522,7 @@ impl EventLoop { } } -impl EventLoopWindowTarget { +impl ActiveEventLoop { #[inline(always)] pub(crate) fn create_thread_executor(&self) -> EventLoopThreadExecutor { EventLoopThreadExecutor { diff --git a/src/platform_impl/windows/icon.rs b/src/platform_impl/windows/icon.rs index 9d0329ffca6..de8bd4910fb 100644 --- a/src/platform_impl/windows/icon.rs +++ b/src/platform_impl/windows/icon.rs @@ -22,7 +22,7 @@ use crate::{ dpi::PhysicalSize, }; -use super::{util, EventLoopWindowTarget}; +use super::{util, ActiveEventLoop}; impl Pixel { fn convert_to_bgra(&mut self) { @@ -237,7 +237,7 @@ impl WinCursor { } } - pub(crate) fn build(cursor: OnlyCursorImageBuilder, _: &EventLoopWindowTarget) -> Self { + pub(crate) fn build(cursor: OnlyCursorImageBuilder, _: &ActiveEventLoop) -> Self { match Self::new(&cursor.0) { Ok(cursor) => cursor, Err(err) => { diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 8f1f33512aa..04b612f7c9a 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -8,7 +8,7 @@ use windows_sys::Win32::{ pub(crate) use self::{ event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }, icon::{SelectedCursor, WinIcon}, diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 546128cc236..98637dc3f59 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -74,7 +74,7 @@ use crate::{ }, dpi::{dpi_to_scale_factor, enable_non_client_dpi_scaling, hwnd_dpi}, drop_handler::FileDropHandler, - event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID}, + event_loop::{self, ActiveEventLoop, DESTROY_MSG_ID}, icon::{self, IconType, WinCursor}, ime::ImeContext, keyboard::KeyEventBuilder, @@ -103,7 +103,7 @@ pub(crate) struct Window { impl Window { pub(crate) fn new( - event_loop: &EventLoopWindowTarget, + event_loop: &ActiveEventLoop, w_attr: WindowAttributes, ) -> Result { // We dispatch an `init` function because of code style. @@ -1141,7 +1141,7 @@ impl Drop for Window { pub(super) struct InitData<'a> { // inputs - pub event_loop: &'a EventLoopWindowTarget, + pub event_loop: &'a ActiveEventLoop, pub attributes: WindowAttributes, pub window_flags: WindowFlags, // outputs @@ -1339,7 +1339,7 @@ impl<'a> InitData<'a> { } unsafe fn init( attributes: WindowAttributes, - event_loop: &EventLoopWindowTarget, + event_loop: &ActiveEventLoop, ) -> Result { let title = util::encode_wide(&attributes.title); diff --git a/src/window.rs b/src/window.rs index 12747113fd0..1dca3289b7a 100644 --- a/src/window.rs +++ b/src/window.rs @@ -4,7 +4,7 @@ use std::fmt; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError}, - event_loop::EventLoopWindowTarget, + event_loop::ActiveEventLoop, monitor::{MonitorHandle, VideoModeHandle}, platform_impl::{self, PlatformSpecificWindowBuilderAttributes}, }; @@ -42,14 +42,21 @@ use serde::{Deserialize, Serialize}; /// /// let mut event_loop = EventLoop::new().unwrap(); /// event_loop.set_control_flow(ControlFlow::Wait); -/// let window = Window::new(&event_loop).unwrap(); +/// let mut windows = Vec::new(); /// -/// event_loop.run(move |event, elwt| { +/// event_loop.run(move |event, event_loop| { /// match event { +/// Event::Resumed => { +/// let window = Window::new(&event_loop).unwrap(); +/// windows.push(window); +/// } /// Event::WindowEvent { /// event: WindowEvent::CloseRequested, /// .. -/// } => elwt.exit(), +/// } => { +/// windows.clear(); +/// event_loop.exit(); +/// } /// _ => (), /// } /// }); @@ -543,7 +550,7 @@ impl WindowBuilder { /// - **Web:** The window is created but not inserted into the web page automatically. Please /// see the web platform module for more information. #[inline] - pub fn build(self, window_target: &EventLoopWindowTarget) -> Result { + pub fn build(self, window_target: &ActiveEventLoop) -> Result { let window = platform_impl::Window::new(&window_target.p, self.window)?; window.maybe_queue_on_main(|w| w.request_redraw()); Ok(Window { window }) @@ -566,7 +573,7 @@ impl Window { /// /// [`Window::builder().build(event_loop)`]: WindowBuilder::build #[inline] - pub fn new(event_loop: &EventLoopWindowTarget) -> Result { + pub fn new(event_loop: &ActiveEventLoop) -> Result { Window::builder().build(event_loop) } @@ -652,11 +659,9 @@ impl Window { /// APIs and software rendering. /// /// ```no_run - /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new().unwrap(); - /// # let window = Window::new(&event_loop).unwrap(); /// # fn swap_buffers() {} + /// # fn scope(window: &Window) { /// // Do the actual drawing with OpenGL. /// /// // Notify winit that we're about to submit buffer to the windowing system. @@ -664,6 +669,7 @@ impl Window { /// /// // Sumbit buffer to the windowing system. /// swap_buffers(); + /// # } /// ``` /// /// ## Platform-specific @@ -742,15 +748,14 @@ impl Window { /// /// ```no_run /// # use winit::dpi::{LogicalPosition, PhysicalPosition}; - /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new().unwrap(); - /// # let window = Window::new(&event_loop).unwrap(); + /// # fn scope(window: &Window) { /// // Specify the position in logical dimensions like this: /// window.set_outer_position(LogicalPosition::new(400.0, 200.0)); /// /// // Or specify the position in physical dimensions like this: /// window.set_outer_position(PhysicalPosition::new(400, 200)); + /// # } /// ``` /// /// ## Platform-specific @@ -804,15 +809,14 @@ impl Window { /// /// ```no_run /// # use winit::dpi::{LogicalSize, PhysicalSize}; - /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new().unwrap(); - /// # let window = Window::new(&event_loop).unwrap(); + /// # fn scope(window: &Window) { /// // Specify the size in logical dimensions like this: /// let _ = window.request_inner_size(LogicalSize::new(400.0, 200.0)); /// /// // Or specify the size in physical dimensions like this: /// let _ = window.request_inner_size(PhysicalSize::new(400, 200)); + /// # } /// ``` /// /// ## Platform-specific @@ -849,15 +853,14 @@ impl Window { /// /// ```no_run /// # use winit::dpi::{LogicalSize, PhysicalSize}; - /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new().unwrap(); - /// # let window = Window::new(&event_loop).unwrap(); + /// # fn scope(window: &Window) { /// // Specify the size in logical dimensions like this: /// window.set_min_inner_size(Some(LogicalSize::new(400.0, 200.0))); /// /// // Or specify the size in physical dimensions like this: /// window.set_min_inner_size(Some(PhysicalSize::new(400, 200))); + /// # } /// ``` /// /// ## Platform-specific @@ -874,15 +877,14 @@ impl Window { /// /// ```no_run /// # use winit::dpi::{LogicalSize, PhysicalSize}; - /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new().unwrap(); - /// # let window = Window::new(&event_loop).unwrap(); + /// # fn scope(window: &Window) { /// // Specify the size in logical dimensions like this: /// window.set_max_inner_size(Some(LogicalSize::new(400.0, 200.0))); /// /// // Or specify the size in physical dimensions like this: /// window.set_max_inner_size(Some(PhysicalSize::new(400, 200))); + /// # } /// ``` /// /// ## Platform-specific @@ -1214,15 +1216,14 @@ impl Window { /// /// ```no_run /// # use winit::dpi::{LogicalPosition, PhysicalPosition, LogicalSize, PhysicalSize}; - /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new().unwrap(); - /// # let window = Window::new(&event_loop).unwrap(); + /// # fn scope(window: &Window) { /// // Specify the position in logical dimensions like this: /// window.set_ime_cursor_area(LogicalPosition::new(400.0, 200.0), LogicalSize::new(100, 100)); /// /// // Or specify the position in physical dimensions like this: /// window.set_ime_cursor_area(PhysicalPosition::new(400, 200), PhysicalSize::new(100, 100)); + /// # } /// ``` /// /// ## Platform-specific @@ -1398,15 +1399,14 @@ impl Window { /// /// ```no_run /// # use winit::dpi::{LogicalPosition, PhysicalPosition}; - /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new().unwrap(); - /// # let window = Window::new(&event_loop).unwrap(); + /// # fn scope(window: &Window) { /// // Specify the position in logical dimensions like this: /// window.set_cursor_position(LogicalPosition::new(400.0, 200.0)); /// /// // Or specify the position in physical dimensions like this: /// window.set_cursor_position(PhysicalPosition::new(400, 200)); + /// # } /// ``` /// /// ## Platform-specific @@ -1426,13 +1426,12 @@ impl Window { /// First try confining the cursor, and if that fails, try locking it instead. /// /// ```no_run - /// # use winit::event_loop::EventLoop; /// # use winit::window::{CursorGrabMode, Window}; - /// # let mut event_loop = EventLoop::new().unwrap(); - /// # let window = Window::new(&event_loop).unwrap(); + /// # fn scope(window: &Window) { /// window.set_cursor_grab(CursorGrabMode::Confined) /// .or_else(|_e| window.set_cursor_grab(CursorGrabMode::Locked)) /// .unwrap(); + /// # } /// ``` #[inline] pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> { @@ -1531,9 +1530,9 @@ impl Window { /// Returns the list of all the monitors available on the system. /// - /// This is the same as [`EventLoopWindowTarget::available_monitors`], and is provided for convenience. + /// This is the same as [`ActiveEventLoop::available_monitors`], and is provided for convenience. /// - /// [`EventLoopWindowTarget::available_monitors`]: crate::event_loop::EventLoopWindowTarget::available_monitors + /// [`ActiveEventLoop::available_monitors`]: crate::event_loop::ActiveEventLoop::available_monitors #[inline] pub fn available_monitors(&self) -> impl Iterator { self.window.maybe_wait_on_main(|w| { @@ -1547,13 +1546,13 @@ impl Window { /// /// Returns `None` if it can't identify any monitor as a primary one. /// - /// This is the same as [`EventLoopWindowTarget::primary_monitor`], and is provided for convenience. + /// This is the same as [`ActiveEventLoop::primary_monitor`], and is provided for convenience. /// /// ## Platform-specific /// /// **Wayland / Web:** Always returns `None`. /// - /// [`EventLoopWindowTarget::primary_monitor`]: crate::event_loop::EventLoopWindowTarget::primary_monitor + /// [`ActiveEventLoop::primary_monitor`]: crate::event_loop::ActiveEventLoop::primary_monitor #[inline] pub fn primary_monitor(&self) -> Option { self.window