diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d447ae177..eda12502b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ Unreleased` header. - On X11, fix xkb state not being updated correctly sometimes leading to wrong input. - Fix compatibility with 32-bit platforms without 64-bit atomics. - Implement `Sync` for `EventLoopProxy`. +- **Breaking:** Move `Window::new` to `ActiveEventLoop::create_window` and `EventLoop::create_window` (with the latter being deprecated). +- **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. @@ -47,7 +51,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::default_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 5d7f7add82..f3ff496c9d 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,51 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { use std::collections::HashMap; - use winit::{ - dpi::{LogicalPosition, LogicalSize, Position}, - event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::{EventLoop, EventLoopWindowTarget}, - raw_window_handle::HasRawWindowHandle, - window::{Window, WindowId}, - }; + use winit::dpi::{LogicalPosition, LogicalSize, Position}; + use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; + use winit::event_loop::{ActiveEventLoop, EventLoop}; + use winit::raw_window_handle::HasRawWindowHandle; + use winit::window::Window; + + #[path = "util/fill.rs"] + mod fill; - 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::default_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 = None; - println!("parent window: {parent_window:?})"); + event_loop.run(move |event: Event<()>, event_loop| { + match event { + Event::Resumed => { + let attributes = Window::default_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 = Some(window.id()); + + println!("Parent window id: {parent_window_id:?})"); + windows.insert(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 +67,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()).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 +79,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 cff46a003b..8568334ca1 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::default_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 b857c19a7d..0000000000 --- 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 ea08c495ff..0000000000 --- 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 0d0fb4469f..0000000000 --- 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 90e8e41d8f..0000000000 --- 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 5f2b597cd9..0000000000 --- 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 e70a68793d..0000000000 --- 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 022433237e..0000000000 --- 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_modifiers()` 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 f44d6dee58..0000000000 --- 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_modifiers()` 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 f18d87cf6a..0000000000 --- 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 dcf18909aa..0000000000 --- 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 35fe11c8f5..0000000000 --- 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 1a5667c018..0000000000 --- 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 cda3548220..0000000000 --- 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_modifiers()` 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 07a9b84eef..0000000000 --- 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 63% rename from examples/window_pump_events.rs rename to examples/pump_events.rs index f6f30dab18..05b33782c9 100644 --- a/examples/window_pump_events.rs +++ b/examples/pump_events.rs @@ -25,38 +25,40 @@ 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::default_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 9b20511744..0000000000 --- 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 9801ba059a..0000000000 --- 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 3bfc4b59ce..0000000000 --- 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 91% rename from examples/window_on_demand.rs rename to examples/run_on_demand.rs index 8406aed4b4..352a8aa47e 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::default_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 2c3730edec..0000000000 --- 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 1723949d72..0000000000 --- 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 76c386f0c7..0000000000 --- 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 52c9a39a3d..0000000000 --- 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 388e7a828e..0000000000 --- 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 75acdbd45b..0000000000 --- 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 8779f3fb10..0000000000 --- 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 6ade931c13..0000000000 --- a/examples/web_aspect_ratio.rs +++ /dev/null @@ -1,101 +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 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 55645edcb5..a539ee95c5 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::default_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 e854b4681d..0000000000 --- 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 74c5e8ff5c..0000000000 --- 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 preferred 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_modifiers()` 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 ef59b4c916..0000000000 --- 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 a5863b05cb..0000000000 --- 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 910221abe8..0000000000 --- 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 2326cfb28a..0000000000 --- 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 c0ff0a6787..0000000000 --- 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 6f96379ac7..c2986568eb 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::default_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 b519b579fb..2e8da938a9 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 a4b5ecec12..45092beebd 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, AtomicUsize, 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) } @@ -260,12 +258,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()) } } @@ -273,7 +312,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()) } } @@ -305,14 +344,21 @@ 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. + #[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 { @@ -387,7 +433,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. @@ -396,7 +442,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() @@ -407,7 +453,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 a746f3e578..fcf3de7cc9 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::default_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 7fe7e23494..f1df3207d1 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 9bdcb03528..e7f6697d48 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 a0f2f876f5..3494cfa7ab 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 bb93f700fe..864cc1bba9 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 51cb605697..804723dcbf 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 ea287ca52f..0010eab886 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 0fc7134754..c9047a03b2 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 985e0e1de2..48d6379591 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 9c0b5a2973..56a69ffcd0 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 cbf9699ca8..456d064eb6 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 ee2375d712..1e8b108046 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::default_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::default_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::default_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 ad56438551..59b5694ec4 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 RootAEL, 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), @@ -205,7 +205,7 @@ impl EventLoop { fn single_iteration(&mut self, main_event: Option>, callback: &mut F) where - F: FnMut(event::Event, &RootELW), + F: FnMut(event::Event, &RootAEL), { trace!("Mainloop iteration"); @@ -377,7 +377,7 @@ impl EventLoop { callback: &mut F, ) -> InputStatus where - F: FnMut(event::Event, &RootELW), + F: FnMut(event::Event, &RootAEL), { let mut input_status = InputStatus::Handled; match event { @@ -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) { @@ -508,7 +508,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(event::Event, &RootELW), + F: FnMut(event::Event, &RootAEL), { if !self.loop_running { self.loop_running = true; @@ -541,7 +541,7 @@ impl EventLoop { fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(event::Event, &RootELW), + F: FnMut(event::Event, &RootAEL), { let start = Instant::now(); @@ -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 PlatformSpecificWindowAttributes; 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 cb1a9202ef..49492617b2 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 fe635545b2..eabeb0ae4f 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 aefad6f749..9550d0a5c8 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::{PlatformSpecificWindowAttributes, 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 5b22bd8268..d37b10cdfc 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 PlatformSpecificWindowAttributes { 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 2754360979..e38a088c72 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 PlatformSpecificWindowAttributes { pub name: Option, pub activation_token: Option, #[cfg(x11_platform)] - pub x11: X11WindowBuilderAttributes, + pub x11: X11WindowAttributes, } #[derive(Clone, Debug)] #[cfg(x11_platform)] -pub struct X11WindowBuilderAttributes { +pub struct X11WindowAttributes { 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 PlatformSpecificWindowAttributes { fn default() -> Self { Self { name: None, activation_token: None, #[cfg(x11_platform)] - x11: X11WindowBuilderAttributes { + x11: X11WindowAttributes { 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)), } } } @@ -829,7 +826,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()) } } @@ -852,19 +849,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, } @@ -874,12 +871,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() } } @@ -888,7 +885,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 380c910d39..0842b4c478 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -18,12 +18,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; @@ -62,7 +60,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. @@ -158,7 +156,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, @@ -178,8 +176,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, }, }; @@ -189,7 +187,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) { @@ -216,7 +214,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; @@ -243,7 +241,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(); @@ -319,7 +317,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 @@ -541,11 +539,11 @@ impl EventLoop { // we can't do much about it. if wake_up { match &self.window_target.p { - PlatformEventLoopWindowTarget::Wayland(window_target) => { + PlatformActiveEventLoop::Wayland(window_target) => { window_target.event_loop_awakener.ping(); } #[cfg(x11_platform)] - PlatformEventLoopWindowTarget::X(_) => unreachable!(), + PlatformActiveEventLoop::X(_) => unreachable!(), } } @@ -560,13 +558,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!(), }; @@ -576,7 +574,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!(), }; @@ -589,7 +587,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!(), }; @@ -632,7 +630,7 @@ impl AsRawFd for EventLoop { } } -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { /// The event loop wakeup source. pub event_loop_awakener: calloop::ping::Ping, @@ -656,7 +654,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 2c0d6b5d3d..3e5939f6db 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 d8a9303a33..666c1b38a3 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 c031d3c698..94cdba42fd 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -32,7 +32,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; @@ -80,7 +80,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 e9bab0d798..9937ca92eb 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -25,13 +25,13 @@ use crate::event::{ WindowEvent, }; use crate::event::{InnerSizeWriter, MouseButton}; -use crate::event_loop::EventLoopWindowTarget as RootELW; +use crate::event_loop::ActiveEventLoop as RootAEL; use crate::keyboard::ModifiersState; use crate::platform_impl::common::xkb::{self, XkbState}; use crate::platform_impl::platform::common::xkb::Context; use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest}; -use crate::platform_impl::platform::x11::EventLoopWindowTarget; -use crate::platform_impl::platform::EventLoopWindowTarget as PlatformEventLoopWindowTarget; +use crate::platform_impl::platform::x11::ActiveEventLoop; +use crate::platform_impl::platform::ActiveEventLoop as PlatformActiveEventLoop; use crate::platform_impl::x11::{ atoms::*, mkdid, mkwid, util, CookieResultExt, Device, DeviceId, DeviceInfo, Dnd, DndState, GenericEventCookie, ImeReceiver, ScrollOrientation, UnownedWindow, WindowId, @@ -48,7 +48,7 @@ pub struct EventProcessor { pub devices: RefCell>, pub xi2ext: ExtensionInformation, pub xkbext: ExtensionInformation, - pub target: RootELW, + pub target: RootAEL, pub xkb_context: Context, // Number of touch events currently in progress pub num_touch: u32, @@ -68,7 +68,7 @@ pub struct EventProcessor { impl EventProcessor { pub fn process_event(&mut self, xev: &mut XEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { self.process_xevent(xev, &mut callback); @@ -135,7 +135,7 @@ impl EventProcessor { fn process_xevent(&mut self, xev: &mut XEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { if self.filter_event(xev) { return; @@ -334,18 +334,18 @@ impl EventProcessor { // NOTE: we avoid `self` to not borrow the entire `self` as not mut. /// Get the platform window target. - pub fn window_target(window_target: &RootELW) -> &EventLoopWindowTarget { + pub fn window_target(window_target: &RootAEL) -> &ActiveEventLoop { match &window_target.p { - PlatformEventLoopWindowTarget::X(target) => target, + PlatformActiveEventLoop::X(target) => target, #[cfg(wayland_platform)] _ => unreachable!(), } } /// Get the platform window target. - pub fn window_target_mut(window_target: &mut RootELW) -> &mut EventLoopWindowTarget { + pub fn window_target_mut(window_target: &mut RootAEL) -> &mut ActiveEventLoop { match &mut window_target.p { - PlatformEventLoopWindowTarget::X(target) => target, + PlatformActiveEventLoop::X(target) => target, #[cfg(wayland_platform)] _ => unreachable!(), } @@ -353,7 +353,7 @@ impl EventProcessor { fn client_message(&mut self, xev: &XClientMessageEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); let atoms = wt.xconn.atoms(); @@ -524,7 +524,7 @@ impl EventProcessor { fn selection_notify(&mut self, xev: &XSelectionEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); let atoms = wt.xconn.atoms(); @@ -558,7 +558,7 @@ impl EventProcessor { fn configure_notify(&self, xev: &XConfigureEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -765,7 +765,7 @@ impl EventProcessor { fn map_notify(&self, xev: &XMapEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let window = xev.window as xproto::Window; let window_id = mkwid(window); @@ -788,7 +788,7 @@ impl EventProcessor { fn destroy_notify(&self, xev: &XDestroyWindowEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -818,7 +818,7 @@ impl EventProcessor { fn property_notify(&mut self, xev: &XPropertyEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); let atoms = wt.x_connection().atoms(); @@ -833,7 +833,7 @@ impl EventProcessor { fn visibility_notify(&self, xev: &XVisibilityEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let xwindow = xev.window as xproto::Window; @@ -850,7 +850,7 @@ impl EventProcessor { fn expose(&self, xev: &XExposeEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { // Multiple Expose events may be received for subareas of a window. // We issue `RedrawRequested` only for the last event of such a series. @@ -873,7 +873,7 @@ impl EventProcessor { state: ElementState, mut callback: F, ) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -976,7 +976,7 @@ impl EventProcessor { state: ElementState, mut callback: F, ) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); let window_id = mkwid(event.event as xproto::Window); @@ -1046,7 +1046,7 @@ impl EventProcessor { fn xinput2_mouse_motion(&self, event: &XIDeviceEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -1137,7 +1137,7 @@ impl EventProcessor { fn xinput2_mouse_enter(&self, event: &XIEnterEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -1188,7 +1188,7 @@ impl EventProcessor { fn xinput2_mouse_left(&self, event: &XILeaveEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); let window = event.event as xproto::Window; @@ -1211,7 +1211,7 @@ impl EventProcessor { fn xinput2_focused(&mut self, xev: &XIFocusInEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); let window = xev.event as xproto::Window; @@ -1281,7 +1281,7 @@ impl EventProcessor { fn xinput2_unfocused(&mut self, xev: &XIFocusOutEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); let window = xev.event as xproto::Window; @@ -1337,7 +1337,7 @@ impl EventProcessor { phase: TouchPhase, mut callback: F, ) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -1383,7 +1383,7 @@ impl EventProcessor { state: ElementState, mut callback: F, ) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -1404,7 +1404,7 @@ impl EventProcessor { fn xinput2_raw_mouse_motion(&self, xev: &XIRawEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -1471,7 +1471,7 @@ impl EventProcessor { state: ElementState, mut callback: F, ) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -1499,7 +1499,7 @@ impl EventProcessor { fn xinput2_hierarchy_changed(&mut self, xev: &XIHierarchyEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); @@ -1532,7 +1532,7 @@ impl EventProcessor { fn xkb_event(&mut self, xev: &XkbAnyEvent, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); match xev.xkb_type { @@ -1597,7 +1597,7 @@ impl EventProcessor { group: &XIModifierState, mut callback: F, ) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { if let Some(state) = self.xkb_context.state_mut() { state.update_modifiers( @@ -1616,7 +1616,7 @@ impl EventProcessor { pub fn udpate_mods_from_core_event(&mut self, state: u16, mut callback: F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let xkb_mask = self.xkb_mod_mask_from_core(state); let xkb_state = match self.xkb_context.state_mut() { @@ -1693,7 +1693,7 @@ impl EventProcessor { /// Send modifiers for the active window. /// /// The event won't be sent when the `modifiers` match the previously `sent` modifiers value. - fn send_modifiers)>( + fn send_modifiers)>( &self, modifiers: ModifiersState, callback: &mut F, @@ -1715,13 +1715,13 @@ impl EventProcessor { } fn handle_pressed_keys( - target: &RootELW, + target: &RootAEL, window_id: crate::window::WindowId, state: ElementState, xkb_context: &mut Context, callback: &mut F, ) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD); @@ -1768,7 +1768,7 @@ impl EventProcessor { fn process_dpi_change(&self, callback: &mut F) where - F: FnMut(&RootELW, Event), + F: FnMut(&RootAEL, Event), { let wt = Self::window_target(&self.target); wt.xconn diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 4e97d10b7f..1dfea98d8e 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -32,7 +32,7 @@ use super::{ControlFlow, OsError}; use crate::{ error::{EventLoopError, OsError as RootOsError}, event::{Event, StartCause, WindowEvent}, - event_loop::{DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, + event_loop::{ActiveEventLoop as RootAEL, DeviceEvents, EventLoopClosed}, platform::pump_events::PumpStatus, platform_impl::common::xkb::Context, platform_impl::platform::{min_timeout, WindowId}, @@ -126,7 +126,7 @@ impl PeekableReceiver { } } -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { xconn: Arc, wm_delete_window: xproto::Atom, net_wm_ping: xproto::Atom, @@ -285,7 +285,7 @@ impl EventLoop { let xkb_context = Context::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()), @@ -309,8 +309,8 @@ impl EventLoop { // Set initial device event filter. window_target.update_listen_device_events(true); - let root_window_target = RootELW { - p: super::EventLoopWindowTarget::X(window_target), + let root_window_target = RootAEL { + p: super::ActiveEventLoop::X(window_target), _marker: PhantomData, }; @@ -379,13 +379,13 @@ impl EventLoop { } } - pub(crate) fn window_target(&self) -> &RootELW { + pub(crate) fn window_target(&self) -> &RootAEL { &self.event_processor.target } pub fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &RootAEL), { let exit = loop { match self.pump_events(None, &mut event_handler) { @@ -415,7 +415,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &RootAEL), { if !self.loop_running { self.loop_running = true; @@ -448,7 +448,7 @@ impl EventLoop { pub fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &RootAEL), { let start = Instant::now(); @@ -526,7 +526,7 @@ impl EventLoop { fn single_iteration(&mut self, callback: &mut F, cause: StartCause) where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &RootAEL), { callback(Event::NewEvents(cause), &self.event_processor.target); @@ -600,7 +600,7 @@ impl EventLoop { fn drain_events(&mut self, callback: &mut F) where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &RootAEL), { let mut xev = MaybeUninit::uninit(); @@ -655,7 +655,7 @@ impl AsRawFd for EventLoop { } } -impl EventLoopWindowTarget { +impl ActiveEventLoop { /// Returns the `XConnection` of this events loop. #[inline] pub(crate) fn x_connection(&self) -> &Arc { @@ -815,7 +815,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 027d236420..f85f6a7321 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 12eedb589a..f45dcd3723 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 226cd6212d..bb7e14d23a 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 6ce9383a6a..3d26da1d19 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 bccb048650..8a7d648e66 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 3950507461..2eaa010047 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::PlatformSpecificWindowAttributes, }; use crate::event::DeviceId as RootDeviceId; diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index c269fd7245..a70deacd51 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 9a496aee58..d00257f4cc 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 PlatformSpecificWindowAttributes { 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 PlatformSpecificWindowAttributes { #[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 ae332b6a62..4cd113ca01 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -308,7 +308,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, } @@ -340,8 +340,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()), @@ -544,10 +544,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); }; @@ -754,7 +754,7 @@ impl EventLoop { Ok(()) } - pub fn window_target(&self) -> &event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &event_loop::ActiveEventLoop { &self.window_target } @@ -794,7 +794,7 @@ impl Clone for EventLoopProxy { impl Unpin for EventLoopProxy {} -pub struct EventLoopWindowTarget { +pub struct ActiveEventLoop { control_flow: Cell, exit: Cell, pub(super) creates: Mutex>>, @@ -804,7 +804,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 945da77ec7..a4def5a0ef 100644 --- a/src/platform_impl/orbital/mod.rs +++ b/src/platform_impl/orbital/mod.rs @@ -11,9 +11,7 @@ use crate::{ keyboard::Key, }; -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; @@ -135,7 +133,7 @@ impl DeviceId { } #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] -pub struct PlatformSpecificWindowBuilderAttributes; +pub struct PlatformSpecificWindowAttributes; struct WindowProperties<'a> { flags: &'a str, diff --git a/src/platform_impl/orbital/window.rs b/src/platform_impl/orbital/window.rs index 155abea7db..0352ced29c 100644 --- a/src/platform_impl/orbital/window.rs +++ b/src/platform_impl/orbital/window.rs @@ -13,8 +13,7 @@ use crate::{ }; use super::{ - EventLoopWindowTarget, MonitorHandle, OsError, RedoxSocket, TimeSocket, WindowId, - WindowProperties, + ActiveEventLoop, MonitorHandle, OsError, RedoxSocket, TimeSocket, WindowId, WindowProperties, }; // These values match the values uses in the `window_new` function in orbital: @@ -37,7 +36,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 1ff90ff227..79c1d61b20 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 2cc9d27d52..84cd171559 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 860e9b8449..9f7ea93464 100644 --- a/src/platform_impl/web/event_loop/runner.rs +++ b/src/platform_impl/web/event_loop/runner.rs @@ -214,7 +214,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(); @@ -735,7 +735,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 3b290dd3c1..f5833278a1 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 a70dacd048..7dd019399e 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::{PlatformSpecificWindowAttributes, 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 7f4239360c..9c477221c7 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 PlatformSpecificWindowAttributes { pub(crate) canvas: Option>>, pub(crate) prevent_default: bool, pub(crate) focusable: bool, pub(crate) append: bool, } -impl PlatformSpecificWindowBuilderAttributes { +impl PlatformSpecificWindowAttributes { 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 PlatformSpecificWindowAttributes { 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 7b34ad126c..3d47d91dd8 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 RootAEL, ControlFlow, DeviceEvents, EventLoopClosed}, keyboard::ModifiersState, platform::pump_events::PumpStatus, platform_impl::platform::{ @@ -156,7 +156,7 @@ pub(crate) enum ProcResult { pub struct EventLoop { user_event_sender: Sender, user_event_receiver: Receiver, - window_target: RootELW, + window_target: RootAEL, msg_hook: Option bool + 'static>>, } @@ -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, @@ -215,8 +215,8 @@ impl EventLoop { Ok(EventLoop { user_event_sender, user_event_receiver, - window_target: RootELW { - p: EventLoopWindowTarget { + window_target: RootAEL { + p: ActiveEventLoop { thread_id, thread_msg_target, runner_shared, @@ -227,20 +227,20 @@ impl EventLoop { }) } - pub fn window_target(&self) -> &RootELW { + pub fn window_target(&self) -> &RootAEL { &self.window_target } pub fn run(mut self, event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &RootAEL), { self.run_on_demand(event_handler) } pub fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &RootAEL), { { let runner = &self.window_target.p.runner_shared; @@ -302,7 +302,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut event_handler: F) -> PumpStatus where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &RootAEL), { { let runner = &self.window_target.p.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 9d0329ffca..de8bd4910f 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 706d67dc74..0e600de78d 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 PlatformSpecificWindowAttributes { 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 PlatformSpecificWindowAttributes { 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 PlatformSpecificWindowAttributes {} +unsafe impl Sync for PlatformSpecificWindowAttributes {} #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DeviceId(u32); diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 546128cc23..98637dc3f5 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 6cce1179af..e6cecac464 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, PlatformSpecificWindowAttributes}, }; 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::default_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: PlatformSpecificWindowAttributes, } 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. + /// Initializes new attributes with default values. #[inline] - #[deprecated = "use `Window::builder` instead"] + #[deprecated = "use `Window::default_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 default_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 { /// /// // Submit 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:** 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 a238d5bb1b..b61e2d7525 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 7740b8fc67..49a7b5d00a 100644 --- a/tests/sync_object.rs +++ b/tests/sync_object.rs @@ -18,7 +18,7 @@ fn window_sync() { #[test] fn window_builder_sync() { - needs_sync::(); + needs_sync::(); } #[test]