From 952f9a02925bd903473b3acf24c3f61d858b312a Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 31 Jan 2024 17:29:59 +0400 Subject: [PATCH] Deprecate window creation with stale event loop. Creating window when event loop is not running generally doesn't work, since a bunch of events and sync OS requests can't be processed. This is also an issue on e.g. Android, since window can't be created outside event loop easily. Thus deprecate the window creation when event loop is not running, as well as other resource creation to running event loop. Given that all the examples use the bad pattern of creating the window when event loop is not running and also most example existence is questionable, since they show single thing and the majority of their code is window/event loop initialization, they wore merged into a single example 'window.rs' example that showcases very simple application using winit. Fixes #3399. --- CHANGELOG.md | 7 +- examples/child_window.rs | 69 +- examples/control_flow.rs | 27 +- examples/cursor.rs | 88 -- examples/cursor_grab.rs | 73 -- examples/custom_cursors.rs | 143 --- examples/custom_events.rs | 60 - examples/{ => data}/icon.png | Bin examples/drag_window.rs | 105 -- examples/focus.rs | 56 - examples/fullscreen.rs | 163 --- examples/handling_close.rs | 86 -- examples/ime.rs | 94 -- examples/key_binding.rs | 62 - examples/monitor_list.rs | 58 - examples/mouse_wheel.rs | 65 -- examples/multithreaded.rs | 211 ---- examples/multiwindow.rs | 64 -- .../{window_pump_events.rs => pump_events.rs} | 37 +- examples/request_redraw.rs | 42 - examples/request_redraw_threaded.rs | 59 - examples/resizable.rs | 54 - .../{window_on_demand.rs => run_on_demand.rs} | 11 +- examples/startup_notification.rs | 115 -- examples/theme.rs | 68 -- examples/timer.rs | 54 - examples/touch_gestures.rs | 62 - examples/transparent.rs | 38 - examples/video_modes.rs | 22 - examples/web.rs | 147 --- examples/web_aspect_ratio.rs | 102 -- examples/window.rs | 1001 ++++++++++++++++- examples/window_buttons.rs | 68 -- examples/window_debug.rs | 137 --- examples/window_drag_resize.rs | 149 --- examples/window_icon.rs | 60 - examples/window_option_as_alt.rs | 72 -- examples/window_resize_increments.rs | 52 - examples/window_tabbing.rs | 107 -- examples/x11_embed.rs | 88 +- src/cursor.rs | 21 +- src/event_loop.rs | 94 +- src/lib.rs | 34 +- src/monitor.rs | 2 +- src/platform/android.rs | 16 +- src/platform/ios.rs | 21 +- src/platform/macos.rs | 41 +- src/platform/pump_events.rs | 71 +- src/platform/run_on_demand.rs | 12 +- src/platform/startup_notify.rs | 16 +- src/platform/wayland.rs | 20 +- src/platform/web.rs | 32 +- src/platform/windows.rs | 40 +- src/platform/x11.rs | 49 +- src/platform_impl/android/mod.rs | 22 +- src/platform_impl/ios/app_state.rs | 6 +- src/platform_impl/ios/event_loop.rs | 25 +- src/platform_impl/ios/mod.rs | 4 +- src/platform_impl/ios/window.rs | 8 +- src/platform_impl/linux/mod.rs | 45 +- .../linux/wayland/event_loop/mod.rs | 34 +- src/platform_impl/linux/wayland/mod.rs | 2 +- src/platform_impl/linux/wayland/output.rs | 4 +- src/platform_impl/linux/wayland/window/mod.rs | 4 +- .../linux/x11/event_processor.rs | 4 +- src/platform_impl/linux/x11/mod.rs | 16 +- src/platform_impl/linux/x11/util/cursor.rs | 7 +- src/platform_impl/linux/x11/window.rs | 5 +- src/platform_impl/macos/app_delegate.rs | 2 +- src/platform_impl/macos/cursor.rs | 4 +- src/platform_impl/macos/event_loop.rs | 12 +- src/platform_impl/macos/mod.rs | 4 +- src/platform_impl/macos/window.rs | 4 +- src/platform_impl/macos/window_delegate.rs | 8 +- src/platform_impl/orbital/event_loop.rs | 16 +- src/platform_impl/orbital/mod.rs | 6 +- src/platform_impl/orbital/window.rs | 6 +- src/platform_impl/web/cursor.rs | 15 +- src/platform_impl/web/event_loop/mod.rs | 20 +- src/platform_impl/web/event_loop/runner.rs | 4 +- .../web/event_loop/window_target.rs | 4 +- src/platform_impl/web/mod.rs | 6 +- src/platform_impl/web/window.rs | 10 +- src/platform_impl/windows/event_loop.rs | 8 +- src/platform_impl/windows/icon.rs | 4 +- src/platform_impl/windows/mod.rs | 10 +- src/platform_impl/windows/window.rs | 8 +- src/window.rs | 195 ++-- tests/send_objects.rs | 2 +- tests/sync_object.rs | 2 +- 90 files changed, 1540 insertions(+), 3441 deletions(-) delete mode 100644 examples/cursor.rs delete mode 100644 examples/cursor_grab.rs delete mode 100644 examples/custom_cursors.rs delete mode 100644 examples/custom_events.rs rename examples/{ => data}/icon.png (100%) delete mode 100644 examples/drag_window.rs delete mode 100644 examples/focus.rs delete mode 100644 examples/fullscreen.rs delete mode 100644 examples/handling_close.rs delete mode 100644 examples/ime.rs delete mode 100644 examples/key_binding.rs delete mode 100644 examples/monitor_list.rs delete mode 100644 examples/mouse_wheel.rs delete mode 100644 examples/multithreaded.rs delete mode 100644 examples/multiwindow.rs rename examples/{window_pump_events.rs => pump_events.rs} (64%) delete mode 100644 examples/request_redraw.rs delete mode 100644 examples/request_redraw_threaded.rs delete mode 100644 examples/resizable.rs rename examples/{window_on_demand.rs => run_on_demand.rs} (92%) delete mode 100644 examples/startup_notification.rs delete mode 100644 examples/theme.rs delete mode 100644 examples/timer.rs delete mode 100644 examples/touch_gestures.rs delete mode 100644 examples/transparent.rs delete mode 100644 examples/video_modes.rs delete mode 100644 examples/web.rs delete mode 100644 examples/web_aspect_ratio.rs delete mode 100644 examples/window_buttons.rs delete mode 100644 examples/window_debug.rs delete mode 100644 examples/window_drag_resize.rs delete mode 100644 examples/window_icon.rs delete mode 100644 examples/window_option_as_alt.rs delete mode 100644 examples/window_resize_increments.rs delete mode 100644 examples/window_tabbing.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index a9d8e4f6ef4..85e87c9193a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ Unreleased` header. # Unreleased +- **Breaking:** Deprecate `EventLoop::create_window`. +- **Breaking:** Move `Window::new` to `ActiveEventLoop::create_window` and `EventLoop::create_window` +- **Breaking:** Rename `EventLoopWindowTarget` to `ActiveEventLoop`. +- **Breaking:** Remove `Deref` implementation for `EventLoop` that gave `EventLoopWindowTarget`. +- **Breaking**: Remove `WindowBuilder` in favor of `WindowAttributes`. - 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. @@ -42,7 +47,7 @@ Unreleased` header. - Added `EventLoop::builder`, which is intended to replace the (now deprecated) `EventLoopBuilder::new`. - **Breaking:** Changed the signature of `EventLoop::with_user_event` to return a builder. - **Breaking:** Removed `EventLoopBuilder::with_user_event`, the functionality is now available in `EventLoop::with_user_event`. -- Add `Window::builder`, which is intended to replace the (now deprecated) `WindowBuilder::new`. +- Add `Window::attributes` to get default `WindowAttributes`. - On X11, reload dpi on `_XSETTINGS_SETTINGS` update. - On X11, fix deadlock when adjusting DPI and resizing at the same time. - On Wayland, fix `Focused(false)` being send when other seats still have window focused. diff --git a/examples/child_window.rs b/examples/child_window.rs index b9e28313c29..ced6afdd185 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,52 +6,53 @@ 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() + let mut window_attributes = Window::attributes() .with_title("child window") .with_inner_size(LogicalSize::new(200.0f32, 200.0f32)) .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) .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(); + window_attributes = unsafe { window_attributes.with_parent_window(Some(parent)) }; - let id = child_window.id(); - windows.insert(id, child_window); - println!("child window created with id: {id:?}"); + event_loop.create_window(window_attributes).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 attributes = Window::attributes() + .with_title("parent window") + .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) + .with_inner_size(LogicalSize::new(640.0f32, 480.0f32)); + let window = event_loop.create_window(attributes).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 +69,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 +81,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..bfd82b7238e 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 => { + let window_attributes = Window::attributes().with_title( + "Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.", + ); + window = Some(event_loop.create_window(window_attributes).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 64% rename from examples/window_pump_events.rs rename to examples/pump_events.rs index f6f30dab181..62d7cddf724 100644 --- a/examples/window_pump_events.rs +++ b/examples/pump_events.rs @@ -25,38 +25,39 @@ 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 => { + let window_attributes = Window::attributes().with_title("A fantastic window!"); + window = Some(event_loop.create_window(window_attributes).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 92% rename from examples/window_on_demand.rs rename to examples/run_on_demand.rs index 8406aed4b48..41be0f2bb5b 100644 --- a/examples/window_on_demand.rs +++ b/examples/run_on_demand.rs @@ -30,7 +30,7 @@ fn main() -> Result<(), impl std::error::Error> { fn run_app(event_loop: &mut EventLoop<()>, idx: usize) -> Result<(), EventLoopError> { let mut app = App::default(); - event_loop.run_on_demand(move |event, elwt| { + event_loop.run_on_demand(move |event, event_loop| { println!("Run {idx}: {:?}", event); if let Some(window) = &app.window { @@ -60,16 +60,15 @@ fn main() -> Result<(), impl std::error::Error> { } if id == window_id => { println!("--------------------------------------------------------- Window {idx} Destroyed"); app.window_id = None; - elwt.exit(); + event_loop.exit(); } _ => (), } } else if let Event::Resumed = event { - let window = Window::builder() + let window_attributes = Window::attributes() .with_title("Fantastic window number one!") - .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) - .build(elwt) - .unwrap(); + .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)); + let window = event_loop.create_window(window_attributes).unwrap(); app.window_id = Some(window.id()); app.window = Some(window); } 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..13bf71f2f4e 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, WindowAttributesExtMacOS, WindowExtMacOS}; +#[cfg(any(x11_platform, wayland_platform))] +use winit::platform::startup_notify::{ + self, EventLoopExtStartupNotify, WindowAttributesExtStartupNotify, 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_attributes = Window::attributes() + .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_attributes = window_attributes.with_activation_token(token); + } + + #[cfg(macos_platform)] + if let Some(tab_id) = _tab_id { + window_attributes = window_attributes.with_tabbing_identifier(&tab_id); + } + + let window = event_loop.create_window(window_attributes)?; + + #[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..a7088c29d4b 100644 --- a/examples/x11_embed.rs +++ b/examples/x11_embed.rs @@ -1,70 +1,62 @@ //! 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, - platform::x11::WindowBuilderExtX11, + platform::x11::WindowAttributesExtX11, 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 mut window = None; + event_loop.run(move |event, event_loop| match event { + Event::Resumed => { + let window_attributes = Window::attributes() + .with_title("An embedded window!") + .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) + .with_embed_parent_window(parent_window_id); - 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(); + window = Some(event_loop.create_window(window_attributes).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); } _ => (), } - })?; - - Ok(()) - } + } + Event::AboutToWait => { + window.as_ref().unwrap().request_redraw(); + } + _ => (), + })?; + + 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..4380dd61a9a 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}; @@ -19,7 +18,8 @@ use std::time::{Duration, Instant}; #[cfg(web_platform)] use web_time::{Duration, Instant}; -use crate::error::EventLoopError; +use crate::error::{EventLoopError, OsError}; +use crate::window::{Window, WindowAttributes}; use crate::{event::Event, monitor::MonitorHandle, platform_impl}; /// Provides a way to retrieve events from the system and from the windows that were registered to @@ -45,11 +45,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 +133,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 +239,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 +257,53 @@ 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) + } + + /// Create a window. + /// + /// Creating window without event loop running often leads to improper window creation; + /// use [`ActiveEventLoop::create_window`] instead. + #[deprecated = "use `ActiveEventLoop::create_window` instead"] + #[inline] + pub fn create_window(&self, window_attributes: WindowAttributes) -> Result { + let window = + platform_impl::Window::new(&self.event_loop.window_target().p, window_attributes)?; + Ok(Window { window }) + } } #[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 +311,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,15 +343,22 @@ impl AsRawFd for EventLoop { } } -impl Deref for EventLoop { - type Target = EventLoopWindowTarget; - fn deref(&self) -> &EventLoopWindowTarget { - self.event_loop.window_target() +impl ActiveEventLoop { + /// Create the window. + /// + /// Possible causes of error include denied permission, incompatible system, and lack of memory. + /// + /// ## Platform-specific + /// + /// - **Web:** The window is created but not inserted into the web page automatically. Please + /// see the web platform module for more information. + /// Returns the list of all the monitors available on the system. + #[inline] + pub fn create_window(&self, window_attributes: WindowAttributes) -> Result { + let window = platform_impl::Window::new(&self.p, window_attributes)?; + Ok(Window { window }) } -} -impl EventLoopWindowTarget { - /// Returns the list of all the monitors available on the system. #[inline] pub fn available_monitors(&self) -> impl Iterator { #[allow(clippy::useless_conversion)] // false positive on some platforms @@ -386,7 +432,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 +441,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 +452,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..371747a8684 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,22 +2,15 @@ //! //! # Building windows //! -//! Before you can build a [`Window`], you first need to build an [`EventLoop`]. This is done with the -//! [`EventLoop::new()`] function. +//! Before you can create a [`Window`], you first need to build an [`EventLoop`]. This is done with +//! the [`EventLoop::new()`] function. //! //! ```no_run //! use winit::event_loop::EventLoop; //! let event_loop = EventLoop::new().unwrap(); //! ``` //! -//! Once this is done, there are two ways to create a [`Window`]: -//! -//! - Calling [`Window::new(&event_loop)`][window_new]. -//! - Calling [`let builder = Window::builder()`][window_builder_new] then [`builder.build(&event_loop)`][window_builder_build]. -//! -//! The first method is the simplest and will give you default values for everything. The second -//! method allows you to customize the way your [`Window`] will look and behave by modifying the -//! fields of the [`WindowBuilder`] object before you create the [`Window`]. +//! Then you create a [`Window`] with [`create_window`]. //! //! # Event handling //! @@ -67,7 +60,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 +70,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(event_loop.create_window(Window::attributes()).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 +92,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, @@ -126,19 +123,18 @@ //! Note that many platforms will display garbage data in the window's client area if the //! application doesn't render anything to the window by the time the desktop compositor is ready to //! display the window to the user. If you notice this happening, you should create the window with -//! [`visible` set to `false`](crate::window::WindowBuilder::with_visible) and explicitly make the +//! [`visible` set to `false`](crate::window::WindowAttributes::with_visible) and explicitly make the //! window visible only once you're ready to render into it. //! //! [`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 +//! [`WindowAttributes`]: window::WindowAttributes //! [window_new]: window::Window::new -//! [window_builder_new]: window::Window::builder -//! [window_builder_build]: window::WindowBuilder::build +//! [`create_window`]: event_loop::ActiveEventLoop::create_window //! [`Window::id()`]: window::Window::id //! [`WindowEvent`]: event::WindowEvent //! [`DeviceEvent`]: event::DeviceEvent 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..e7f6697d483 100644 --- a/src/platform/android.rs +++ b/src/platform/android.rs @@ -1,6 +1,6 @@ use crate::{ - event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget}, - window::{Window, WindowBuilder}, + event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder}, + window::{Window, WindowAttributes}, }; use self::activity::{AndroidApp, ConfigurationRef, Rect}; @@ -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,12 +30,12 @@ impl WindowExtAndroid for Window { } } -impl EventLoopWindowTargetExtAndroid for EventLoopWindowTarget {} +impl ActiveEventLoopExtAndroid for ActiveEventLoop {} -/// Additional methods on [`WindowBuilder`] that are specific to Android. -pub trait WindowBuilderExtAndroid {} +/// Additional methods on [`WindowAttributes`] that are specific to Android. +pub trait WindowAttributesExtAndroid {} -impl WindowBuilderExtAndroid for WindowBuilder {} +impl WindowAttributesExtAndroid for WindowAttributes {} pub trait EventLoopBuilderExtAndroid { /// Associates the `AndroidApp` that was passed to `android_main()` with the event loop diff --git a/src/platform/ios.rs b/src/platform/ios.rs index a0f2f876f5c..3494cfa7aba 100644 --- a/src/platform/ios.rs +++ b/src/platform/ios.rs @@ -3,7 +3,7 @@ use std::os::raw::c_void; use crate::{ event_loop::EventLoop, monitor::{MonitorHandle, VideoModeHandle}, - window::{Window, WindowBuilder}, + window::{Window, WindowAttributes}, }; /// Additional methods on [`EventLoop`] that are specific to iOS. @@ -159,8 +159,8 @@ impl WindowExtIOS for Window { } } -/// Additional methods on [`WindowBuilder`] that are specific to iOS. -pub trait WindowBuilderExtIOS { +/// Additional methods on [`WindowAttributes`] that are specific to iOS. +pub trait WindowAttributesExtIOS { /// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `scale_factor`. /// /// The default value is device dependent, and it's recommended GLES or Metal applications set @@ -214,42 +214,41 @@ pub trait WindowBuilderExtIOS { fn with_preferred_status_bar_style(self, status_bar_style: StatusBarStyle) -> Self; } -impl WindowBuilderExtIOS for WindowBuilder { +impl WindowAttributesExtIOS for WindowAttributes { #[inline] fn with_scale_factor(mut self, scale_factor: f64) -> Self { - self.window.platform_specific.scale_factor = Some(scale_factor); + self.platform_specific.scale_factor = Some(scale_factor); self } #[inline] fn with_valid_orientations(mut self, valid_orientations: ValidOrientations) -> Self { - self.window.platform_specific.valid_orientations = valid_orientations; + self.platform_specific.valid_orientations = valid_orientations; self } #[inline] fn with_prefers_home_indicator_hidden(mut self, hidden: bool) -> Self { - self.window.platform_specific.prefers_home_indicator_hidden = hidden; + self.platform_specific.prefers_home_indicator_hidden = hidden; self } #[inline] fn with_preferred_screen_edges_deferring_system_gestures(mut self, edges: ScreenEdge) -> Self { - self.window - .platform_specific + self.platform_specific .preferred_screen_edges_deferring_system_gestures = edges; self } #[inline] fn with_prefers_status_bar_hidden(mut self, hidden: bool) -> Self { - self.window.platform_specific.prefers_status_bar_hidden = hidden; + self.platform_specific.prefers_status_bar_hidden = hidden; self } #[inline] fn with_preferred_status_bar_style(mut self, status_bar_style: StatusBarStyle) -> Self { - self.window.platform_specific.preferred_status_bar_style = status_bar_style; + self.platform_specific.preferred_status_bar_style = status_bar_style; self } } diff --git a/src/platform/macos.rs b/src/platform/macos.rs index bb93f700fe3..864cc1bba94 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -4,9 +4,9 @@ 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}, + window::{Window, WindowAttributes}, }; /// Additional methods on [`Window`] that are specific to MacOS. @@ -174,15 +174,15 @@ pub enum ActivationPolicy { Prohibited, } -/// Additional methods on [`WindowBuilder`] that are specific to MacOS. +/// Additional methods on [`WindowAttributes`] that are specific to MacOS. /// -/// **Note:** Properties dealing with the titlebar will be overwritten by the [`WindowBuilder::with_decorations`] method: +/// **Note:** Properties dealing with the titlebar will be overwritten by the [`WindowAttributes::with_decorations`] method: /// - `with_titlebar_transparent` /// - `with_title_hidden` /// - `with_titlebar_hidden` /// - `with_titlebar_buttons_hidden` /// - `with_fullsize_content_view` -pub trait WindowBuilderExtMacOS { +pub trait WindowAttributesExtMacOS { /// Enables click-and-drag behavior for the entire window, not just the titlebar. fn with_movable_by_window_background(self, movable_by_window_background: bool) -> Self; /// Makes the titlebar transparent and allows the content to appear behind it. @@ -209,65 +209,64 @@ pub trait WindowBuilderExtMacOS { fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> Self; } -impl WindowBuilderExtMacOS for WindowBuilder { +impl WindowAttributesExtMacOS for WindowAttributes { #[inline] fn with_movable_by_window_background(mut self, movable_by_window_background: bool) -> Self { - self.window.platform_specific.movable_by_window_background = movable_by_window_background; + self.platform_specific.movable_by_window_background = movable_by_window_background; self } #[inline] fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> Self { - self.window.platform_specific.titlebar_transparent = titlebar_transparent; + self.platform_specific.titlebar_transparent = titlebar_transparent; self } #[inline] fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> Self { - self.window.platform_specific.titlebar_hidden = titlebar_hidden; + self.platform_specific.titlebar_hidden = titlebar_hidden; self } #[inline] fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> Self { - self.window.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden; + self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden; self } #[inline] fn with_title_hidden(mut self, title_hidden: bool) -> Self { - self.window.platform_specific.title_hidden = title_hidden; + self.platform_specific.title_hidden = title_hidden; self } #[inline] fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> Self { - self.window.platform_specific.fullsize_content_view = fullsize_content_view; + self.platform_specific.fullsize_content_view = fullsize_content_view; self } #[inline] fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> Self { - self.window.platform_specific.disallow_hidpi = disallow_hidpi; + self.platform_specific.disallow_hidpi = disallow_hidpi; self } #[inline] fn with_has_shadow(mut self, has_shadow: bool) -> Self { - self.window.platform_specific.has_shadow = has_shadow; + self.platform_specific.has_shadow = has_shadow; self } #[inline] fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> Self { - self.window.platform_specific.accepts_first_mouse = accepts_first_mouse; + self.platform_specific.accepts_first_mouse = accepts_first_mouse; self } #[inline] fn with_tabbing_identifier(mut self, tabbing_identifier: &str) -> Self { - self.window - .platform_specific + self.platform_specific .tabbing_identifier .replace(tabbing_identifier.to_string()); self @@ -275,7 +274,7 @@ impl WindowBuilderExtMacOS for WindowBuilder { #[inline] fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> Self { - self.window.platform_specific.option_as_alt = option_as_alt; + self.platform_specific.option_as_alt = option_as_alt; self } } @@ -375,8 +374,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 +388,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..c9047a03b2f 100644 --- a/src/platform/startup_notify.rs +++ b/src/platform/startup_notify.rs @@ -24,8 +24,8 @@ use std::env; use crate::error::NotSupportedError; -use crate::event_loop::{AsyncRequestSerial, EventLoopWindowTarget}; -use crate::window::{ActivationToken, Window, WindowBuilder}; +use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial}; +use crate::window::{ActivationToken, Window, WindowAttributes}; /// The variable which is used mostly on X11. const X11_VAR: &str = "DESKTOP_STARTUP_ID"; @@ -47,7 +47,7 @@ pub trait WindowExtStartupNotify { fn request_activation_token(&self) -> Result; } -pub trait WindowBuilderExtStartupNotify { +pub trait WindowAttributesExtStartupNotify { /// Use this [`ActivationToken`] during window creation. /// /// Not using such a token upon a window could make your window not gaining @@ -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) @@ -74,9 +74,9 @@ impl WindowExtStartupNotify for Window { } } -impl WindowBuilderExtStartupNotify for WindowBuilder { +impl WindowAttributesExtStartupNotify for WindowAttributes { fn with_activation_token(mut self, token: ActivationToken) -> Self { - self.window.platform_specific.activation_token = Some(token); + self.platform_specific.activation_token = Some(token); self } } diff --git a/src/platform/wayland.rs b/src/platform/wayland.rs index e8f3fd5d90f..8a0508550ec 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}, + window::{Window, WindowAttributes}, }; 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() @@ -50,8 +50,8 @@ pub trait WindowExtWayland {} impl WindowExtWayland for Window {} -/// Additional methods on [`WindowBuilder`] that are specific to Wayland. -pub trait WindowBuilderExtWayland { +/// Additional methods on [`WindowAttributes`] that are specific to Wayland. +pub trait WindowAttributesExtWayland { /// Build window with the given name. /// /// The `general` name sets an application ID, which should match the `.desktop` @@ -62,10 +62,10 @@ pub trait WindowBuilderExtWayland { fn with_name(self, general: impl Into, instance: impl Into) -> Self; } -impl WindowBuilderExtWayland for WindowBuilder { +impl WindowAttributesExtWayland for WindowAttributes { #[inline] fn with_name(mut self, general: impl Into, instance: impl Into) -> Self { - self.window.platform_specific.name = Some(crate::platform_impl::ApplicationName::new( + self.platform_specific.name = Some(crate::platform_impl::ApplicationName::new( general.into(), instance.into(), )); diff --git a/src/platform/web.rs b/src/platform/web.rs index 9c0b5a29735..56a69ffcd0c 100644 --- a/src/platform/web.rs +++ b/src/platform/web.rs @@ -1,6 +1,6 @@ //! The web target does not automatically insert the canvas element object into the web page, to //! allow end users to determine how the page should be laid out. Use the [`WindowExtWebSys`] trait -//! to retrieve the canvas from the Window. Alternatively, use the [`WindowBuilderExtWebSys`] trait +//! to retrieve the canvas from the Window. Alternatively, use the [`WindowAttributesExtWebSys`] trait //! to provide your own canvas. //! //! It is recommended **not** to apply certain CSS properties to the canvas: @@ -39,11 +39,11 @@ 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}; -use crate::window::{CustomCursor, Window, WindowBuilder}; +use crate::window::{CustomCursor, Window, WindowAttributes}; #[cfg(not(web_platform))] #[doc(hidden)] @@ -85,9 +85,9 @@ impl WindowExtWebSys for Window { } } -pub trait WindowBuilderExtWebSys { +pub trait WindowAttributesExtWebSys { /// Pass an [`HtmlCanvasElement`] to be used for this [`Window`]. If [`None`], - /// [`WindowBuilder::build()`] will create one. + /// [`WindowAttributes::default()`] will create one. /// /// In any case, the canvas won't be automatically inserted into the web page. /// @@ -119,24 +119,24 @@ pub trait WindowBuilderExtWebSys { fn with_append(self, append: bool) -> Self; } -impl WindowBuilderExtWebSys for WindowBuilder { +impl WindowAttributesExtWebSys for WindowAttributes { fn with_canvas(mut self, canvas: Option) -> Self { - self.window.platform_specific.set_canvas(canvas); + self.platform_specific.set_canvas(canvas); self } fn with_prevent_default(mut self, prevent_default: bool) -> Self { - self.window.platform_specific.prevent_default = prevent_default; + self.platform_specific.prevent_default = prevent_default; self } fn with_focusable(mut self, focusable: bool) -> Self { - self.window.platform_specific.focusable = focusable; + self.platform_specific.focusable = focusable; self } fn with_append(mut self, append: bool) -> Self { - self.window.platform_specific.append = append; + self.platform_specific.append = append; self } } @@ -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/windows.rs b/src/platform/windows.rs index cbf9699ca8f..456d064eb66 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -5,7 +5,7 @@ use crate::{ event::DeviceId, event_loop::EventLoopBuilder, monitor::MonitorHandle, - window::{BadIcon, Icon, Window, WindowBuilder}, + window::{BadIcon, Icon, Window, WindowAttributes}, }; /// Window Handle type used by Win32 API @@ -198,7 +198,7 @@ pub trait WindowExtWindows { /// /// A window must be enabled before it can be activated. /// If an application has create a modal dialog box by disabling its owner window - /// (as described in [`WindowBuilderExtWindows::with_owner_window`]), the application must enable + /// (as described in [`WindowAttributesExtWindows::with_owner_window`]), the application must enable /// the owner window before destroying the dialog box. /// Otherwise, another window will receive the keyboard focus and be activated. /// @@ -296,11 +296,11 @@ impl WindowExtWindows for Window { } } -/// Additional methods on `WindowBuilder` that are specific to Windows. +/// Additional methods on `WindowAttributes` that are specific to Windows. #[allow(rustdoc::broken_intra_doc_links)] -pub trait WindowBuilderExtWindows { +pub trait WindowAttributesExtWindows { /// Set an owner to the window to be created. Can be used to create a dialog box, for example. - /// This only works when [`WindowBuilder::with_parent_window`] isn't called or set to `None`. + /// This only works when [`WindowAttributes::with_parent_window`] isn't called or set to `None`. /// Can be used in combination with [`WindowExtWindows::set_enable(false)`](WindowExtWindows::set_enable) /// on the owner window to create a modal dialog box. /// @@ -386,88 +386,88 @@ pub trait WindowBuilderExtWindows { fn with_corner_preference(self, corners: CornerPreference) -> Self; } -impl WindowBuilderExtWindows for WindowBuilder { +impl WindowAttributesExtWindows for WindowAttributes { #[inline] fn with_owner_window(mut self, parent: HWND) -> Self { - self.window.platform_specific.owner = Some(parent); + self.platform_specific.owner = Some(parent); self } #[inline] fn with_menu(mut self, menu: HMENU) -> Self { - self.window.platform_specific.menu = Some(menu); + self.platform_specific.menu = Some(menu); self } #[inline] fn with_taskbar_icon(mut self, taskbar_icon: Option) -> Self { - self.window.platform_specific.taskbar_icon = taskbar_icon; + self.platform_specific.taskbar_icon = taskbar_icon; self } #[inline] fn with_no_redirection_bitmap(mut self, flag: bool) -> Self { - self.window.platform_specific.no_redirection_bitmap = flag; + self.platform_specific.no_redirection_bitmap = flag; self } #[inline] fn with_drag_and_drop(mut self, flag: bool) -> Self { - self.window.platform_specific.drag_and_drop = flag; + self.platform_specific.drag_and_drop = flag; self } #[inline] fn with_skip_taskbar(mut self, skip: bool) -> Self { - self.window.platform_specific.skip_taskbar = skip; + self.platform_specific.skip_taskbar = skip; self } #[inline] fn with_class_name>(mut self, class_name: S) -> Self { - self.window.platform_specific.class_name = class_name.into(); + self.platform_specific.class_name = class_name.into(); self } #[inline] fn with_undecorated_shadow(mut self, shadow: bool) -> Self { - self.window.platform_specific.decoration_shadow = shadow; + self.platform_specific.decoration_shadow = shadow; self } #[inline] fn with_system_backdrop(mut self, backdrop_type: BackdropType) -> Self { - self.window.platform_specific.backdrop_type = backdrop_type; + self.platform_specific.backdrop_type = backdrop_type; self } #[inline] fn with_clip_children(mut self, flag: bool) -> Self { - self.window.platform_specific.clip_children = flag; + self.platform_specific.clip_children = flag; self } #[inline] fn with_border_color(mut self, color: Option) -> Self { - self.window.platform_specific.border_color = Some(color.unwrap_or(Color::NONE)); + self.platform_specific.border_color = Some(color.unwrap_or(Color::NONE)); self } #[inline] fn with_title_background_color(mut self, color: Option) -> Self { - self.window.platform_specific.title_background_color = Some(color.unwrap_or(Color::NONE)); + self.platform_specific.title_background_color = Some(color.unwrap_or(Color::NONE)); self } #[inline] fn with_title_text_color(mut self, color: Color) -> Self { - self.window.platform_specific.title_text_color = Some(color); + self.platform_specific.title_text_color = Some(color); self } #[inline] fn with_corner_preference(mut self, corners: CornerPreference) -> Self { - self.window.platform_specific.corner_preference = Some(corners); + self.platform_specific.corner_preference = Some(corners); self } } diff --git a/src/platform/x11.rs b/src/platform/x11.rs index 7dc3e8cde79..90020050206 100644 --- a/src/platform/x11.rs +++ b/src/platform/x11.rs @@ -2,9 +2,9 @@ use serde::{Deserialize, Serialize}; use crate::{ - event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoopBuilder}, monitor::MonitorHandle, - window::{Window, WindowBuilder}, + window::{Window, WindowAttributes}, }; use crate::dpi::Size; @@ -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() @@ -133,8 +133,8 @@ pub trait WindowExtX11 {} impl WindowExtX11 for Window {} -/// Additional methods on [`WindowBuilder`] that are specific to X11. -pub trait WindowBuilderExtX11 { +/// Additional methods on [`WindowAttributes`] that are specific to X11. +pub trait WindowAttributesExtX11 { /// Create this window with a specific X11 visual. fn with_x11_visual(self, visual_id: XVisualID) -> Self; @@ -160,12 +160,12 @@ pub trait WindowBuilderExtX11 { /// ``` /// # use winit::dpi::{LogicalSize, PhysicalSize}; /// # use winit::window::Window; - /// # use winit::platform::x11::WindowBuilderExtX11; + /// # use winit::platform::x11::WindowAttributesExtX11; /// // Specify the size in logical dimensions like this: - /// Window::builder().with_base_size(LogicalSize::new(400.0, 200.0)); + /// Window::attributes().with_base_size(LogicalSize::new(400.0, 200.0)); /// /// // Or specify the size in physical dimensions like this: - /// Window::builder().with_base_size(PhysicalSize::new(400, 200)); + /// Window::attributes().with_base_size(PhysicalSize::new(400, 200)); /// ``` fn with_base_size>(self, base_size: S) -> Self; @@ -175,34 +175,33 @@ pub trait WindowBuilderExtX11 { /// /// ```no_run /// use winit::window::Window; - /// use winit::platform::x11::{XWindow, WindowBuilderExtX11}; - /// # fn main() -> Result<(), Box> { - /// let event_loop = winit::event_loop::EventLoop::new().unwrap(); + /// use winit::event_loop::ActiveEventLoop; + /// use winit::platform::x11::{XWindow, WindowAttributesExtX11}; + /// # 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) - /// .build(&event_loop)?; + /// let window_attributes = Window::attributes().with_embed_parent_window(parent_window_id); + /// let window = event_loop.create_window(window_attributes)?; /// # Ok(()) } /// ``` fn with_embed_parent_window(self, parent_window_id: XWindow) -> Self; } -impl WindowBuilderExtX11 for WindowBuilder { +impl WindowAttributesExtX11 for WindowAttributes { #[inline] fn with_x11_visual(mut self, visual_id: XVisualID) -> Self { - self.window.platform_specific.x11.visual_id = Some(visual_id); + self.platform_specific.x11.visual_id = Some(visual_id); self } #[inline] fn with_x11_screen(mut self, screen_id: i32) -> Self { - self.window.platform_specific.x11.screen_id = Some(screen_id); + self.platform_specific.x11.screen_id = Some(screen_id); self } #[inline] fn with_name(mut self, general: impl Into, instance: impl Into) -> Self { - self.window.platform_specific.name = Some(crate::platform_impl::ApplicationName::new( + self.platform_specific.name = Some(crate::platform_impl::ApplicationName::new( general.into(), instance.into(), )); @@ -211,25 +210,25 @@ impl WindowBuilderExtX11 for WindowBuilder { #[inline] fn with_override_redirect(mut self, override_redirect: bool) -> Self { - self.window.platform_specific.x11.override_redirect = override_redirect; + self.platform_specific.x11.override_redirect = override_redirect; self } #[inline] fn with_x11_window_type(mut self, x11_window_types: Vec) -> Self { - self.window.platform_specific.x11.x11_window_types = x11_window_types; + self.platform_specific.x11.x11_window_types = x11_window_types; self } #[inline] fn with_base_size>(mut self, base_size: S) -> Self { - self.window.platform_specific.x11.base_size = Some(base_size.into()); + self.platform_specific.x11.base_size = Some(base_size.into()); self } #[inline] fn with_embed_parent_window(mut self, parent_window_id: XWindow) -> Self { - self.window.platform_specific.x11.embed_window = Some(parent_window_id); + self.platform_specific.x11.embed_window = Some(parent_window_id); self } } diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index ad564385516..e8512a32f3c 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())) } @@ -773,7 +773,7 @@ impl DeviceId { } #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] -pub struct PlatformSpecificWindowBuilderAttributes; +pub struct PlatformSpecificWindowAttributesAttributes; pub(crate) struct Window { app: AndroidApp, @@ -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..020a4bfbc47 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -72,11 +72,11 @@ use crate::event::DeviceId as RootDeviceId; pub(crate) use self::{ event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }, monitor::{MonitorHandle, VideoModeHandle}, - window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId}, + window::{PlatformSpecificWindowAttributesAttributes, Window, WindowId}, }; pub(crate) use crate::cursor::NoCustomCursor as PlatformCustomCursor; pub(crate) use crate::cursor::NoCustomCursor as PlatformCustomCursorBuilder; diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 5b22bd8268f..706c3caf1c5 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; @@ -678,7 +676,7 @@ impl From<&AnyObject> for WindowId { } #[derive(Clone, Debug, Default)] -pub struct PlatformSpecificWindowBuilderAttributes { +pub struct PlatformSpecificWindowAttributesAttributes { pub scale_factor: Option, pub valid_orientations: ValidOrientations, pub prefers_home_indicator_hidden: bool, diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 4589eb4d67a..7355569c36a 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, @@ -72,16 +71,16 @@ impl ApplicationName { } #[derive(Clone, Debug)] -pub struct PlatformSpecificWindowBuilderAttributes { +pub struct PlatformSpecificWindowAttributesAttributes { pub name: Option, pub activation_token: Option, #[cfg(x11_platform)] - pub x11: X11WindowBuilderAttributes, + pub x11: X11WindowAttributesAttributes, } #[derive(Clone, Debug)] #[cfg(x11_platform)] -pub struct X11WindowBuilderAttributes { +pub struct X11WindowAttributesAttributes { pub visual_id: Option, pub screen_id: Option, pub base_size: Option, @@ -92,13 +91,13 @@ pub struct X11WindowBuilderAttributes { pub embed_window: Option, } -impl Default for PlatformSpecificWindowBuilderAttributes { +impl Default for PlatformSpecificWindowAttributesAttributes { fn default() -> Self { Self { name: None, activation_token: None, #[cfg(x11_platform)] - x11: X11WindowBuilderAttributes { + x11: X11WindowAttributesAttributes { visual_id: None, screen_id: None, base_size: None, @@ -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..84528b96dd8 100644 --- a/src/platform_impl/macos/mod.rs +++ b/src/platform_impl/macos/mod.rs @@ -19,12 +19,12 @@ 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}, window::WindowId, - window_delegate::PlatformSpecificWindowBuilderAttributes, + window_delegate::PlatformSpecificWindowAttributesAttributes, }; use crate::event::DeviceId as RootDeviceId; 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/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index 118e6da8b0a..0e53de17381 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -44,7 +44,7 @@ use crate::window::{ }; #[derive(Clone, Debug)] -pub struct PlatformSpecificWindowBuilderAttributes { +pub struct PlatformSpecificWindowAttributesAttributes { pub movable_by_window_background: bool, pub titlebar_transparent: bool, pub title_hidden: bool, @@ -58,7 +58,7 @@ pub struct PlatformSpecificWindowBuilderAttributes { pub option_as_alt: OptionAsAlt, } -impl Default for PlatformSpecificWindowBuilderAttributes { +impl Default for PlatformSpecificWindowAttributesAttributes { #[inline] fn default() -> Self { Self { @@ -104,7 +104,7 @@ pub(crate) struct State { /// bar in exclusive fullscreen but want to restore the original options when /// transitioning back to borderless fullscreen. save_presentation_opts: Cell>, - // This is set when WindowBuilder::with_fullscreen was set, + // This is set when WindowAttributes::with_fullscreen was set, // see comments of `window_did_fail_to_enter_fullscreen` initial_fullscreen: Cell, /// This field tracks the current fullscreen state of the window @@ -1492,7 +1492,7 @@ impl WindowDelegate { // only be used when the window is in some way representing a specific // file/directory. For instance, Terminal.app uses this for the CWD. // Anyway, that should eventually be implemented as - // `WindowBuilderExt::with_represented_file` or something, and doesn't + // `WindowAttributesExt::with_represented_file` or something, and doesn't // have anything to do with `set_window_icon`. // https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/WinPanel/Tasks/SettingWindowTitle.html } 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..a289d36c1aa 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; @@ -130,7 +128,7 @@ impl DeviceId { } #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] -pub struct PlatformSpecificWindowBuilderAttributes; +pub struct PlatformSpecificWindowAttributesAttributes; struct WindowProperties<'a> { flags: &'a str, 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..ceec6f6ca39 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,11 +33,11 @@ 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}; -pub use self::window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId}; +pub use self::window::{PlatformSpecificWindowAttributesAttributes, Window, WindowId}; pub(crate) use self::keyboard::KeyEventExtra; pub(crate) use crate::icon::NoIcon as PlatformIcon; diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index 7f4239360c8..3a8b00839a7 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(); @@ -466,14 +466,14 @@ impl From for WindowId { } #[derive(Clone, Debug)] -pub struct PlatformSpecificWindowBuilderAttributes { +pub struct PlatformSpecificWindowAttributesAttributes { pub(crate) canvas: Option>>, pub(crate) prevent_default: bool, pub(crate) focusable: bool, pub(crate) append: bool, } -impl PlatformSpecificWindowBuilderAttributes { +impl PlatformSpecificWindowAttributesAttributes { pub(crate) fn set_canvas(&mut self, canvas: Option) { let Some(canvas) = canvas else { self.canvas = None; @@ -487,7 +487,7 @@ impl PlatformSpecificWindowBuilderAttributes { } } -impl Default for PlatformSpecificWindowBuilderAttributes { +impl Default for PlatformSpecificWindowAttributesAttributes { fn default() -> Self { Self { canvas: None, 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..e1879d9598e 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}, @@ -28,7 +28,7 @@ use crate::keyboard::Key; use crate::platform::windows::{BackdropType, Color, CornerPreference}; #[derive(Clone, Debug)] -pub struct PlatformSpecificWindowBuilderAttributes { +pub struct PlatformSpecificWindowAttributesAttributes { pub owner: Option, pub menu: Option, pub taskbar_icon: Option, @@ -45,7 +45,7 @@ pub struct PlatformSpecificWindowBuilderAttributes { pub corner_preference: Option, } -impl Default for PlatformSpecificWindowBuilderAttributes { +impl Default for PlatformSpecificWindowAttributesAttributes { fn default() -> Self { Self { owner: None, @@ -66,8 +66,8 @@ impl Default for PlatformSpecificWindowBuilderAttributes { } } -unsafe impl Send for PlatformSpecificWindowBuilderAttributes {} -unsafe impl Sync for PlatformSpecificWindowBuilderAttributes {} +unsafe impl Send for PlatformSpecificWindowAttributesAttributes {} +unsafe impl Sync for PlatformSpecificWindowAttributesAttributes {} // Cursor name in UTF-16. Used to set cursor in `WM_SETCURSOR`. #[derive(Debug, Clone, Copy)] 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..fdcdb4c61d4 100644 --- a/src/window.rs +++ b/src/window.rs @@ -3,10 +3,9 @@ use std::fmt; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, - error::{ExternalError, NotSupportedError, OsError}, - event_loop::EventLoopWindowTarget, + error::{ExternalError, NotSupportedError}, monitor::{MonitorHandle, VideoModeHandle}, - platform_impl::{self, PlatformSpecificWindowBuilderAttributes}, + platform_impl::{self, PlatformSpecificWindowAttributesAttributes}, }; pub use crate::cursor::{BadImage, Cursor, CustomCursor, CustomCursorBuilder, MAX_CURSOR_SIZE}; @@ -42,14 +41,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 = event_loop.create_window(Window::attributes()).unwrap(); +/// windows.push(window); +/// } /// Event::WindowEvent { /// event: WindowEvent::CloseRequested, /// .. -/// } => elwt.exit(), +/// } => { +/// windows.clear(); +/// event_loop.exit(); +/// } /// _ => (), /// } /// }); @@ -123,24 +129,6 @@ impl From for WindowId { } } -/// Configure windows before creation. -/// -/// You can access this from [`Window::builder`]. -#[derive(Clone, Default)] -#[must_use] -pub struct WindowBuilder { - /// The attributes to use to create the window. - pub(crate) window: WindowAttributes, -} - -impl fmt::Debug for WindowBuilder { - fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result { - fmtr.debug_struct("WindowBuilder") - .field("window", &self.window) - .finish() - } -} - /// Attributes used when creating a window. #[derive(Debug, Clone)] pub struct WindowAttributes { @@ -168,7 +156,7 @@ pub struct WindowAttributes { pub fullscreen: Option, // Platform-specific configuration. #[allow(dead_code)] - pub(crate) platform_specific: PlatformSpecificWindowBuilderAttributes, + pub(crate) platform_specific: PlatformSpecificWindowAttributesAttributes, } impl Default for WindowAttributes { @@ -206,7 +194,7 @@ impl Default for WindowAttributes { /// /// # Safety /// -/// The user has to account for that when using [`WindowBuilder::with_parent_window()`], +/// The user has to account for that when using [`WindowAttributes::with_parent_window()`], /// which is `unsafe`. #[derive(Debug, Clone)] #[cfg(feature = "rwh_06")] @@ -218,26 +206,19 @@ unsafe impl Send for SendSyncRawWindowHandle {} unsafe impl Sync for SendSyncRawWindowHandle {} impl WindowAttributes { - /// Get the parent window stored on the attributes. - #[cfg(feature = "rwh_06")] - pub fn parent_window(&self) -> Option<&rwh_06::RawWindowHandle> { - self.parent_window.as_ref().map(|handle| &handle.0) - } -} - -impl WindowBuilder { /// Initializes a new builder with default values. #[inline] - #[deprecated = "use `Window::builder` instead"] + #[deprecated = "use `Window::attributes` instead"] pub fn new() -> Self { Default::default() } } -impl WindowBuilder { - /// Get the current window attributes. - pub fn window_attributes(&self) -> &WindowAttributes { - &self.window +impl WindowAttributes { + /// Get the parent window stored on the attributes. + #[cfg(feature = "rwh_06")] + pub fn parent_window(&self) -> Option<&rwh_06::RawWindowHandle> { + self.parent_window.as_ref().map(|handle| &handle.0) } /// Requests the window to be of specific dimensions. @@ -247,7 +228,7 @@ impl WindowBuilder { /// See [`Window::request_inner_size`] for details. #[inline] pub fn with_inner_size>(mut self, size: S) -> Self { - self.window.inner_size = Some(size.into()); + self.inner_size = Some(size.into()); self } @@ -259,7 +240,7 @@ impl WindowBuilder { /// See [`Window::set_min_inner_size`] for details. #[inline] pub fn with_min_inner_size>(mut self, min_size: S) -> Self { - self.window.min_inner_size = Some(min_size.into()); + self.min_inner_size = Some(min_size.into()); self } @@ -271,7 +252,7 @@ impl WindowBuilder { /// See [`Window::set_max_inner_size`] for details. #[inline] pub fn with_max_inner_size>(mut self, max_size: S) -> Self { - self.window.max_inner_size = Some(max_size.into()); + self.max_inner_size = Some(max_size.into()); self } @@ -299,7 +280,7 @@ impl WindowBuilder { /// - **Others:** Ignored. #[inline] pub fn with_position>(mut self, position: P) -> Self { - self.window.position = Some(position.into()); + self.position = Some(position.into()); self } @@ -310,7 +291,7 @@ impl WindowBuilder { /// See [`Window::set_resizable`] for details. #[inline] pub fn with_resizable(mut self, resizable: bool) -> Self { - self.window.resizable = resizable; + self.resizable = resizable; self } @@ -321,7 +302,7 @@ impl WindowBuilder { /// See [`Window::set_enabled_buttons`] for details. #[inline] pub fn with_enabled_buttons(mut self, buttons: WindowButtons) -> Self { - self.window.enabled_buttons = buttons; + self.enabled_buttons = buttons; self } @@ -332,7 +313,7 @@ impl WindowBuilder { /// See [`Window::set_title`] for details. #[inline] pub fn with_title>(mut self, title: T) -> Self { - self.window.title = title.into(); + self.title = title.into(); self } @@ -343,7 +324,7 @@ impl WindowBuilder { /// See [`Window::set_fullscreen`] for details. #[inline] pub fn with_fullscreen(mut self, fullscreen: Option) -> Self { - self.window.fullscreen = fullscreen; + self.fullscreen = fullscreen; self } @@ -354,7 +335,7 @@ impl WindowBuilder { /// See [`Window::set_maximized`] for details. #[inline] pub fn with_maximized(mut self, maximized: bool) -> Self { - self.window.maximized = maximized; + self.maximized = maximized; self } @@ -365,7 +346,7 @@ impl WindowBuilder { /// See [`Window::set_visible`] for details. #[inline] pub fn with_visible(mut self, visible: bool) -> Self { - self.window.visible = visible; + self.visible = visible; self } @@ -379,7 +360,7 @@ impl WindowBuilder { /// The default is `false`. #[inline] pub fn with_transparent(mut self, transparent: bool) -> Self { - self.window.transparent = transparent; + self.transparent = transparent; self } @@ -390,14 +371,14 @@ impl WindowBuilder { /// See [`Window::set_blur`] for details. #[inline] pub fn with_blur(mut self, blur: bool) -> Self { - self.window.blur = blur; + self.blur = blur; self } /// Get whether the window will support transparency. #[inline] pub fn transparent(&self) -> bool { - self.window.transparent + self.transparent } /// Sets whether the window should have a border, a title bar, etc. @@ -407,7 +388,7 @@ impl WindowBuilder { /// See [`Window::set_decorations`] for details. #[inline] pub fn with_decorations(mut self, decorations: bool) -> Self { - self.window.decorations = decorations; + self.decorations = decorations; self } @@ -420,7 +401,7 @@ impl WindowBuilder { /// See [`WindowLevel`] for details. #[inline] pub fn with_window_level(mut self, level: WindowLevel) -> Self { - self.window.window_level = level; + self.window_level = level; self } @@ -431,7 +412,7 @@ impl WindowBuilder { /// See [`Window::set_window_icon`] for details. #[inline] pub fn with_window_icon(mut self, window_icon: Option) -> Self { - self.window.window_icon = window_icon; + self.window_icon = window_icon; self } @@ -450,7 +431,7 @@ impl WindowBuilder { /// - **iOS / Android / Web / x11 / Orbital:** Ignored. #[inline] pub fn with_theme(mut self, theme: Option) -> Self { - self.window.preferred_theme = theme; + self.preferred_theme = theme; self } @@ -461,7 +442,7 @@ impl WindowBuilder { /// See [`Window::set_resize_increments`] for details. #[inline] pub fn with_resize_increments>(mut self, resize_increments: S) -> Self { - self.window.resize_increments = Some(resize_increments.into()); + self.resize_increments = Some(resize_increments.into()); self } @@ -478,7 +459,7 @@ impl WindowBuilder { /// [`NSWindowSharingNone`]: https://developer.apple.com/documentation/appkit/nswindowsharingtype/nswindowsharingnone #[inline] pub fn with_content_protected(mut self, protected: bool) -> Self { - self.window.content_protected = protected; + self.content_protected = protected; self } @@ -494,7 +475,7 @@ impl WindowBuilder { /// [`WindowEvent::Focused`]: crate::event::WindowEvent::Focused. #[inline] pub fn with_active(mut self, active: bool) -> Self { - self.window.active = active; + self.active = active; self } @@ -505,7 +486,7 @@ impl WindowBuilder { /// See [`Window::set_cursor()`] for more details. #[inline] pub fn with_cursor(mut self, cursor: impl Into) -> Self { - self.window.cursor = cursor.into(); + self.cursor = cursor.into(); self } @@ -530,50 +511,18 @@ impl WindowBuilder { mut self, parent_window: Option, ) -> Self { - self.window.parent_window = parent_window.map(SendSyncRawWindowHandle); + self.parent_window = parent_window.map(SendSyncRawWindowHandle); self } - - /// Builds the window. - /// - /// Possible causes of error include denied permission, incompatible system, and lack of memory. - /// - /// ## Platform-specific - /// - /// - **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 { - let window = platform_impl::Window::new(&window_target.p, self.window)?; - window.maybe_queue_on_main(|w| w.request_redraw()); - Ok(Window { window }) - } } /// Base Window functions. impl Window { - /// Creates a new Window for platforms where this is appropriate. - /// - /// This function is equivalent to [`Window::builder().build(event_loop)`]. - /// - /// Error should be very rare and only occur in case of permission denied, incompatible system, - /// out of memory, etc. - /// - /// ## Platform-specific - /// - /// - **Web:** The window is created but not inserted into the web page automatically. Please - /// see the web platform module for more information. - /// - /// [`Window::builder().build(event_loop)`]: WindowBuilder::build - #[inline] - pub fn new(event_loop: &EventLoopWindowTarget) -> Result { - Window::builder().build(event_loop) - } - - /// Create a new [`WindowBuilder`] which allows modifying the window's attributes before creation. + /// Create a new [`WindowAttributes`] which allows modifying the window's attributes before + /// creation. #[inline] - pub fn builder() -> WindowBuilder { - WindowBuilder::default() + pub fn attributes() -> WindowAttributes { + WindowAttributes::default() } /// Returns an identifier unique to the window. @@ -652,11 +601,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 +611,7 @@ impl Window { /// /// // Sumbit buffer to the windowing system. /// swap_buffers(); + /// # } /// ``` /// /// ## Platform-specific @@ -742,15 +690,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 +751,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 +795,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 +819,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 @@ -942,12 +886,12 @@ impl Window { /// the content of your window and this hint may result in /// visual artifacts. /// - /// The default value follows the [`WindowBuilder::with_transparent`]. + /// The default value follows the [`WindowAttributes::with_transparent`]. /// /// ## Platform-specific /// /// - **Web / iOS / Android / Orbital:** Unsupported. - /// - **X11:** Can only be set while building the window, with [`WindowBuilder::with_transparent`]. + /// - **X11:** Can only be set while building the window, with [`WindowAttributes::with_transparent`]. #[inline] pub fn set_transparent(&self, transparent: bool) { self.window @@ -1214,15 +1158,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 +1341,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 +1368,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 +1472,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 +1488,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 diff --git a/tests/send_objects.rs b/tests/send_objects.rs index 0a5d1a9eb38..8e2a9ba4a70 100644 --- a/tests/send_objects.rs +++ b/tests/send_objects.rs @@ -18,7 +18,7 @@ fn window_send() { #[test] fn window_builder_send() { - needs_send::(); + needs_send::(); } #[test] diff --git a/tests/sync_object.rs b/tests/sync_object.rs index 8500ac5fa7a..590965aa695 100644 --- a/tests/sync_object.rs +++ b/tests/sync_object.rs @@ -9,7 +9,7 @@ fn window_sync() { #[test] fn window_builder_sync() { - needs_sync::(); + needs_sync::(); } #[test]