Re-organize into module structure

This commit is contained in:
Osspial
2018-08-22 23:01:36 -04:00
parent f20fac99f6
commit 4377680a44
31 changed files with 740 additions and 701 deletions

View File

@@ -1,11 +1,13 @@
extern crate winit; 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() { fn main() {
let events_loop = EventLoop::new(); 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!"); window.set_title("A fantastic window!");
let mut cursor_idx = 0; let mut cursor_idx = 0;

View File

@@ -1,31 +1,34 @@
extern crate winit; extern crate winit;
fn main() { use winit::window::WindowBuilder;
let events_loop = winit::EventLoop::new(); 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") .with_title("Super Cursor Grab'n'Hide Simulator 9000")
.build(&events_loop) .build(&events_loop)
.unwrap(); .unwrap();
events_loop.run(move |event, _, control_flow| { events_loop.run(move |event, _, control_flow| {
*control_flow = winit::ControlFlow::Wait; *control_flow = ControlFlow::Wait;
if let winit::Event::WindowEvent { event, .. } = event { if let Event::WindowEvent { event, .. } = event {
use winit::WindowEvent::*;
match event { match event {
CloseRequested => *control_flow = winit::ControlFlow::Exit, WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
KeyboardInput { WindowEvent::KeyboardInput {
input: winit::KeyboardInput { input: KeyboardInput {
state: winit::ElementState::Released, state: ElementState::Released,
virtual_keycode: Some(key), virtual_keycode: Some(key),
modifiers, modifiers,
.. ..
}, },
.. ..
} => { } => {
use winit::VirtualKeyCode::*; use winit::event::VirtualKeyCode::*;
match key { match key {
Escape => *control_flow = winit::ControlFlow::Exit, Escape => *control_flow = ControlFlow::Exit,
G => window.grab_cursor(!modifiers.shift).unwrap(), G => window.grab_cursor(!modifiers.shift).unwrap(),
H => window.hide_cursor(!modifiers.shift), H => window.hide_cursor(!modifiers.shift),
_ => (), _ => (),

View File

@@ -1,10 +1,12 @@
extern crate winit; extern crate winit;
use std::io::{self, Write}; 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() { fn main() {
let events_loop = winit::EventLoop::new(); let events_loop = EventLoop::new();
// enumerating monitors // enumerating monitors
let monitor = { let monitor = {
@@ -25,7 +27,7 @@ fn main() {
monitor monitor
}; };
let window = winit::WindowBuilder::new() let window = WindowBuilder::new()
.with_title("Hello world!") .with_title("Hello world!")
.with_fullscreen(Some(monitor)) .with_fullscreen(Some(monitor))
.build(&events_loop) .build(&events_loop)
@@ -44,15 +46,15 @@ fn main() {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
input: input:
winit::KeyboardInput { KeyboardInput {
virtual_keycode: Some(virtual_code), virtual_keycode: Some(virtual_code),
state, state,
.. ..
}, },
.. ..
} => match (virtual_code, state) { } => match (virtual_code, state) {
(winit::VirtualKeyCode::Escape, _) => *control_flow = ControlFlow::Exit, (VirtualKeyCode::Escape, _) => *control_flow = ControlFlow::Exit,
(winit::VirtualKeyCode::F, winit::ElementState::Pressed) => { (VirtualKeyCode::F, ElementState::Pressed) => {
is_fullscreen = !is_fullscreen; is_fullscreen = !is_fullscreen;
if !is_fullscreen { if !is_fullscreen {
window.set_fullscreen(None); window.set_fullscreen(None);
@@ -60,11 +62,11 @@ fn main() {
window.set_fullscreen(Some(window.get_current_monitor())); window.set_fullscreen(Some(window.get_current_monitor()));
} }
} }
(winit::VirtualKeyCode::M, winit::ElementState::Pressed) => { (VirtualKeyCode::M, ElementState::Pressed) => {
is_maximized = !is_maximized; is_maximized = !is_maximized;
window.set_maximized(is_maximized); window.set_maximized(is_maximized);
} }
(winit::VirtualKeyCode::D, winit::ElementState::Pressed) => { (VirtualKeyCode::D, ElementState::Pressed) => {
decorations = !decorations; decorations = !decorations;
window.set_decorations(decorations); window.set_decorations(decorations);
} }

View File

@@ -1,9 +1,13 @@
extern crate winit; extern crate winit;
fn main() { use winit::window::WindowBuilder;
let events_loop = winit::EventLoop::new(); 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") .with_title("Your faithful window")
.build(&events_loop) .build(&events_loop)
.unwrap(); .unwrap();
@@ -11,13 +15,12 @@ fn main() {
let mut close_requested = false; let mut close_requested = false;
events_loop.run(move |event, _, control_flow| { events_loop.run(move |event, _, control_flow| {
use winit::WindowEvent::*; use winit::event::ElementState::Released;
use winit::ElementState::Released; use winit::event::VirtualKeyCode::{N, Y};
use winit::VirtualKeyCode::{N, Y};
match event { match event {
winit::Event::WindowEvent { event, .. } => match event { Event::WindowEvent { event, .. } => match event {
CloseRequested => { WindowEvent::CloseRequested => {
// `CloseRequested` is sent when the close button on the window is pressed (or // `CloseRequested` is sent when the close button on the window is pressed (or
// through whatever other mechanisms the window manager provides for closing a // 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 // 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 // closing the window. How to close the window is detailed in the handler for
// the Y key. // the Y key.
} }
KeyboardInput { WindowEvent::KeyboardInput {
input: input:
winit::KeyboardInput { KeyboardInput {
virtual_keycode: Some(virtual_code), virtual_keycode: Some(virtual_code),
state: Released, state: Released,
.. ..
@@ -53,7 +56,7 @@ fn main() {
// event loop (i.e. if it's a multi-window application), you need to // 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 // drop the window. That closes it, and results in `Destroyed` being
// sent. // sent.
*control_flow = winit::ControlFlow::Exit; *control_flow = ControlFlow::Exit;
} }
} }
N => { N => {
@@ -69,6 +72,6 @@ fn main() {
_ => (), _ => (),
} }
*control_flow = winit::ControlFlow::Wait; *control_flow = ControlFlow::Wait;
}); });
} }

View File

@@ -1,11 +1,14 @@
extern crate winit; extern crate winit;
use winit::dpi::LogicalSize; use winit::dpi::LogicalSize;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() { 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) .build(&events_loop)
.unwrap(); .unwrap();
@@ -16,9 +19,9 @@ fn main() {
println!("{:?}", event); println!("{:?}", event);
match event { match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
*control_flow = winit::ControlFlow::Exit, *control_flow = ControlFlow::Exit,
_ => *control_flow = winit::ControlFlow::Wait, _ => *control_flow = ControlFlow::Wait,
} }
}); });
} }

View File

@@ -1,7 +1,9 @@
extern crate winit; extern crate winit;
use winit::event_loop::EventLoop;
use winit::window::WindowBuilder;
fn main() { fn main() {
let event_loop = winit::EventLoop::new(); let event_loop = EventLoop::new();
let window = winit::WindowBuilder::new().build(&event_loop).unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap();
println!("{:#?}\nPrimary: {:#?}", window.get_available_monitors(), window.get_primary_monitor()); println!("{:#?}\nPrimary: {:#?}", window.get_available_monitors(), window.get_primary_monitor());
} }

View File

@@ -1,33 +1,36 @@
extern crate winit; extern crate winit;
use std::collections::HashMap; use std::collections::HashMap;
use winit::window::Window;
use winit::event::{Event, WindowEvent, ElementState, KeyboardInput};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() { fn main() {
let events_loop = winit::EventLoop::new(); let events_loop = EventLoop::new();
let mut windows = HashMap::new(); let mut windows = HashMap::new();
for _ in 0..3 { for _ in 0..3 {
let window = winit::Window::new(&events_loop).unwrap(); let window = Window::new(&events_loop).unwrap();
windows.insert(window.id(), window); windows.insert(window.id(), window);
} }
events_loop.run(move |event, events_loop, control_flow| { events_loop.run(move |event, events_loop, control_flow| {
*control_flow = winit::ControlFlow::Wait; *control_flow = ControlFlow::Wait;
match event { match event {
winit::Event::WindowEvent { event, window_id } => { Event::WindowEvent { event, window_id } => {
match event { match event {
winit::WindowEvent::CloseRequested => { WindowEvent::CloseRequested => {
println!("Window {:?} has received the signal to close", window_id); println!("Window {:?} has received the signal to close", window_id);
// This drops the window, causing it to close. // This drops the window, causing it to close.
windows.remove(&window_id); windows.remove(&window_id);
if windows.is_empty() { if windows.is_empty() {
*control_flow = winit::ControlFlow::Exit; *control_flow = ControlFlow::Exit;
} }
}, },
winit::WindowEvent::KeyboardInput{..} => { WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. } => {
let window = winit::Window::new(&events_loop).unwrap(); let window = Window::new(&events_loop).unwrap();
windows.insert(window.id(), window); windows.insert(window.id(), window);
}, },
_ => () _ => ()

View File

@@ -1,5 +1,7 @@
extern crate winit; extern crate winit;
use winit::{EventLoop, WindowBuilder}; use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() { fn main() {
let events_loop: EventLoop<i32> = EventLoop::new_user_event(); let events_loop: EventLoop<i32> = EventLoop::new_user_event();
@@ -24,9 +26,9 @@ fn main() {
events_loop.run(move |event, _, control_flow| { events_loop.run(move |event, _, control_flow| {
println!("{:?}", event); println!("{:?}", event);
match event { match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
*control_flow = winit::ControlFlow::Exit, *control_flow = ControlFlow::Exit,
_ => *control_flow = winit::ControlFlow::Wait, _ => *control_flow = ControlFlow::Wait,
} }
}); });
} }

View File

@@ -1,11 +1,14 @@
extern crate winit; extern crate winit;
use winit::{Event, WindowEvent};
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
fn main() { use winit::window::WindowBuilder;
let events_loop = winit::EventLoop::new(); 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!") .with_title("A fantastic window!")
.build(&events_loop) .build(&events_loop)
.unwrap(); .unwrap();
@@ -17,10 +20,10 @@ fn main() {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => *control_flow = winit::ControlFlow::Exit, } => *control_flow = ControlFlow::Exit,
Event::EventsCleared => { Event::EventsCleared => {
window.request_redraw(); window.request_redraw();
*control_flow = winit::ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0)) *control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0))
}, },
_ => () _ => ()
} }

View File

@@ -1,11 +1,14 @@
extern crate winit; extern crate winit;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent, VirtualKeyCode, ElementState, KeyboardInput};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() { fn main() {
let events_loop = winit::EventLoop::new(); let events_loop = EventLoop::new();
let mut resizable = false; let mut resizable = false;
let window = winit::WindowBuilder::new() let window = WindowBuilder::new()
.with_title("Hit space to toggle resizability.") .with_title("Hit space to toggle resizability.")
.with_dimensions((400, 200).into()) .with_dimensions((400, 200).into())
.with_resizable(resizable) .with_resizable(resizable)
@@ -13,15 +16,15 @@ fn main() {
.unwrap(); .unwrap();
events_loop.run(move |event, _, control_flow| { events_loop.run(move |event, _, control_flow| {
*control_flow = winit::ControlFlow::Wait; *control_flow = ControlFlow::Wait;
match event { match event {
winit::Event::WindowEvent { event, .. } => match event { Event::WindowEvent { event, .. } => match event {
winit::WindowEvent::CloseRequested => *control_flow = winit::ControlFlow::Exit, WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
winit::WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
input: input:
winit::KeyboardInput { KeyboardInput {
virtual_keycode: Some(winit::VirtualKeyCode::Space), virtual_keycode: Some(VirtualKeyCode::Space),
state: winit::ElementState::Released, state: ElementState::Released,
.. ..
}, },
.. ..

View File

@@ -1,10 +1,14 @@
extern crate winit; extern crate winit;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
use winit::platform::desktop::EventLoopExtDesktop; use winit::platform::desktop::EventLoopExtDesktop;
fn main() { 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!") .with_title("A fantastic window!")
.build(&events_loop) .build(&events_loop)
.unwrap(); .unwrap();
@@ -12,16 +16,16 @@ fn main() {
println!("Close the window to continue."); println!("Close the window to continue.");
events_loop.run_return(|event, _, control_flow| { events_loop.run_return(|event, _, control_flow| {
match event { match event {
winit::Event::WindowEvent { Event::WindowEvent {
event: winit::WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => *control_flow = winit::ControlFlow::Exit, } => *control_flow = ControlFlow::Exit,
_ => *control_flow = winit::ControlFlow::Wait, _ => *control_flow = ControlFlow::Wait,
} }
}); });
drop(window); drop(window);
let _window_2 = winit::WindowBuilder::new() let _window_2 = WindowBuilder::new()
.with_title("A second, fantasticer window!") .with_title("A second, fantasticer window!")
.build(&events_loop) .build(&events_loop)
.unwrap(); .unwrap();
@@ -29,11 +33,11 @@ fn main() {
println!("Wa ha ha! You thought that closing the window would finish this?!"); println!("Wa ha ha! You thought that closing the window would finish this?!");
events_loop.run_return(|event, _, control_flow| { events_loop.run_return(|event, _, control_flow| {
match event { match event {
winit::Event::WindowEvent { Event::WindowEvent {
event: winit::WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => *control_flow = winit::ControlFlow::Exit, } => *control_flow = ControlFlow::Exit,
_ => *control_flow = winit::ControlFlow::Wait, _ => *control_flow = ControlFlow::Wait,
} }
}); });

View File

@@ -1,11 +1,13 @@
extern crate winit; extern crate winit;
use std::time::{Duration, Instant}; 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() { 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!") .with_title("A fantastic window!")
.build(&events_loop) .build(&events_loop)
.unwrap(); .unwrap();

View File

@@ -1,9 +1,12 @@
extern crate winit; extern crate winit;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() { 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) .with_transparency(true)
.build(&events_loop).unwrap(); .build(&events_loop).unwrap();
@@ -13,9 +16,9 @@ fn main() {
println!("{:?}", event); println!("{:?}", event);
match event { match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
*control_flow = winit::ControlFlow::Exit, *control_flow = ControlFlow::Exit,
_ => *control_flow = winit::ControlFlow::Wait, _ => *control_flow = ControlFlow::Wait,
} }
}); });
} }

View File

@@ -1,9 +1,12 @@
extern crate winit; extern crate winit;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() { 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!") .with_title("A fantastic window!")
.build(&events_loop) .build(&events_loop)
.unwrap(); .unwrap();
@@ -12,11 +15,11 @@ fn main() {
println!("{:?}", event); println!("{:?}", event);
match event { match event {
winit::Event::WindowEvent { Event::WindowEvent {
event: winit::WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => *control_flow = winit::ControlFlow::Exit, } => *control_flow = ControlFlow::Exit,
_ => *control_flow = winit::ControlFlow::Wait, _ => *control_flow = ControlFlow::Wait,
} }
}); });
} }

View File

@@ -8,7 +8,14 @@ extern crate image;
#[cfg(feature = "icon_loading")] #[cfg(feature = "icon_loading")]
fn main() { fn main() {
<<<<<<< HEAD
use winit::Icon; 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 // 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, // 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 // 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). // feature enabled).
let icon = Icon::from_path(path).expect("Failed to open icon"); 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!") .with_title("An iconic window!")
// At present, this only does anything on Windows and X11, so if you want to save load // 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. // time, you can put icon loading behind a function that returns `None` on other platforms.
@@ -31,11 +38,11 @@ fn main() {
.unwrap(); .unwrap();
events_loop.run(move |event, _, control_flow| { events_loop.run(move |event, _, control_flow| {
*control_flow = winit::ControlFlow::Wait; *control_flow = ControlFlow::Wait;
if let winit::Event::WindowEvent { event, .. } = event { if let Event::WindowEvent { event, .. } = event {
use winit::WindowEvent::*; use winit::event::WindowEvent::*;
match event { match event {
CloseRequested => *control_flow = winit::ControlFlow::Exit, CloseRequested => *control_flow = ControlFlow::Exit,
DroppedFile(path) => { DroppedFile(path) => {
use image::GenericImageView; use image::GenericImageView;

View File

@@ -1,7 +1,9 @@
use std::time::Instant; use std::time::Instant;
use std::path::PathBuf; use std::path::PathBuf;
use {DeviceId, LogicalPosition, LogicalSize, WindowId}; use dpi::{LogicalPosition, LogicalSize};
use window::WindowId;
use platform_impl;
/// Describes a generic event. /// Describes a generic event.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@@ -158,6 +160,14 @@ pub enum WindowEvent {
HiDpiFactorChanged(f64), 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. /// 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 /// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person

151
src/event_loop.rs Normal file
View File

@@ -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<T> {
pub(crate) events_loop: platform_impl::EventLoop<T>,
pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync
}
impl<T> std::fmt::Debug for EventLoop<T> {
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<T> EventLoop<T> {
/// 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<T> {
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<F>(self, event_handler: F) -> !
where F: 'static + FnMut(Event<T>, &EventLoop<T>, &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<T> {
EventLoopProxy {
events_loop_proxy: self.events_loop.create_proxy(),
}
}
}
/// Used to wake up the `EventLoop` from another thread.
#[derive(Clone)]
pub struct EventLoopProxy<T> {
events_loop_proxy: platform_impl::EventLoopProxy<T>,
}
impl<T> EventLoopProxy<T> {
/// 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<T> std::fmt::Debug for EventLoopProxy<T> {
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`"
}
}

View File

@@ -6,7 +6,7 @@
//! `EventLoop::new()` function. Example: //! `EventLoop::new()` function. Example:
//! //!
//! ```no_run //! ```no_run
//! use winit::EventLoop; //! use winit::event_loop::EventLoop;
//! let events_loop = EventLoop::new(); //! let events_loop = EventLoop::new();
//! ``` //! ```
//! //!
@@ -32,8 +32,9 @@
//! stopped by returning `ControlFlow::Exit`, at which point the entire program will terminate. //! stopped by returning `ControlFlow::Exit`, at which point the entire program will terminate.
//! //!
//! ```no_run //! ```no_run
//! use winit::{ControlFlow, Event, WindowEvent}; //! use winit::event_loop::ControlFlow;
//! # use winit::EventLoop; //! use winit::event::{Event, WindowEvent};
//! # use winit::event_loop::EventLoop;
//! # let events_loop = EventLoop::new(); //! # let events_loop = EventLoop::new();
//! //!
//! events_loop.run(move |event, _, control_flow| { //! events_loop.run(move |event, _, control_flow| {
@@ -54,7 +55,7 @@
//! # Drawing on the window //! # Drawing on the window
//! //!
//! Winit doesn't provide any function that allows drawing on a window. However it allows you to //! 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. //! 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"))] #[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
extern crate smithay_client_toolkit as sctk; 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; pub mod dpi;
mod events; pub mod event;
pub mod event_loop;
mod icon; mod icon;
mod platform_impl; mod platform_impl;
mod window; pub mod window;
pub mod monitor;
pub mod platform; 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<T> {
events_loop: platform_impl::EventLoop<T>,
_marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync
}
impl<T> std::fmt::Debug for EventLoop<T> {
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<T> EventLoop<T> {
/// 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<T> {
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<F>(self, event_handler: F) -> !
where F: 'static + FnMut(Event<T>, &EventLoop<T>, &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<T> {
EventLoopProxy {
events_loop_proxy: self.events_loop.create_proxy(),
}
}
}
/// Used to wake up the `EventLoop` from another thread.
#[derive(Clone)]
pub struct EventLoopProxy<T> {
events_loop_proxy: platform_impl::EventLoopProxy<T>,
}
impl<T> std::fmt::Debug for EventLoopProxy<T> {
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
fmtr.pad("EventLoopProxy { .. }")
}
}
impl<T> EventLoopProxy<T> {
/// 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<LogicalSize>,
/// 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<LogicalSize>,
/// 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<LogicalSize>,
/// 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<MonitorId>,
/// 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<Icon>,
/// [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,
}
}
}

68
src/monitor.rs Normal file
View File

@@ -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<platform_impl::MonitorId>,
}
impl Iterator for AvailableMonitorsIter {
type Item = MonitorId;
#[inline]
fn next(&mut self) -> Option<MonitorId> {
self.data.next().map(|id| MonitorId { inner: id })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
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<String> {
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()
}
}

View File

@@ -4,7 +4,8 @@
target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" 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. /// Additional methods on `EventLoop` that are specific to desktop platforms.
pub trait EventLoopExtDesktop { pub trait EventLoopExtDesktop {

View File

@@ -5,7 +5,10 @@ use std::os::raw::c_void;
use libc; use libc;
use winapi::shared::windef::HWND; 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; use platform_impl::EventLoop as WindowsEventLoop;
/// Additional methods on `EventLoop` that are specific to Windows. /// Additional methods on `EventLoop` that are specific to Windows.

View File

@@ -17,7 +17,8 @@ use winapi::um::{shellapi, unknwnbase};
use platform_impl::platform::WindowId; use platform_impl::platform::WindowId;
use {Event, WindowId as SuperWindowId}; use event::Event;
use window::WindowId as SuperWindowId;
#[repr(C)] #[repr(C)]
pub struct FileDropHandlerData { pub struct FileDropHandlerData {
@@ -81,7 +82,7 @@ impl FileDropHandler {
_pt: *const POINTL, _pt: *const POINTL,
_pdwEffect: *mut DWORD, _pdwEffect: *mut DWORD,
) -> HRESULT { ) -> HRESULT {
use events::WindowEvent::HoveredFile; use event::WindowEvent::HoveredFile;
let drop_handler = Self::from_interface(this); let drop_handler = Self::from_interface(this);
Self::iterate_filenames(pDataObj, |filename| { Self::iterate_filenames(pDataObj, |filename| {
drop_handler.send_event(Event::WindowEvent { drop_handler.send_event(Event::WindowEvent {
@@ -103,7 +104,7 @@ impl FileDropHandler {
} }
pub unsafe extern "system" fn DragLeave(this: *mut IDropTarget) -> HRESULT { 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); let drop_handler = Self::from_interface(this);
drop_handler.send_event(Event::WindowEvent { drop_handler.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(drop_handler.window)), window_id: SuperWindowId(WindowId(drop_handler.window)),
@@ -120,7 +121,7 @@ impl FileDropHandler {
_pt: *const POINTL, _pt: *const POINTL,
_pdwEffect: *mut DWORD, _pdwEffect: *mut DWORD,
) -> HRESULT { ) -> HRESULT {
use events::WindowEvent::DroppedFile; use event::WindowEvent::DroppedFile;
let drop_handler = Self::from_interface(this); let drop_handler = Self::from_interface(this);
let hdrop = Self::iterate_filenames(pDataObj, |filename| { let hdrop = Self::iterate_filenames(pDataObj, |filename| {
drop_handler.send_event(Event::WindowEvent { drop_handler.send_event(Event::WindowEvent {

View File

@@ -1,14 +1,11 @@
use std::char; use std::char;
use std::os::raw::c_int; use std::os::raw::c_int;
use events::VirtualKeyCode; use event::{ScanCode, ModifiersState, VirtualKeyCode};
use events::ModifiersState;
use winapi::shared::minwindef::{WPARAM, LPARAM, UINT}; use winapi::shared::minwindef::{WPARAM, LPARAM, UINT};
use winapi::um::winuser; use winapi::um::winuser;
use ScanCode;
pub fn get_key_mods() -> ModifiersState { pub fn get_key_mods() -> ModifiersState {
let mut mods = ModifiersState::default(); let mut mods = ModifiersState::default();
unsafe { unsafe {

View File

@@ -40,18 +40,11 @@ use winapi::shared::windowsx;
use winapi::um::{winuser, winbase, ole2, processthreadsapi, commctrl, libloaderapi}; use winapi::um::{winuser, winbase, ole2, processthreadsapi, commctrl, libloaderapi};
use winapi::um::winnt::{LONG, LPCSTR, SHORT}; use winapi::um::winnt::{LONG, LPCSTR, SHORT};
use { use window::WindowId as RootWindowId;
ControlFlow, use monitor::MonitorId;
Event, use event_loop::{ControlFlow, EventLoop as RootEventLoop, EventLoopClosed};
EventLoopClosed, use dpi::{LogicalPosition, LogicalSize, PhysicalSize};
KeyboardInput, use event::{DeviceEvent, Touch, TouchPhase, StartCause, KeyboardInput, Event, WindowEvent};
LogicalPosition,
LogicalSize,
PhysicalSize,
WindowEvent,
WindowId as SuperWindowId,
};
use events::{DeviceEvent, Touch, TouchPhase, StartCause};
use platform_impl::platform::{event, Cursor, WindowId, DEVICE_ID, wrap_device_id, util}; use platform_impl::platform::{event, Cursor, WindowId, DEVICE_ID, wrap_device_id, util};
use platform_impl::platform::dpi::{ use platform_impl::platform::dpi::{
become_dpi_aware, 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 // 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. // fullscreen. This will always be the most recent DPI for the window.
pub dpi_factor: f64, pub dpi_factor: f64,
pub fullscreen: Option<::MonitorId>, pub fullscreen: Option<MonitorId>,
pub window_icon: Option<WinIcon>, pub window_icon: Option<WinIcon>,
pub taskbar_icon: Option<WinIcon>, pub taskbar_icon: Option<WinIcon>,
pub decorations: bool, pub decorations: bool,
@@ -183,14 +176,14 @@ impl<T> EventLoop<T> {
} }
pub fn run<F>(mut self, event_handler: F) -> ! pub fn run<F>(mut self, event_handler: F) -> !
where F: 'static + FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow) where F: 'static + FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow)
{ {
self.run_return(event_handler); self.run_return(event_handler);
::std::process::exit(0); ::std::process::exit(0);
} }
pub fn run_return<F>(&mut self, mut event_handler: F) pub fn run_return<F>(&mut self, mut event_handler: F)
where F: FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow) where F: FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow)
{ {
unsafe{ winuser::IsGUIThread(1); } unsafe{ winuser::IsGUIThread(1); }
let mut runner = EventLoopRunner { let mut runner = EventLoopRunner {
@@ -201,8 +194,8 @@ impl<T> EventLoop<T> {
event_handler: unsafe { event_handler: unsafe {
// Transmute used to erase lifetimes. // Transmute used to erase lifetimes.
mem::transmute::< mem::transmute::<
&mut FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow), &mut FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow),
*mut FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow) *mut FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow)
>(&mut event_handler) >(&mut event_handler)
} }
}; };
@@ -294,7 +287,7 @@ pub(crate) struct EventLoopRunner<T> {
control_flow: ControlFlow, control_flow: ControlFlow,
runner_state: RunnerState, runner_state: RunnerState,
modal_loop_data: Option<ModalLoopData>, modal_loop_data: Option<ModalLoopData>,
event_handler: *mut FnMut(Event<T>, &::EventLoop<T>, &mut ControlFlow) event_handler: *mut FnMut(Event<T>, &RootEventLoop<T>, &mut ControlFlow)
} }
struct ModalLoopData { struct ModalLoopData {
@@ -468,8 +461,8 @@ impl<T> EventLoopRunner<T> {
_ => () _ => ()
} }
assert_eq!(mem::size_of::<::EventLoop<T>>(), mem::size_of::<EventLoop<T>>()); assert_eq!(mem::size_of::<RootEventLoop<T>>(), mem::size_of::<EventLoop<T>>());
let event_loop_ref = &*(self.event_loop as *const ::EventLoop<T>); let event_loop_ref = &*(self.event_loop as *const RootEventLoop<T>);
if self.control_flow != ControlFlow::Exit { if self.control_flow != ControlFlow::Exit {
(*self.event_handler)(event, event_loop_ref, &mut self.control_flow); (*self.event_handler)(event, event_loop_ref, &mut self.control_flow);
@@ -800,16 +793,16 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
winuser::WM_CLOSE => { winuser::WM_CLOSE => {
use events::WindowEvent::CloseRequested; use event::WindowEvent::CloseRequested;
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: CloseRequested event: CloseRequested
}); });
0 0
}, },
winuser::WM_DESTROY => { winuser::WM_DESTROY => {
use events::WindowEvent::Destroyed; use event::WindowEvent::Destroyed;
ole2::RevokeDragDrop(window); ole2::RevokeDragDrop(window);
{ {
let window_state = subclass_input.window_state.lock(); let window_state = subclass_input.window_state.lock();
@@ -818,7 +811,7 @@ unsafe extern "system" fn public_window_callback<T>(
} }
} }
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: Destroyed event: Destroyed
}); });
@@ -828,14 +821,14 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
_ if msg == *REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID => { _ 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(); let runner = subclass_input.event_loop_runner.borrow_mut();
if let ELRSharedOption::Runner(runner) = *runner { if let ELRSharedOption::Runner(runner) = *runner {
let runner = &mut *runner; let runner = &mut *runner;
match runner.runner_state { match runner.runner_state {
RunnerState::Idle(..) | RunnerState::Idle(..) |
RunnerState::DeferredNewEvents(..) => runner.call_event_handler(Event::WindowEvent { RunnerState::DeferredNewEvents(..) => runner.call_event_handler(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: RedrawRequested, event: RedrawRequested,
}), }),
_ => () _ => ()
@@ -844,9 +837,9 @@ unsafe extern "system" fn public_window_callback<T>(
0 0
}, },
winuser::WM_PAINT => { winuser::WM_PAINT => {
use events::WindowEvent::RedrawRequested; use event::WindowEvent::RedrawRequested;
let event = || Event::WindowEvent { let event = || Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: RedrawRequested, event: RedrawRequested,
}; };
@@ -870,7 +863,7 @@ unsafe extern "system" fn public_window_callback<T>(
// WM_MOVE supplies client area positions, so we send Moved here instead. // WM_MOVE supplies client area positions, so we send Moved here instead.
winuser::WM_WINDOWPOSCHANGED => { winuser::WM_WINDOWPOSCHANGED => {
use events::WindowEvent::Moved; use event::WindowEvent::Moved;
let windowpos = lparam as *const winuser::WINDOWPOS; let windowpos = lparam as *const winuser::WINDOWPOS;
if (*windowpos).flags & winuser::SWP_NOMOVE != winuser::SWP_NOMOVE { if (*windowpos).flags & winuser::SWP_NOMOVE != winuser::SWP_NOMOVE {
@@ -880,7 +873,7 @@ unsafe extern "system" fn public_window_callback<T>(
dpi_factor, dpi_factor,
); );
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: Moved(logical_position), event: Moved(logical_position),
}); });
} }
@@ -890,14 +883,14 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
winuser::WM_SIZE => { winuser::WM_SIZE => {
use events::WindowEvent::Resized; use event::WindowEvent::Resized;
let w = LOWORD(lparam as DWORD) as u32; let w = LOWORD(lparam as DWORD) as u32;
let h = HIWORD(lparam as DWORD) as u32; let h = HIWORD(lparam as DWORD) as u32;
let dpi_factor = get_hwnd_scale_factor(window); let dpi_factor = get_hwnd_scale_factor(window);
let logical_size = LogicalSize::from_physical((w, h), dpi_factor); let logical_size = LogicalSize::from_physical((w, h), dpi_factor);
let event = Event::WindowEvent { let event = Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: Resized(logical_size), event: Resized(logical_size),
}; };
@@ -907,10 +900,10 @@ unsafe extern "system" fn public_window_callback<T>(
winuser::WM_CHAR => { winuser::WM_CHAR => {
use std::mem; use std::mem;
use events::WindowEvent::ReceivedCharacter; use event::WindowEvent::ReceivedCharacter;
let chr: char = mem::transmute(wparam as u32); let chr: char = mem::transmute(wparam as u32);
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: ReceivedCharacter(chr), event: ReceivedCharacter(chr),
}); });
0 0
@@ -925,7 +918,7 @@ unsafe extern "system" fn public_window_callback<T>(
} }
winuser::WM_MOUSEMOVE => { winuser::WM_MOUSEMOVE => {
use events::WindowEvent::{CursorEntered, CursorMoved}; use event::WindowEvent::{CursorEntered, CursorMoved};
let mouse_outside_window = { let mouse_outside_window = {
let mut window = subclass_input.window_state.lock(); let mut window = subclass_input.window_state.lock();
if !window.mouse_in_window { if !window.mouse_in_window {
@@ -938,7 +931,7 @@ unsafe extern "system" fn public_window_callback<T>(
if mouse_outside_window { if mouse_outside_window {
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: CursorEntered { device_id: DEVICE_ID }, event: CursorEntered { device_id: DEVICE_ID },
}); });
@@ -957,7 +950,7 @@ unsafe extern "system" fn public_window_callback<T>(
let position = LogicalPosition::from_physical((x, y), dpi_factor); let position = LogicalPosition::from_physical((x, y), dpi_factor);
subclass_input.send_event(Event::WindowEvent { 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() }, event: CursorMoved { device_id: DEVICE_ID, position, modifiers: event::get_key_mods() },
}); });
@@ -965,7 +958,7 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
winuser::WM_MOUSELEAVE => { winuser::WM_MOUSELEAVE => {
use events::WindowEvent::CursorLeft; use event::WindowEvent::CursorLeft;
let mouse_in_window = { let mouse_in_window = {
let mut window = subclass_input.window_state.lock(); let mut window = subclass_input.window_state.lock();
if window.mouse_in_window { if window.mouse_in_window {
@@ -978,7 +971,7 @@ unsafe extern "system" fn public_window_callback<T>(
if mouse_in_window { if mouse_in_window {
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: CursorLeft { device_id: DEVICE_ID } event: CursorLeft { device_id: DEVICE_ID }
}); });
} }
@@ -987,15 +980,15 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
winuser::WM_MOUSEWHEEL => { winuser::WM_MOUSEWHEEL => {
use events::MouseScrollDelta::LineDelta; use event::MouseScrollDelta::LineDelta;
use events::TouchPhase; use event::TouchPhase;
let value = (wparam >> 16) as i16; let value = (wparam >> 16) as i16;
let value = value as i32; let value = value as i32;
let value = value as f32 / winuser::WHEEL_DELTA as f32; let value = value as f32 / winuser::WHEEL_DELTA as f32;
subclass_input.send_event(Event::WindowEvent { 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() }, 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<T>(
}, },
winuser::WM_KEYDOWN | winuser::WM_SYSKEYDOWN => { winuser::WM_KEYDOWN | winuser::WM_SYSKEYDOWN => {
use events::ElementState::Pressed; use event::ElementState::Pressed;
use events::VirtualKeyCode; use event::VirtualKeyCode;
if msg == winuser::WM_SYSKEYDOWN && wparam as i32 == winuser::VK_F4 { if msg == winuser::WM_SYSKEYDOWN && wparam as i32 == winuser::VK_F4 {
commctrl::DefSubclassProc(window, msg, wparam, lparam) commctrl::DefSubclassProc(window, msg, wparam, lparam)
} else { } else {
if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { if let Some((scancode, vkey)) = process_key_params(wparam, lparam) {
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: WindowEvent::KeyboardInput { event: WindowEvent::KeyboardInput {
device_id: DEVICE_ID, device_id: DEVICE_ID,
input: KeyboardInput { input: KeyboardInput {
@@ -1025,7 +1018,7 @@ unsafe extern "system" fn public_window_callback<T>(
// consistent with the other platforms we'll emit a delete character here. // consistent with the other platforms we'll emit a delete character here.
if vkey == Some(VirtualKeyCode::Delete) { if vkey == Some(VirtualKeyCode::Delete) {
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: WindowEvent::ReceivedCharacter('\u{7F}'), event: WindowEvent::ReceivedCharacter('\u{7F}'),
}); });
} }
@@ -1035,10 +1028,10 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
winuser::WM_KEYUP | winuser::WM_SYSKEYUP => { winuser::WM_KEYUP | winuser::WM_SYSKEYUP => {
use events::ElementState::Released; use event::ElementState::Released;
if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { if let Some((scancode, vkey)) = process_key_params(wparam, lparam) {
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: WindowEvent::KeyboardInput { event: WindowEvent::KeyboardInput {
device_id: DEVICE_ID, device_id: DEVICE_ID,
input: KeyboardInput { input: KeyboardInput {
@@ -1054,114 +1047,114 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
winuser::WM_LBUTTONDOWN => { winuser::WM_LBUTTONDOWN => {
use events::WindowEvent::MouseInput; use event::WindowEvent::MouseInput;
use events::MouseButton::Left; use event::MouseButton::Left;
use events::ElementState::Pressed; use event::ElementState::Pressed;
capture_mouse(window, &mut *subclass_input.window_state.lock()); capture_mouse(window, &mut *subclass_input.window_state.lock());
subclass_input.send_event(Event::WindowEvent { 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() } event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Left, modifiers: event::get_key_mods() }
}); });
0 0
}, },
winuser::WM_LBUTTONUP => { winuser::WM_LBUTTONUP => {
use events::WindowEvent::MouseInput; use event::WindowEvent::MouseInput;
use events::MouseButton::Left; use event::MouseButton::Left;
use events::ElementState::Released; use event::ElementState::Released;
release_mouse(&mut *subclass_input.window_state.lock()); release_mouse(&mut *subclass_input.window_state.lock());
subclass_input.send_event(Event::WindowEvent { 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() } event: MouseInput { device_id: DEVICE_ID, state: Released, button: Left, modifiers: event::get_key_mods() }
}); });
0 0
}, },
winuser::WM_RBUTTONDOWN => { winuser::WM_RBUTTONDOWN => {
use events::WindowEvent::MouseInput; use event::WindowEvent::MouseInput;
use events::MouseButton::Right; use event::MouseButton::Right;
use events::ElementState::Pressed; use event::ElementState::Pressed;
capture_mouse(window, &mut *subclass_input.window_state.lock()); capture_mouse(window, &mut *subclass_input.window_state.lock());
subclass_input.send_event(Event::WindowEvent { 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() } event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Right, modifiers: event::get_key_mods() }
}); });
0 0
}, },
winuser::WM_RBUTTONUP => { winuser::WM_RBUTTONUP => {
use events::WindowEvent::MouseInput; use event::WindowEvent::MouseInput;
use events::MouseButton::Right; use event::MouseButton::Right;
use events::ElementState::Released; use event::ElementState::Released;
release_mouse(&mut *subclass_input.window_state.lock()); release_mouse(&mut *subclass_input.window_state.lock());
subclass_input.send_event(Event::WindowEvent { 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() } event: MouseInput { device_id: DEVICE_ID, state: Released, button: Right, modifiers: event::get_key_mods() }
}); });
0 0
}, },
winuser::WM_MBUTTONDOWN => { winuser::WM_MBUTTONDOWN => {
use events::WindowEvent::MouseInput; use event::WindowEvent::MouseInput;
use events::MouseButton::Middle; use event::MouseButton::Middle;
use events::ElementState::Pressed; use event::ElementState::Pressed;
capture_mouse(window, &mut *subclass_input.window_state.lock()); capture_mouse(window, &mut *subclass_input.window_state.lock());
subclass_input.send_event(Event::WindowEvent { 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() } event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Middle, modifiers: event::get_key_mods() }
}); });
0 0
}, },
winuser::WM_MBUTTONUP => { winuser::WM_MBUTTONUP => {
use events::WindowEvent::MouseInput; use event::WindowEvent::MouseInput;
use events::MouseButton::Middle; use event::MouseButton::Middle;
use events::ElementState::Released; use event::ElementState::Released;
release_mouse(&mut *subclass_input.window_state.lock()); release_mouse(&mut *subclass_input.window_state.lock());
subclass_input.send_event(Event::WindowEvent { 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() } event: MouseInput { device_id: DEVICE_ID, state: Released, button: Middle, modifiers: event::get_key_mods() }
}); });
0 0
}, },
winuser::WM_XBUTTONDOWN => { winuser::WM_XBUTTONDOWN => {
use events::WindowEvent::MouseInput; use event::WindowEvent::MouseInput;
use events::MouseButton::Other; use event::MouseButton::Other;
use events::ElementState::Pressed; use event::ElementState::Pressed;
let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); let xbutton = winuser::GET_XBUTTON_WPARAM(wparam);
capture_mouse(window, &mut *subclass_input.window_state.lock()); capture_mouse(window, &mut *subclass_input.window_state.lock());
subclass_input.send_event(Event::WindowEvent { 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() } event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Other(xbutton as u8), modifiers: event::get_key_mods() }
}); });
0 0
}, },
winuser::WM_XBUTTONUP => { winuser::WM_XBUTTONUP => {
use events::WindowEvent::MouseInput; use event::WindowEvent::MouseInput;
use events::MouseButton::Other; use event::MouseButton::Other;
use events::ElementState::Released; use event::ElementState::Released;
let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); let xbutton = winuser::GET_XBUTTON_WPARAM(wparam);
release_mouse(&mut *subclass_input.window_state.lock()); release_mouse(&mut *subclass_input.window_state.lock());
subclass_input.send_event(Event::WindowEvent { 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() } event: MouseInput { device_id: DEVICE_ID, state: Released, button: Other(xbutton as u8), modifiers: event::get_key_mods() }
}); });
0 0
@@ -1183,9 +1176,9 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
winuser::WM_INPUT => { winuser::WM_INPUT => {
use events::DeviceEvent::{Motion, MouseMotion, MouseWheel, Button, Key}; use event::DeviceEvent::{Motion, MouseMotion, MouseWheel, Button, Key};
use events::MouseScrollDelta::LineDelta; use event::MouseScrollDelta::LineDelta;
use events::ElementState::{Pressed, Released}; use event::ElementState::{Pressed, Released};
if let Some(data) = get_raw_input_data(lparam as _) { if let Some(data) = get_raw_input_data(lparam as _) {
let device_id = wrap_device_id(data.header.hDevice as _); let device_id = wrap_device_id(data.header.hDevice as _);
@@ -1303,7 +1296,7 @@ unsafe extern "system" fn public_window_callback<T>(
let y = (input.y as f64) / 100f64; let y = (input.y as f64) / 100f64;
let location = LogicalPosition::from_physical((x, y), dpi_factor); let location = LogicalPosition::from_physical((x, y), dpi_factor);
subclass_input.send_event( Event::WindowEvent { subclass_input.send_event( Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: WindowEvent::Touch(Touch { event: WindowEvent::Touch(Touch {
phase: phase:
if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 { if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 {
@@ -1327,9 +1320,9 @@ unsafe extern "system" fn public_window_callback<T>(
} }
winuser::WM_SETFOCUS => { winuser::WM_SETFOCUS => {
use events::WindowEvent::{Focused, CursorMoved}; use event::WindowEvent::{Focused, CursorMoved};
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: Focused(true) event: Focused(true)
}); });
@@ -1339,7 +1332,7 @@ unsafe extern "system" fn public_window_callback<T>(
let position = LogicalPosition::from_physical((x, y), dpi_factor); let position = LogicalPosition::from_physical((x, y), dpi_factor);
subclass_input.send_event(Event::WindowEvent { 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() }, event: CursorMoved { device_id: DEVICE_ID, position, modifiers: event::get_key_mods() },
}); });
@@ -1347,9 +1340,9 @@ unsafe extern "system" fn public_window_callback<T>(
}, },
winuser::WM_KILLFOCUS => { winuser::WM_KILLFOCUS => {
use events::WindowEvent::Focused; use event::WindowEvent::Focused;
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: Focused(false) event: Focused(false)
}); });
0 0
@@ -1406,7 +1399,7 @@ unsafe extern "system" fn public_window_callback<T>(
// Only sent on Windows 8.1 or newer. On Windows 7 and older user has to log out to change // 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. // DPI, therefore all applications are closed while DPI is changing.
winuser::WM_DPICHANGED => { 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 // 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 // "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<T>(
} }
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: HiDpiFactorChanged(new_dpi_factor), event: HiDpiFactorChanged(new_dpi_factor),
}); });
@@ -1466,10 +1459,10 @@ unsafe extern "system" fn public_window_callback<T>(
winuser::DestroyWindow(window); winuser::DestroyWindow(window);
0 0
} else if msg == *INITIAL_DPI_MSG_ID { } 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); let scale_factor = dpi_to_scale_factor(wparam as u32);
subclass_input.send_event(Event::WindowEvent { subclass_input.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(window)), window_id: RootWindowId(WindowId(window)),
event: HiDpiFactorChanged(scale_factor), event: HiDpiFactorChanged(scale_factor),
}); });
// Automatically resize for actual DPI // Automatically resize for actual DPI

View File

@@ -7,7 +7,7 @@ use winapi::shared::minwindef::{BYTE, LPARAM, WPARAM};
use winapi::shared::windef::{HICON, HWND}; use winapi::shared::windef::{HICON, HWND};
use winapi::um::winuser; use winapi::um::winuser;
use {Pixel, PIXEL_SIZE, Icon}; use icon::{Pixel, PIXEL_SIZE, Icon};
use platform_impl::platform::util; use platform_impl::platform::util;
impl Pixel { impl Pixel {

View File

@@ -7,10 +7,13 @@ pub use self::events_loop::{EventLoop, EventLoopProxy};
pub use self::monitor::MonitorId; pub use self::monitor::MonitorId;
pub use self::window::Window; pub use self::window::Window;
use window::Icon;
use event::DeviceId as RootDeviceId;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes { pub struct PlatformSpecificWindowBuilderAttributes {
pub parent: Option<HWND>, pub parent: Option<HWND>,
pub taskbar_icon: Option<::Icon>, pub taskbar_icon: Option<Icon>,
pub no_redirection_bitmap: bool, 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. // 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 { fn wrap_device_id(id: u32) -> RootDeviceId {
::DeviceId(DeviceId(id)) RootDeviceId(DeviceId(id))
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]

View File

@@ -32,7 +32,7 @@ use winapi::um::winuser::{
}; };
use platform_impl::platform::util; use platform_impl::platform::util;
use events::ElementState; use event::ElementState;
#[allow(dead_code)] #[allow(dead_code)]
pub fn get_raw_input_device_list() -> Option<Vec<RAWINPUTDEVICELIST>> { pub fn get_raw_input_device_list() -> Option<Vec<RAWINPUTDEVICELIST>> {

View File

@@ -18,16 +18,9 @@ use winapi::um::wingdi::{CreateRectRgn, DeleteObject};
use winapi::um::oleidl::LPDROPTARGET; use winapi::um::oleidl::LPDROPTARGET;
use winapi::um::winnt::{LONG, LPCWSTR}; use winapi::um::winnt::{LONG, LPCWSTR};
use { use window::{CreationError, Icon, WindowAttributes, MouseCursor};
CreationError, use dpi::{LogicalPosition, LogicalSize, PhysicalSize};
Icon, use monitor::MonitorId as RootMonitorId;
LogicalPosition,
LogicalSize,
MonitorId as RootMonitorId,
MouseCursor,
PhysicalSize,
WindowAttributes,
};
use platform_impl::platform::{Cursor, PlatformSpecificWindowBuilderAttributes, WindowId}; use platform_impl::platform::{Cursor, PlatformSpecificWindowBuilderAttributes, WindowId};
use platform_impl::platform::dpi::{dpi_to_scale_factor, get_hwnd_dpi}; 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}; use platform_impl::platform::events_loop::{self, EventLoop, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID, REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID};

View File

@@ -1,20 +1,160 @@
use std::collections::vec_deque::IntoIter as VecDequeIter; use std::{fmt, error};
use { use platform_impl;
CreationError, use event_loop::EventLoop;
EventLoop, use monitor::{AvailableMonitorsIter, MonitorId};
Icon, use dpi::{LogicalPosition, LogicalSize};
LogicalPosition,
LogicalSize,
MouseCursor,
PhysicalPosition,
PhysicalSize,
platform_impl,
Window,
WindowBuilder,
WindowId,
};
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<LogicalSize>,
/// 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<LogicalSize>,
/// 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<LogicalSize>,
/// 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<MonitorId>,
/// 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<Icon>,
/// [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 { impl WindowBuilder {
/// Initializes a new `WindowBuilder` with default values. /// Initializes a new `WindowBuilder` with default values.
#[inline] #[inline]
@@ -444,66 +584,94 @@ impl Window {
} }
} }
/// An iterator for the list of available monitors. /// Error that can happen while creating a window or a headless renderer.
// 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<platform_impl::MonitorId>,
}
impl Iterator for AvailableMonitorsIter {
type Item = MonitorId;
#[inline]
fn next(&mut self) -> Option<MonitorId> {
self.data.next().map(|id| MonitorId { inner: id })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.data.size_hint()
}
}
/// Identifier for a monitor.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MonitorId { pub enum CreationError {
pub(crate) inner: platform_impl::MonitorId OsError(String),
/// TODO: remove this error
NotSupported,
} }
impl MonitorId { impl CreationError {
/// Returns a human-readable name of the monitor. fn to_string(&self) -> &str {
/// match *self {
/// Returns `None` if the monitor doesn't exist anymore. CreationError::OsError(ref text) => &text,
#[inline] CreationError::NotSupported => "Some of the requested attributes are not supported",
pub fn get_name(&self) -> Option<String> { }
self.inner.get_name() }
} }
/// Returns the monitor's resolution. impl fmt::Display for CreationError {
#[inline] fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
pub fn get_dimensions(&self) -> PhysicalSize { formatter.write_str(self.to_string())
self.inner.get_dimensions() }
} }
/// Returns the top-left corner position of the monitor relative to the larger full impl error::Error for CreationError {
/// screen area. fn description(&self) -> &str {
#[inline] self.to_string()
pub fn get_position(&self) -> PhysicalPosition { }
self.inner.get_position() }
}
/// Describes the appearance of the mouse cursor.
/// Returns the DPI factor that can be used to map logical pixels to physical pixels, and vice versa. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
/// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
/// See the [`dpi`](dpi/index.html) module for more information. pub enum MouseCursor {
/// /// The platform-dependent default cursor.
/// ## Platform-specific Default,
/// /// A simple crosshair.
/// - **X11:** Can be overridden using the `WINIT_HIDPI_FACTOR` environment variable. Crosshair,
/// - **Android:** Always returns 1.0. /// A hand (often used to indicate links in web browsers).
#[inline] Hand,
pub fn get_hidpi_factor(&self) -> f64 { /// Self explanatory.
self.inner.get_hidpi_factor() 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
} }
} }

View File

@@ -5,19 +5,19 @@ fn needs_send<T:Send>() {}
#[test] #[test]
fn events_loop_proxy_send() { fn events_loop_proxy_send() {
// ensures that `winit::EventLoopProxy` implements `Send` // ensures that `winit::EventLoopProxy` implements `Send`
needs_send::<winit::EventLoopProxy<()>>(); needs_send::<winit::event_loop::EventLoopProxy<()>>();
} }
#[test] #[test]
fn window_send() { fn window_send() {
// ensures that `winit::Window` implements `Send` // ensures that `winit::Window` implements `Send`
needs_send::<winit::Window>(); needs_send::<winit::window::Window>();
} }
#[test] #[test]
fn ids_send() { fn ids_send() {
// ensures that the various `..Id` types implement `Send` // ensures that the various `..Id` types implement `Send`
needs_send::<winit::WindowId>(); needs_send::<winit::window::WindowId>();
needs_send::<winit::DeviceId>(); needs_send::<winit::event::DeviceId>();
needs_send::<winit::MonitorId>(); needs_send::<winit::monitor::MonitorId>();
} }

View File

@@ -5,5 +5,5 @@ fn needs_sync<T:Sync>() {}
#[test] #[test]
fn window_sync() { fn window_sync() {
// ensures that `winit::Window` implements `Sync` // ensures that `winit::Window` implements `Sync`
needs_sync::<winit::Window>(); needs_sync::<winit::window::Window>();
} }