From 4377680a44ea86dad52954f90bc7d8ad7ed0b4bf Mon Sep 17 00:00:00 2001 From: Osspial Date: Wed, 22 Aug 2018 23:01:36 -0400 Subject: [PATCH] Re-organize into module structure --- examples/cursor.rs | 6 +- examples/cursor_grab.rs | 27 +- examples/fullscreen.rs | 18 +- examples/handling_close.rs | 27 +- examples/min_max_size.rs | 13 +- examples/monitor_list.rs | 6 +- examples/multiwindow.rs | 19 +- examples/proxy.rs | 10 +- examples/request_redraw.rs | 15 +- examples/resizable.rs | 21 +- examples/run_return.rs | 26 +- examples/timer.rs | 8 +- examples/transparent.rs | 13 +- examples/window.rs | 15 +- examples/window_icon.rs | 19 +- src/{events.rs => event.rs} | 12 +- src/event_loop.rs | 151 ++++++++ src/lib.rs | 412 +--------------------- src/monitor.rs | 68 ++++ src/platform/desktop.rs | 3 +- src/platform/windows.rs | 5 +- src/platform_impl/windows/drop_handler.rs | 9 +- src/platform_impl/windows/event.rs | 5 +- src/platform_impl/windows/events_loop.rs | 179 +++++----- src/platform_impl/windows/icon.rs | 2 +- src/platform_impl/windows/mod.rs | 11 +- src/platform_impl/windows/raw_input.rs | 2 +- src/platform_impl/windows/window.rs | 13 +- src/window.rs | 314 +++++++++++++---- tests/send_objects.rs | 10 +- tests/sync_object.rs | 2 +- 31 files changed, 740 insertions(+), 701 deletions(-) rename src/{events.rs => event.rs} (96%) create mode 100644 src/event_loop.rs create mode 100644 src/monitor.rs diff --git a/examples/cursor.rs b/examples/cursor.rs index 81a1a1cd3..31d28aef7 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -1,11 +1,13 @@ extern crate winit; -use winit::{Event, EventLoop, ElementState, MouseCursor, WindowEvent, KeyboardInput, ControlFlow}; +use winit::window::{WindowBuilder, MouseCursor}; +use winit::event::{Event, WindowEvent, ElementState, KeyboardInput}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { let events_loop = EventLoop::new(); - let window = winit::WindowBuilder::new().build(&events_loop).unwrap(); + let window = WindowBuilder::new().build(&events_loop).unwrap(); window.set_title("A fantastic window!"); let mut cursor_idx = 0; diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index 392a68d2e..101cf33fb 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -1,31 +1,34 @@ extern crate winit; -fn main() { - let events_loop = winit::EventLoop::new(); +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent, ElementState, KeyboardInput}; +use winit::event_loop::{EventLoop, ControlFlow}; - let window = winit::WindowBuilder::new() +fn main() { + let events_loop = EventLoop::new(); + + let window = WindowBuilder::new() .with_title("Super Cursor Grab'n'Hide Simulator 9000") .build(&events_loop) .unwrap(); events_loop.run(move |event, _, control_flow| { - *control_flow = winit::ControlFlow::Wait; - if let winit::Event::WindowEvent { event, .. } = event { - use winit::WindowEvent::*; + *control_flow = ControlFlow::Wait; + if let Event::WindowEvent { event, .. } = event { match event { - CloseRequested => *control_flow = winit::ControlFlow::Exit, - KeyboardInput { - input: winit::KeyboardInput { - state: winit::ElementState::Released, + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::KeyboardInput { + input: KeyboardInput { + state: ElementState::Released, virtual_keycode: Some(key), modifiers, .. }, .. } => { - use winit::VirtualKeyCode::*; + use winit::event::VirtualKeyCode::*; match key { - Escape => *control_flow = winit::ControlFlow::Exit, + Escape => *control_flow = ControlFlow::Exit, G => window.grab_cursor(!modifiers.shift).unwrap(), H => window.hide_cursor(!modifiers.shift), _ => (), diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 95afca067..eda82b72a 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -1,10 +1,12 @@ extern crate winit; use std::io::{self, Write}; -use winit::{ControlFlow, Event, WindowEvent}; +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent, VirtualKeyCode, ElementState, KeyboardInput}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { - let events_loop = winit::EventLoop::new(); + let events_loop = EventLoop::new(); // enumerating monitors let monitor = { @@ -25,7 +27,7 @@ fn main() { monitor }; - let window = winit::WindowBuilder::new() + let window = WindowBuilder::new() .with_title("Hello world!") .with_fullscreen(Some(monitor)) .build(&events_loop) @@ -44,15 +46,15 @@ fn main() { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, WindowEvent::KeyboardInput { input: - winit::KeyboardInput { + KeyboardInput { virtual_keycode: Some(virtual_code), state, .. }, .. } => match (virtual_code, state) { - (winit::VirtualKeyCode::Escape, _) => *control_flow = ControlFlow::Exit, - (winit::VirtualKeyCode::F, winit::ElementState::Pressed) => { + (VirtualKeyCode::Escape, _) => *control_flow = ControlFlow::Exit, + (VirtualKeyCode::F, ElementState::Pressed) => { is_fullscreen = !is_fullscreen; if !is_fullscreen { window.set_fullscreen(None); @@ -60,11 +62,11 @@ fn main() { window.set_fullscreen(Some(window.get_current_monitor())); } } - (winit::VirtualKeyCode::M, winit::ElementState::Pressed) => { + (VirtualKeyCode::M, ElementState::Pressed) => { is_maximized = !is_maximized; window.set_maximized(is_maximized); } - (winit::VirtualKeyCode::D, winit::ElementState::Pressed) => { + (VirtualKeyCode::D, ElementState::Pressed) => { decorations = !decorations; window.set_decorations(decorations); } diff --git a/examples/handling_close.rs b/examples/handling_close.rs index b0189c3b7..8702270bc 100644 --- a/examples/handling_close.rs +++ b/examples/handling_close.rs @@ -1,9 +1,13 @@ extern crate winit; -fn main() { - let events_loop = winit::EventLoop::new(); +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent, KeyboardInput}; +use winit::event_loop::{EventLoop, ControlFlow}; - let _window = winit::WindowBuilder::new() +fn main() { + let events_loop = EventLoop::new(); + + let _window = WindowBuilder::new() .with_title("Your faithful window") .build(&events_loop) .unwrap(); @@ -11,13 +15,12 @@ fn main() { let mut close_requested = false; events_loop.run(move |event, _, control_flow| { - use winit::WindowEvent::*; - use winit::ElementState::Released; - use winit::VirtualKeyCode::{N, Y}; + use winit::event::ElementState::Released; + use winit::event::VirtualKeyCode::{N, Y}; match event { - winit::Event::WindowEvent { event, .. } => match event { - CloseRequested => { + Event::WindowEvent { 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 @@ -34,9 +37,9 @@ fn main() { // closing the window. How to close the window is detailed in the handler for // the Y key. } - KeyboardInput { + WindowEvent::KeyboardInput { input: - winit::KeyboardInput { + KeyboardInput { virtual_keycode: Some(virtual_code), state: Released, .. @@ -53,7 +56,7 @@ fn main() { // 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. - *control_flow = winit::ControlFlow::Exit; + *control_flow = ControlFlow::Exit; } } N => { @@ -69,6 +72,6 @@ fn main() { _ => (), } - *control_flow = winit::ControlFlow::Wait; + *control_flow = ControlFlow::Wait; }); } diff --git a/examples/min_max_size.rs b/examples/min_max_size.rs index 88d4823d8..4a8a4e25d 100644 --- a/examples/min_max_size.rs +++ b/examples/min_max_size.rs @@ -1,11 +1,14 @@ extern crate winit; use winit::dpi::LogicalSize; +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { - let events_loop = winit::EventLoop::new(); + let events_loop = EventLoop::new(); - let window = winit::WindowBuilder::new() + let window = WindowBuilder::new() .build(&events_loop) .unwrap(); @@ -16,9 +19,9 @@ fn main() { println!("{:?}", event); match event { - winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => - *control_flow = winit::ControlFlow::Exit, - _ => *control_flow = winit::ControlFlow::Wait, + Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => + *control_flow = ControlFlow::Exit, + _ => *control_flow = ControlFlow::Wait, } }); } diff --git a/examples/monitor_list.rs b/examples/monitor_list.rs index 635f2fb80..335aa0228 100644 --- a/examples/monitor_list.rs +++ b/examples/monitor_list.rs @@ -1,7 +1,9 @@ extern crate winit; +use winit::event_loop::EventLoop; +use winit::window::WindowBuilder; fn main() { - let event_loop = winit::EventLoop::new(); - let window = winit::WindowBuilder::new().build(&event_loop).unwrap(); + let event_loop = EventLoop::new(); + let window = WindowBuilder::new().build(&event_loop).unwrap(); println!("{:#?}\nPrimary: {:#?}", window.get_available_monitors(), window.get_primary_monitor()); } diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index c4278828d..b5774b506 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -1,33 +1,36 @@ extern crate winit; use std::collections::HashMap; +use winit::window::Window; +use winit::event::{Event, WindowEvent, ElementState, KeyboardInput}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { - let events_loop = winit::EventLoop::new(); + let events_loop = EventLoop::new(); let mut windows = HashMap::new(); for _ in 0..3 { - let window = winit::Window::new(&events_loop).unwrap(); + let window = Window::new(&events_loop).unwrap(); windows.insert(window.id(), window); } events_loop.run(move |event, events_loop, control_flow| { - *control_flow = winit::ControlFlow::Wait; + *control_flow = ControlFlow::Wait; match event { - winit::Event::WindowEvent { event, window_id } => { + Event::WindowEvent { event, window_id } => { match event { - winit::WindowEvent::CloseRequested => { + WindowEvent::CloseRequested => { println!("Window {:?} has received the signal to close", window_id); // This drops the window, causing it to close. windows.remove(&window_id); if windows.is_empty() { - *control_flow = winit::ControlFlow::Exit; + *control_flow = ControlFlow::Exit; } }, - winit::WindowEvent::KeyboardInput{..} => { - let window = winit::Window::new(&events_loop).unwrap(); + WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. } => { + let window = Window::new(&events_loop).unwrap(); windows.insert(window.id(), window); }, _ => () diff --git a/examples/proxy.rs b/examples/proxy.rs index fe648ed66..f1106fb89 100644 --- a/examples/proxy.rs +++ b/examples/proxy.rs @@ -1,5 +1,7 @@ extern crate winit; -use winit::{EventLoop, WindowBuilder}; +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { let events_loop: EventLoop = EventLoop::new_user_event(); @@ -24,9 +26,9 @@ fn main() { events_loop.run(move |event, _, control_flow| { println!("{:?}", event); match event { - winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => - *control_flow = winit::ControlFlow::Exit, - _ => *control_flow = winit::ControlFlow::Wait, + Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => + *control_flow = ControlFlow::Exit, + _ => *control_flow = ControlFlow::Wait, } }); } diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs index a870fb8df..2943953b3 100644 --- a/examples/request_redraw.rs +++ b/examples/request_redraw.rs @@ -1,11 +1,14 @@ extern crate winit; -use winit::{Event, WindowEvent}; use std::time::{Instant, Duration}; -fn main() { - let events_loop = winit::EventLoop::new(); +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::{EventLoop, ControlFlow}; - let window = winit::WindowBuilder::new() +fn main() { + let events_loop = EventLoop::new(); + + let window = WindowBuilder::new() .with_title("A fantastic window!") .build(&events_loop) .unwrap(); @@ -17,10 +20,10 @@ fn main() { Event::WindowEvent { event: WindowEvent::CloseRequested, .. - } => *control_flow = winit::ControlFlow::Exit, + } => *control_flow = ControlFlow::Exit, Event::EventsCleared => { window.request_redraw(); - *control_flow = winit::ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0)) + *control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0)) }, _ => () } diff --git a/examples/resizable.rs b/examples/resizable.rs index fd75860d8..b9df0a5f0 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -1,11 +1,14 @@ extern crate winit; +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent, VirtualKeyCode, ElementState, KeyboardInput}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { - let events_loop = winit::EventLoop::new(); + let events_loop = EventLoop::new(); let mut resizable = false; - let window = winit::WindowBuilder::new() + let window = WindowBuilder::new() .with_title("Hit space to toggle resizability.") .with_dimensions((400, 200).into()) .with_resizable(resizable) @@ -13,15 +16,15 @@ fn main() { .unwrap(); events_loop.run(move |event, _, control_flow| { - *control_flow = winit::ControlFlow::Wait; + *control_flow = ControlFlow::Wait; match event { - winit::Event::WindowEvent { event, .. } => match event { - winit::WindowEvent::CloseRequested => *control_flow = winit::ControlFlow::Exit, - winit::WindowEvent::KeyboardInput { + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::KeyboardInput { input: - winit::KeyboardInput { - virtual_keycode: Some(winit::VirtualKeyCode::Space), - state: winit::ElementState::Released, + KeyboardInput { + virtual_keycode: Some(VirtualKeyCode::Space), + state: ElementState::Released, .. }, .. diff --git a/examples/run_return.rs b/examples/run_return.rs index d93b9aa81..d38dcf5c4 100644 --- a/examples/run_return.rs +++ b/examples/run_return.rs @@ -1,10 +1,14 @@ extern crate winit; + +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::{EventLoop, ControlFlow}; use winit::platform::desktop::EventLoopExtDesktop; fn main() { - let mut events_loop = winit::EventLoop::new(); + let mut events_loop = EventLoop::new(); - let window = winit::WindowBuilder::new() + let window = WindowBuilder::new() .with_title("A fantastic window!") .build(&events_loop) .unwrap(); @@ -12,16 +16,16 @@ fn main() { println!("Close the window to continue."); events_loop.run_return(|event, _, control_flow| { match event { - winit::Event::WindowEvent { - event: winit::WindowEvent::CloseRequested, + Event::WindowEvent { + event: WindowEvent::CloseRequested, .. - } => *control_flow = winit::ControlFlow::Exit, - _ => *control_flow = winit::ControlFlow::Wait, + } => *control_flow = ControlFlow::Exit, + _ => *control_flow = ControlFlow::Wait, } }); drop(window); - let _window_2 = winit::WindowBuilder::new() + let _window_2 = WindowBuilder::new() .with_title("A second, fantasticer window!") .build(&events_loop) .unwrap(); @@ -29,11 +33,11 @@ fn main() { println!("Wa ha ha! You thought that closing the window would finish this?!"); events_loop.run_return(|event, _, control_flow| { match event { - winit::Event::WindowEvent { - event: winit::WindowEvent::CloseRequested, + Event::WindowEvent { + event: WindowEvent::CloseRequested, .. - } => *control_flow = winit::ControlFlow::Exit, - _ => *control_flow = winit::ControlFlow::Wait, + } => *control_flow = ControlFlow::Exit, + _ => *control_flow = ControlFlow::Wait, } }); diff --git a/examples/timer.rs b/examples/timer.rs index 3df30c919..fb28a73b8 100644 --- a/examples/timer.rs +++ b/examples/timer.rs @@ -1,11 +1,13 @@ extern crate winit; use std::time::{Duration, Instant}; -use winit::{Event, WindowEvent, StartCause, ControlFlow}; +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent, StartCause}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { - let events_loop = winit::EventLoop::new(); + let events_loop = EventLoop::new(); - let _window = winit::WindowBuilder::new() + let _window = WindowBuilder::new() .with_title("A fantastic window!") .build(&events_loop) .unwrap(); diff --git a/examples/transparent.rs b/examples/transparent.rs index 321b90716..593f2865d 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -1,9 +1,12 @@ extern crate winit; +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { - let events_loop = winit::EventLoop::new(); + let events_loop = EventLoop::new(); - let window = winit::WindowBuilder::new().with_decorations(false) + let window = WindowBuilder::new().with_decorations(false) .with_transparency(true) .build(&events_loop).unwrap(); @@ -13,9 +16,9 @@ fn main() { println!("{:?}", event); match event { - winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => - *control_flow = winit::ControlFlow::Exit, - _ => *control_flow = winit::ControlFlow::Wait, + Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => + *control_flow = ControlFlow::Exit, + _ => *control_flow = ControlFlow::Wait, } }); } diff --git a/examples/window.rs b/examples/window.rs index 5c6f753e8..ef7c790c6 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -1,9 +1,12 @@ extern crate winit; +use winit::window::WindowBuilder; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::{EventLoop, ControlFlow}; fn main() { - let events_loop = winit::EventLoop::new(); + let events_loop = EventLoop::new(); - let _window = winit::WindowBuilder::new() + let _window = WindowBuilder::new() .with_title("A fantastic window!") .build(&events_loop) .unwrap(); @@ -12,11 +15,11 @@ fn main() { println!("{:?}", event); match event { - winit::Event::WindowEvent { - event: winit::WindowEvent::CloseRequested, + Event::WindowEvent { + event: WindowEvent::CloseRequested, .. - } => *control_flow = winit::ControlFlow::Exit, - _ => *control_flow = winit::ControlFlow::Wait, + } => *control_flow = ControlFlow::Exit, + _ => *control_flow = ControlFlow::Wait, } }); } diff --git a/examples/window_icon.rs b/examples/window_icon.rs index 691ec09ad..9db3e0f05 100644 --- a/examples/window_icon.rs +++ b/examples/window_icon.rs @@ -8,7 +8,14 @@ extern crate image; #[cfg(feature = "icon_loading")] fn main() { +<<<<<<< HEAD use winit::Icon; +======= + use winit::window::{WindowBuilder, Icon}; + use winit::event::Event; + use winit::event_loop::{EventLoop, ControlFlow}; + +>>>>>>> Re-organize into module structure // 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 @@ -20,9 +27,9 @@ fn main() { // feature enabled). let icon = Icon::from_path(path).expect("Failed to open icon"); - let events_loop = winit::EventLoop::new(); + let events_loop = EventLoop::new(); - let window = winit::WindowBuilder::new() + let window = WindowBuilder::new() .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. @@ -31,11 +38,11 @@ fn main() { .unwrap(); events_loop.run(move |event, _, control_flow| { - *control_flow = winit::ControlFlow::Wait; - if let winit::Event::WindowEvent { event, .. } = event { - use winit::WindowEvent::*; + *control_flow = ControlFlow::Wait; + if let Event::WindowEvent { event, .. } = event { + use winit::event::WindowEvent::*; match event { - CloseRequested => *control_flow = winit::ControlFlow::Exit, + CloseRequested => *control_flow = ControlFlow::Exit, DroppedFile(path) => { use image::GenericImageView; diff --git a/src/events.rs b/src/event.rs similarity index 96% rename from src/events.rs rename to src/event.rs index dab2d7d06..ad73473d6 100644 --- a/src/events.rs +++ b/src/event.rs @@ -1,7 +1,9 @@ use std::time::Instant; use std::path::PathBuf; -use {DeviceId, LogicalPosition, LogicalSize, WindowId}; +use dpi::{LogicalPosition, LogicalSize}; +use window::WindowId; +use platform_impl; /// Describes a generic event. #[derive(Clone, Debug, PartialEq)] @@ -158,6 +160,14 @@ pub enum WindowEvent { HiDpiFactorChanged(f64), } +/// Identifier of an input device. +/// +/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which +/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or +/// physical. Virtual devices typically aggregate inputs from multiple physical devices. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct DeviceId(pub(crate) platform_impl::DeviceId); + /// Represents raw hardware events that are not associated with any particular window. /// /// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person diff --git a/src/event_loop.rs b/src/event_loop.rs new file mode 100644 index 000000000..3870c70a8 --- /dev/null +++ b/src/event_loop.rs @@ -0,0 +1,151 @@ +use std::{fmt, error}; +use std::time::Instant; + +use platform_impl; +use event::Event; +use monitor::{AvailableMonitorsIter, MonitorId}; + +/// Provides a way to retrieve events from the system and from the windows that were registered to +/// the events loop. +/// +/// An `EventLoop` can be seen more or less as a "context". Calling `EventLoop::new()` +/// initializes everything that will be required to create windows. For example on Linux creating +/// an events loop opens a connection to the X or Wayland server. +/// +/// To wake up an `EventLoop` from a another thread, see the `EventLoopProxy` docs. +/// +/// Note that the `EventLoop` cannot be shared accross threads (due to platform-dependant logic +/// forbiding it), as such it is neither `Send` nor `Sync`. If you need cross-thread access, the +/// `Window` created from this `EventLoop` _can_ be sent to an other thread, and the +/// `EventLoopProxy` allows you to wakeup an `EventLoop` from an other thread. +pub struct EventLoop { + pub(crate) events_loop: platform_impl::EventLoop, + pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync +} + +impl std::fmt::Debug for EventLoop { + fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { + fmtr.pad("EventLoop { .. }") + } +} + +/// Returned by the user callback given to the `EventLoop::run_forever` method. +/// +/// Indicates whether the `run_forever` method should continue or complete. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum ControlFlow { + /// When the current loop iteration finishes, suspend the thread until another event arrives. + Wait, + /// When the current loop iteration finishes, suspend the thread until either another event + /// arrives or the given time is reached. + WaitUntil(Instant), + /// When the current loop iteration finishes, immediately begin a new iteration regardless of + /// whether or not new events are available to process. + Poll, + /// Send a `LoopDestroyed` event and stop the event loop. + Exit +} + +impl Default for ControlFlow { + #[inline(always)] + fn default() -> ControlFlow { + ControlFlow::Poll + } +} + +impl EventLoop<()> { + pub fn new() -> EventLoop<()> { + EventLoop::<()>::new_user_event() + } +} + +impl EventLoop { + /// Builds a new events loop. + /// + /// Usage will result in display backend initialisation, this can be controlled on linux + /// using an environment variable `WINIT_UNIX_BACKEND`. Legal values are `x11` and `wayland`. + /// If it is not set, winit will try to connect to a wayland connection, and if it fails will + /// fallback on x11. If this variable is set with any other value, winit will panic. + pub fn new_user_event() -> EventLoop { + EventLoop { + events_loop: platform_impl::EventLoop::new(), + _marker: ::std::marker::PhantomData, + } + } + + /// Returns the list of all the monitors available on the system. + /// + // Note: should be replaced with `-> impl Iterator` once stable. + #[inline] + pub fn get_available_monitors(&self) -> AvailableMonitorsIter { + let data = self.events_loop.get_available_monitors(); + AvailableMonitorsIter{ data: data.into_iter() } + } + + /// Returns the primary monitor of the system. + #[inline] + pub fn get_primary_monitor(&self) -> MonitorId { + MonitorId { inner: self.events_loop.get_primary_monitor() } + } + + /// Hijacks the calling thread and initializes the `winit` event loop. Can take a + /// `FnMut(Event, &EventLoop) -> ControlFlow` or a custom `EventHandler` type. + /// + /// Any values not passed to this function will *not* be dropped. + #[inline] + pub fn run(self, event_handler: F) -> ! + where F: 'static + FnMut(Event, &EventLoop, &mut ControlFlow) + { + self.events_loop.run(event_handler) + } + + /// Creates an `EventLoopProxy` that can be used to wake up the `EventLoop` from another + /// thread. + pub fn create_proxy(&self) -> EventLoopProxy { + EventLoopProxy { + events_loop_proxy: self.events_loop.create_proxy(), + } + } +} + +/// Used to wake up the `EventLoop` from another thread. +#[derive(Clone)] +pub struct EventLoopProxy { + events_loop_proxy: platform_impl::EventLoopProxy, +} + +impl EventLoopProxy { + /// Send an event to the `EventLoop` from which this proxy was created. This emits a + /// `UserEvent(event)` event in the event loop, where `event` is the value passed to this + /// function. + /// + /// Returns an `Err` if the associated `EventLoop` no longer exists. + pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { + self.events_loop_proxy.send_event(event) + } +} + +impl std::fmt::Debug for EventLoopProxy { + fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { + fmtr.pad("EventLoopProxy { .. }") + } +} + +/// The error that is returned when an `EventLoopProxy` attempts to wake up an `EventLoop` that +/// no longer exists. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct EventLoopClosed; + +impl fmt::Display for EventLoopClosed { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", error::Error::description(self)) + } +} + +impl error::Error for EventLoopClosed { + fn description(&self) -> &str { + "Tried to wake up a closed `EventLoop`" + } +} + diff --git a/src/lib.rs b/src/lib.rs index a06315cf3..d814170b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ //! `EventLoop::new()` function. Example: //! //! ```no_run -//! use winit::EventLoop; +//! use winit::event_loop::EventLoop; //! let events_loop = EventLoop::new(); //! ``` //! @@ -32,8 +32,9 @@ //! stopped by returning `ControlFlow::Exit`, at which point the entire program will terminate. //! //! ```no_run -//! use winit::{ControlFlow, Event, WindowEvent}; -//! # use winit::EventLoop; +//! use winit::event_loop::ControlFlow; +//! use winit::event::{Event, WindowEvent}; +//! # use winit::event_loop::EventLoop; //! # let events_loop = EventLoop::new(); //! //! events_loop.run(move |event, _, control_flow| { @@ -54,7 +55,7 @@ //! # Drawing on the window //! //! Winit doesn't provide any function that allows drawing on a window. However it allows you to -//! retrieve the raw handle of the window (see the `os` module for that), which in turn allows you +//! retrieve the raw handle of the window (see the `platform` module for that), which in turn allows you //! to create an OpenGL/Vulkan/DirectX/Metal/etc. context that will draw on the window. //! @@ -93,407 +94,12 @@ extern crate percent_encoding; #[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))] extern crate smithay_client_toolkit as sctk; -use std::time::Instant; -pub(crate) use dpi::*; // TODO: Actually change the imports throughout the codebase. -pub use events::*; -pub use window::{AvailableMonitorsIter, MonitorId}; -pub use icon::*; - pub mod dpi; -mod events; +pub mod event; +pub mod event_loop; mod icon; mod platform_impl; -mod window; +pub mod window; +pub mod monitor; pub mod platform; - -/// Represents a window. -/// -/// # Example -/// -/// ```no_run -/// use winit::{Event, EventLoop, Window, WindowEvent, ControlFlow}; -/// -/// let mut events_loop = EventLoop::new(); -/// let window = Window::new(&events_loop).unwrap(); -/// -/// events_loop.run(move |event, _, control_flow| { -/// match event { -/// Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { -/// *control_flow = ControlFlow::Exit -/// }, -/// _ => *control_flow = ControlFlow::Wait, -/// } -/// }); -/// ``` -pub struct Window { - window: platform_impl::Window, -} - -impl std::fmt::Debug for Window { - fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { - fmtr.pad("Window { .. }") - } -} - -/// Identifier of a window. Unique for each window. -/// -/// Can be obtained with `window.id()`. -/// -/// Whenever you receive an event specific to a window, this event contains a `WindowId` which you -/// can then compare to the ids of your windows. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct WindowId(platform_impl::WindowId); - -/// Identifier of an input device. -/// -/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which -/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or -/// physical. Virtual devices typically aggregate inputs from multiple physical devices. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct DeviceId(platform_impl::DeviceId); - -/// Provides a way to retrieve events from the system and from the windows that were registered to -/// the events loop. -/// -/// An `EventLoop` can be seen more or less as a "context". Calling `EventLoop::new()` -/// initializes everything that will be required to create windows. For example on Linux creating -/// an events loop opens a connection to the X or Wayland server. -/// -/// To wake up an `EventLoop` from a another thread, see the `EventLoopProxy` docs. -/// -/// Note that the `EventLoop` cannot be shared accross threads (due to platform-dependant logic -/// forbiding it), as such it is neither `Send` nor `Sync`. If you need cross-thread access, the -/// `Window` created from this `EventLoop` _can_ be sent to an other thread, and the -/// `EventLoopProxy` allows you to wakeup an `EventLoop` from an other thread. -pub struct EventLoop { - events_loop: platform_impl::EventLoop, - _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync -} - -impl std::fmt::Debug for EventLoop { - fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { - fmtr.pad("EventLoop { .. }") - } -} - -/// Returned by the user callback given to the `EventLoop::run_forever` method. -/// -/// Indicates whether the `run_forever` method should continue or complete. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum ControlFlow { - /// When the current loop iteration finishes, suspend the thread until another event arrives. - Wait, - /// When the current loop iteration finishes, suspend the thread until either another event - /// arrives or the given time is reached. - WaitUntil(Instant), - /// When the current loop iteration finishes, immediately begin a new iteration regardless of - /// whether or not new events are available to process. - Poll, - /// Send a `LoopDestroyed` event and stop the event loop. - Exit -} - -impl Default for ControlFlow { - #[inline(always)] - fn default() -> ControlFlow { - ControlFlow::Poll - } -} - -impl EventLoop<()> { - pub fn new() -> EventLoop<()> { - EventLoop::<()>::new_user_event() - } -} - -impl EventLoop { - /// Builds a new events loop. - /// - /// Usage will result in display backend initialisation, this can be controlled on linux - /// using an environment variable `WINIT_UNIX_BACKEND`. Legal values are `x11` and `wayland`. - /// If it is not set, winit will try to connect to a wayland connection, and if it fails will - /// fallback on x11. If this variable is set with any other value, winit will panic. - pub fn new_user_event() -> EventLoop { - EventLoop { - events_loop: platform_impl::EventLoop::new(), - _marker: ::std::marker::PhantomData, - } - } - - /// Returns the list of all the monitors available on the system. - /// - // Note: should be replaced with `-> impl Iterator` once stable. - #[inline] - pub fn get_available_monitors(&self) -> AvailableMonitorsIter { - let data = self.events_loop.get_available_monitors(); - AvailableMonitorsIter{ data: data.into_iter() } - } - - /// Returns the primary monitor of the system. - #[inline] - pub fn get_primary_monitor(&self) -> MonitorId { - MonitorId { inner: self.events_loop.get_primary_monitor() } - } - - /// Hijacks the calling thread and initializes the `winit` event loop. Can take a - /// `FnMut(Event, &EventLoop) -> ControlFlow` or a custom `EventHandler` type. - /// - /// Any values not passed to this function will *not* be dropped. - #[inline] - pub fn run(self, event_handler: F) -> ! - where F: 'static + FnMut(Event, &EventLoop, &mut ControlFlow) - { - self.events_loop.run(event_handler) - } - - /// Creates an `EventLoopProxy` that can be used to wake up the `EventLoop` from another - /// thread. - pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy { - events_loop_proxy: self.events_loop.create_proxy(), - } - } -} - -/// Used to wake up the `EventLoop` from another thread. -#[derive(Clone)] -pub struct EventLoopProxy { - events_loop_proxy: platform_impl::EventLoopProxy, -} - -impl std::fmt::Debug for EventLoopProxy { - fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { - fmtr.pad("EventLoopProxy { .. }") - } -} - -impl EventLoopProxy { - /// Send an event to the `EventLoop` from which this proxy was created. This emits a - /// `UserEvent(event)` event in the event loop, where `event` is the value passed to this - /// function. - /// - /// Returns an `Err` if the associated `EventLoop` no longer exists. - pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { - self.events_loop_proxy.send_event(event) - } -} - -/// The error that is returned when an `EventLoopProxy` attempts to wake up an `EventLoop` that -/// no longer exists. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct EventLoopClosed; - -impl std::fmt::Display for EventLoopClosed { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", std::error::Error::description(self)) - } -} - -impl std::error::Error for EventLoopClosed { - fn description(&self) -> &str { - "Tried to wake up a closed `EventLoop`" - } -} - -/// Object that allows you to build windows. -#[derive(Clone)] -pub struct WindowBuilder { - /// The attributes to use to create the window. - pub window: WindowAttributes, - - // Platform-specific configuration. Private. - platform_specific: platform_impl::PlatformSpecificWindowBuilderAttributes, -} - -impl std::fmt::Debug for WindowBuilder { - fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { - fmtr.debug_struct("WindowBuilder") - .field("window", &self.window) - .finish() - } -} - -/// Error that can happen while creating a window or a headless renderer. -#[derive(Debug, Clone)] -pub enum CreationError { - OsError(String), - /// TODO: remove this error - NotSupported, -} - -impl CreationError { - fn to_string(&self) -> &str { - match *self { - CreationError::OsError(ref text) => &text, - CreationError::NotSupported => "Some of the requested attributes are not supported", - } - } -} - -impl std::fmt::Display for CreationError { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - formatter.write_str(self.to_string()) - } -} - -impl std::error::Error for CreationError { - fn description(&self) -> &str { - self.to_string() - } -} - -/// Describes the appearance of the mouse cursor. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum MouseCursor { - /// The platform-dependent default cursor. - Default, - /// A simple crosshair. - Crosshair, - /// A hand (often used to indicate links in web browsers). - Hand, - /// Self explanatory. - Arrow, - /// Indicates something is to be moved. - Move, - /// Indicates text that may be selected or edited. - Text, - /// Program busy indicator. - Wait, - /// Help indicator (often rendered as a "?") - Help, - /// Progress indicator. Shows that processing is being done. But in contrast - /// with "Wait" the user may still interact with the program. Often rendered - /// as a spinning beach ball, or an arrow with a watch or hourglass. - Progress, - - /// Cursor showing that something cannot be done. - NotAllowed, - ContextMenu, - Cell, - VerticalText, - Alias, - Copy, - NoDrop, - Grab, - Grabbing, - AllScroll, - ZoomIn, - ZoomOut, - - /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor - /// is used when the movement starts from the south-east corner of the box. - EResize, - NResize, - NeResize, - NwResize, - SResize, - SeResize, - SwResize, - WResize, - EwResize, - NsResize, - NeswResize, - NwseResize, - ColResize, - RowResize, -} - -impl Default for MouseCursor { - fn default() -> Self { - MouseCursor::Default - } -} - -/// Attributes to use when creating a window. -#[derive(Debug, Clone)] -pub struct WindowAttributes { - /// The dimensions of the window. If this is `None`, some platform-specific dimensions will be - /// used. - /// - /// The default is `None`. - pub dimensions: Option, - - /// The minimum dimensions a window can be, If this is `None`, the window will have no minimum dimensions (aside from reserved). - /// - /// The default is `None`. - pub min_dimensions: Option, - - /// The maximum dimensions a window can be, If this is `None`, the maximum will have no maximum or will be set to the primary monitor's dimensions by the platform. - /// - /// The default is `None`. - pub max_dimensions: Option, - - /// Whether the window is resizable or not. - /// - /// The default is `true`. - pub resizable: bool, - - /// Whether the window should be set as fullscreen upon creation. - /// - /// The default is `None`. - pub fullscreen: Option, - - /// The title of the window in the title bar. - /// - /// The default is `"winit window"`. - pub title: String, - - /// Whether the window should be maximized upon creation. - /// - /// The default is `false`. - pub maximized: bool, - - /// Whether the window should be immediately visible upon creation. - /// - /// The default is `true`. - pub visible: bool, - - /// Whether the the window should be transparent. If this is true, writing colors - /// with alpha values different than `1.0` will produce a transparent window. - /// - /// The default is `false`. - pub transparent: bool, - - /// Whether the window should have borders and bars. - /// - /// The default is `true`. - pub decorations: bool, - - /// Whether the window should always be on top of other windows. - /// - /// The default is `false`. - pub always_on_top: bool, - - /// The window icon. - /// - /// The default is `None`. - pub window_icon: Option, - - /// [iOS only] Enable multitouch, - /// see [multipleTouchEnabled](https://developer.apple.com/documentation/uikit/uiview/1622519-multipletouchenabled) - pub multitouch: bool, -} - -impl Default for WindowAttributes { - #[inline] - fn default() -> WindowAttributes { - WindowAttributes { - dimensions: None, - min_dimensions: None, - max_dimensions: None, - resizable: true, - title: "winit window".to_owned(), - maximized: false, - fullscreen: None, - visible: true, - transparent: false, - decorations: true, - always_on_top: false, - window_icon: None, - multitouch: false, - } - } -} diff --git a/src/monitor.rs b/src/monitor.rs new file mode 100644 index 000000000..4697b1f84 --- /dev/null +++ b/src/monitor.rs @@ -0,0 +1,68 @@ +use std::collections::vec_deque::IntoIter as VecDequeIter; + +use platform_impl; +use dpi::{PhysicalPosition, PhysicalSize}; + +/// An iterator for the list of available monitors. +// Implementation note: we retrieve the list once, then serve each element by one by one. +// This may change in the future. +#[derive(Debug)] +pub struct AvailableMonitorsIter { + pub(crate) data: VecDequeIter, +} + +impl Iterator for AvailableMonitorsIter { + type Item = MonitorId; + + #[inline] + fn next(&mut self) -> Option { + self.data.next().map(|id| MonitorId { inner: id }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.data.size_hint() + } +} + +/// Identifier for a monitor. +#[derive(Debug, Clone)] +pub struct MonitorId { + pub(crate) inner: platform_impl::MonitorId +} + +impl MonitorId { + /// Returns a human-readable name of the monitor. + /// + /// Returns `None` if the monitor doesn't exist anymore. + #[inline] + pub fn get_name(&self) -> Option { + self.inner.get_name() + } + + /// Returns the monitor's resolution. + #[inline] + pub fn get_dimensions(&self) -> PhysicalSize { + self.inner.get_dimensions() + } + + /// Returns the top-left corner position of the monitor relative to the larger full + /// screen area. + #[inline] + pub fn get_position(&self) -> PhysicalPosition { + self.inner.get_position() + } + + /// Returns the DPI factor that can be used to map logical pixels to physical pixels, and vice versa. + /// + /// See the [`dpi`](dpi/index.html) module for more information. + /// + /// ## Platform-specific + /// + /// - **X11:** Can be overridden using the `WINIT_HIDPI_FACTOR` environment variable. + /// - **Android:** Always returns 1.0. + #[inline] + pub fn get_hidpi_factor(&self) -> f64 { + self.inner.get_hidpi_factor() + } +} diff --git a/src/platform/desktop.rs b/src/platform/desktop.rs index 5ab9be666..51da32010 100644 --- a/src/platform/desktop.rs +++ b/src/platform/desktop.rs @@ -4,7 +4,8 @@ target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] -use {EventLoop, Event, ControlFlow}; +use event::Event; +use event_loop::{EventLoop, ControlFlow}; /// Additional methods on `EventLoop` that are specific to desktop platforms. pub trait EventLoopExtDesktop { diff --git a/src/platform/windows.rs b/src/platform/windows.rs index b792d9aa8..3a4e08bab 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -5,7 +5,10 @@ use std::os::raw::c_void; use libc; use winapi::shared::windef::HWND; -use {DeviceId, EventLoop, Icon, MonitorId, Window, WindowBuilder}; +use event::DeviceId; +use monitor::MonitorId; +use event_loop::EventLoop; +use window::{Icon, Window, WindowBuilder}; use platform_impl::EventLoop as WindowsEventLoop; /// Additional methods on `EventLoop` that are specific to Windows. diff --git a/src/platform_impl/windows/drop_handler.rs b/src/platform_impl/windows/drop_handler.rs index 0d94c1234..188d7be0c 100644 --- a/src/platform_impl/windows/drop_handler.rs +++ b/src/platform_impl/windows/drop_handler.rs @@ -17,7 +17,8 @@ use winapi::um::{shellapi, unknwnbase}; use platform_impl::platform::WindowId; -use {Event, WindowId as SuperWindowId}; +use event::Event; +use window::WindowId as SuperWindowId; #[repr(C)] pub struct FileDropHandlerData { @@ -81,7 +82,7 @@ impl FileDropHandler { _pt: *const POINTL, _pdwEffect: *mut DWORD, ) -> HRESULT { - use events::WindowEvent::HoveredFile; + use event::WindowEvent::HoveredFile; let drop_handler = Self::from_interface(this); Self::iterate_filenames(pDataObj, |filename| { drop_handler.send_event(Event::WindowEvent { @@ -103,7 +104,7 @@ impl FileDropHandler { } pub unsafe extern "system" fn DragLeave(this: *mut IDropTarget) -> HRESULT { - use events::WindowEvent::HoveredFileCancelled; + use event::WindowEvent::HoveredFileCancelled; let drop_handler = Self::from_interface(this); drop_handler.send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(drop_handler.window)), @@ -120,7 +121,7 @@ impl FileDropHandler { _pt: *const POINTL, _pdwEffect: *mut DWORD, ) -> HRESULT { - use events::WindowEvent::DroppedFile; + use event::WindowEvent::DroppedFile; let drop_handler = Self::from_interface(this); let hdrop = Self::iterate_filenames(pDataObj, |filename| { drop_handler.send_event(Event::WindowEvent { diff --git a/src/platform_impl/windows/event.rs b/src/platform_impl/windows/event.rs index dfdff6ee6..60e1b910f 100644 --- a/src/platform_impl/windows/event.rs +++ b/src/platform_impl/windows/event.rs @@ -1,14 +1,11 @@ use std::char; use std::os::raw::c_int; -use events::VirtualKeyCode; -use events::ModifiersState; +use event::{ScanCode, ModifiersState, VirtualKeyCode}; use winapi::shared::minwindef::{WPARAM, LPARAM, UINT}; use winapi::um::winuser; -use ScanCode; - pub fn get_key_mods() -> ModifiersState { let mut mods = ModifiersState::default(); unsafe { diff --git a/src/platform_impl/windows/events_loop.rs b/src/platform_impl/windows/events_loop.rs index dba70c059..5cafe32d0 100644 --- a/src/platform_impl/windows/events_loop.rs +++ b/src/platform_impl/windows/events_loop.rs @@ -40,18 +40,11 @@ use winapi::shared::windowsx; use winapi::um::{winuser, winbase, ole2, processthreadsapi, commctrl, libloaderapi}; use winapi::um::winnt::{LONG, LPCSTR, SHORT}; -use { - ControlFlow, - Event, - EventLoopClosed, - KeyboardInput, - LogicalPosition, - LogicalSize, - PhysicalSize, - WindowEvent, - WindowId as SuperWindowId, -}; -use events::{DeviceEvent, Touch, TouchPhase, StartCause}; +use window::WindowId as RootWindowId; +use monitor::MonitorId; +use event_loop::{ControlFlow, EventLoop as RootEventLoop, EventLoopClosed}; +use dpi::{LogicalPosition, LogicalSize, PhysicalSize}; +use event::{DeviceEvent, Touch, TouchPhase, StartCause, KeyboardInput, Event, WindowEvent}; use platform_impl::platform::{event, Cursor, WindowId, DEVICE_ID, wrap_device_id, util}; use platform_impl::platform::dpi::{ become_dpi_aware, @@ -98,7 +91,7 @@ pub struct WindowState { // This is different from the value in `SavedWindowInfo`! That one represents the DPI saved upon entering // fullscreen. This will always be the most recent DPI for the window. pub dpi_factor: f64, - pub fullscreen: Option<::MonitorId>, + pub fullscreen: Option, pub window_icon: Option, pub taskbar_icon: Option, pub decorations: bool, @@ -183,14 +176,14 @@ impl EventLoop { } pub fn run(mut self, event_handler: F) -> ! - where F: 'static + FnMut(Event, &::EventLoop, &mut ControlFlow) + where F: 'static + FnMut(Event, &RootEventLoop, &mut ControlFlow) { self.run_return(event_handler); ::std::process::exit(0); } pub fn run_return(&mut self, mut event_handler: F) - where F: FnMut(Event, &::EventLoop, &mut ControlFlow) + where F: FnMut(Event, &RootEventLoop, &mut ControlFlow) { unsafe{ winuser::IsGUIThread(1); } let mut runner = EventLoopRunner { @@ -201,8 +194,8 @@ impl EventLoop { event_handler: unsafe { // Transmute used to erase lifetimes. mem::transmute::< - &mut FnMut(Event, &::EventLoop, &mut ControlFlow), - *mut FnMut(Event, &::EventLoop, &mut ControlFlow) + &mut FnMut(Event, &RootEventLoop, &mut ControlFlow), + *mut FnMut(Event, &RootEventLoop, &mut ControlFlow) >(&mut event_handler) } }; @@ -294,7 +287,7 @@ pub(crate) struct EventLoopRunner { control_flow: ControlFlow, runner_state: RunnerState, modal_loop_data: Option, - event_handler: *mut FnMut(Event, &::EventLoop, &mut ControlFlow) + event_handler: *mut FnMut(Event, &RootEventLoop, &mut ControlFlow) } struct ModalLoopData { @@ -468,8 +461,8 @@ impl EventLoopRunner { _ => () } - assert_eq!(mem::size_of::<::EventLoop>(), mem::size_of::>()); - let event_loop_ref = &*(self.event_loop as *const ::EventLoop); + assert_eq!(mem::size_of::>(), mem::size_of::>()); + let event_loop_ref = &*(self.event_loop as *const RootEventLoop); if self.control_flow != ControlFlow::Exit { (*self.event_handler)(event, event_loop_ref, &mut self.control_flow); @@ -800,16 +793,16 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_CLOSE => { - use events::WindowEvent::CloseRequested; + use event::WindowEvent::CloseRequested; subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: CloseRequested }); 0 }, winuser::WM_DESTROY => { - use events::WindowEvent::Destroyed; + use event::WindowEvent::Destroyed; ole2::RevokeDragDrop(window); { let window_state = subclass_input.window_state.lock(); @@ -818,7 +811,7 @@ unsafe extern "system" fn public_window_callback( } } subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: Destroyed }); @@ -828,14 +821,14 @@ unsafe extern "system" fn public_window_callback( }, _ if msg == *REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID => { - use events::WindowEvent::RedrawRequested; + use event::WindowEvent::RedrawRequested; let runner = subclass_input.event_loop_runner.borrow_mut(); if let ELRSharedOption::Runner(runner) = *runner { let runner = &mut *runner; match runner.runner_state { RunnerState::Idle(..) | RunnerState::DeferredNewEvents(..) => runner.call_event_handler(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: RedrawRequested, }), _ => () @@ -844,9 +837,9 @@ unsafe extern "system" fn public_window_callback( 0 }, winuser::WM_PAINT => { - use events::WindowEvent::RedrawRequested; + use event::WindowEvent::RedrawRequested; let event = || Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: RedrawRequested, }; @@ -870,7 +863,7 @@ unsafe extern "system" fn public_window_callback( // WM_MOVE supplies client area positions, so we send Moved here instead. winuser::WM_WINDOWPOSCHANGED => { - use events::WindowEvent::Moved; + use event::WindowEvent::Moved; let windowpos = lparam as *const winuser::WINDOWPOS; if (*windowpos).flags & winuser::SWP_NOMOVE != winuser::SWP_NOMOVE { @@ -880,7 +873,7 @@ unsafe extern "system" fn public_window_callback( dpi_factor, ); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: Moved(logical_position), }); } @@ -890,14 +883,14 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_SIZE => { - use events::WindowEvent::Resized; + use event::WindowEvent::Resized; let w = LOWORD(lparam as DWORD) as u32; let h = HIWORD(lparam as DWORD) as u32; let dpi_factor = get_hwnd_scale_factor(window); let logical_size = LogicalSize::from_physical((w, h), dpi_factor); let event = Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: Resized(logical_size), }; @@ -907,10 +900,10 @@ unsafe extern "system" fn public_window_callback( winuser::WM_CHAR => { use std::mem; - use events::WindowEvent::ReceivedCharacter; + use event::WindowEvent::ReceivedCharacter; let chr: char = mem::transmute(wparam as u32); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: ReceivedCharacter(chr), }); 0 @@ -925,7 +918,7 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_MOUSEMOVE => { - use events::WindowEvent::{CursorEntered, CursorMoved}; + use event::WindowEvent::{CursorEntered, CursorMoved}; let mouse_outside_window = { let mut window = subclass_input.window_state.lock(); if !window.mouse_in_window { @@ -938,7 +931,7 @@ unsafe extern "system" fn public_window_callback( if mouse_outside_window { subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: CursorEntered { device_id: DEVICE_ID }, }); @@ -957,7 +950,7 @@ unsafe extern "system" fn public_window_callback( let position = LogicalPosition::from_physical((x, y), dpi_factor); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: CursorMoved { device_id: DEVICE_ID, position, modifiers: event::get_key_mods() }, }); @@ -965,7 +958,7 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_MOUSELEAVE => { - use events::WindowEvent::CursorLeft; + use event::WindowEvent::CursorLeft; let mouse_in_window = { let mut window = subclass_input.window_state.lock(); if window.mouse_in_window { @@ -978,7 +971,7 @@ unsafe extern "system" fn public_window_callback( if mouse_in_window { subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: CursorLeft { device_id: DEVICE_ID } }); } @@ -987,15 +980,15 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_MOUSEWHEEL => { - use events::MouseScrollDelta::LineDelta; - use events::TouchPhase; + use event::MouseScrollDelta::LineDelta; + use event::TouchPhase; let value = (wparam >> 16) as i16; let value = value as i32; let value = value as f32 / winuser::WHEEL_DELTA as f32; subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: WindowEvent::MouseWheel { device_id: DEVICE_ID, delta: LineDelta(0.0, value), phase: TouchPhase::Moved, modifiers: event::get_key_mods() }, }); @@ -1003,14 +996,14 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_KEYDOWN | winuser::WM_SYSKEYDOWN => { - use events::ElementState::Pressed; - use events::VirtualKeyCode; + use event::ElementState::Pressed; + use event::VirtualKeyCode; if msg == winuser::WM_SYSKEYDOWN && wparam as i32 == winuser::VK_F4 { commctrl::DefSubclassProc(window, msg, wparam, lparam) } else { if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: WindowEvent::KeyboardInput { device_id: DEVICE_ID, input: KeyboardInput { @@ -1025,7 +1018,7 @@ unsafe extern "system" fn public_window_callback( // consistent with the other platforms we'll emit a delete character here. if vkey == Some(VirtualKeyCode::Delete) { subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: WindowEvent::ReceivedCharacter('\u{7F}'), }); } @@ -1035,10 +1028,10 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_KEYUP | winuser::WM_SYSKEYUP => { - use events::ElementState::Released; + use event::ElementState::Released; if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: WindowEvent::KeyboardInput { device_id: DEVICE_ID, input: KeyboardInput { @@ -1054,114 +1047,114 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_LBUTTONDOWN => { - use events::WindowEvent::MouseInput; - use events::MouseButton::Left; - use events::ElementState::Pressed; + use event::WindowEvent::MouseInput; + use event::MouseButton::Left; + use event::ElementState::Pressed; capture_mouse(window, &mut *subclass_input.window_state.lock()); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Left, modifiers: event::get_key_mods() } }); 0 }, winuser::WM_LBUTTONUP => { - use events::WindowEvent::MouseInput; - use events::MouseButton::Left; - use events::ElementState::Released; + use event::WindowEvent::MouseInput; + use event::MouseButton::Left; + use event::ElementState::Released; release_mouse(&mut *subclass_input.window_state.lock()); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Released, button: Left, modifiers: event::get_key_mods() } }); 0 }, winuser::WM_RBUTTONDOWN => { - use events::WindowEvent::MouseInput; - use events::MouseButton::Right; - use events::ElementState::Pressed; + use event::WindowEvent::MouseInput; + use event::MouseButton::Right; + use event::ElementState::Pressed; capture_mouse(window, &mut *subclass_input.window_state.lock()); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Right, modifiers: event::get_key_mods() } }); 0 }, winuser::WM_RBUTTONUP => { - use events::WindowEvent::MouseInput; - use events::MouseButton::Right; - use events::ElementState::Released; + use event::WindowEvent::MouseInput; + use event::MouseButton::Right; + use event::ElementState::Released; release_mouse(&mut *subclass_input.window_state.lock()); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Released, button: Right, modifiers: event::get_key_mods() } }); 0 }, winuser::WM_MBUTTONDOWN => { - use events::WindowEvent::MouseInput; - use events::MouseButton::Middle; - use events::ElementState::Pressed; + use event::WindowEvent::MouseInput; + use event::MouseButton::Middle; + use event::ElementState::Pressed; capture_mouse(window, &mut *subclass_input.window_state.lock()); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Middle, modifiers: event::get_key_mods() } }); 0 }, winuser::WM_MBUTTONUP => { - use events::WindowEvent::MouseInput; - use events::MouseButton::Middle; - use events::ElementState::Released; + use event::WindowEvent::MouseInput; + use event::MouseButton::Middle; + use event::ElementState::Released; release_mouse(&mut *subclass_input.window_state.lock()); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Released, button: Middle, modifiers: event::get_key_mods() } }); 0 }, winuser::WM_XBUTTONDOWN => { - use events::WindowEvent::MouseInput; - use events::MouseButton::Other; - use events::ElementState::Pressed; + use event::WindowEvent::MouseInput; + use event::MouseButton::Other; + use event::ElementState::Pressed; let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); capture_mouse(window, &mut *subclass_input.window_state.lock()); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Other(xbutton as u8), modifiers: event::get_key_mods() } }); 0 }, winuser::WM_XBUTTONUP => { - use events::WindowEvent::MouseInput; - use events::MouseButton::Other; - use events::ElementState::Released; + use event::WindowEvent::MouseInput; + use event::MouseButton::Other; + use event::ElementState::Released; let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); release_mouse(&mut *subclass_input.window_state.lock()); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Released, button: Other(xbutton as u8), modifiers: event::get_key_mods() } }); 0 @@ -1183,9 +1176,9 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_INPUT => { - use events::DeviceEvent::{Motion, MouseMotion, MouseWheel, Button, Key}; - use events::MouseScrollDelta::LineDelta; - use events::ElementState::{Pressed, Released}; + use event::DeviceEvent::{Motion, MouseMotion, MouseWheel, Button, Key}; + use event::MouseScrollDelta::LineDelta; + use event::ElementState::{Pressed, Released}; if let Some(data) = get_raw_input_data(lparam as _) { let device_id = wrap_device_id(data.header.hDevice as _); @@ -1303,7 +1296,7 @@ unsafe extern "system" fn public_window_callback( let y = (input.y as f64) / 100f64; let location = LogicalPosition::from_physical((x, y), dpi_factor); subclass_input.send_event( Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: WindowEvent::Touch(Touch { phase: if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 { @@ -1327,9 +1320,9 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_SETFOCUS => { - use events::WindowEvent::{Focused, CursorMoved}; + use event::WindowEvent::{Focused, CursorMoved}; subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: Focused(true) }); @@ -1339,7 +1332,7 @@ unsafe extern "system" fn public_window_callback( let position = LogicalPosition::from_physical((x, y), dpi_factor); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: CursorMoved { device_id: DEVICE_ID, position, modifiers: event::get_key_mods() }, }); @@ -1347,9 +1340,9 @@ unsafe extern "system" fn public_window_callback( }, winuser::WM_KILLFOCUS => { - use events::WindowEvent::Focused; + use event::WindowEvent::Focused; subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: Focused(false) }); 0 @@ -1406,7 +1399,7 @@ unsafe extern "system" fn public_window_callback( // Only sent on Windows 8.1 or newer. On Windows 7 and older user has to log out to change // DPI, therefore all applications are closed while DPI is changing. winuser::WM_DPICHANGED => { - use events::WindowEvent::HiDpiFactorChanged; + use event::WindowEvent::HiDpiFactorChanged; // This message actually provides two DPI values - x and y. However MSDN says that // "you only need to use either the X-axis or the Y-axis value when scaling your @@ -1454,7 +1447,7 @@ unsafe extern "system" fn public_window_callback( } subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: HiDpiFactorChanged(new_dpi_factor), }); @@ -1466,10 +1459,10 @@ unsafe extern "system" fn public_window_callback( winuser::DestroyWindow(window); 0 } else if msg == *INITIAL_DPI_MSG_ID { - use events::WindowEvent::HiDpiFactorChanged; + use event::WindowEvent::HiDpiFactorChanged; let scale_factor = dpi_to_scale_factor(wparam as u32); subclass_input.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(window)), + window_id: RootWindowId(WindowId(window)), event: HiDpiFactorChanged(scale_factor), }); // Automatically resize for actual DPI diff --git a/src/platform_impl/windows/icon.rs b/src/platform_impl/windows/icon.rs index fb265c929..c45bdf6fd 100644 --- a/src/platform_impl/windows/icon.rs +++ b/src/platform_impl/windows/icon.rs @@ -7,7 +7,7 @@ use winapi::shared::minwindef::{BYTE, LPARAM, WPARAM}; use winapi::shared::windef::{HICON, HWND}; use winapi::um::winuser; -use {Pixel, PIXEL_SIZE, Icon}; +use icon::{Pixel, PIXEL_SIZE, Icon}; use platform_impl::platform::util; impl Pixel { diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 0e981e091..02b18770d 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -7,10 +7,13 @@ pub use self::events_loop::{EventLoop, EventLoopProxy}; pub use self::monitor::MonitorId; pub use self::window::Window; +use window::Icon; +use event::DeviceId as RootDeviceId; + #[derive(Clone, Default)] pub struct PlatformSpecificWindowBuilderAttributes { pub parent: Option, - pub taskbar_icon: Option<::Icon>, + pub taskbar_icon: Option, pub no_redirection_bitmap: bool, } @@ -37,10 +40,10 @@ impl DeviceId { } // Constant device ID, to be removed when this backend is updated to report real device IDs. -const DEVICE_ID: ::DeviceId = ::DeviceId(DeviceId(0)); +const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId(0)); -fn wrap_device_id(id: u32) -> ::DeviceId { - ::DeviceId(DeviceId(id)) +fn wrap_device_id(id: u32) -> RootDeviceId { + RootDeviceId(DeviceId(id)) } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/src/platform_impl/windows/raw_input.rs b/src/platform_impl/windows/raw_input.rs index 12664435b..03c26d11d 100644 --- a/src/platform_impl/windows/raw_input.rs +++ b/src/platform_impl/windows/raw_input.rs @@ -32,7 +32,7 @@ use winapi::um::winuser::{ }; use platform_impl::platform::util; -use events::ElementState; +use event::ElementState; #[allow(dead_code)] pub fn get_raw_input_device_list() -> Option> { diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index aed979a57..37d1f3386 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -18,16 +18,9 @@ use winapi::um::wingdi::{CreateRectRgn, DeleteObject}; use winapi::um::oleidl::LPDROPTARGET; use winapi::um::winnt::{LONG, LPCWSTR}; -use { - CreationError, - Icon, - LogicalPosition, - LogicalSize, - MonitorId as RootMonitorId, - MouseCursor, - PhysicalSize, - WindowAttributes, -}; +use window::{CreationError, Icon, WindowAttributes, MouseCursor}; +use dpi::{LogicalPosition, LogicalSize, PhysicalSize}; +use monitor::MonitorId as RootMonitorId; use platform_impl::platform::{Cursor, PlatformSpecificWindowBuilderAttributes, WindowId}; use platform_impl::platform::dpi::{dpi_to_scale_factor, get_hwnd_dpi}; use platform_impl::platform::events_loop::{self, EventLoop, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID, REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID}; diff --git a/src/window.rs b/src/window.rs index d80807e80..36652072e 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,20 +1,160 @@ -use std::collections::vec_deque::IntoIter as VecDequeIter; +use std::{fmt, error}; -use { - CreationError, - EventLoop, - Icon, - LogicalPosition, - LogicalSize, - MouseCursor, - PhysicalPosition, - PhysicalSize, - platform_impl, - Window, - WindowBuilder, - WindowId, -}; +use platform_impl; +use event_loop::EventLoop; +use monitor::{AvailableMonitorsIter, MonitorId}; +use dpi::{LogicalPosition, LogicalSize}; +pub use icon::*; + +/// Represents a window. +/// +/// # Example +/// +/// ```no_run +/// use winit::window::Window; +/// use winit::event::{Event, WindowEvent}; +/// use winit::event_loop::{EventLoop, ControlFlow}; +/// +/// let mut events_loop = EventLoop::new(); +/// let window = Window::new(&events_loop).unwrap(); +/// +/// events_loop.run(move |event, _, control_flow| { +/// match event { +/// Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { +/// *control_flow = ControlFlow::Exit +/// }, +/// _ => *control_flow = ControlFlow::Wait, +/// } +/// }); +/// ``` +pub struct Window { + pub(crate) window: platform_impl::Window, +} + +impl std::fmt::Debug for Window { + fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { + fmtr.pad("Window { .. }") + } +} + +/// Identifier of a window. Unique for each window. +/// +/// Can be obtained with `window.id()`. +/// +/// Whenever you receive an event specific to a window, this event contains a `WindowId` which you +/// can then compare to the ids of your windows. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WindowId(pub(crate) platform_impl::WindowId); + +/// Object that allows you to build windows. +#[derive(Clone)] +pub struct WindowBuilder { + /// The attributes to use to create the window. + pub window: WindowAttributes, + + // Platform-specific configuration. Private. + pub(crate) platform_specific: platform_impl::PlatformSpecificWindowBuilderAttributes, +} + +impl std::fmt::Debug for WindowBuilder { + fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { + fmtr.debug_struct("WindowBuilder") + .field("window", &self.window) + .finish() + } +} + +/// Attributes to use when creating a window. +#[derive(Debug, Clone)] +pub struct WindowAttributes { + /// The dimensions of the window. If this is `None`, some platform-specific dimensions will be + /// used. + /// + /// The default is `None`. + pub dimensions: Option, + + /// The minimum dimensions a window can be, If this is `None`, the window will have no minimum dimensions (aside from reserved). + /// + /// The default is `None`. + pub min_dimensions: Option, + + /// The maximum dimensions a window can be, If this is `None`, the maximum will have no maximum or will be set to the primary monitor's dimensions by the platform. + /// + /// The default is `None`. + pub max_dimensions: Option, + + /// Whether the window is resizable or not. + /// + /// The default is `true`. + pub resizable: bool, + + /// Whether the window should be set as fullscreen upon creation. + /// + /// The default is `None`. + pub fullscreen: Option, + + /// The title of the window in the title bar. + /// + /// The default is `"winit window"`. + pub title: String, + + /// Whether the window should be maximized upon creation. + /// + /// The default is `false`. + pub maximized: bool, + + /// Whether the window should be immediately visible upon creation. + /// + /// The default is `true`. + pub visible: bool, + + /// Whether the the window should be transparent. If this is true, writing colors + /// with alpha values different than `1.0` will produce a transparent window. + /// + /// The default is `false`. + pub transparent: bool, + + /// Whether the window should have borders and bars. + /// + /// The default is `true`. + pub decorations: bool, + + /// Whether the window should always be on top of other windows. + /// + /// The default is `false`. + pub always_on_top: bool, + + /// The window icon. + /// + /// The default is `None`. + pub window_icon: Option, + + /// [iOS only] Enable multitouch, + /// see [multipleTouchEnabled](https://developer.apple.com/documentation/uikit/uiview/1622519-multipletouchenabled) + pub multitouch: bool, +} + +impl Default for WindowAttributes { + #[inline] + fn default() -> WindowAttributes { + WindowAttributes { + dimensions: None, + min_dimensions: None, + max_dimensions: None, + resizable: true, + title: "winit window".to_owned(), + maximized: false, + fullscreen: None, + visible: true, + transparent: false, + decorations: true, + always_on_top: false, + window_icon: None, + multitouch: false, + } + } +} impl WindowBuilder { /// Initializes a new `WindowBuilder` with default values. #[inline] @@ -444,66 +584,94 @@ impl Window { } } -/// An iterator for the list of available monitors. -// Implementation note: we retrieve the list once, then serve each element by one by one. -// This may change in the future. -#[derive(Debug)] -pub struct AvailableMonitorsIter { - pub(crate) data: VecDequeIter, -} - -impl Iterator for AvailableMonitorsIter { - type Item = MonitorId; - - #[inline] - fn next(&mut self) -> Option { - self.data.next().map(|id| MonitorId { inner: id }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.data.size_hint() - } -} - -/// Identifier for a monitor. +/// Error that can happen while creating a window or a headless renderer. #[derive(Debug, Clone)] -pub struct MonitorId { - pub(crate) inner: platform_impl::MonitorId +pub enum CreationError { + OsError(String), + /// TODO: remove this error + NotSupported, } -impl MonitorId { - /// Returns a human-readable name of the monitor. - /// - /// Returns `None` if the monitor doesn't exist anymore. - #[inline] - pub fn get_name(&self) -> Option { - self.inner.get_name() - } - - /// Returns the monitor's resolution. - #[inline] - pub fn get_dimensions(&self) -> PhysicalSize { - self.inner.get_dimensions() - } - - /// Returns the top-left corner position of the monitor relative to the larger full - /// screen area. - #[inline] - pub fn get_position(&self) -> PhysicalPosition { - self.inner.get_position() - } - - /// Returns the DPI factor that can be used to map logical pixels to physical pixels, and vice versa. - /// - /// See the [`dpi`](dpi/index.html) module for more information. - /// - /// ## Platform-specific - /// - /// - **X11:** Can be overridden using the `WINIT_HIDPI_FACTOR` environment variable. - /// - **Android:** Always returns 1.0. - #[inline] - pub fn get_hidpi_factor(&self) -> f64 { - self.inner.get_hidpi_factor() +impl CreationError { + fn to_string(&self) -> &str { + match *self { + CreationError::OsError(ref text) => &text, + CreationError::NotSupported => "Some of the requested attributes are not supported", + } + } +} + +impl fmt::Display for CreationError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + formatter.write_str(self.to_string()) + } +} + +impl error::Error for CreationError { + fn description(&self) -> &str { + self.to_string() + } +} + +/// Describes the appearance of the mouse cursor. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum MouseCursor { + /// The platform-dependent default cursor. + Default, + /// A simple crosshair. + Crosshair, + /// A hand (often used to indicate links in web browsers). + Hand, + /// Self explanatory. + Arrow, + /// Indicates something is to be moved. + Move, + /// Indicates text that may be selected or edited. + Text, + /// Program busy indicator. + Wait, + /// Help indicator (often rendered as a "?") + Help, + /// Progress indicator. Shows that processing is being done. But in contrast + /// with "Wait" the user may still interact with the program. Often rendered + /// as a spinning beach ball, or an arrow with a watch or hourglass. + Progress, + + /// Cursor showing that something cannot be done. + NotAllowed, + ContextMenu, + Cell, + VerticalText, + Alias, + Copy, + NoDrop, + Grab, + Grabbing, + AllScroll, + ZoomIn, + ZoomOut, + + /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor + /// is used when the movement starts from the south-east corner of the box. + EResize, + NResize, + NeResize, + NwResize, + SResize, + SeResize, + SwResize, + WResize, + EwResize, + NsResize, + NeswResize, + NwseResize, + ColResize, + RowResize, +} + +impl Default for MouseCursor { + fn default() -> Self { + MouseCursor::Default } } diff --git a/tests/send_objects.rs b/tests/send_objects.rs index 6cb0fe43c..4e61938c1 100644 --- a/tests/send_objects.rs +++ b/tests/send_objects.rs @@ -5,19 +5,19 @@ fn needs_send() {} #[test] fn events_loop_proxy_send() { // ensures that `winit::EventLoopProxy` implements `Send` - needs_send::>(); + needs_send::>(); } #[test] fn window_send() { // ensures that `winit::Window` implements `Send` - needs_send::(); + needs_send::(); } #[test] fn ids_send() { // ensures that the various `..Id` types implement `Send` - needs_send::(); - needs_send::(); - needs_send::(); + needs_send::(); + needs_send::(); + needs_send::(); } diff --git a/tests/sync_object.rs b/tests/sync_object.rs index eb9a06e34..c59cc077f 100644 --- a/tests/sync_object.rs +++ b/tests/sync_object.rs @@ -5,5 +5,5 @@ fn needs_sync() {} #[test] fn window_sync() { // ensures that `winit::Window` implements `Sync` - needs_sync::(); + needs_sync::(); }