Event Loop 2.0 API and Windows implementation (#638)

* Rename EventsLoop and associated types to EventLoop

* Rename WindowEvent::Refresh to WindowEvent::Redraw

* Remove second thread from win32 backend

* Update run_forever to hijack thread

* Replace windows Mutex with parking_lot Mutex

* Implement new ControlFlow and associated events

* Add StartCause::Init support, timer example

* Add ability to send custom user events

* Fully invert windows control flow so win32 calls into winit's callback

* Add request_redraw

* Rename platform to platform_impl

* Rename os to platform, add Ext trait postfixes

* Add platform::desktop module with EventLoopExt::run_return

* Re-organize into module structure

* Improve documentation

* Small changes to examples

* Improve docs for run and run_return

* Change instances of "events_loop" to "event_loop"

* Rename MonitorId to MonitorHandle

* Add CHANGELOG entry

* Improve WaitUntil timer precision

* When SendEvent is called during event closure, buffer events

* Fix resize lag when waiting in some situations

* Update send test and errors that broke some examples/APIs

* Improve clarity/fix typos in docs

* Fix unreachable panic after setting ControlFlow to Poll during some RedrawRequested events.

* Fix crash when running in release mode

* Remove crossbeam dependency and make drop events work again

* Remove serde implementations from ControlFlow

* Fix 1.24.1 build

* Fix freeze when setting decorations

* Replace &EventLoop in callback with &EventLoopWindowTarget

* Document and implement Debug for EventLoopWindowTarget

* Fix some deadlocks that could occur when changing window state

* Fix thread executor not executing closure when called from non-loop thread

* Fix buffered events not getting dispatched

* Fix crash with runner refcell not getting dropped

* Address review feedback

* Fix CHANGELOG typo

* Catch panics in user callback
This commit is contained in:
Osspial 2019-02-05 10:30:33 -05:00 committed by GitHub
parent 7be1d16263
commit 9602716ed2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
92 changed files with 3467 additions and 1260 deletions

View file

@ -1,5 +1,41 @@
# Unreleased
- Changes below are considered **breaking**.
- Change all occurrences of `EventsLoop` to `EventLoop`.
- Previously flat API is now exposed through `event`, `event_loop`, `monitor`, and `window` modules.
- `os` module changes:
- Renamed to `platform`.
- All traits now have platform-specific suffixes.
- Exposes new `desktop` module on Windows, Mac, and Linux.
- Changes to event loop types:
- `EventLoopProxy::wakeup` has been removed in favor of `send_event`.
- **Major:** New `run` method drives winit event loop.
- Returns `!` to ensure API behaves identically across all supported platforms.
- This allows `emscripten` implementation to work without lying about the API.
- `ControlFlow`'s variants have been replaced with `Wait`, `WaitUntil(Instant)`, `Poll`, and `Exit`.
- Is read after `EventsCleared` is processed.
- `Wait` waits until new events are available.
- `WaitUntil` waits until either new events are available or the provided time has been reached.
- `Poll` instantly resumes the event loop.
- `Exit` aborts the event loop.
- Takes a closure that implements `'static + FnMut(Event<T>, &EventLoop<T>, &mut ControlFlow)`.
- `&EventLoop<T>` is provided to allow new `Window`s to be created.
- **Major:** `platform::desktop` module exposes `EventLoopExtDesktop` trait with `run_return` method.
- Behaves identically to `run`, but returns control flow to the calling context and can take non-`'static` closures.
- `EventLoop`'s `poll_events` and `run_forever` methods have been removed in favor of `run` and `run_return`.
- Changes to events:
- Remove `Event::Awakened` in favor of `Event::UserEvent(T)`.
- Can be sent with `EventLoopProxy::send_event`.
- Rename `WindowEvent::Refresh` to `WindowEvent::RedrawRequested`.
- `RedrawRequested` can be sent by the user with the `Window::request_redraw` method.
- `EventLoop`, `EventLoopProxy`, and `Event` are now generic over `T`, for use in `UserEvent`.
- **Major:** Add `NewEvents(StartCause)`, `EventsCleared`, and `LoopDestroyed` variants to `Event`.
- `NewEvents` is emitted when new events are ready to be processed by event loop.
- `StartCause` describes why new events are available, with `ResumeTimeReached`, `Poll`, `WaitCancelled`, and `Init` (sent once at start of loop).
- `EventsCleared` is emitted when all available events have been processed.
- Can be used to perform logic that depends on all events being processed (e.g. an iteration of a game loop).
- `LoopDestroyed` is emitted when the `run` or `run_return` method is about to exit.
- Rename `MonitorId` to `MonitorHandle`.
- Removed `serde` implementations from `ControlFlow`.
- On Wayland, add `set_wayland_theme()` to control client decoration color theme
- Added serde serialization to `os::unix::XWindowType`.
- **Breaking:** `image` crate upgraded to 0.21. This is exposed as part of the `icon_loading` API.

View file

@ -43,6 +43,7 @@ bitflags = "1"
version = "0.3.6"
features = [
"combaseapi",
"commctrl",
"dwmapi",
"errhandlingapi",
"hidusage",
@ -68,3 +69,6 @@ smithay-client-toolkit = "0.4.3"
x11-dl = "2.18.3"
parking_lot = "0.7"
percent-encoding = "1.0"
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "windows"))'.dependencies.parking_lot]
version = "0.7"

View file

@ -26,10 +26,10 @@ another library.
extern crate winit;
fn main() {
let mut events_loop = winit::EventsLoop::new();
let window = winit::Window::new(&events_loop).unwrap();
let mut event_loop = winit::EventLoop::new();
let window = winit::Window::new(&event_loop).unwrap();
events_loop.run_forever(|event| {
event_loop.run(|event| {
match event {
winit::Event::WindowEvent {
event: winit::WindowEvent::CloseRequested,

View file

@ -1,32 +1,48 @@
extern crate winit;
use winit::{Event, 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 mut events_loop = winit::EventsLoop::new();
let event_loop = EventLoop::new();
let window = winit::WindowBuilder::new().build(&events_loop).unwrap();
let window = WindowBuilder::new().build(&event_loop).unwrap();
window.set_title("A fantastic window!");
let cursors = [MouseCursor::Default, MouseCursor::Crosshair, MouseCursor::Hand, MouseCursor::Arrow, MouseCursor::Move, MouseCursor::Text, MouseCursor::Wait, MouseCursor::Help, MouseCursor::Progress, MouseCursor::NotAllowed, MouseCursor::ContextMenu, MouseCursor::Cell, MouseCursor::VerticalText, MouseCursor::Alias, MouseCursor::Copy, MouseCursor::NoDrop, MouseCursor::Grab, MouseCursor::Grabbing, MouseCursor::AllScroll, MouseCursor::ZoomIn, MouseCursor::ZoomOut, MouseCursor::EResize, MouseCursor::NResize, MouseCursor::NeResize, MouseCursor::NwResize, MouseCursor::SResize, MouseCursor::SeResize, MouseCursor::SwResize, MouseCursor::WResize, MouseCursor::EwResize, MouseCursor::NsResize, MouseCursor::NeswResize, MouseCursor::NwseResize, MouseCursor::ColResize, MouseCursor::RowResize];
let mut cursor_idx = 0;
events_loop.run_forever(|event| {
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent { event: WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. }, .. } => {
println!("Setting cursor to \"{:?}\"", cursors[cursor_idx]);
window.set_cursor(cursors[cursor_idx]);
if cursor_idx < cursors.len() - 1 {
println!("Setting cursor to \"{:?}\"", CURSORS[cursor_idx]);
window.set_cursor(CURSORS[cursor_idx]);
if cursor_idx < CURSORS.len() - 1 {
cursor_idx += 1;
} else {
cursor_idx = 0;
}
},
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
return ControlFlow::Break;
*control_flow = ControlFlow::Exit;
return;
},
_ => ()
}
ControlFlow::Continue
});
}
const CURSORS: &[MouseCursor] = &[
MouseCursor::Default, MouseCursor::Crosshair, MouseCursor::Hand,
MouseCursor::Arrow, MouseCursor::Move, MouseCursor::Text,
MouseCursor::Wait, MouseCursor::Help, MouseCursor::Progress,
MouseCursor::NotAllowed, MouseCursor::ContextMenu, MouseCursor::Cell,
MouseCursor::VerticalText, MouseCursor::Alias, MouseCursor::Copy,
MouseCursor::NoDrop, MouseCursor::Grab, MouseCursor::Grabbing,
MouseCursor::AllScroll, MouseCursor::ZoomIn, MouseCursor::ZoomOut,
MouseCursor::EResize, MouseCursor::NResize, MouseCursor::NeResize,
MouseCursor::NwResize, MouseCursor::SResize, MouseCursor::SeResize,
MouseCursor::SwResize, MouseCursor::WResize, MouseCursor::EwResize,
MouseCursor::NsResize, MouseCursor::NeswResize, MouseCursor::NwseResize,
MouseCursor::ColResize, MouseCursor::RowResize
];

View file

@ -1,30 +1,34 @@
extern crate winit;
fn main() {
let mut events_loop = winit::EventsLoop::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 event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("Super Cursor Grab'n'Hide Simulator 9000")
.build(&events_loop)
.build(&event_loop)
.unwrap();
events_loop.run_forever(|event| {
if let winit::Event::WindowEvent { event, .. } = event {
use winit::WindowEvent::*;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
if let Event::WindowEvent { event, .. } = event {
match event {
CloseRequested => return winit::ControlFlow::Break,
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 => return winit::ControlFlow::Break,
Escape => *control_flow = ControlFlow::Exit,
G => window.grab_cursor(!modifiers.shift).unwrap(),
H => window.hide_cursor(!modifiers.shift),
_ => (),
@ -33,6 +37,5 @@ fn main() {
_ => (),
}
}
winit::ControlFlow::Continue
});
}

View file

@ -1,10 +1,13 @@
extern crate winit;
use std::io::{self, Write};
use winit::{ControlFlow, Event, WindowEvent};
use winit::monitor::MonitorHandle;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent, VirtualKeyCode, ElementState, KeyboardInput};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() {
let mut events_loop = winit::EventsLoop::new();
let event_loop = EventLoop::new();
#[cfg(target_os = "macos")]
let mut macos_use_simple_fullscreen = false;
@ -26,43 +29,44 @@ fn main() {
// Prompt for monitor when using native fullscreen
if !macos_use_simple_fullscreen {
Some(prompt_for_monitor(&events_loop))
Some(prompt_for_monitor(&event_loop))
} else {
None
}
}
#[cfg(not(target_os = "macos"))]
Some(prompt_for_monitor(&events_loop))
Some(prompt_for_monitor(&event_loop))
};
let mut is_fullscreen = monitor.is_some();
let mut is_maximized = false;
let mut decorations = true;
let window = winit::WindowBuilder::new()
let window = WindowBuilder::new()
.with_title("Hello world!")
.with_fullscreen(monitor)
.build(&events_loop)
.build(&event_loop)
.unwrap();
events_loop.run_forever(|event| {
event_loop.run(move |event, _, control_flow| {
println!("{:?}", event);
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => return ControlFlow::Break,
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, _) => return ControlFlow::Break,
(winit::VirtualKeyCode::F, winit::ElementState::Pressed) => {
(VirtualKeyCode::Escape, _) => *control_flow = ControlFlow::Exit,
(VirtualKeyCode::F, ElementState::Pressed) => {
#[cfg(target_os = "macos")]
{
if macos_use_simple_fullscreen {
@ -82,11 +86,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);
}
@ -96,14 +100,12 @@ fn main() {
},
_ => {}
}
ControlFlow::Continue
});
}
// Enumerate monitors and prompt user to choose one
fn prompt_for_monitor(events_loop: &winit::EventsLoop) -> winit::MonitorId {
for (num, monitor) in events_loop.get_available_monitors().enumerate() {
fn prompt_for_monitor(event_loop: &EventLoop<()>) -> MonitorHandle {
for (num, monitor) in event_loop.get_available_monitors().enumerate() {
println!("Monitor #{}: {:?}", num, monitor.get_name());
}
@ -113,7 +115,7 @@ fn prompt_for_monitor(events_loop: &winit::EventsLoop) -> winit::MonitorId {
let mut num = String::new();
io::stdin().read_line(&mut num).unwrap();
let num = num.trim().parse().ok().expect("Please enter a number");
let monitor = events_loop.get_available_monitors().nth(num).expect("Please enter a valid ID");
let monitor = event_loop.get_available_monitors().nth(num).expect("Please enter a valid ID");
println!("Using {:?}", monitor.get_name());

View file

@ -1,23 +1,27 @@
extern crate winit;
fn main() {
let mut events_loop = winit::EventsLoop::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 event_loop = EventLoop::new();
let _window = WindowBuilder::new()
.with_title("Your faithful window")
.build(&events_loop)
.build(&event_loop)
.unwrap();
let mut close_requested = false;
events_loop.run_forever(|event| {
use winit::WindowEvent::*;
use winit::ElementState::Released;
use winit::VirtualKeyCode::{N, Y};
event_loop.run(move |event, _, control_flow| {
use winit::event::ElementState::Released;
use winit::event::VirtualKeyCode::{N, Y};
*control_flow = ControlFlow::Wait;
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 +38,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 +57,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.
return winit::ControlFlow::Break;
*control_flow = ControlFlow::Exit;
}
}
N => {
@ -68,7 +72,5 @@ fn main() {
},
_ => (),
}
winit::ControlFlow::Continue
});
}

View file

@ -1,23 +1,27 @@
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 mut events_loop = winit::EventsLoop::new();
let event_loop = EventLoop::new();
let window = winit::WindowBuilder::new()
.build(&events_loop)
let window = WindowBuilder::new()
.build(&event_loop)
.unwrap();
window.set_min_dimensions(Some(LogicalSize::new(400.0, 200.0)));
window.set_max_dimensions(Some(LogicalSize::new(800.0, 400.0)));
events_loop.run_forever(|event| {
event_loop.run(move |event, _, control_flow| {
println!("{:?}", event);
match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
*control_flow = ControlFlow::Exit,
_ => *control_flow = ControlFlow::Wait,
}
});
}

View file

@ -1,7 +1,9 @@
extern crate winit;
use winit::event_loop::EventLoop;
use winit::window::WindowBuilder;
fn main() {
let event_loop = winit::EventsLoop::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());
}

View file

@ -1,33 +1,42 @@
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 mut events_loop = winit::EventsLoop::new();
let event_loop = EventLoop::new();
let mut windows = HashMap::new();
for _ in 0..3 {
let window = winit::Window::new(&events_loop).unwrap();
let window = Window::new(&event_loop).unwrap();
windows.insert(window.id(), window);
}
events_loop.run_forever(|event| {
event_loop.run(move |event, event_loop, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
winit::Event::WindowEvent {
event: winit::WindowEvent::CloseRequested,
window_id,
} => {
println!("Window {:?} has received the signal to close", window_id);
Event::WindowEvent { event, window_id } => {
match event {
WindowEvent::CloseRequested => {
println!("Window {:?} has received the signal to close", window_id);
// This drops the window, causing it to close.
windows.remove(&window_id);
// This drops the window, causing it to close.
windows.remove(&window_id);
if windows.is_empty() {
return winit::ControlFlow::Break;
if windows.is_empty() {
*control_flow = ControlFlow::Exit;
}
},
WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, .. }, .. } => {
let window = Window::new(&event_loop).unwrap();
windows.insert(window.id(), window);
},
_ => ()
}
}
_ => (),
}
winit::ControlFlow::Continue
})
}

View file

@ -1,29 +1,34 @@
extern crate winit;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() {
let mut events_loop = winit::EventsLoop::new();
let event_loop: EventLoop<i32> = EventLoop::new_user_event();
let _window = winit::WindowBuilder::new()
let _window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&events_loop)
.build(&event_loop)
.unwrap();
let proxy = events_loop.create_proxy();
let proxy = event_loop.create_proxy();
std::thread::spawn(move || {
// Wake up the `events_loop` once every second.
let mut counter = 0;
// Wake up the `event_loop` once every second.
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
proxy.wakeup().unwrap();
proxy.send_event(counter).unwrap();
counter += 1;
}
});
events_loop.run_forever(|event| {
event_loop.run(move |event, _, control_flow| {
println!("{:?}", event);
match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } =>
winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
*control_flow = ControlFlow::Exit,
_ => *control_flow = ControlFlow::Wait,
}
});
}

View file

@ -0,0 +1,31 @@
extern crate winit;
use std::time::{Instant, Duration};
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
event_loop.run(move |event, _, control_flow| {
println!("{:?}", event);
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
Event::EventsCleared => {
window.request_redraw();
*control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0))
},
_ => ()
}
});
}

View file

@ -1,26 +1,30 @@
extern crate winit;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent, VirtualKeyCode, ElementState, KeyboardInput};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() {
let mut events_loop = winit::EventsLoop::new();
let event_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)
.build(&events_loop)
.build(&event_loop)
.unwrap();
events_loop.run_forever(|event| {
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
winit::Event::WindowEvent { event, .. } => match event {
winit::WindowEvent::CloseRequested => return winit::ControlFlow::Break,
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,
..
},
..
@ -33,6 +37,5 @@ fn main() {
},
_ => (),
};
winit::ControlFlow::Continue
});
}

32
examples/timer.rs Normal file
View file

@ -0,0 +1,32 @@
extern crate winit;
use std::time::{Duration, Instant};
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent, StartCause};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() {
let event_loop = EventLoop::new();
let _window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
event_loop.run(move |event, _, control_flow| {
println!("{:?}", event);
match event {
Event::NewEvents(StartCause::Init) =>
*control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0)),
Event::NewEvents(StartCause::ResumeTimeReached{..}) => {
*control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0));
println!("\nTimer\n");
},
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => ()
}
});
}

View file

@ -1,20 +1,24 @@
extern crate winit;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() {
let mut events_loop = winit::EventsLoop::new();
let event_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();
.build(&event_loop).unwrap();
window.set_title("A fantastic window!");
events_loop.run_forever(|event| {
event_loop.run(move |event, _, control_flow| {
println!("{:?}", event);
match event {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
*control_flow = ControlFlow::Exit,
_ => *control_flow = ControlFlow::Wait,
}
});
}

View file

@ -1,22 +1,25 @@
extern crate winit;
use winit::window::WindowBuilder;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow};
fn main() {
let mut events_loop = winit::EventsLoop::new();
let event_loop = EventLoop::new();
let _window = winit::WindowBuilder::new()
let _window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&events_loop)
.build(&event_loop)
.unwrap();
events_loop.run_forever(|event| {
event_loop.run(|event, _, control_flow| {
println!("{:?}", event);
match event {
winit::Event::WindowEvent {
event: winit::WindowEvent::CloseRequested,
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => winit::ControlFlow::Break,
_ => winit::ControlFlow::Continue,
} => *control_flow = ControlFlow::Exit,
_ => *control_flow = ControlFlow::Wait,
}
});
}

View file

@ -8,7 +8,10 @@ extern crate image;
#[cfg(feature = "icon_loading")]
fn main() {
use winit::Icon;
use winit::window::{WindowBuilder, Icon};
use winit::event::Event;
use winit::event_loop::{EventLoop, ControlFlow};
// 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,21 +23,22 @@ fn main() {
// feature enabled).
let icon = Icon::from_path(path).expect("Failed to open icon");
let mut events_loop = winit::EventsLoop::new();
let event_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.
.with_window_icon(Some(icon))
.build(&events_loop)
.build(&event_loop)
.unwrap();
events_loop.run_forever(|event| {
if let winit::Event::WindowEvent { event, .. } = event {
use winit::WindowEvent::*;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
if let Event::WindowEvent { event, .. } = event {
use winit::event::WindowEvent::*;
match event {
CloseRequested => return winit::ControlFlow::Break,
CloseRequested => *control_flow = ControlFlow::Exit,
DroppedFile(path) => {
use image::GenericImageView;
@ -81,7 +85,6 @@ fn main() {
_ => (),
}
}
winit::ControlFlow::Continue
});
}

View file

@ -0,0 +1,45 @@
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 event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
println!("Close the window to continue.");
event_loop.run_return(|event, _, control_flow| {
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => *control_flow = ControlFlow::Wait,
}
});
drop(window);
let _window_2 = WindowBuilder::new()
.with_title("A second, fantasticer window!")
.build(&event_loop)
.unwrap();
println!("Wa ha ha! You thought that closing the window would finish this?!");
event_loop.run_return(|event, _, control_flow| {
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => *control_flow = ControlFlow::Wait,
}
});
println!("Okay we're done now for real.");
}

View file

@ -33,9 +33,9 @@
//! windows. This event is sent any time the DPI factor changes, either because the window moved to another monitor,
//! or because the user changed the configuration of their screen.
//! - You can also retrieve the DPI factor of a monitor by calling
//! [`MonitorId::get_hidpi_factor`](../struct.MonitorId.html#method.get_hidpi_factor), or the
//! [`MonitorHandle::get_hidpi_factor`](../monitor/struct.MonitorHandle.html#method.get_hidpi_factor), or the
//! current DPI factor applied to a window by calling
//! [`Window::get_hidpi_factor`](../struct.Window.html#method.get_hidpi_factor), which is roughly equivalent
//! [`Window::get_hidpi_factor`](../window/struct.Window.html#method.get_hidpi_factor), which is roughly equivalent
//! to `window.get_current_monitor().get_hidpi_factor()`.
//!
//! Depending on the platform, the window's actual DPI factor may only be known after
@ -59,9 +59,9 @@
//!
//! The window's logical size is conserved across DPI changes, resulting in the physical size changing instead. This
//! may be surprising on X11, but is quite standard elsewhere. Physical size changes always produce a
//! [`Resized`](../enum.WindowEvent.html#variant.Resized) event, even on platforms where no resize actually occurs,
//! [`Resized`](../event/enum.WindowEvent.html#variant.Resized) event, even on platforms where no resize actually occurs,
//! such as macOS and Wayland. As a result, it's not necessary to separately handle
//! [`HiDpiFactorChanged`](../enum.WindowEvent.html#variant.HiDpiFactorChanged) if you're only listening for size.
//! [`HiDpiFactorChanged`](../event/enum.WindowEvent.html#variant.HiDpiFactorChanged) if you're only listening for size.
//!
//! Your GPU has no awareness of the concept of logical pixels, and unless you like wasting pixel density, your
//! framebuffer's size should be in physical pixels.

View file

@ -1,26 +1,88 @@
//! The `Event` enum and assorted supporting types.
//!
//! These are sent to the closure given to [`EventLoop::run(...)`][event_loop_run], where they get
//! processed and used to modify the program state. For more details, see the root-level documentation.
//!
//! [event_loop_run]: ../event_loop/struct.EventLoop.html#method.run
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)]
pub enum Event {
pub enum Event<T> {
/// Emitted when the OS sends an event to a winit window.
WindowEvent {
window_id: WindowId,
event: WindowEvent,
},
/// Emitted when the OS sends an event to a device.
DeviceEvent {
device_id: DeviceId,
event: DeviceEvent,
},
Awakened,
/// Emitted when an event is sent from [`EventLoopProxy::send_event`](../event_loop/struct.EventLoopProxy.html#method.send_event)
UserEvent(T),
/// Emitted when new events arrive from the OS to be processed.
NewEvents(StartCause),
/// Emitted when all of the event loop's events have been processed and control flow is about
/// to be taken away from the program.
EventsCleared,
/// The application has been suspended or resumed.
/// Emitted when the event loop is being shut down. This is irreversable - if this event is
/// emitted, it is guaranteed to be the last event emitted.
LoopDestroyed,
/// Emitted when the application has been suspended or resumed.
///
/// The parameter is true if app was suspended, and false if it has been resumed.
Suspended(bool),
}
impl<T> Event<T> {
pub fn map_nonuser_event<U>(self) -> Result<Event<U>, Event<T>> {
use self::Event::*;
match self {
UserEvent(_) => Err(self),
WindowEvent{window_id, event} => Ok(WindowEvent{window_id, event}),
DeviceEvent{device_id, event} => Ok(DeviceEvent{device_id, event}),
NewEvents(cause) => Ok(NewEvents(cause)),
EventsCleared => Ok(EventsCleared),
LoopDestroyed => Ok(LoopDestroyed),
Suspended(suspended) => Ok(Suspended(suspended)),
}
}
}
/// Describes the reason the event loop is resuming.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StartCause {
/// Sent if the time specified by `ControlFlow::WaitUntil` has been reached. Contains the
/// moment the timeout was requested and the requested resume time. The actual resume time is
/// guaranteed to be equal to or after the requested resume time.
ResumeTimeReached {
start: Instant,
requested_resume: Instant
},
/// Sent if the OS has new events to send to the window, after a wait was requested. Contains
/// the moment the wait was requested and the resume time, if requested.
WaitCancelled {
start: Instant,
requested_resume: Option<Instant>
},
/// Sent if the event loop is being resumed after the loop's control flow was set to
/// `ControlFlow::Poll`.
Poll,
/// Sent once, immediately after `run` is called. Indicates that the loop was just initialized.
Init
}
/// Describes an event from a `Window`.
#[derive(Clone, Debug, PartialEq)]
pub enum WindowEvent {
@ -37,19 +99,19 @@ pub enum WindowEvent {
Destroyed,
/// A file has been dropped into the window.
///
///
/// When the user drops multiple files at once, this event will be emitted for each file
/// separately.
DroppedFile(PathBuf),
/// A file is being hovered over the window.
///
///
/// When the user hovers multiple files at once, this event will be emitted for each file
/// separately.
HoveredFile(PathBuf),
/// A file was hovered, but has exited the window.
///
///
/// There will be a single `HoveredFileCancelled` event triggered even if multiple files were
/// hovered.
HoveredFileCancelled,
@ -99,8 +161,8 @@ pub enum WindowEvent {
/// Motion on some analog axis. May report data redundant to other, more specific events.
AxisMotion { device_id: DeviceId, axis: AxisId, value: f64 },
/// The window needs to be redrawn.
Refresh,
/// The OS or application has requested that the window be redrawn.
RedrawRequested,
/// Touch event has been received
Touch(Touch),
@ -117,6 +179,25 @@ 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);
impl DeviceId {
/// Returns a dummy `DeviceId`, useful for unit testing. The only guarantee made about the return
/// value of this function is that it will always be equal to itself and to future values returned
/// by this function. No other guarantees are made. This may be equal to a real `DeviceId`.
///
/// **Passing this into a winit function will result in undefined behavior.**
pub unsafe fn dummy() -> Self {
DeviceId(platform_impl::DeviceId::dummy())
}
}
/// 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

203
src/event_loop.rs Normal file
View file

@ -0,0 +1,203 @@
//! The `EventLoop` struct and assorted supporting types, including `ControlFlow`.
//!
//! If you want to send custom events to the event loop, use [`EventLoop::create_proxy()`][create_proxy]
//! to acquire an [`EventLoopProxy`][event_loop_proxy] and call its [`send_event`][send_event] method.
//!
//! See the root-level documentation for information on how to create and use an event loop to
//! handle events.
//!
//! [create_proxy]: ./struct.EventLoop.html#method.create_proxy
//! [event_loop_proxy]: ./struct.EventLoopProxy.html
//! [send_event]: ./struct.EventLoopProxy.html#method.send_event
use std::{fmt, error};
use std::time::Instant;
use std::ops::Deref;
use platform_impl;
use event::Event;
use monitor::{AvailableMonitorsIter, MonitorHandle};
/// 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 across threads (due to platform-dependant logic
/// forbidding 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 wake up an `EventLoop` from an other thread.
pub struct EventLoop<T: 'static> {
pub(crate) event_loop: platform_impl::EventLoop<T>,
pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync
}
/// Target that associates windows with an `EventLoop`.
///
/// This type exists to allow you to create new windows while Winit executes your callback.
/// `EventLoop` will coerce into this type, so functions that take this as a parameter can also
/// take `&EventLoop`.
pub struct EventLoopWindowTarget<T: 'static> {
pub(crate) p: platform_impl::EventLoopWindowTarget<T>,
pub(crate) _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync
}
impl<T> fmt::Debug for EventLoop<T> {
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
fmtr.pad("EventLoop { .. }")
}
}
impl<T> fmt::Debug for EventLoopWindowTarget<T> {
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
fmtr.pad("EventLoopWindowTarget { .. }")
}
}
/// Set by the user callback given to the `EventLoop::run` method.
///
/// Indicates the desired behavior of the event loop after [`Event::EventsCleared`][events_cleared]
/// is emitted. Defaults to `Poll`.
///
/// ## Persistency
/// Almost every change is persistent between multiple calls to the event loop closure within a
/// given run loop. The only exception to this is `Exit` which, once set, cannot be unset. Changes
/// are **not** persistent between multiple calls to `run_return` - issuing a new call will reset
/// the control flow to `Poll`.
///
/// [events_cleared]: ../event/enum.Event.html#variant.EventsCleared
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ControlFlow {
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
/// whether or not new events are available to process.
Poll,
/// 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),
/// Send a `LoopDestroyed` event and stop the event loop. This variant is *sticky* - once set,
/// `control_flow` cannot be changed from `Exit`, and any future attempts to do so will result
/// in the `control_flow` parameter being reset to `Exit`.
Exit
}
impl Default for ControlFlow {
#[inline(always)]
fn default() -> ControlFlow {
ControlFlow::Poll
}
}
impl EventLoop<()> {
/// Builds a new event loop with a `()` as the user event type.
pub fn new() -> EventLoop<()> {
EventLoop::<()>::new_user_event()
}
}
impl<T> EventLoop<T> {
/// Builds a new event 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 {
event_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.event_loop.get_available_monitors();
AvailableMonitorsIter{ data: data.into_iter() }
}
/// Returns the primary monitor of the system.
#[inline]
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle { inner: self.event_loop.get_primary_monitor() }
}
/// Hijacks the calling thread and initializes the `winit` event loop with the provided
/// closure. Since the closure is `'static`, it must be a `move` closure if it needs to
/// access any data from the calling context.
///
/// See the [`ControlFlow`] docs for information on how changes to `&mut ControlFlow` impact the
/// event loop's behavior.
///
/// Any values not passed to this function will *not* be dropped.
///
/// [`ControlFlow`]: ./enum.ControlFlow.html
#[inline]
pub fn run<F>(self, event_handler: F) -> !
where F: 'static + FnMut(Event<T>, &EventLoopWindowTarget<T>, &mut ControlFlow)
{
self.event_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 {
event_loop_proxy: self.event_loop.create_proxy(),
}
}
}
impl<T> Deref for EventLoop<T> {
type Target = EventLoopWindowTarget<T>;
fn deref(&self) -> &EventLoopWindowTarget<T> {
self.event_loop.window_target()
}
}
/// Used to send custom events to `EventLoop`.
#[derive(Clone)]
pub struct EventLoopProxy<T> {
event_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.event_loop_proxy.send_event(event)
}
}
impl<T> fmt::Debug for EventLoopProxy<T> {
fn fmt(&self, fmtr: &mut fmt::Formatter) -> 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

@ -2,87 +2,78 @@
//!
//! # Building a window
//!
//! Before you can build a window, you first need to build an `EventsLoop`. This is done with the
//! `EventsLoop::new()` function. Example:
//! Before you can build a [`Window`], you first need to build an [`EventLoop`]. This is done with the
//! [`EventLoop::new()`] function.
//!
//! ```no_run
//! use winit::EventsLoop;
//! let events_loop = EventsLoop::new();
//! use winit::event_loop::EventLoop;
//! let event_loop = EventLoop::new();
//! ```
//!
//! Once this is done there are two ways to create a window:
//! Once this is done there are two ways to create a [`Window`]:
//!
//! - Calling `Window::new(&events_loop)`.
//! - Calling `let builder = WindowBuilder::new()` then `builder.build(&events_loop)`.
//! - Calling [`Window::new(&event_loop)`][window_new].
//! - Calling [`let builder = WindowBuilder::new()`][window_builder_new] then [`builder.build(&event_loop)`][window_builder_build].
//!
//! The first way is the simplest way and will give you default values for everything.
//!
//! The second way allows you to customize the way your window will look and behave by modifying
//! the fields of the `WindowBuilder` object before you create the window.
//! The second way allows you to customize the way your [`Window`] will look and behave by modifying
//! the fields of the [`WindowBuilder`] object before you create the [`Window`].
//!
//! # Events handling
//! # Event handling
//!
//! Once a window has been created, it will *generate events*. For example whenever the user moves
//! the window, resizes the window, moves the mouse, etc. an event is generated.
//! Once a [`Window`] has been created, it will *generate events*. For example whenever the user moves
//! the [`Window`], resizes the [`Window`], moves the mouse, etc. an event is generated.
//!
//! The events generated by a window can be retrieved from the `EventsLoop` the window was created
//! The events generated by a [`Window`] can be retreived from the [`EventLoop`] the [`Window`] was created
//! with.
//!
//! There are two ways to do so. The first is to call `events_loop.poll_events(...)`, which will
//! retrieve all the events pending on the windows and immediately return after no new event is
//! available. You usually want to use this method in application that render continuously on the
//! screen, such as video games.
//! You do this by calling [`event_loop.run(...)`][event_loop_run]. This function will run forever
//! unless `control_flow` is set to [`ControlFlow`]`::`[`Exit`], at which point [`Event`]`::`[`LoopDestroyed`]
//! is emitted and the entire program terminates.
//!
//! ```no_run
//! use winit::{Event, WindowEvent};
//! use winit::dpi::LogicalSize;
//! # use winit::EventsLoop;
//! # let mut events_loop = EventsLoop::new();
//! use winit::event_loop::ControlFlow;
//! use winit::event::{Event, WindowEvent};
//! # use winit::event_loop::EventLoop;
//! # let event_loop = EventLoop::new();
//!
//! loop {
//! events_loop.poll_events(|event| {
//! match event {
//! Event::WindowEvent {
//! event: WindowEvent::Resized(LogicalSize { width, height }),
//! ..
//! } => {
//! println!("The window was resized to {}x{}", width, height);
//! },
//! _ => ()
//! }
//! });
//! }
//! ```
//!
//! The second way is to call `events_loop.run_forever(...)`. As its name tells, it will run
//! forever unless it is stopped by returning `ControlFlow::Break`.
//!
//! ```no_run
//! use winit::{ControlFlow, Event, WindowEvent};
//! # use winit::EventsLoop;
//! # let mut events_loop = EventsLoop::new();
//!
//! events_loop.run_forever(|event| {
//! event_loop.run(move |event, _, control_flow| {
//! match event {
//! Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
//! println!("The close button was pressed; stopping");
//! ControlFlow::Break
//! *control_flow = ControlFlow::Exit
//! },
//! _ => ControlFlow::Continue,
//! _ => *control_flow = ControlFlow::Wait,
//! }
//! });
//! ```
//!
//! If you use multiple windows, the `WindowEvent` event has a member named `window_id`. You can
//! compare it with the value returned by the `id()` method of `Window` in order to know which
//! window has received the event.
//! If you use multiple [`Window`]s, [`Event`]`::`[`WindowEvent`] has a member named `window_id`. You can
//! compare it with the value returned by the [`id()`][window_id_fn] method of [`Window`] in order to know which
//! [`Window`] has received the event.
//!
//! # 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
//! to create an OpenGL/Vulkan/DirectX/Metal/etc. context that will draw 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 [`platform`] module), which in turn allows you
//! to create an OpenGL/Vulkan/DirectX/Metal/etc. context that will draw on the [`Window`].
//!
//! [`EventLoop`]: ./event_loop/struct.EventLoop.html
//! [`EventLoop::new()`]: ./event_loop/struct.EventLoop.html#method.new
//! [event_loop_run]: ./event_loop/struct.EventLoop.html#method.run
//! [`ControlFlow`]: ./event_loop/enum.ControlFlow.html
//! [`Exit`]: ./event_loop/enum.ControlFlow.html#variant.Exit
//! [`Window`]: ./window/struct.Window.html
//! [`WindowBuilder`]: ./window/struct.WindowBuilder.html
//! [window_new]: ./window/struct.Window.html#method.new
//! [window_builder_new]: ./window/struct.WindowBuilder.html#method.new
//! [window_builder_build]: ./window/struct.WindowBuilder.html#method.build
//! [window_id_fn]: ./window/struct.Window.html#method.id
//! [`Event`]: ./event/enum.Event.html
//! [`WindowEvent`]: ./event/enum.Event.html#variant.WindowEvent
//! [`LoopDestroyed`]: ./event/enum.Event.html#variant.LoopDestroyed
//! [`platform`]: ./platform/index.html
#[allow(unused_imports)]
#[macro_use]
@ -114,429 +105,19 @@ extern crate core_foundation;
extern crate core_graphics;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
extern crate x11_dl;
#[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", target_os = "windows"))]
extern crate parking_lot;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
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;
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;
mod window;
mod platform_impl;
pub mod window;
pub mod monitor;
pub mod os;
/// Represents a window.
///
/// # Example
///
/// ```no_run
/// use winit::{Event, EventsLoop, Window, WindowEvent, ControlFlow};
///
/// let mut events_loop = EventsLoop::new();
/// let window = Window::new(&events_loop).unwrap();
///
/// events_loop.run_forever(|event| {
/// match event {
/// Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
/// ControlFlow::Break
/// },
/// _ => ControlFlow::Continue,
/// }
/// });
/// ```
pub struct Window {
window: platform::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::WindowId);
impl WindowId {
/// Returns a dummy `WindowId`, useful for unit testing. The only guarantee made about the return
/// value of this function is that it will always be equal to itself and to future values returned
/// by this function. No other guarantees are made. This may be equal to a real `WindowId`.
///
/// **Passing this into a winit function will result in undefined behavior.**
pub unsafe fn dummy() -> Self {
WindowId(platform::WindowId::dummy())
}
}
/// 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::DeviceId);
impl DeviceId {
/// Returns a dummy `DeviceId`, useful for unit testing. The only guarantee made about the return
/// value of this function is that it will always be equal to itself and to future values returned
/// by this function. No other guarantees are made. This may be equal to a real `DeviceId`.
///
/// **Passing this into a winit function will result in undefined behavior.**
pub unsafe fn dummy() -> Self {
DeviceId(platform::DeviceId::dummy())
}
}
/// Provides a way to retrieve events from the system and from the windows that were registered to
/// the events loop.
///
/// An `EventsLoop` can be seen more or less as a "context". Calling `EventsLoop::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 `EventsLoop` from a another thread, see the `EventsLoopProxy` docs.
///
/// Note that the `EventsLoop` 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 `EventsLoop` _can_ be sent to an other thread, and the
/// `EventsLoopProxy` allows you to wakeup an `EventsLoop` from an other thread.
pub struct EventsLoop {
events_loop: platform::EventsLoop,
_marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync
}
impl std::fmt::Debug for EventsLoop {
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
fmtr.pad("EventsLoop { .. }")
}
}
/// Returned by the user callback given to the `EventsLoop::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 {
/// Continue looping and waiting for events.
Continue,
/// Break from the event loop.
Break,
}
impl EventsLoop {
/// 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() -> EventsLoop {
EventsLoop {
events_loop: platform::EventsLoop::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() }
}
/// Fetches all the events that are pending, calls the callback function for each of them,
/// and returns.
#[inline]
pub fn poll_events<F>(&mut self, callback: F)
where F: FnMut(Event)
{
self.events_loop.poll_events(callback)
}
/// Calls `callback` every time an event is received. If no event is available, sleeps the
/// current thread and waits for an event. If the callback returns `ControlFlow::Break` then
/// `run_forever` will immediately return.
///
/// # Danger!
///
/// The callback is run after *every* event, so if its execution time is non-trivial the event queue may not empty
/// at a sufficient rate. Rendering in the callback with vsync enabled **will** cause significant lag.
#[inline]
pub fn run_forever<F>(&mut self, callback: F)
where F: FnMut(Event) -> ControlFlow
{
self.events_loop.run_forever(callback)
}
/// Creates an `EventsLoopProxy` that can be used to wake up the `EventsLoop` from another
/// thread.
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy {
events_loop_proxy: self.events_loop.create_proxy(),
}
}
}
/// Used to wake up the `EventsLoop` from another thread.
#[derive(Clone)]
pub struct EventsLoopProxy {
events_loop_proxy: platform::EventsLoopProxy,
}
impl std::fmt::Debug for EventsLoopProxy {
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
fmtr.pad("EventsLoopProxy { .. }")
}
}
impl EventsLoopProxy {
/// Wake up the `EventsLoop` from which this proxy was created.
///
/// This causes the `EventsLoop` to emit an `Awakened` event.
///
/// Returns an `Err` if the associated `EventsLoop` no longer exists.
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
self.events_loop_proxy.wakeup()
}
}
/// The error that is returned when an `EventsLoopProxy` attempts to wake up an `EventsLoop` that
/// no longer exists.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct EventsLoopClosed;
impl std::fmt::Display for EventsLoopClosed {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", std::error::Error::description(self))
}
}
impl std::error::Error for EventsLoopClosed {
fn description(&self) -> &str {
"Tried to wake up a closed `EventsLoop`"
}
}
/// 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::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,
}
}
}
pub mod platform;

91
src/monitor.rs Normal file
View file

@ -0,0 +1,91 @@
//! Types useful for interacting with a user's monitors.
//!
//! If you want to get basic information about a monitor, you can use the [`MonitorHandle`][monitor_id]
//! type. This is retreived from an [`AvailableMonitorsIter`][monitor_iter], which can be acquired
//! with:
//! - [`EventLoop::get_available_monitors`][loop_get]
//! - [`Window::get_available_monitors`][window_get].
//!
//! [monitor_id]: ./struct.MonitorHandle.html
//! [monitor_iter]: ./struct.AvailableMonitorsIter.html
//! [loop_get]: ../event_loop/struct.EventLoop.html#method.get_available_monitors
//! [window_get]: ../window/struct.Window.html#method.get_available_monitors
use std::collections::vec_deque::IntoIter as VecDequeIter;
use platform_impl;
use dpi::{PhysicalPosition, PhysicalSize};
/// An iterator over all available monitors.
///
/// Can be acquired with:
/// - [`EventLoop::get_available_monitors`][loop_get]
/// - [`Window::get_available_monitors`][window_get].
///
/// [loop_get]: ../event_loop/struct.EventLoop.html#method.get_available_monitors
/// [window_get]: ../window/struct.Window.html#method.get_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::MonitorHandle>,
}
impl Iterator for AvailableMonitorsIter {
type Item = MonitorHandle;
#[inline]
fn next(&mut self) -> Option<MonitorHandle> {
self.data.next().map(|id| MonitorHandle { inner: id })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.data.size_hint()
}
}
/// Handle to a monitor.
///
/// Allows you to retrieve information about a given monitor and can be used in [`Window`] creation.
///
/// [`Window`]: ../window/struct.Window.html
#[derive(Debug, Clone)]
pub struct MonitorHandle {
pub(crate) inner: platform_impl::MonitorHandle
}
impl MonitorHandle {
/// 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

@ -1,17 +0,0 @@
//! Contains traits with platform-specific methods in them.
//!
//! Contains the follow modules:
//!
//! - `android`
//! - `ios`
//! - `macos`
//! - `unix`
//! - `windows`
//!
//! However only the module corresponding to the platform you're compiling to will be available.
//!
pub mod android;
pub mod ios;
pub mod macos;
pub mod unix;
pub mod windows;

View file

@ -1,28 +1,28 @@
#![cfg(any(target_os = "android"))]
use std::os::raw::c_void;
use EventsLoop;
use EventLoop;
use Window;
use WindowBuilder;
/// Additional methods on `EventsLoop` that are specific to Android.
pub trait EventsLoopExt {
/// Additional methods on `EventLoop` that are specific to Android.
pub trait EventLoopExtAndroid {
/// Makes it possible for glutin to register a callback when a suspend event happens on Android
fn set_suspend_callback(&self, cb: Option<Box<Fn(bool) -> ()>>);
}
impl EventsLoopExt for EventsLoop {
impl EventLoopExtAndroid for EventLoop {
fn set_suspend_callback(&self, cb: Option<Box<Fn(bool) -> ()>>) {
self.events_loop.set_suspend_callback(cb);
self.event_loop.set_suspend_callback(cb);
}
}
/// Additional methods on `Window` that are specific to Android.
pub trait WindowExt {
pub trait WindowExtAndroid {
fn get_native_window(&self) -> *const c_void;
}
impl WindowExt for Window {
impl WindowExtAndroid for Window {
#[inline]
fn get_native_window(&self) -> *const c_void {
self.window.get_native_window()
@ -30,9 +30,9 @@ impl WindowExt for Window {
}
/// Additional methods on `WindowBuilder` that are specific to Android.
pub trait WindowBuilderExt {
pub trait WindowBuilderExtAndroid {
}
impl WindowBuilderExt for WindowBuilder {
impl WindowBuilderExtAndroid for WindowBuilder {
}

31
src/platform/desktop.rs Normal file
View file

@ -0,0 +1,31 @@
#![cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"
))]
use event::Event;
use event_loop::{EventLoop, EventLoopWindowTarget, ControlFlow};
/// Additional methods on `EventLoop` that are specific to desktop platforms.
pub trait EventLoopExtDesktop {
/// A type provided by the user that can be passed through `Event::UserEvent`.
type UserEvent;
/// Initializes the `winit` event loop.
///
/// Unlike `run`, this function accepts non-`'static` (i.e. non-`move`) closures and returns
/// control flow to the caller when `control_flow` is set to `ControlFlow::Exit`.
fn run_return<F>(&mut self, event_handler: F)
where F: FnMut(Event<Self::UserEvent>, &EventLoopWindowTarget<Self::UserEvent>, &mut ControlFlow);
}
impl<T> EventLoopExtDesktop for EventLoop<T> {
type UserEvent = T;
fn run_return<F>(&mut self, event_handler: F)
where F: FnMut(Event<T>, &EventLoopWindowTarget<T>, &mut ControlFlow)
{
self.event_loop.run_return(event_handler)
}
}

View file

@ -2,10 +2,10 @@
use std::os::raw::c_void;
use {MonitorId, Window, WindowBuilder};
use {MonitorHandle, Window, WindowBuilder};
/// Additional methods on `Window` that are specific to iOS.
pub trait WindowExt {
pub trait WindowExtIOS {
/// Returns a pointer to the `UIWindow` that is used by this window.
///
/// The pointer will become invalid when the `Window` is destroyed.
@ -17,7 +17,7 @@ pub trait WindowExt {
fn get_uiview(&self) -> *mut c_void;
}
impl WindowExt for Window {
impl WindowExtIOS for Window {
#[inline]
fn get_uiwindow(&self) -> *mut c_void {
self.window.get_uiwindow() as _
@ -30,14 +30,14 @@ impl WindowExt for Window {
}
/// Additional methods on `WindowBuilder` that are specific to iOS.
pub trait WindowBuilderExt {
pub trait WindowBuilderExtIOS {
/// Sets the root view class used by the `Window`, otherwise a barebones `UIView` is provided.
///
/// The class will be initialized by calling `[root_view initWithFrame:CGRect]`
fn with_root_view_class(self, root_view_class: *const c_void) -> WindowBuilder;
}
impl WindowBuilderExt for WindowBuilder {
impl WindowBuilderExtIOS for WindowBuilder {
#[inline]
fn with_root_view_class(mut self, root_view_class: *const c_void) -> WindowBuilder {
self.platform_specific.root_view_class = unsafe { &*(root_view_class as *const _) };
@ -45,13 +45,13 @@ impl WindowBuilderExt for WindowBuilder {
}
}
/// Additional methods on `MonitorId` that are specific to iOS.
pub trait MonitorIdExt {
/// Additional methods on `MonitorHandle` that are specific to iOS.
pub trait MonitorHandleExtIOS {
/// Returns a pointer to the `UIScreen` that is used by this monitor.
fn get_uiscreen(&self) -> *mut c_void;
}
impl MonitorIdExt for MonitorId {
impl MonitorHandleExtIOS for MonitorHandle {
#[inline]
fn get_uiscreen(&self) -> *mut c_void {
self.inner.get_uiscreen() as _

View file

@ -1,10 +1,10 @@
#![cfg(target_os = "macos")]
use std::os::raw::c_void;
use {LogicalSize, MonitorId, Window, WindowBuilder};
use {LogicalSize, MonitorHandle, Window, WindowBuilder};
/// Additional methods on `Window` that are specific to MacOS.
pub trait WindowExt {
pub trait WindowExtMacOS {
/// Returns a pointer to the cocoa `NSWindow` that is used by this window.
///
/// The pointer will become invalid when the `Window` is destroyed.
@ -33,7 +33,7 @@ pub trait WindowExt {
fn set_simple_fullscreen(&self, fullscreen: bool) -> bool;
}
impl WindowExt for Window {
impl WindowExtMacOS for Window {
#[inline]
fn get_nswindow(&self) -> *mut c_void {
self.window.get_nswindow()
@ -82,7 +82,7 @@ impl Default for ActivationPolicy {
/// - `with_titlebar_hidden`
/// - `with_titlebar_buttons_hidden`
/// - `with_fullsize_content_view`
pub trait WindowBuilderExt {
pub trait WindowBuilderExtMacOS {
/// Sets the activation policy for the window being built.
fn with_activation_policy(self, activation_policy: ActivationPolicy) -> WindowBuilder;
/// Enables click-and-drag behavior for the entire window, not just the titlebar.
@ -101,7 +101,7 @@ pub trait WindowBuilderExt {
fn with_resize_increments(self, increments: LogicalSize) -> WindowBuilder;
}
impl WindowBuilderExt for WindowBuilder {
impl WindowBuilderExtMacOS for WindowBuilder {
#[inline]
fn with_activation_policy(mut self, activation_policy: ActivationPolicy) -> WindowBuilder {
self.platform_specific.activation_policy = activation_policy;
@ -151,15 +151,15 @@ impl WindowBuilderExt for WindowBuilder {
}
}
/// Additional methods on `MonitorId` that are specific to MacOS.
pub trait MonitorIdExt {
/// Additional methods on `MonitorHandle` that are specific to MacOS.
pub trait MonitorHandleExtMacOS {
/// Returns the identifier of the monitor for Cocoa.
fn native_id(&self) -> u32;
/// Returns a pointer to the NSScreen representing this monitor.
fn get_nsscreen(&self) -> Option<*mut c_void>;
}
impl MonitorIdExt for MonitorId {
impl MonitorHandleExtMacOS for MonitorHandle {
#[inline]
fn native_id(&self) -> u32 {
self.inner.get_native_identifier()

View file

@ -1,26 +1,23 @@
pub use self::platform::*;
//! Contains traits with platform-specific methods in them.
//!
//! Contains the follow OS-specific modules:
//!
//! - `android`
//! - `ios`
//! - `macos`
//! - `unix`
//! - `windows`
//!
//! And the following platform-specific module:
//!
//! - `desktop` (available on `windows`, `unix`, and `macos`)
//!
//! However only the module corresponding to the platform you're compiling to will be available.
#[cfg(target_os = "windows")]
#[path="windows/mod.rs"]
mod platform;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
#[path="linux/mod.rs"]
mod platform;
#[cfg(target_os = "macos")]
#[path="macos/mod.rs"]
mod platform;
#[cfg(target_os = "android")]
#[path="android/mod.rs"]
mod platform;
#[cfg(target_os = "ios")]
#[path="ios/mod.rs"]
mod platform;
#[cfg(target_os = "emscripten")]
#[path="emscripten/mod.rs"]
mod platform;
pub mod android;
pub mod ios;
pub mod macos;
pub mod unix;
pub mod windows;
#[cfg(all(not(target_os = "ios"), not(target_os = "windows"), not(target_os = "linux"),
not(target_os = "macos"), not(target_os = "android"), not(target_os = "dragonfly"),
not(target_os = "freebsd"), not(target_os = "netbsd"), not(target_os = "openbsd"),
not(target_os = "emscripten")))]
compile_error!("The platform you're compiling for is not supported by winit");
pub mod desktop;

View file

@ -7,25 +7,25 @@ use std::sync::Arc;
use sctk::window::{ButtonState, Theme};
use {
EventsLoop,
EventLoop,
LogicalSize,
MonitorId,
MonitorHandle,
Window,
WindowBuilder,
};
use platform::{
EventsLoop as LinuxEventsLoop,
use platform_impl::{
EventLoop as LinuxEventLoop,
Window as LinuxWindow,
};
use platform::x11::XConnection;
use platform::x11::ffi::XVisualInfo;
use platform_impl::x11::XConnection;
use platform_impl::x11::ffi::XVisualInfo;
// TODO: stupid hack so that glutin can do its work
#[doc(hidden)]
pub use platform::x11;
pub use platform_impl::x11;
pub use platform::XNotSupported;
pub use platform::x11::util::WindowType as XWindowType;
pub use platform_impl::XNotSupported;
pub use platform_impl::x11::util::WindowType as XWindowType;
/// Theme for wayland client side decorations
///
@ -95,32 +95,32 @@ impl Theme for WaylandThemeObject {
}
}
/// Additional methods on `EventsLoop` that are specific to Linux.
pub trait EventsLoopExt {
/// Additional methods on `EventLoop` that are specific to Unix.
pub trait EventLoopExtUnix {
/// Builds a new `EventsLoop` that is forced to use X11.
fn new_x11() -> Result<Self, XNotSupported>
where Self: Sized;
/// Builds a new `EventsLoop` that is forced to use Wayland.
/// Builds a new `EventLoop` that is forced to use Wayland.
fn new_wayland() -> Self
where Self: Sized;
/// True if the `EventsLoop` uses Wayland.
/// True if the `EventLoop` uses Wayland.
fn is_wayland(&self) -> bool;
/// True if the `EventsLoop` uses X11.
/// True if the `EventLoop` uses X11.
fn is_x11(&self) -> bool;
#[doc(hidden)]
fn get_xlib_xconnection(&self) -> Option<Arc<XConnection>>;
}
impl EventsLoopExt for EventsLoop {
impl EventLoopExtUnix for EventLoop {
#[inline]
fn new_x11() -> Result<Self, XNotSupported> {
LinuxEventsLoop::new_x11().map(|ev|
EventsLoop {
events_loop: ev,
LinuxEventLoop::new_x11().map(|ev|
EventLoop {
event_loop: ev,
_marker: ::std::marker::PhantomData,
}
)
@ -128,8 +128,8 @@ impl EventsLoopExt for EventsLoop {
#[inline]
fn new_wayland() -> Self {
EventsLoop {
events_loop: match LinuxEventsLoop::new_wayland() {
EventLoop {
event_loop: match LinuxEventLoop::new_wayland() {
Ok(e) => e,
Err(_) => panic!() // TODO: propagate
},
@ -139,23 +139,23 @@ impl EventsLoopExt for EventsLoop {
#[inline]
fn is_wayland(&self) -> bool {
self.events_loop.is_wayland()
self.event_loop.is_wayland()
}
#[inline]
fn is_x11(&self) -> bool {
!self.events_loop.is_wayland()
!self.event_loop.is_wayland()
}
#[inline]
#[doc(hidden)]
fn get_xlib_xconnection(&self) -> Option<Arc<XConnection>> {
self.events_loop.x_connection().cloned()
self.event_loop.x_connection().cloned()
}
}
/// Additional methods on `Window` that are specific to Unix.
pub trait WindowExt {
pub trait WindowExtUnix {
/// Returns the ID of the `Window` xlib object that is used by this window.
///
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
@ -210,7 +210,7 @@ pub trait WindowExt {
fn is_ready(&self) -> bool;
}
impl WindowExt for Window {
impl WindowExtUnix for Window {
#[inline]
fn get_xlib_window(&self) -> Option<raw::c_ulong> {
match self.window {
@ -290,7 +290,7 @@ impl WindowExt for Window {
}
/// Additional methods on `WindowBuilder` that are specific to Unix.
pub trait WindowBuilderExt {
pub trait WindowBuilderExtUnix {
fn with_x11_visual<T>(self, visual_infos: *const T) -> WindowBuilder;
fn with_x11_screen(self, screen_id: i32) -> WindowBuilder;
@ -315,7 +315,7 @@ pub trait WindowBuilderExt {
fn with_app_id(self, app_id: String) -> WindowBuilder;
}
impl WindowBuilderExt for WindowBuilder {
impl WindowBuilderExtUnix for WindowBuilder {
#[inline]
fn with_x11_visual<T>(mut self, visual_infos: *const T) -> WindowBuilder {
self.platform_specific.visual_infos = Some(
@ -373,13 +373,13 @@ impl WindowBuilderExt for WindowBuilder {
}
}
/// Additional methods on `MonitorId` that are specific to Linux.
pub trait MonitorIdExt {
/// Additional methods on `MonitorHandle` that are specific to Linux.
pub trait MonitorHandleExtUnix {
/// Returns the inner identifier of the monitor.
fn native_id(&self) -> u32;
}
impl MonitorIdExt for MonitorId {
impl MonitorHandleExtUnix for MonitorHandle {
#[inline]
fn native_id(&self) -> u32 {
self.inner.get_native_identifier()

View file

@ -5,28 +5,31 @@ use std::os::raw::c_void;
use libc;
use winapi::shared::windef::HWND;
use {DeviceId, EventsLoop, Icon, MonitorId, Window, WindowBuilder};
use platform::EventsLoop as WindowsEventsLoop;
use event::DeviceId;
use monitor::MonitorHandle;
use event_loop::EventLoop;
use window::{Icon, Window, WindowBuilder};
use platform_impl::EventLoop as WindowsEventLoop;
/// Additional methods on `EventsLoop` that are specific to Windows.
pub trait EventsLoopExt {
/// Additional methods on `EventLoop` that are specific to Windows.
pub trait EventLoopExtWindows {
/// By default, winit on Windows will attempt to enable process-wide DPI awareness. If that's
/// undesirable, you can create an `EventsLoop` using this function instead.
/// undesirable, you can create an `EventLoop` using this function instead.
fn new_dpi_unaware() -> Self where Self: Sized;
}
impl EventsLoopExt for EventsLoop {
impl<T> EventLoopExtWindows for EventLoop<T> {
#[inline]
fn new_dpi_unaware() -> Self {
EventsLoop {
events_loop: WindowsEventsLoop::with_dpi_awareness(false),
EventLoop {
event_loop: WindowsEventLoop::with_dpi_awareness(false),
_marker: ::std::marker::PhantomData,
}
}
}
/// Additional methods on `Window` that are specific to Windows.
pub trait WindowExt {
pub trait WindowExtWindows {
/// Returns the native handle that is used by this window.
///
/// The pointer will become invalid when the native window was destroyed.
@ -36,7 +39,7 @@ pub trait WindowExt {
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>);
}
impl WindowExt for Window {
impl WindowExtWindows for Window {
#[inline]
fn get_hwnd(&self) -> *mut libc::c_void {
self.window.hwnd() as *mut _
@ -49,7 +52,7 @@ impl WindowExt for Window {
}
/// Additional methods on `WindowBuilder` that are specific to Windows.
pub trait WindowBuilderExt {
pub trait WindowBuilderExtWindows {
/// Sets a parent to the window to be created.
fn with_parent_window(self, parent: HWND) -> WindowBuilder;
@ -60,7 +63,7 @@ pub trait WindowBuilderExt {
fn with_no_redirection_bitmap(self, flag: bool) -> WindowBuilder;
}
impl WindowBuilderExt for WindowBuilder {
impl WindowBuilderExtWindows for WindowBuilder {
#[inline]
fn with_parent_window(mut self, parent: HWND) -> WindowBuilder {
self.platform_specific.parent = Some(parent);
@ -80,8 +83,8 @@ impl WindowBuilderExt for WindowBuilder {
}
}
/// Additional methods on `MonitorId` that are specific to Windows.
pub trait MonitorIdExt {
/// Additional methods on `MonitorHandle` that are specific to Windows.
pub trait MonitorHandleExtWindows {
/// Returns the name of the monitor adapter specific to the Win32 API.
fn native_id(&self) -> String;
@ -89,7 +92,7 @@ pub trait MonitorIdExt {
fn hmonitor(&self) -> *mut c_void;
}
impl MonitorIdExt for MonitorId {
impl MonitorHandleExtWindows for MonitorHandle {
#[inline]
fn native_id(&self) -> String {
self.inner.get_native_identifier()
@ -102,14 +105,14 @@ impl MonitorIdExt for MonitorId {
}
/// Additional methods on `DeviceId` that are specific to Windows.
pub trait DeviceIdExt {
pub trait DeviceIdExtWindows {
/// Returns an identifier that persistently refers to this specific device.
///
/// Will return `None` if the device is no longer available.
fn get_persistent_identifier(&self) -> Option<String>;
}
impl DeviceIdExt for DeviceId {
impl DeviceIdExtWindows for DeviceId {
#[inline]
fn get_persistent_identifier(&self) -> Option<String> {
self.0.get_persistent_identifier()

View file

@ -24,36 +24,36 @@ use {
};
use CreationError::OsError;
use events::{Touch, TouchPhase};
use window::MonitorId as RootMonitorId;
use window::MonitorHandle as RootMonitorHandle;
pub struct EventsLoop {
pub struct EventLoop {
event_rx: Receiver<android_glue::Event>,
suspend_callback: RefCell<Option<Box<Fn(bool) -> ()>>>,
}
#[derive(Clone)]
pub struct EventsLoopProxy;
pub struct EventLoopProxy;
impl EventsLoop {
pub fn new() -> EventsLoop {
impl EventLoop {
pub fn new() -> EventLoop {
let (tx, rx) = channel();
android_glue::add_sender(tx);
EventsLoop {
EventLoop {
event_rx: rx,
suspend_callback: Default::default(),
}
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut rb = VecDeque::with_capacity(1);
rb.push_back(MonitorId);
rb.push_back(MonitorHandle);
rb
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle
}
pub fn poll_events<F>(&mut self, mut callback: F)
@ -62,7 +62,7 @@ impl EventsLoop {
while let Ok(event) = self.event_rx.try_recv() {
let e = match event{
android_glue::Event::EventMotion(motion) => {
let dpi_factor = MonitorId.get_hidpi_factor();
let dpi_factor = MonitorHandle.get_hidpi_factor();
let location = LogicalPosition::from_physical(
(motion.x as f64, motion.y as f64),
dpi_factor,
@ -103,8 +103,8 @@ impl EventsLoop {
if native_window.is_null() {
None
} else {
let dpi_factor = MonitorId.get_hidpi_factor();
let physical_size = MonitorId.get_dimensions();
let dpi_factor = MonitorHandle.get_hidpi_factor();
let physical_size = MonitorHandle.get_dimensions();
let size = LogicalSize::from_physical(physical_size, dpi_factor);
Some(Event::WindowEvent {
window_id: RootWindowId(WindowId),
@ -116,7 +116,7 @@ impl EventsLoop {
// The activity needs to be redrawn.
Some(Event::WindowEvent {
window_id: RootWindowId(WindowId),
event: WindowEvent::Refresh,
event: WindowEvent::Redraw,
})
}
android_glue::Event::Wake => {
@ -155,13 +155,13 @@ impl EventsLoop {
}
}
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy
}
}
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
impl EventLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventLoopClosed> {
android_glue::wake_event_loop();
Ok(())
}
@ -190,19 +190,19 @@ pub struct Window {
}
#[derive(Clone)]
pub struct MonitorId;
pub struct MonitorHandle;
impl fmt::Debug for MonitorId {
impl fmt::Debug for MonitorHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[derive(Debug)]
struct MonitorId {
struct MonitorHandle {
name: Option<String>,
dimensions: PhysicalSize,
position: PhysicalPosition,
hidpi_factor: f64,
}
let monitor_id_proxy = MonitorId {
let monitor_id_proxy = MonitorHandle {
name: self.get_name(),
dimensions: self.get_dimensions(),
position: self.get_position(),
@ -213,7 +213,7 @@ impl fmt::Debug for MonitorId {
}
}
impl MonitorId {
impl MonitorHandle {
#[inline]
pub fn get_name(&self) -> Option<String> {
Some("Primary".to_string())
@ -248,7 +248,7 @@ pub struct PlatformSpecificWindowBuilderAttributes;
pub struct PlatformSpecificHeadlessBuilderAttributes;
impl Window {
pub fn new(_: &EventsLoop, win_attribs: WindowAttributes,
pub fn new(_: &EventLoop, win_attribs: WindowAttributes,
_: PlatformSpecificWindowBuilderAttributes)
-> Result<Window, CreationError>
{
@ -369,7 +369,7 @@ impl Window {
}
#[inline]
pub fn set_fullscreen(&self, _monitor: Option<RootMonitorId>) {
pub fn set_fullscreen(&self, _monitor: Option<RootMonitorHandle>) {
// N/A
// Android has single screen maximized apps so nothing to do
}
@ -395,20 +395,20 @@ impl Window {
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
RootMonitorId { inner: MonitorId }
pub fn get_current_monitor(&self) -> RootMonitorHandle {
RootMonitorHandle { inner: MonitorHandle }
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut rb = VecDeque::with_capacity(1);
rb.push_back(MonitorId);
rb.push_back(MonitorHandle);
rb
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle
}
#[inline]

View file

@ -10,7 +10,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Mutex, Arc};
use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize};
use window::MonitorId as RootMonitorId;
use window::MonitorHandle as RootMonitorHandle;
const DOCUMENT_NAME: &'static str = "#document\0";
@ -37,9 +37,9 @@ impl DeviceId {
pub struct PlatformSpecificHeadlessBuilderAttributes;
#[derive(Debug, Clone)]
pub struct MonitorId;
pub struct MonitorHandle;
impl MonitorId {
impl MonitorHandle {
#[inline]
pub fn get_name(&self) -> Option<String> {
Some("Canvas".to_owned())
@ -81,22 +81,22 @@ pub fn set_main_loop_callback<F>(callback : F) where F : FnMut() {
}
#[derive(Clone)]
pub struct EventsLoopProxy;
pub struct EventLoopProxy;
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
impl EventLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventLoopClosed> {
unimplemented!()
}
}
pub struct EventsLoop {
pub struct EventLoop {
window: Mutex<Option<Arc<Window2>>>,
interrupted: AtomicBool,
}
impl EventsLoop {
pub fn new() -> EventsLoop {
EventsLoop {
impl EventLoop {
pub fn new() -> EventLoop {
EventLoop {
window: Mutex::new(None),
interrupted: AtomicBool::new(false),
}
@ -108,20 +108,20 @@ impl EventsLoop {
}
#[inline]
pub fn create_proxy(&self) -> EventsLoopProxy {
pub fn create_proxy(&self) -> EventLoopProxy {
unimplemented!()
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut list = VecDeque::with_capacity(1);
list.push_back(MonitorId);
list.push_back(MonitorHandle);
list
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle
}
pub fn poll_events<F>(&self, mut callback: F)
@ -378,11 +378,11 @@ fn em_try(res: ffi::EMSCRIPTEN_RESULT) -> Result<(), String> {
}
impl Window {
pub fn new(events_loop: &EventsLoop, attribs: ::WindowAttributes,
pub fn new(event_loop: &EventLoop, attribs: ::WindowAttributes,
_pl_attribs: PlatformSpecificWindowBuilderAttributes)
-> Result<Window, ::CreationError>
{
if events_loop.window.lock().unwrap().is_some() {
if event_loop.window.lock().unwrap().is_some() {
return Err(::CreationError::OsError("Cannot create another window".to_owned()));
}
@ -431,7 +431,7 @@ impl Window {
window.set_inner_size(size);
}
*events_loop.window.lock().unwrap() = Some(window.window.clone());
*event_loop.window.lock().unwrap() = Some(window.window.clone());
Ok(window)
}
@ -581,7 +581,7 @@ impl Window {
}
#[inline]
pub fn set_fullscreen(&self, _monitor: Option<::MonitorId>) {
pub fn set_fullscreen(&self, _monitor: Option<::MonitorHandle>) {
// iOS has single screen maximized apps so nothing to do
}
@ -606,28 +606,28 @@ impl Window {
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
RootMonitorId { inner: MonitorId }
pub fn get_current_monitor(&self) -> RootMonitorHandle {
RootMonitorHandle { inner: MonitorHandle }
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut list = VecDeque::with_capacity(1);
list.push_back(MonitorId);
list.push_back(MonitorHandle);
list
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle
}
}
impl Drop for Window {
fn drop(&mut self) {
// Delete window from events_loop
// Delete window from event_loop
// TODO: ?
/*if let Some(ev) = self.events_loop.upgrade() {
/*if let Some(ev) = self.event_loop.upgrade() {
let _ = ev.window.lock().unwrap().take().unwrap();
}*/

View file

@ -82,7 +82,7 @@ use {
WindowId as RootEventId,
};
use events::{Touch, TouchPhase};
use window::MonitorId as RootMonitorId;
use window::MonitorHandle as RootMonitorHandle;
mod ffi;
use self::ffi::{
@ -145,19 +145,19 @@ impl Drop for DelegateState {
}
#[derive(Clone)]
pub struct MonitorId;
pub struct MonitorHandle;
impl fmt::Debug for MonitorId {
impl fmt::Debug for MonitorHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[derive(Debug)]
struct MonitorId {
struct MonitorHandle {
name: Option<String>,
dimensions: PhysicalSize,
position: PhysicalPosition,
hidpi_factor: f64,
}
let monitor_id_proxy = MonitorId {
let monitor_id_proxy = MonitorHandle {
name: self.get_name(),
dimensions: self.get_dimensions(),
position: self.get_position(),
@ -168,7 +168,7 @@ impl fmt::Debug for MonitorId {
}
}
impl MonitorId {
impl MonitorHandle {
#[inline]
pub fn get_uiscreen(&self) -> id {
let class = class!(UIScreen);
@ -199,33 +199,33 @@ impl MonitorId {
}
}
pub struct EventsLoop {
pub struct EventLoop {
events_queue: Arc<RefCell<VecDeque<Event>>>,
}
#[derive(Clone)]
pub struct EventsLoopProxy;
pub struct EventLoopProxy;
impl EventsLoop {
pub fn new() -> EventsLoop {
impl EventLoop {
pub fn new() -> EventLoop {
unsafe {
if !msg_send![class!(NSThread), isMainThread] {
panic!("`EventsLoop` can only be created on the main thread on iOS");
panic!("`EventLoop` can only be created on the main thread on iOS");
}
}
EventsLoop { events_queue: Default::default() }
EventLoop { events_queue: Default::default() }
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut rb = VecDeque::with_capacity(1);
rb.push_back(MonitorId);
rb.push_back(MonitorHandle);
rb
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle
}
pub fn poll_events<F>(&mut self, mut callback: F)
@ -238,7 +238,7 @@ impl EventsLoop {
unsafe {
// jump hack, so we won't quit on willTerminate event before processing it
assert!(JMPBUF.is_some(), "`EventsLoop::poll_events` must be called after window creation on iOS");
assert!(JMPBUF.is_some(), "`EventLoop::poll_events` must be called after window creation on iOS");
if setjmp(mem::transmute_copy(&mut JMPBUF)) != 0 {
if let Some(event) = self.events_queue.borrow_mut().pop_front() {
callback(event);
@ -276,13 +276,13 @@ impl EventsLoop {
}
}
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy
}
}
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
impl EventLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventLoopClosed> {
unimplemented!()
}
}
@ -322,7 +322,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
// so to be consistent with other platforms we have to change that.
impl Window {
pub fn new(
ev: &EventsLoop,
ev: &EventLoop,
_attributes: WindowAttributes,
pl_attributes: PlatformSpecificWindowBuilderAttributes,
) -> Result<Window, CreationError> {
@ -342,7 +342,7 @@ impl Window {
(&mut *delegate).set_ivar("eventsQueue", mem::transmute::<_, *mut c_void>(events_queue));
// easiest? way to get access to PlatformSpecificWindowBuilderAttributes to configure the view
let rect: CGRect = msg_send![MonitorId.get_uiscreen(), bounds];
let rect: CGRect = msg_send![MonitorHandle.get_uiscreen(), bounds];
let uiview_class = class!(UIView);
let root_view_class = pl_attributes.root_view_class;
@ -474,7 +474,7 @@ impl Window {
}
#[inline]
pub fn set_fullscreen(&self, _monitor: Option<RootMonitorId>) {
pub fn set_fullscreen(&self, _monitor: Option<RootMonitorHandle>) {
// N/A
// iOS has single screen maximized apps so nothing to do
}
@ -500,20 +500,20 @@ impl Window {
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
RootMonitorId { inner: MonitorId }
pub fn get_current_monitor(&self) -> RootMonitorHandle {
RootMonitorHandle { inner: MonitorHandle }
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut rb = VecDeque::with_capacity(1);
rb.push_back(MonitorId);
rb.push_back(MonitorHandle);
rb
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle
}
#[inline]

View file

@ -11,14 +11,14 @@ use sctk::reexports::client::ConnectError;
use {
CreationError,
EventsLoopClosed,
EventLoopClosed,
Icon,
MouseCursor,
ControlFlow,
WindowAttributes,
};
use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize};
use window::MonitorId as RootMonitorId;
use window::MonitorHandle as RootMonitorHandle;
use self::x11::{XConnection, XError};
use self::x11::ffi::XVisualInfo;
pub use self::x11::XNotSupported;
@ -85,49 +85,49 @@ impl DeviceId {
}
#[derive(Debug, Clone)]
pub enum MonitorId {
X(x11::MonitorId),
Wayland(wayland::MonitorId),
pub enum MonitorHandle {
X(x11::MonitorHandle),
Wayland(wayland::MonitorHandle),
}
impl MonitorId {
impl MonitorHandle {
#[inline]
pub fn get_name(&self) -> Option<String> {
match self {
&MonitorId::X(ref m) => m.get_name(),
&MonitorId::Wayland(ref m) => m.get_name(),
&MonitorHandle::X(ref m) => m.get_name(),
&MonitorHandle::Wayland(ref m) => m.get_name(),
}
}
#[inline]
pub fn get_native_identifier(&self) -> u32 {
match self {
&MonitorId::X(ref m) => m.get_native_identifier(),
&MonitorId::Wayland(ref m) => m.get_native_identifier(),
&MonitorHandle::X(ref m) => m.get_native_identifier(),
&MonitorHandle::Wayland(ref m) => m.get_native_identifier(),
}
}
#[inline]
pub fn get_dimensions(&self) -> PhysicalSize {
match self {
&MonitorId::X(ref m) => m.get_dimensions(),
&MonitorId::Wayland(ref m) => m.get_dimensions(),
&MonitorHandle::X(ref m) => m.get_dimensions(),
&MonitorHandle::Wayland(ref m) => m.get_dimensions(),
}
}
#[inline]
pub fn get_position(&self) -> PhysicalPosition {
match self {
&MonitorId::X(ref m) => m.get_position(),
&MonitorId::Wayland(ref m) => m.get_position(),
&MonitorHandle::X(ref m) => m.get_position(),
&MonitorHandle::Wayland(ref m) => m.get_position(),
}
}
#[inline]
pub fn get_hidpi_factor(&self) -> f64 {
match self {
&MonitorId::X(ref m) => m.get_hidpi_factor(),
&MonitorId::Wayland(ref m) => m.get_hidpi_factor() as f64,
&MonitorHandle::X(ref m) => m.get_hidpi_factor(),
&MonitorHandle::Wayland(ref m) => m.get_hidpi_factor() as f64,
}
}
}
@ -135,16 +135,16 @@ impl MonitorId {
impl Window {
#[inline]
pub fn new(
events_loop: &EventsLoop,
event_loop: &EventLoop,
attribs: WindowAttributes,
pl_attribs: PlatformSpecificWindowBuilderAttributes,
) -> Result<Self, CreationError> {
match *events_loop {
EventsLoop::Wayland(ref events_loop) => {
wayland::Window::new(events_loop, attribs, pl_attribs).map(Window::Wayland)
match *event_loop {
EventsLoop::Wayland(ref event_loop) => {
wayland::Window::new(event_loop, attribs, pl_attribs).map(Window::Wayland)
},
EventsLoop::X(ref events_loop) => {
x11::Window::new(events_loop, attribs, pl_attribs).map(Window::X)
EventLoop::X(ref event_loop) => {
x11::Window::new(event_loop, attribs, pl_attribs).map(Window::X)
},
}
}
@ -302,7 +302,7 @@ impl Window {
}
#[inline]
pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
pub fn set_fullscreen(&self, monitor: Option<RootMonitorHandle>) {
match self {
&Window::X(ref w) => w.set_fullscreen(monitor),
&Window::Wayland(ref w) => w.set_fullscreen(monitor)
@ -342,32 +342,32 @@ impl Window {
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
pub fn get_current_monitor(&self) -> RootMonitorHandle {
match self {
&Window::X(ref window) => RootMonitorId { inner: MonitorId::X(window.get_current_monitor()) },
&Window::Wayland(ref window) => RootMonitorId { inner: MonitorId::Wayland(window.get_current_monitor()) },
&Window::X(ref window) => RootMonitorHandle { inner: MonitorHandle::X(window.get_current_monitor()) },
&Window::Wayland(ref window) => RootMonitorHandle { inner: MonitorHandle::Wayland(window.get_current_monitor()) },
}
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
match self {
&Window::X(ref window) => window.get_available_monitors()
.into_iter()
.map(MonitorId::X)
.map(MonitorHandle::X)
.collect(),
&Window::Wayland(ref window) => window.get_available_monitors()
.into_iter()
.map(MonitorId::Wayland)
.map(MonitorHandle::Wayland)
.collect(),
}
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
match self {
&Window::X(ref window) => MonitorId::X(window.get_primary_monitor()),
&Window::Wayland(ref window) => MonitorId::Wayland(window.get_primary_monitor()),
&Window::X(ref window) => MonitorHandle::X(window.get_primary_monitor()),
&Window::Wayland(ref window) => MonitorHandle::Wayland(window.get_primary_monitor()),
}
}
}
@ -402,27 +402,27 @@ unsafe extern "C" fn x_error_callback(
0
}
pub enum EventsLoop {
Wayland(wayland::EventsLoop),
X(x11::EventsLoop)
pub enum EventLoop {
Wayland(wayland::EventLoop),
X(x11::EventLoop)
}
#[derive(Clone)]
pub enum EventsLoopProxy {
X(x11::EventsLoopProxy),
Wayland(wayland::EventsLoopProxy),
pub enum EventLoopProxy {
X(x11::EventLoopProxy),
Wayland(wayland::EventLoopProxy),
}
impl EventsLoop {
pub fn new() -> EventsLoop {
impl EventLoop {
pub fn new() -> EventLoop {
if let Ok(env_var) = env::var(BACKEND_PREFERENCE_ENV_VAR) {
match env_var.as_str() {
"x11" => {
// TODO: propagate
return EventsLoop::new_x11().expect("Failed to initialize X11 backend");
return EventLoop::new_x11().expect("Failed to initialize X11 backend");
},
"wayland" => {
return EventsLoop::new_wayland()
return EventLoop::new_wayland()
.expect("Failed to initialize Wayland backend");
},
_ => panic!(
@ -432,12 +432,12 @@ impl EventsLoop {
}
}
let wayland_err = match EventsLoop::new_wayland() {
let wayland_err = match EventLoop::new_wayland() {
Ok(event_loop) => return event_loop,
Err(err) => err,
};
let x11_err = match EventsLoop::new_x11() {
let x11_err = match EventLoop::new_x11() {
Ok(event_loop) => return event_loop,
Err(err) => err,
};
@ -450,50 +450,50 @@ impl EventsLoop {
panic!(err_string);
}
pub fn new_wayland() -> Result<EventsLoop, ConnectError> {
wayland::EventsLoop::new()
.map(EventsLoop::Wayland)
pub fn new_wayland() -> Result<EventLoop, ConnectError> {
wayland::EventLoop::new()
.map(EventLoop::Wayland)
}
pub fn new_x11() -> Result<EventsLoop, XNotSupported> {
pub fn new_x11() -> Result<EventLoop, XNotSupported> {
X11_BACKEND
.lock()
.as_ref()
.map(Arc::clone)
.map(x11::EventsLoop::new)
.map(EventsLoop::X)
.map(x11::EventLoop::new)
.map(EventLoop::X)
.map_err(|err| err.clone())
}
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
match *self {
EventsLoop::Wayland(ref evlp) => evlp
EventLoop::Wayland(ref evlp) => evlp
.get_available_monitors()
.into_iter()
.map(MonitorId::Wayland)
.map(MonitorHandle::Wayland)
.collect(),
EventsLoop::X(ref evlp) => evlp
EventLoop::X(ref evlp) => evlp
.x_connection()
.get_available_monitors()
.into_iter()
.map(MonitorId::X)
.map(MonitorHandle::X)
.collect(),
}
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
match *self {
EventsLoop::Wayland(ref evlp) => MonitorId::Wayland(evlp.get_primary_monitor()),
EventsLoop::X(ref evlp) => MonitorId::X(evlp.x_connection().get_primary_monitor()),
EventLoop::Wayland(ref evlp) => MonitorHandle::Wayland(evlp.get_primary_monitor()),
EventLoop::X(ref evlp) => MonitorHandle::X(evlp.x_connection().get_primary_monitor()),
}
}
pub fn create_proxy(&self) -> EventsLoopProxy {
pub fn create_proxy(&self) -> EventLoopProxy {
match *self {
EventsLoop::Wayland(ref evlp) => EventsLoopProxy::Wayland(evlp.create_proxy()),
EventsLoop::X(ref evlp) => EventsLoopProxy::X(evlp.create_proxy()),
EventLoop::Wayland(ref evlp) => EventLoopProxy::Wayland(evlp.create_proxy()),
EventLoop::X(ref evlp) => EventLoopProxy::X(evlp.create_proxy()),
}
}
@ -501,8 +501,8 @@ impl EventsLoop {
where F: FnMut(::Event)
{
match *self {
EventsLoop::Wayland(ref mut evlp) => evlp.poll_events(callback),
EventsLoop::X(ref mut evlp) => evlp.poll_events(callback)
EventLoop::Wayland(ref mut evlp) => evlp.poll_events(callback),
EventLoop::X(ref mut evlp) => evlp.poll_events(callback)
}
}
@ -510,33 +510,33 @@ impl EventsLoop {
where F: FnMut(::Event) -> ControlFlow
{
match *self {
EventsLoop::Wayland(ref mut evlp) => evlp.run_forever(callback),
EventsLoop::X(ref mut evlp) => evlp.run_forever(callback)
EventLoop::Wayland(ref mut evlp) => evlp.run_forever(callback),
EventLoop::X(ref mut evlp) => evlp.run_forever(callback)
}
}
#[inline]
pub fn is_wayland(&self) -> bool {
match *self {
EventsLoop::Wayland(_) => true,
EventsLoop::X(_) => false,
EventLoop::Wayland(_) => true,
EventLoop::X(_) => false,
}
}
#[inline]
pub fn x_connection(&self) -> Option<&Arc<XConnection>> {
match *self {
EventsLoop::Wayland(_) => None,
EventsLoop::X(ref ev) => Some(ev.x_connection()),
EventLoop::Wayland(_) => None,
EventLoop::X(ref ev) => Some(ev.x_connection()),
}
}
}
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
impl EventLoopProxy {
pub fn wakeup(&self) -> Result<(), EventLoopClosed> {
match *self {
EventsLoopProxy::Wayland(ref proxy) => proxy.wakeup(),
EventsLoopProxy::X(ref proxy) => proxy.wakeup(),
EventLoopProxy::Wayland(ref proxy) => proxy.wakeup(),
EventLoopProxy::X(ref proxy) => proxy.wakeup(),
}
}
}

View file

@ -4,7 +4,7 @@ use std::fmt;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex, Weak};
use {ControlFlow, EventsLoopClosed, PhysicalPosition, PhysicalSize};
use {ControlFlow, EventLoopClosed, PhysicalPosition, PhysicalSize};
use super::window::WindowStore;
use super::WindowId;
@ -21,13 +21,13 @@ use sctk::reexports::client::protocol::wl_surface::RequestsTrait;
use ModifiersState;
pub struct EventsLoopSink {
pub struct EventLoopSink {
buffer: VecDeque<::Event>,
}
impl EventsLoopSink {
pub fn new() -> EventsLoopSink {
EventsLoopSink {
impl EventLoopSink {
pub fn new() -> EventLoopSink {
EventLoopSink {
buffer: VecDeque::new(),
}
}
@ -54,11 +54,11 @@ impl EventsLoopSink {
}
}
pub struct EventsLoop {
pub struct EventLoop {
// The Event Queue
pub evq: RefCell<EventQueue>,
// our sink, shared with some handlers, buffering the events
sink: Arc<Mutex<EventsLoopSink>>,
sink: Arc<Mutex<EventLoopSink>>,
// Whether or not there is a pending `Awakened` event to be emitted.
pending_wakeup: Arc<AtomicBool>,
// The window store
@ -73,43 +73,43 @@ pub struct EventsLoop {
pub seats: Arc<Mutex<Vec<(u32, Proxy<wl_seat::WlSeat>)>>>,
}
// A handle that can be sent across threads and used to wake up the `EventsLoop`.
// A handle that can be sent across threads and used to wake up the `EventLoop`.
//
// We should only try and wake up the `EventsLoop` if it still exists, so we hold Weak ptrs.
// We should only try and wake up the `EventLoop` if it still exists, so we hold Weak ptrs.
#[derive(Clone)]
pub struct EventsLoopProxy {
pub struct EventLoopProxy {
display: Weak<Display>,
pending_wakeup: Weak<AtomicBool>,
}
impl EventsLoopProxy {
// Causes the `EventsLoop` to stop blocking on `run_forever` and emit an `Awakened` event.
impl EventLoopProxy {
// Causes the `EventLoop` to stop blocking on `run_forever` and emit an `Awakened` event.
//
// Returns `Err` if the associated `EventsLoop` no longer exists.
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
// Returns `Err` if the associated `EventLoop` no longer exists.
pub fn wakeup(&self) -> Result<(), EventLoopClosed> {
let display = self.display.upgrade();
let wakeup = self.pending_wakeup.upgrade();
match (display, wakeup) {
(Some(display), Some(wakeup)) => {
// Update the `EventsLoop`'s `pending_wakeup` flag.
// Update the `EventLoop`'s `pending_wakeup` flag.
wakeup.store(true, Ordering::Relaxed);
// Cause the `EventsLoop` to break from `dispatch` if it is currently blocked.
// Cause the `EventLoop` to break from `dispatch` if it is currently blocked.
let _ = display.sync(|callback| callback.implement(|_, _| {}, ()));
display.flush().map_err(|_| EventsLoopClosed)?;
display.flush().map_err(|_| EventLoopClosed)?;
Ok(())
}
_ => Err(EventsLoopClosed),
_ => Err(EventLoopClosed),
}
}
}
impl EventsLoop {
pub fn new() -> Result<EventsLoop, ConnectError> {
impl EventLoop {
pub fn new() -> Result<EventLoop, ConnectError> {
let (display, mut event_queue) = Display::connect_to_env()?;
let display = Arc::new(display);
let pending_wakeup = Arc::new(AtomicBool::new(false));
let sink = Arc::new(Mutex::new(EventsLoopSink::new()));
let sink = Arc::new(Mutex::new(EventLoopSink::new()));
let store = Arc::new(Mutex::new(WindowStore::new()));
let seats = Arc::new(Mutex::new(Vec::new()));
@ -142,7 +142,7 @@ impl EventsLoop {
},
).unwrap();
Ok(EventsLoop {
Ok(EventLoop {
display,
evq: RefCell::new(event_queue),
sink,
@ -154,8 +154,8 @@ impl EventsLoop {
})
}
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy {
display: Arc::downgrade(&self.display),
pending_wakeup: Arc::downgrade(&self.pending_wakeup),
}
@ -222,20 +222,20 @@ impl EventsLoop {
}
}
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
get_primary_monitor(&self.env.outputs)
}
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
get_available_monitors(&self.env.outputs)
}
}
/*
* Private EventsLoop Internals
* Private EventLoop Internals
*/
impl EventsLoop {
impl EventLoop {
fn post_dispatch_triggers(&mut self) {
let mut sink = self.sink.lock().unwrap();
// process a possible pending wakeup call
@ -275,7 +275,7 @@ impl EventsLoop {
sink.send_event(::WindowEvent::HiDpiFactorChanged(dpi as f64), wid);
}
if refresh {
sink.send_event(::WindowEvent::Refresh, wid);
sink.send_event(::WindowEvent::Redraw, wid);
}
if closed {
sink.send_event(::WindowEvent::CloseRequested, wid);
@ -290,10 +290,10 @@ impl EventsLoop {
*/
struct SeatManager {
sink: Arc<Mutex<EventsLoopSink>>,
sink: Arc<Mutex<EventLoopSink>>,
store: Arc<Mutex<WindowStore>>,
seats: Arc<Mutex<Vec<(u32, Proxy<wl_seat::WlSeat>)>>>,
events_loop_proxy: EventsLoopProxy,
event_loop_proxy: EventLoopProxy,
}
impl SeatManager {
@ -323,24 +323,80 @@ impl SeatManager {
fn remove_seat(&mut self, id: u32) {
use self::wl_seat::RequestsTrait as SeatRequests;
<<<<<<< HEAD:src/platform_impl/linux/wayland/event_loop.rs
match evt {
GlobalEvent::New {
id,
ref interface,
version,
} if interface == "wl_seat" =>
{
use std::cmp::min;
let mut seat_data = SeatData {
sink: self.sink.clone(),
store: self.store.clone(),
pointer: None,
keyboard: None,
touch: None,
events_loop_proxy: self.events_loop_proxy.clone(),
modifiers_tracker: Arc::new(Mutex::new(ModifiersState::default())),
};
let seat = registry
<<<<<<< HEAD
.bind(min(version, 5), id, move |seat| {
seat.implement(move |event, seat| {
seat_data.receive(event, seat)
}, ())
})
.unwrap();
=======
.bind::<wl_seat::WlSeat>(min(version, 5), id)
.unwrap()
.implement(SeatData {
sink: self.sink.clone(),
store: self.store.clone(),
pointer: None,
keyboard: None,
touch: None,
event_loop_proxy: self.event_loop_proxy.clone(),
});
>>>>>>> Change instances of "events_loop" to "event_loop"
self.store.lock().unwrap().new_seat(&seat);
self.seats.lock().unwrap().push((id, seat));
}
GlobalEvent::Removed { id, ref interface } if interface == "wl_seat" => {
let mut seats = self.seats.lock().unwrap();
if let Some(idx) = seats.iter().position(|&(i, _)| i == id) {
let (_, seat) = seats.swap_remove(idx);
if seat.version() >= 5 {
seat.release();
}
}
=======
let mut seats = self.seats.lock().unwrap();
if let Some(idx) = seats.iter().position(|&(i, _)| i == id) {
let (_, seat) = seats.swap_remove(idx);
if seat.version() >= 5 {
seat.release();
>>>>>>> master:src/platform/linux/wayland/event_loop.rs
}
}
}
}
struct SeatData {
sink: Arc<Mutex<EventsLoopSink>>,
sink: Arc<Mutex<EventLoopSink>>,
store: Arc<Mutex<WindowStore>>,
pointer: Option<Proxy<wl_pointer::WlPointer>>,
keyboard: Option<Proxy<wl_keyboard::WlKeyboard>>,
touch: Option<Proxy<wl_touch::WlTouch>>,
<<<<<<< HEAD
events_loop_proxy: EventsLoopProxy,
modifiers_tracker: Arc<Mutex<ModifiersState>>,
=======
event_loop_proxy: EventLoopProxy,
>>>>>>> Change instances of "events_loop" to "event_loop"
}
impl SeatData {
@ -371,8 +427,12 @@ impl SeatData {
self.keyboard = Some(super::keyboard::init_keyboard(
&seat,
self.sink.clone(),
<<<<<<< HEAD
self.events_loop_proxy.clone(),
self.modifiers_tracker.clone(),
=======
self.event_loop_proxy.clone(),
>>>>>>> Change instances of "events_loop" to "event_loop"
))
}
// destroy keyboard if applicable
@ -433,24 +493,24 @@ impl Drop for SeatData {
* Monitor stuff
*/
pub struct MonitorId {
pub struct MonitorHandle {
pub(crate) proxy: Proxy<wl_output::WlOutput>,
pub(crate) mgr: OutputMgr,
}
impl Clone for MonitorId {
fn clone(&self) -> MonitorId {
MonitorId {
impl Clone for MonitorHandle {
fn clone(&self) -> MonitorHandle {
MonitorHandle {
proxy: self.proxy.clone(),
mgr: self.mgr.clone(),
}
}
}
impl fmt::Debug for MonitorId {
impl fmt::Debug for MonitorHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[derive(Debug)]
struct MonitorId {
struct MonitorHandle {
name: Option<String>,
native_identifier: u32,
dimensions: PhysicalSize,
@ -458,7 +518,7 @@ impl fmt::Debug for MonitorId {
hidpi_factor: i32,
}
let monitor_id_proxy = MonitorId {
let monitor_id_proxy = MonitorHandle {
name: self.get_name(),
native_identifier: self.get_native_identifier(),
dimensions: self.get_dimensions(),
@ -470,7 +530,7 @@ impl fmt::Debug for MonitorId {
}
}
impl MonitorId {
impl MonitorHandle {
pub fn get_name(&self) -> Option<String> {
self.mgr.with_info(&self.proxy, |_, info| {
format!("{} ({})", info.model, info.make)
@ -509,10 +569,10 @@ impl MonitorId {
}
}
pub fn get_primary_monitor(outputs: &OutputMgr) -> MonitorId {
pub fn get_primary_monitor(outputs: &OutputMgr) -> MonitorHandle {
outputs.with_all(|list| {
if let Some(&(_, ref proxy, _)) = list.first() {
MonitorId {
MonitorHandle {
proxy: proxy.clone(),
mgr: outputs.clone(),
}
@ -522,10 +582,10 @@ pub fn get_primary_monitor(outputs: &OutputMgr) -> MonitorId {
})
}
pub fn get_available_monitors(outputs: &OutputMgr) -> VecDeque<MonitorId> {
pub fn get_available_monitors(outputs: &OutputMgr) -> VecDeque<MonitorHandle> {
outputs.with_all(|list| {
list.iter()
.map(|&(_, ref proxy, _)| MonitorId {
.map(|&(_, ref proxy, _)| MonitorHandle {
proxy: proxy.clone(),
mgr: outputs.clone(),
})

View file

@ -1,6 +1,6 @@
use std::sync::{Arc, Mutex};
use super::{make_wid, DeviceId, EventsLoopProxy, EventsLoopSink};
use super::{make_wid, DeviceId, EventLoopProxy, EventLoopSink};
use sctk::keyboard::{
self, map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatEvent, KeyRepeatKind,
};
@ -13,8 +13,8 @@ use {ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent};
pub fn init_keyboard(
seat: &Proxy<wl_seat::WlSeat>,
sink: Arc<Mutex<EventsLoopSink>>,
events_loop_proxy: EventsLoopProxy,
sink: Arc<Mutex<EventLoopSink>>,
event_loop_proxy: EventLoopProxy,
modifiers_tracker: Arc<Mutex<ModifiersState>>,
) -> Proxy<wl_keyboard::WlKeyboard> {
// { variables to be captured by the closures
@ -108,7 +108,7 @@ pub fn init_keyboard(
guard.send_event(WindowEvent::ReceivedCharacter(chr), wid);
}
}
events_loop_proxy.wakeup().unwrap();
event_loop_proxy.wakeup().unwrap();
}
},
);

View file

@ -2,7 +2,7 @@
target_os = "netbsd", target_os = "openbsd"))]
pub use self::window::Window;
pub use self::event_loop::{EventsLoop, EventsLoopProxy, EventsLoopSink, MonitorId};
pub use self::event_loop::{EventLoop, EventLoopProxy, EventLoopSink, MonitorHandle};
use sctk::reexports::client::protocol::wl_surface;
use sctk::reexports::client::Proxy;

View file

@ -4,7 +4,7 @@ use {ElementState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent};
use events::ModifiersState;
use super::DeviceId;
use super::event_loop::EventsLoopSink;
use super::event_loop::EventLoopSink;
use super::window::WindowStore;
use sctk::reexports::client::Proxy;
@ -14,7 +14,7 @@ use sctk::reexports::client::protocol::wl_seat::RequestsTrait as SeatRequests;
pub fn implement_pointer(
seat: &Proxy<wl_seat::WlSeat>,
sink: Arc<Mutex<EventsLoopSink>>,
sink: Arc<Mutex<EventLoopSink>>,
store: Arc<Mutex<WindowStore>>,
modifiers_tracker: Arc<Mutex<ModifiersState>>,
) -> Proxy<WlPointer> {

View file

@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
use {TouchPhase, WindowEvent};
use super::{DeviceId, WindowId};
use super::event_loop::EventsLoopSink;
use super::event_loop::EventLoopSink;
use super::window::WindowStore;
use sctk::reexports::client::Proxy;
@ -19,7 +19,7 @@ struct TouchPoint {
pub(crate) fn implement_touch(
seat: &Proxy<wl_seat::WlSeat>,
sink: Arc<Mutex<EventsLoopSink>>,
sink: Arc<Mutex<EventLoopSink>>,
store: Arc<Mutex<WindowStore>>,
) -> Proxy<WlTouch> {
let mut pending_ids = Vec::new();

View file

@ -3,8 +3,13 @@ use std::sync::{Arc, Mutex, Weak};
use {CreationError, MouseCursor, WindowAttributes};
use dpi::{LogicalPosition, LogicalSize};
<<<<<<< HEAD:src/platform_impl/linux/wayland/window.rs
use platform_impl::MonitorHandle as PlatformMonitorHandle;
use window::MonitorHandle as RootMonitorHandle;
=======
use platform::{MonitorId as PlatformMonitorId, PlatformSpecificWindowBuilderAttributes as PlAttributes};
use window::MonitorId as RootMonitorId;
>>>>>>> master:src/platform/linux/wayland/window.rs
use sctk::surface::{get_dpi_factor, get_outputs};
use sctk::window::{ConceptFrame, Event as WEvent, Window as SWindow, Theme};
@ -13,8 +18,8 @@ use sctk::reexports::client::protocol::{wl_seat, wl_surface};
use sctk::reexports::client::protocol::wl_surface::RequestsTrait as SurfaceRequests;
use sctk::output::OutputMgr;
use super::{make_wid, EventsLoop, MonitorId, WindowId};
use platform::platform::wayland::event_loop::{get_available_monitors, get_primary_monitor};
use super::{make_wid, EventLoop, MonitorHandle, WindowId};
use platform_impl::platform::wayland::event_loop::{get_available_monitors, get_primary_monitor};
pub struct Window {
surface: Proxy<wl_surface::WlSurface>,
@ -27,7 +32,7 @@ pub struct Window {
}
impl Window {
pub fn new(evlp: &EventsLoop, attributes: WindowAttributes, pl_attribs: PlAttributes) -> Result<Window, CreationError> {
pub fn new(evlp: &EventLoop, attributes: WindowAttributes, pl_attribs: PlAttributes) -> Result<Window, CreationError> {
let (width, height) = attributes.dimensions.map(Into::into).unwrap_or((800, 600));
// Create the window
let size = Arc::new(Mutex::new((width, height)));
@ -86,8 +91,8 @@ impl Window {
}
// Check for fullscreen requirements
if let Some(RootMonitorId {
inner: PlatformMonitorId::Wayland(ref monitor_id),
if let Some(RootMonitorHandle {
inner: PlatformMonitorHandle::Wayland(ref monitor_id),
}) = attributes.fullscreen
{
frame.set_fullscreen(Some(&monitor_id.proxy));
@ -221,9 +226,9 @@ impl Window {
}
}
pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
if let Some(RootMonitorId {
inner: PlatformMonitorId::Wayland(ref monitor_id),
pub fn set_fullscreen(&self, monitor: Option<RootMonitorHandle>) {
if let Some(RootMonitorHandle {
inner: PlatformMonitorHandle::Wayland(ref monitor_id),
}) = monitor
{
self.frame
@ -268,19 +273,27 @@ impl Window {
&self.surface
}
<<<<<<< HEAD:src/platform_impl/linux/wayland/window.rs
pub fn get_current_monitor(&self) -> MonitorHandle {
// we don't know how much each monitor sees us so...
// just return the most recent one ?
let guard = self.monitors.lock().unwrap();
guard.monitors.last().unwrap().clone()
=======
pub fn get_current_monitor(&self) -> MonitorId {
let output = get_outputs(&self.surface).last().unwrap().clone();
MonitorId {
proxy: output,
mgr: self.outputs.clone(),
}
>>>>>>> master:src/platform/linux/wayland/window.rs
}
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
get_available_monitors(&self.outputs)
}
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
get_primary_monitor(&self.outputs)
}
}
@ -386,3 +399,53 @@ impl WindowStore {
}
}
}
<<<<<<< HEAD:src/platform_impl/linux/wayland/window.rs
/*
* Monitor list with some covenience method to compute DPI
*/
struct MonitorList {
monitors: Vec<MonitorHandle>
}
impl MonitorList {
fn new() -> MonitorList {
MonitorList {
monitors: Vec::new()
}
}
fn compute_hidpi_factor(&self) -> i32 {
let mut factor = 1;
for monitor_id in &self.monitors {
let monitor_dpi = monitor_id.get_hidpi_factor();
if monitor_dpi > factor { factor = monitor_dpi; }
}
factor
}
fn add_output(&mut self, monitor: MonitorHandle) -> Option<i32> {
let old_dpi = self.compute_hidpi_factor();
let monitor_dpi = monitor.get_hidpi_factor();
self.monitors.push(monitor);
if monitor_dpi > old_dpi {
Some(monitor_dpi)
} else {
None
}
}
fn del_output(&mut self, output: &Proxy<wl_output::WlOutput>) -> Option<i32> {
let old_dpi = self.compute_hidpi_factor();
self.monitors.retain(|m| !m.proxy.equals(output));
let new_dpi = self.compute_hidpi_factor();
if new_dpi != old_dpi {
Some(new_dpi)
} else {
None
}
}
}
=======
>>>>>>> master:src/platform/linux/wayland/window.rs

View file

@ -9,7 +9,7 @@ mod dnd;
mod ime;
pub mod util;
pub use self::monitor::MonitorId;
pub use self::monitor::MonitorHandle;
pub use self::window::UnownedWindow;
pub use self::xdisplay::{XConnection, XNotSupported, XError};
@ -29,7 +29,7 @@ use {
CreationError,
DeviceEvent,
Event,
EventsLoopClosed,
EventLoopClosed,
KeyboardInput,
LogicalPosition,
LogicalSize,
@ -37,11 +37,11 @@ use {
WindowEvent,
};
use events::ModifiersState;
use platform::PlatformSpecificWindowBuilderAttributes;
use platform_impl::PlatformSpecificWindowBuilderAttributes;
use self::dnd::{Dnd, DndState};
use self::ime::{ImeReceiver, ImeSender, ImeCreationError, Ime};
pub struct EventsLoop {
pub struct EventLoop {
xconn: Arc<XConnection>,
wm_delete_window: ffi::Atom,
dnd: Dnd,
@ -60,14 +60,14 @@ pub struct EventsLoop {
}
#[derive(Clone)]
pub struct EventsLoopProxy {
pub struct EventLoopProxy {
pending_wakeup: Weak<AtomicBool>,
xconn: Weak<XConnection>,
wakeup_dummy_window: ffi::Window,
}
impl EventsLoop {
pub fn new(xconn: Arc<XConnection>) -> EventsLoop {
impl EventLoop {
pub fn new(xconn: Arc<XConnection>) -> EventLoop {
let root = unsafe { (xconn.xlib.XDefaultRootWindow)(xconn.display) };
let wm_delete_window = unsafe { xconn.get_atom_unchecked(b"WM_DELETE_WINDOW\0") };
@ -142,7 +142,7 @@ impl EventsLoop {
)
};
let result = EventsLoop {
let result = EventLoop {
xconn,
wm_delete_window,
dnd,
@ -177,8 +177,8 @@ impl EventsLoop {
&self.xconn
}
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy {
pending_wakeup: Arc::downgrade(&self.pending_wakeup),
xconn: Arc::downgrade(&self.xconn),
wakeup_dummy_window: self.wakeup_dummy_window,
@ -582,7 +582,7 @@ impl EventsLoop {
let window = xev.window;
let window_id = mkwid(window);
callback(Event::WindowEvent { window_id, event: WindowEvent::Refresh });
callback(Event::WindowEvent { window_id, event: WindowEvent::Redraw });
}
ffi::KeyPress | ffi::KeyRelease => {
@ -1189,15 +1189,15 @@ impl EventsLoop {
}
}
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
// Update the `EventsLoop`'s `pending_wakeup` flag.
impl EventLoopProxy {
pub fn wakeup(&self) -> Result<(), EventLoopClosed> {
// Update the `EventLoop`'s `pending_wakeup` flag.
let display = match (self.pending_wakeup.upgrade(), self.xconn.upgrade()) {
(Some(wakeup), Some(display)) => {
wakeup.store(true, atomic::Ordering::Relaxed);
display
},
_ => return Err(EventsLoopClosed),
_ => return Err(EventLoopClosed),
};
// Push an event on the X event queue so that methods run_forever will advance.
@ -1289,7 +1289,7 @@ impl Deref for Window {
impl Window {
pub fn new(
event_loop: &EventsLoop,
event_loop: &EventLoop,
attribs: WindowAttributes,
pl_attribs: PlatformSpecificWindowBuilderAttributes
) -> Result<Self, CreationError> {
@ -1374,7 +1374,7 @@ enum ScrollOrientation {
}
impl Device {
fn new(el: &EventsLoop, info: &ffi::XIDeviceInfo) -> Self {
fn new(el: &EventLoop, info: &ffi::XIDeviceInfo) -> Self {
let name = unsafe { CStr::from_ptr(info.name).to_string_lossy() };
let mut scroll_axes = Vec::new();

View file

@ -20,7 +20,7 @@ const DISABLE_MONITOR_LIST_CACHING: bool = false;
lazy_static! {
static ref XRANDR_VERSION: Mutex<Option<(c_int, c_int)>> = Mutex::default();
static ref MONITORS: Mutex<Option<Vec<MonitorId>>> = Mutex::default();
static ref MONITORS: Mutex<Option<Vec<MonitorHandle>>> = Mutex::default();
}
fn version_is_at_least(major: c_int, minor: c_int) -> bool {
@ -35,13 +35,13 @@ fn version_is_at_least(major: c_int, minor: c_int) -> bool {
}
}
pub fn invalidate_cached_monitor_list() -> Option<Vec<MonitorId>> {
pub fn invalidate_cached_monitor_list() -> Option<Vec<MonitorHandle>> {
// We update this lazily.
(*MONITORS.lock()).take()
}
#[derive(Debug, Clone)]
pub struct MonitorId {
pub struct MonitorHandle {
/// The actual id
id: u32,
/// The name of the monitor
@ -58,7 +58,7 @@ pub struct MonitorId {
pub(crate) rect: util::AaRect,
}
impl MonitorId {
impl MonitorHandle {
fn from_repr(
xconn: &XConnection,
resources: *mut XRRScreenResources,
@ -69,7 +69,7 @@ impl MonitorId {
let (name, hidpi_factor) = unsafe { xconn.get_output_info(resources, &repr)? };
let (dimensions, position) = unsafe { (repr.get_dimensions(), repr.get_position()) };
let rect = util::AaRect::new(position, dimensions);
Some(MonitorId {
Some(MonitorHandle {
id,
name,
hidpi_factor,
@ -104,7 +104,7 @@ impl MonitorId {
}
impl XConnection {
pub fn get_monitor_for_window(&self, window_rect: Option<util::AaRect>) -> MonitorId {
pub fn get_monitor_for_window(&self, window_rect: Option<util::AaRect>) -> MonitorHandle {
let monitors = self.get_available_monitors();
let default = monitors
.get(0)
@ -128,7 +128,7 @@ impl XConnection {
matched_monitor.to_owned()
}
fn query_monitor_list(&self) -> Vec<MonitorId> {
fn query_monitor_list(&self) -> Vec<MonitorHandle> {
unsafe {
let root = (self.xlib.XDefaultRootWindow)(self.display);
// WARNING: this function is supposedly very slow, on the order of hundreds of ms.
@ -153,7 +153,7 @@ impl XConnection {
let monitor = monitors.offset(monitor_index as isize);
let is_primary = (*monitor).primary != 0;
has_primary |= is_primary;
MonitorId::from_repr(
MonitorHandle::from_repr(
self,
resources,
monitor_index as u32,
@ -176,7 +176,7 @@ impl XConnection {
let crtc = util::MonitorRepr::from(crtc);
let is_primary = crtc.get_output() == primary;
has_primary |= is_primary;
MonitorId::from_repr(
MonitorHandle::from_repr(
self,
resources,
crtc_id as u32,
@ -201,7 +201,7 @@ impl XConnection {
}
}
pub fn get_available_monitors(&self) -> Vec<MonitorId> {
pub fn get_available_monitors(&self) -> Vec<MonitorHandle> {
let mut monitors_lock = MONITORS.lock();
(*monitors_lock)
.as_ref()
@ -217,7 +217,7 @@ impl XConnection {
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
self.get_available_monitors()
.into_iter()
.find(|monitor| monitor.primary)

View file

@ -10,12 +10,12 @@ use parking_lot::Mutex;
use {Icon, MouseCursor, WindowAttributes};
use CreationError::{self, OsError};
use dpi::{LogicalPosition, LogicalSize};
use platform::MonitorId as PlatformMonitorId;
use platform::PlatformSpecificWindowBuilderAttributes;
use platform::x11::MonitorId as X11MonitorId;
use window::MonitorId as RootMonitorId;
use platform_impl::MonitorHandle as PlatformMonitorHandle;
use platform_impl::PlatformSpecificWindowBuilderAttributes;
use platform_impl::x11::MonitorHandle as X11MonitorHandle;
use window::MonitorHandle as RootMonitorHandle;
use super::{ffi, util, ImeSender, XConnection, XError, WindowId, EventsLoop};
use super::{ffi, util, ImeSender, XConnection, XError, WindowId, EventLoop};
unsafe extern "C" fn visibility_predicate(
_display: *mut ffi::Display,
@ -35,7 +35,7 @@ pub struct SharedState {
pub inner_position: Option<(i32, i32)>,
pub inner_position_rel_parent: Option<(i32, i32)>,
pub guessed_dpi: Option<f64>,
pub last_monitor: Option<X11MonitorId>,
pub last_monitor: Option<X11MonitorHandle>,
pub dpi_adjusted: Option<(f64, f64)>,
// Used to restore position after exiting fullscreen.
pub restore_position: Option<(i32, i32)>,
@ -70,7 +70,7 @@ pub struct UnownedWindow {
impl UnownedWindow {
pub fn new(
event_loop: &EventsLoop,
event_loop: &EventLoop,
window_attrs: WindowAttributes,
pl_attribs: PlatformSpecificWindowBuilderAttributes,
) -> Result<UnownedWindow, CreationError> {
@ -513,7 +513,7 @@ impl UnownedWindow {
self.set_netwm(fullscreen.into(), (fullscreen_atom as c_long, 0, 0, 0))
}
fn set_fullscreen_inner(&self, monitor: Option<RootMonitorId>) -> util::Flusher {
fn set_fullscreen_inner(&self, monitor: Option<RootMonitorHandle>) -> util::Flusher {
match monitor {
None => {
let flusher = self.set_fullscreen_hint(false);
@ -522,7 +522,7 @@ impl UnownedWindow {
}
flusher
},
Some(RootMonitorId { inner: PlatformMonitorId::X(monitor) }) => {
Some(RootMonitorHandle { inner: PlatformMonitorHandle::X(monitor) }) => {
let window_position = self.get_position_physical();
self.shared_state.lock().restore_position = window_position;
let monitor_origin: (i32, i32) = monitor.get_position().into();
@ -534,7 +534,7 @@ impl UnownedWindow {
}
#[inline]
pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
pub fn set_fullscreen(&self, monitor: Option<RootMonitorHandle>) {
self.set_fullscreen_inner(monitor)
.flush()
.expect("Failed to change window fullscreen state");
@ -551,7 +551,7 @@ impl UnownedWindow {
}
#[inline]
pub fn get_current_monitor(&self) -> X11MonitorId {
pub fn get_current_monitor(&self) -> X11MonitorHandle {
let monitor = self.shared_state
.lock()
.last_monitor
@ -565,11 +565,11 @@ impl UnownedWindow {
})
}
pub fn get_available_monitors(&self) -> Vec<X11MonitorId> {
pub fn get_available_monitors(&self) -> Vec<X11MonitorHandle> {
self.xconn.get_available_monitors()
}
pub fn get_primary_monitor(&self) -> X11MonitorId {
pub fn get_primary_monitor(&self) -> X11MonitorHandle {
self.xconn.get_primary_monitor()
}

View file

@ -1,4 +1,4 @@
use {ControlFlow, EventsLoopClosed};
use {ControlFlow, EventLoopClosed};
use cocoa::{self, appkit, foundation};
use cocoa::appkit::{NSApplication, NSEvent, NSEventMask, NSEventModifierFlags, NSEventPhase, NSView, NSWindow};
use events::{self, ElementState, Event, TouchPhase, WindowEvent, DeviceEvent, ModifiersState, KeyboardInput};
@ -9,12 +9,12 @@ use std;
use std::os::raw::*;
use super::DeviceId;
pub struct EventsLoop {
pub struct EventLoop {
modifiers: Modifiers,
pub shared: Arc<Shared>,
}
// State shared between the `EventsLoop` and its registered windows.
// State shared between the `EventLoop` and its registered windows.
pub struct Shared {
pub windows: Mutex<Vec<Weak<Window2>>>,
pub pending_events: Mutex<VecDeque<Event>>,
@ -42,7 +42,7 @@ struct Modifiers {
// Wrapping the user callback in a type allows us to:
//
// - ensure the callback pointer is never accidentally cloned
// - ensure that only the `EventsLoop` can `store` and `drop` the callback pointer
// - ensure that only the `EventLoop` can `store` and `drop` the callback pointer
// - Share access to the user callback with the NSWindow callbacks.
pub struct UserCallback {
mutex: Mutex<Option<*mut FnMut(Event)>>,
@ -160,17 +160,17 @@ impl UserCallback {
}
impl EventsLoop {
impl EventLoop {
pub fn new() -> Self {
// Mark this thread as the main thread of the Cocoa event system.
//
// This must be done before any worker threads get a chance to call it
// (e.g., via `EventsLoopProxy::wakeup()`), causing a wrong thread to be
// (e.g., via `EventLoopProxy::wakeup()`), causing a wrong thread to be
// marked as the main thread.
unsafe { appkit::NSApp(); }
EventsLoop {
EventLoop {
shared: Arc::new(Shared::new()),
modifiers: Modifiers::new(),
}
@ -521,7 +521,7 @@ impl EventsLoop {
}
impl Proxy {
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
pub fn wakeup(&self) -> Result<(), EventLoopClosed> {
// Awaken the event loop by triggering `NSApplicationActivatedEventType`.
unsafe {
let pool = foundation::NSAutoreleasePool::new(cocoa::base::nil);

View file

@ -1,7 +1,7 @@
#![cfg(target_os = "macos")]
pub use self::events_loop::{EventsLoop, Proxy as EventsLoopProxy};
pub use self::monitor::MonitorId;
pub use self::event_loop::{EventLoop, Proxy as EventLoopProxy};
pub use self::monitor::MonitorHandle;
pub use self::window::{Id as WindowId, PlatformSpecificWindowBuilderAttributes, Window2};
use std::sync::Arc;
@ -30,20 +30,20 @@ impl ::std::ops::Deref for Window {
impl Window {
pub fn new(events_loop: &EventsLoop,
pub fn new(event_loop: &EventLoop,
attributes: ::WindowAttributes,
pl_attribs: PlatformSpecificWindowBuilderAttributes) -> Result<Self, CreationError>
{
let weak_shared = Arc::downgrade(&events_loop.shared);
let weak_shared = Arc::downgrade(&event_loop.shared);
let window = Arc::new(try!(Window2::new(weak_shared, attributes, pl_attribs)));
let weak_window = Arc::downgrade(&window);
events_loop.shared.windows.lock().unwrap().push(weak_window);
event_loop.shared.windows.lock().unwrap().push(weak_window);
Ok(Window { window: window })
}
}
mod events_loop;
mod event_loop;
mod ffi;
mod monitor;
mod util;

View file

@ -7,17 +7,17 @@ use cocoa::foundation::{NSString, NSUInteger};
use core_graphics::display::{CGDirectDisplayID, CGDisplay, CGDisplayBounds};
use {PhysicalPosition, PhysicalSize};
use super::EventsLoop;
use super::EventLoop;
use super::window::{IdRef, Window2};
#[derive(Clone, PartialEq)]
pub struct MonitorId(CGDirectDisplayID);
pub struct MonitorHandle(CGDirectDisplayID);
fn get_available_monitors() -> VecDeque<MonitorId> {
fn get_available_monitors() -> VecDeque<MonitorHandle> {
if let Ok(displays) = CGDisplay::active_displays() {
let mut monitors = VecDeque::with_capacity(displays.len());
for d in displays {
monitors.push_back(MonitorId(d));
monitors.push_back(MonitorHandle(d));
}
monitors
} else {
@ -25,44 +25,44 @@ fn get_available_monitors() -> VecDeque<MonitorId> {
}
}
pub fn get_primary_monitor() -> MonitorId {
let id = MonitorId(CGDisplay::main().id);
pub fn get_primary_monitor() -> MonitorHandle {
let id = MonitorHandle(CGDisplay::main().id);
id
}
impl EventsLoop {
impl EventLoop {
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
get_available_monitors()
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
get_primary_monitor()
}
pub fn make_monitor_from_display(id: CGDirectDisplayID) -> MonitorId {
let id = MonitorId(id);
pub fn make_monitor_from_display(id: CGDirectDisplayID) -> MonitorHandle {
let id = MonitorHandle(id);
id
}
}
impl Window2 {
#[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
get_available_monitors()
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
get_primary_monitor()
}
}
impl fmt::Debug for MonitorId {
impl fmt::Debug for MonitorHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[derive(Debug)]
struct MonitorId {
struct MonitorHandle {
name: Option<String>,
native_identifier: u32,
dimensions: PhysicalSize,
@ -70,7 +70,7 @@ impl fmt::Debug for MonitorId {
hidpi_factor: f64,
}
let monitor_id_proxy = MonitorId {
let monitor_id_proxy = MonitorHandle {
name: self.get_name(),
native_identifier: self.get_native_identifier(),
dimensions: self.get_dimensions(),
@ -82,9 +82,9 @@ impl fmt::Debug for MonitorId {
}
}
impl MonitorId {
impl MonitorHandle {
pub fn get_name(&self) -> Option<String> {
let MonitorId(display_id) = *self;
let MonitorHandle(display_id) = *self;
let screen_num = CGDisplay::new(display_id).model_number();
Some(format!("Monitor #{}", screen_num))
}
@ -95,7 +95,7 @@ impl MonitorId {
}
pub fn get_dimensions(&self) -> PhysicalSize {
let MonitorId(display_id) = *self;
let MonitorHandle(display_id) = *self;
let display = CGDisplay::new(display_id);
let height = display.pixels_high();
let width = display.pixels_wide();

View file

@ -0,0 +1,38 @@
use cocoa::appkit::NSWindowStyleMask;
use cocoa::base::{id, nil};
use cocoa::foundation::{NSRect, NSUInteger};
use core_graphics::display::CGDisplay;
use platform_impl::platform::ffi;
use platform_impl::platform::window::IdRef;
pub const EMPTY_RANGE: ffi::NSRange = ffi::NSRange {
location: ffi::NSNotFound as NSUInteger,
length: 0,
};
// For consistency with other platforms, this will...
// 1. translate the bottom-left window corner into the top-left window corner
// 2. translate the coordinate from a bottom-left origin coordinate system to a top-left one
pub fn bottom_left_to_top_left(rect: NSRect) -> f64 {
CGDisplay::main().pixels_high() as f64 - (rect.origin.y + rect.size.height)
}
pub unsafe fn set_style_mask(window: id, view: id, mask: NSWindowStyleMask) {
use cocoa::appkit::NSWindow;
window.setStyleMask_(mask);
// If we don't do this, key handling will break. Therefore, never call `setStyleMask` directly!
window.makeFirstResponder_(view);
}
pub unsafe fn create_input_context(view: id) -> IdRef {
let input_context: id = msg_send![class!(NSTextInputContext), alloc];
let input_context: id = msg_send![input_context, initWithClient:view];
IdRef::new(input_context)
}
#[allow(dead_code)]
pub unsafe fn open_emoji_picker() {
let app: id = msg_send![class!(NSApplication), sharedApplication];
let _: () = msg_send![app, orderFrontCharacterPalette:nil];
}

View file

@ -14,10 +14,10 @@ use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Protocol, Sel, BOOL, YES};
use {ElementState, Event, KeyboardInput, MouseButton, WindowEvent, WindowId};
use platform::platform::events_loop::{DEVICE_ID, event_mods, Shared, to_virtual_key_code, check_additional_virtual_key_codes};
use platform::platform::util;
use platform::platform::ffi::*;
use platform::platform::window::{get_window_id, IdRef};
use platform_impl::platform::event_loop::{DEVICE_ID, event_mods, Shared, to_virtual_key_code, check_additional_virtual_key_codes};
use platform_impl::platform::util;
use platform_impl::platform::ffi::*;
use platform_impl::platform::window::{get_window_id, IdRef};
struct ViewState {
window: id,

View file

@ -42,10 +42,10 @@ use {
};
use CreationError::OsError;
use os::macos::{ActivationPolicy, WindowExt};
use platform::platform::{ffi, util};
use platform::platform::events_loop::{EventsLoop, Shared};
use platform::platform::view::{new_view, set_ime_spot};
use window::MonitorId as RootMonitorId;
use platform_impl::platform::{ffi, util};
use platform_impl::platform::event_loop::{EventLoop, Shared};
use platform_impl::platform::view::{new_view, set_ime_spot};
use window::MonitorHandle as RootMonitorHandle;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Id(pub usize);
@ -183,7 +183,7 @@ pub struct WindowDelegate {
}
impl WindowDelegate {
// Emits an event via the `EventsLoop`'s callback or stores it in the pending queue.
// Emits an event via the `EventLoop`'s callback or stores it in the pending queue.
pub fn emit_event(state: &mut DelegateState, window_event: WindowEvent) {
let window_id = get_window_id(*state.window);
let event = Event::WindowEvent {
@ -554,13 +554,13 @@ pub struct Window2 {
unsafe impl Send for Window2 {}
unsafe impl Sync for Window2 {}
unsafe fn get_current_monitor(window: id) -> RootMonitorId {
unsafe fn get_current_monitor(window: id) -> RootMonitorHandle {
let screen: id = msg_send![window, screen];
let desc = NSScreen::deviceDescription(screen);
let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
let value = NSDictionary::valueForKey_(desc, *key);
let display_id = msg_send![value, unsignedIntegerValue];
RootMonitorId { inner: EventsLoop::make_monitor_from_display(display_id) }
RootMonitorHandle { inner: EventLoop::make_monitor_from_display(display_id) }
}
impl Drop for Window2 {
@ -1140,7 +1140,7 @@ impl Window2 {
#[inline]
/// TODO: Right now set_fullscreen do not work on switching monitors
/// in fullscreen mode
pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
pub fn set_fullscreen(&self, monitor: Option<RootMonitorHandle>) {
let state = &self.delegate.state;
// Do nothing if simple fullscreen is active.
@ -1248,7 +1248,7 @@ impl Window2 {
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
pub fn get_current_monitor(&self) -> RootMonitorHandle {
unsafe {
self::get_current_monitor(*self.window)
}

26
src/platform_impl/mod.rs Normal file
View file

@ -0,0 +1,26 @@
pub use self::platform::*;
#[cfg(target_os = "windows")]
#[path="windows/mod.rs"]
mod platform;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
#[path="linux/mod.rs"]
mod platform;
#[cfg(target_os = "macos")]
#[path="macos/mod.rs"]
mod platform;
#[cfg(target_os = "android")]
#[path="android/mod.rs"]
mod platform;
#[cfg(target_os = "ios")]
#[path="ios/mod.rs"]
mod platform;
#[cfg(target_os = "emscripten")]
#[path="emscripten/mod.rs"]
mod platform;
#[cfg(all(not(target_os = "ios"), not(target_os = "windows"), not(target_os = "linux"),
not(target_os = "macos"), not(target_os = "android"), not(target_os = "dragonfly"),
not(target_os = "freebsd"), not(target_os = "netbsd"), not(target_os = "openbsd"),
not(target_os = "emscripten")))]
compile_error!("The platform you're compiling for is not supported by winit");

View file

@ -14,16 +14,17 @@ use winapi::um::oleidl::{DROPEFFECT_COPY, DROPEFFECT_NONE, IDropTarget, IDropTar
use winapi::um::winnt::HRESULT;
use winapi::um::{shellapi, unknwnbase};
use platform::platform::events_loop::send_event;
use platform::platform::WindowId;
use platform_impl::platform::WindowId;
use {Event, WindowId as SuperWindowId};
use event::Event;
use window::WindowId as SuperWindowId;
#[repr(C)]
pub struct FileDropHandlerData {
pub interface: IDropTarget,
refcount: AtomicUsize,
window: HWND,
send_event: Box<Fn(Event<()>)>,
cursor_effect: DWORD,
hovered_is_valid: bool, // If the currently hovered item is not valid there must not be any `HoveredFileCancelled` emitted
}
@ -34,13 +35,14 @@ pub struct FileDropHandler {
#[allow(non_snake_case)]
impl FileDropHandler {
pub fn new(window: HWND) -> FileDropHandler {
pub fn new(window: HWND, send_event: Box<Fn(Event<()>)>) -> FileDropHandler {
let data = Box::new(FileDropHandlerData {
interface: IDropTarget {
lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl,
},
refcount: AtomicUsize::new(1),
window,
send_event,
cursor_effect: DROPEFFECT_NONE,
hovered_is_valid: false,
});
@ -83,10 +85,10 @@ impl FileDropHandler {
_pt: *const POINTL,
pdwEffect: *mut DWORD,
) -> HRESULT {
use events::WindowEvent::HoveredFile;
use event::WindowEvent::HoveredFile;
let drop_handler = Self::from_interface(this);
let hdrop = Self::iterate_filenames(pDataObj, |filename| {
send_event(Event::WindowEvent {
drop_handler.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(drop_handler.window)),
event: HoveredFile(filename),
});
@ -115,10 +117,10 @@ 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);
if drop_handler.hovered_is_valid {
send_event(Event::WindowEvent {
drop_handler.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(drop_handler.window)),
event: HoveredFileCancelled,
});
@ -134,10 +136,10 @@ 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| {
send_event(Event::WindowEvent {
drop_handler.send_event(Event::WindowEvent {
window_id: SuperWindowId(WindowId(drop_handler.window)),
event: DroppedFile(filename),
});
@ -205,6 +207,12 @@ impl FileDropHandler {
}
}
impl FileDropHandlerData {
fn send_event(&self, event: Event<()>) {
(self.send_event)(event);
}
}
impl Drop for FileDropHandler {
fn drop(&mut self) {
unsafe {

View file

@ -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 {

File diff suppressed because it is too large Load diff

View file

@ -7,8 +7,8 @@ use winapi::shared::minwindef::{BYTE, LPARAM, WPARAM};
use winapi::shared::windef::{HICON, HWND};
use winapi::um::winuser;
use {Pixel, PIXEL_SIZE, Icon};
use platform::platform::util;
use icon::{Pixel, PIXEL_SIZE, Icon};
use platform_impl::platform::util;
impl Pixel {
fn to_bgra(&mut self) {

View file

@ -3,14 +3,17 @@
use winapi;
use winapi::shared::windef::HWND;
pub use self::events_loop::{EventsLoop, EventsLoopProxy};
pub use self::monitor::MonitorId;
pub use self::event_loop::{EventLoop, EventLoopWindowTarget, EventLoopProxy};
pub use self::monitor::MonitorHandle;
pub use self::window::Window;
use window::Icon;
use event::DeviceId as RootDeviceId;
#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes {
pub parent: Option<HWND>,
pub taskbar_icon: Option<::Icon>,
pub taskbar_icon: Option<Icon>,
pub no_redirection_bitmap: bool,
}
@ -43,10 +46,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)]
@ -65,7 +68,7 @@ impl WindowId {
mod dpi;
mod drop_handler;
mod event;
mod events_loop;
mod event_loop;
mod icon;
mod monitor;
mod raw_input;

View file

@ -6,14 +6,14 @@ use winapi::um::winuser;
use std::{mem, ptr};
use std::collections::VecDeque;
use super::{EventsLoop, util};
use super::{EventLoop, util};
use dpi::{PhysicalPosition, PhysicalSize};
use platform::platform::dpi::{dpi_to_scale_factor, get_monitor_dpi};
use platform::platform::window::Window;
use platform_impl::platform::dpi::{dpi_to_scale_factor, get_monitor_dpi};
use platform_impl::platform::window::Window;
/// Win32 implementation of the main `MonitorId` object.
/// Win32 implementation of the main `MonitorHandle` object.
#[derive(Debug, Clone)]
pub struct MonitorId {
pub struct MonitorHandle {
/// Monitor handle.
hmonitor: HMonitor,
/// The system name of the monitor.
@ -45,13 +45,13 @@ unsafe extern "system" fn monitor_enum_proc(
_place: LPRECT,
data: LPARAM,
) -> BOOL {
let monitors = data as *mut VecDeque<MonitorId>;
(*monitors).push_back(MonitorId::from_hmonitor(hmonitor));
let monitors = data as *mut VecDeque<MonitorHandle>;
(*monitors).push_back(MonitorHandle::from_hmonitor(hmonitor));
TRUE // continue enumeration
}
pub fn get_available_monitors() -> VecDeque<MonitorId> {
let mut monitors: VecDeque<MonitorId> = VecDeque::new();
pub fn get_available_monitors() -> VecDeque<MonitorHandle> {
let mut monitors: VecDeque<MonitorHandle> = VecDeque::new();
unsafe {
winuser::EnumDisplayMonitors(
ptr::null_mut(),
@ -63,38 +63,38 @@ pub fn get_available_monitors() -> VecDeque<MonitorId> {
monitors
}
pub fn get_primary_monitor() -> MonitorId {
pub fn get_primary_monitor() -> MonitorHandle {
const ORIGIN: POINT = POINT { x: 0, y: 0 };
let hmonitor = unsafe {
winuser::MonitorFromPoint(ORIGIN, winuser::MONITOR_DEFAULTTOPRIMARY)
};
MonitorId::from_hmonitor(hmonitor)
MonitorHandle::from_hmonitor(hmonitor)
}
impl EventsLoop {
pub fn get_current_monitor(hwnd: HWND) -> MonitorHandle {
let hmonitor = unsafe {
winuser::MonitorFromWindow(hwnd, winuser::MONITOR_DEFAULTTONEAREST)
};
MonitorHandle::from_hmonitor(hmonitor)
}
impl<T> EventLoop<T> {
// TODO: Investigate opportunities for caching
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
get_available_monitors()
}
pub fn get_current_monitor(hwnd: HWND) -> MonitorId {
let hmonitor = unsafe {
winuser::MonitorFromWindow(hwnd, winuser::MONITOR_DEFAULTTONEAREST)
};
MonitorId::from_hmonitor(hmonitor)
}
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
get_primary_monitor()
}
}
impl Window {
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
pub fn get_available_monitors(&self) -> VecDeque<MonitorHandle> {
get_available_monitors()
}
pub fn get_primary_monitor(&self) -> MonitorId {
pub fn get_primary_monitor(&self) -> MonitorHandle {
get_primary_monitor()
}
}
@ -115,7 +115,7 @@ pub(crate) fn get_monitor_info(hmonitor: HMONITOR) -> Result<winuser::MONITORINF
}
}
impl MonitorId {
impl MonitorHandle {
pub(crate) fn from_hmonitor(hmonitor: HMONITOR) -> Self {
let monitor_info = get_monitor_info(hmonitor).expect("`GetMonitorInfoW` failed");
let place = monitor_info.rcMonitor;
@ -123,7 +123,7 @@ impl MonitorId {
(place.right - place.left) as u32,
(place.bottom - place.top) as u32,
);
MonitorId {
MonitorHandle {
hmonitor: HMonitor(hmonitor),
monitor_name: util::wchar_ptr_to_string(monitor_info.szDevice.as_ptr()),
primary: util::has_flag(monitor_info.dwFlags, winuser::MONITORINFOF_PRIMARY),

View file

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

View file

@ -2,7 +2,7 @@ use std::{self, mem, ptr, slice, io};
use std::ops::BitAnd;
use std::sync::atomic::{AtomicBool, Ordering};
use MouseCursor;
use window::MouseCursor;
use winapi::ctypes::wchar_t;
use winapi::shared::minwindef::{BOOL, DWORD};
use winapi::shared::windef::{HWND, POINT, RECT};

View file

@ -4,36 +4,34 @@ use std::{io, mem, ptr};
use std::cell::Cell;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::sync::mpsc::channel;
use parking_lot::Mutex;
use winapi::ctypes::c_int;
use winapi::shared::minwindef::{DWORD, LPARAM, UINT, WORD, WPARAM};
use winapi::shared::windef::{HWND, POINT, RECT};
use winapi::um::{combaseapi, dwmapi, libloaderapi, winuser};
use winapi::um::objbase::COINIT_MULTITHREADED;
use winapi::um::{combaseapi, dwmapi, libloaderapi, ole2, winuser};
use winapi::um::objbase::COINIT_APARTMENTTHREADED;
use winapi::um::shobjidl_core::{CLSID_TaskbarList, ITaskbarList2};
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, MouseCursor, WindowAttributes};
use dpi::{LogicalPosition, LogicalSize, PhysicalSize};
use monitor::MonitorHandle as RootMonitorHandle;
use platform_impl::platform::{
{PlatformSpecificWindowBuilderAttributes, WindowId},
dpi::{dpi_to_scale_factor, get_hwnd_dpi},
drop_handler::FileDropHandler,
event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID, REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID},
icon::{self, IconType, WinIcon},
monitor,
raw_input::register_all_mice_and_keyboards_for_raw_input,
util,
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
};
use platform::platform::{PlatformSpecificWindowBuilderAttributes, WindowId};
use platform::platform::dpi::{dpi_to_scale_factor, get_hwnd_dpi};
use platform::platform::events_loop::{self, EventsLoop, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID};
use platform::platform::icon::{self, IconType, WinIcon};
use platform::platform::monitor::get_available_monitors;
use platform::platform::raw_input::register_all_mice_and_keyboards_for_raw_input;
use platform::platform::util;
use platform::platform::window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState};
/// The Win32 implementation of the main `Window` object.
pub struct Window {
@ -44,24 +42,54 @@ pub struct Window {
window_state: Arc<Mutex<WindowState>>,
// The events loop proxy.
events_loop_proxy: events_loop::EventsLoopProxy,
thread_executor: event_loop::EventLoopThreadExecutor,
}
impl Window {
pub fn new(
events_loop: &EventsLoop,
pub fn new<T: 'static>(
event_loop: &EventLoopWindowTarget<T>,
w_attr: WindowAttributes,
pl_attr: PlatformSpecificWindowBuilderAttributes,
) -> Result<Window, CreationError> {
let (tx, rx) = channel();
let proxy = events_loop.create_proxy();
events_loop.execute_in_thread(move |inserter| {
// We dispatch an `init` function because of code style.
// First person to remove the need for cloning here gets a cookie!
let win = unsafe { init(w_attr.clone(), pl_attr.clone(), inserter, proxy.clone()) };
let _ = tx.send(win);
});
rx.recv().unwrap()
// We dispatch an `init` function because of code style.
// First person to remove the need for cloning here gets a cookie!
//
// done. you owe me -- ossi
unsafe {
init(w_attr, pl_attr, event_loop).map(|win| {
let file_drop_handler = {
use winapi::shared::winerror::{OLE_E_WRONGCOMPOBJ, RPC_E_CHANGED_MODE, S_OK};
let ole_init_result = ole2::OleInitialize(ptr::null_mut());
// It is ok if the initialize result is `S_FALSE` because it might happen that
// multiple windows are created on the same thread.
if ole_init_result == OLE_E_WRONGCOMPOBJ {
panic!("OleInitialize failed! Result was: `OLE_E_WRONGCOMPOBJ`");
} else if ole_init_result == RPC_E_CHANGED_MODE {
panic!("OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`");
}
let file_drop_runner = event_loop.runner_shared.clone();
let file_drop_handler = FileDropHandler::new(
win.window.0,
Box::new(move |event| if let Ok(e) = event.map_nonuser_event() {file_drop_runner.send_event(e)})
);
let handler_interface_ptr = &mut (*file_drop_handler.data).interface as LPDROPTARGET;
assert_eq!(ole2::RegisterDragDrop(win.window.0, handler_interface_ptr), S_OK);
file_drop_handler
};
let subclass_input = event_loop::SubclassInput {
window_state: win.window_state.clone(),
event_loop_runner: event_loop.runner_shared.clone(),
file_drop_handler,
};
event_loop::subclass_window(win.window.0, subclass_input);
win
})
}
}
pub fn set_title(&self, text: &str) {
@ -88,6 +116,22 @@ impl Window {
}
}
#[inline]
pub fn request_redraw(&self) {
unsafe {
if self.thread_executor.trigger_newevents_on_redraw() {
winuser::RedrawWindow(
self.window.0,
ptr::null(),
ptr::null_mut(),
winuser::RDW_INTERNALPAINT
);
} else {
winuser::PostMessageW(self.window.0, *REQUEST_REDRAW_NO_NEWEVENTS_MSG_ID, 0, 0);
}
}
}
pub(crate) fn get_position_physical(&self) -> Option<(i32, i32)> {
util::get_window_rect(self.window.0)
.map(|rect| (rect.left as i32, rect.top as i32))
@ -216,7 +260,7 @@ impl Window {
}
pub(crate) fn set_min_dimensions_physical(&self, dimensions: Option<(u32, u32)>) {
self.window_state.lock().unwrap().min_size = dimensions.map(Into::into);
self.window_state.lock().min_size = dimensions.map(Into::into);
// Make windows re-check the window size bounds.
self.get_inner_size_physical()
.map(|(width, height)| self.set_inner_size_physical(width, height));
@ -232,7 +276,7 @@ impl Window {
}
pub fn set_max_dimensions_physical(&self, dimensions: Option<(u32, u32)>) {
self.window_state.lock().unwrap().max_size = dimensions.map(Into::into);
self.window_state.lock().max_size = dimensions.map(Into::into);
// Make windows re-check the window size bounds.
self.get_inner_size_physical()
.map(|(width, height)| self.set_inner_size_physical(width, height));
@ -252,9 +296,9 @@ impl Window {
let window = self.window.clone();
let window_state = Arc::clone(&self.window_state);
self.events_loop_proxy.execute_in_thread(move |_| {
self.thread_executor.execute_in_thread(move || {
WindowState::set_window_flags(
window_state.lock().unwrap(),
window_state.lock(),
window.0,
None,
|f| f.set(WindowFlags::RESIZABLE, resizable),
@ -270,8 +314,8 @@ impl Window {
#[inline]
pub fn set_cursor(&self, cursor: MouseCursor) {
self.window_state.lock().unwrap().mouse.cursor = cursor;
self.events_loop_proxy.execute_in_thread(move |_| unsafe {
self.window_state.lock().mouse.cursor = cursor;
self.thread_executor.execute_in_thread(move || unsafe {
let cursor = winuser::LoadCursorW(
ptr::null_mut(),
cursor.to_windows_cursor(),
@ -286,8 +330,8 @@ impl Window {
let window_state = Arc::clone(&self.window_state);
let (tx, rx) = channel();
self.events_loop_proxy.execute_in_thread(move |_| {
let result = window_state.lock().unwrap().mouse
self.thread_executor.execute_in_thread(move || {
let result = window_state.lock().mouse
.set_cursor_flags(window.0, |f| f.set(CursorFlags::GRABBED, grab))
.map_err(|e| e.to_string());
let _ = tx.send(result);
@ -301,8 +345,8 @@ impl Window {
let window_state = Arc::clone(&self.window_state);
let (tx, rx) = channel();
self.events_loop_proxy.execute_in_thread(move |_| {
let result = window_state.lock().unwrap().mouse
self.thread_executor.execute_in_thread(move || {
let result = window_state.lock().mouse
.set_cursor_flags(window.0, |f| f.set(CursorFlags::HIDDEN, hide))
.map_err(|e| e.to_string());
let _ = tx.send(result);
@ -312,7 +356,7 @@ impl Window {
#[inline]
pub fn get_hidpi_factor(&self) -> f64 {
self.window_state.lock().unwrap().dpi_factor
self.window_state.lock().dpi_factor
}
fn set_cursor_position_physical(&self, x: i32, y: i32) -> Result<(), String> {
@ -345,9 +389,9 @@ impl Window {
let window = self.window.clone();
let window_state = Arc::clone(&self.window_state);
self.events_loop_proxy.execute_in_thread(move |_| {
self.thread_executor.execute_in_thread(move || {
WindowState::set_window_flags(
window_state.lock().unwrap(),
window_state.lock(),
window.0,
None,
|f| f.set(WindowFlags::MAXIMIZED, maximized),
@ -356,19 +400,19 @@ impl Window {
}
#[inline]
pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
pub fn set_fullscreen(&self, monitor: Option<RootMonitorHandle>) {
unsafe {
let window = self.window.clone();
let window_state = Arc::clone(&self.window_state);
match &monitor {
&Some(RootMonitorId { ref inner }) => {
&Some(RootMonitorHandle { ref inner }) => {
let (x, y): (i32, i32) = inner.get_position().into();
let (width, height): (u32, u32) = inner.get_dimensions().into();
let mut monitor = monitor.clone();
self.events_loop_proxy.execute_in_thread(move |_| {
let mut window_state_lock = window_state.lock().unwrap();
self.thread_executor.execute_in_thread(move || {
let mut window_state_lock = window_state.lock();
let client_rect = util::get_client_rect(window.0).expect("get client rect failed!");
window_state_lock.saved_window = Some(SavedWindow {
@ -392,8 +436,8 @@ impl Window {
});
}
&None => {
self.events_loop_proxy.execute_in_thread(move |_| {
let mut window_state_lock = window_state.lock().unwrap();
self.thread_executor.execute_in_thread(move || {
let mut window_state_lock = window_state.lock();
window_state_lock.fullscreen = None;
if let Some(SavedWindow{client_rect, dpi_factor}) = window_state_lock.saved_window {
@ -419,10 +463,10 @@ impl Window {
let window = self.window.clone();
let window_state = Arc::clone(&self.window_state);
self.events_loop_proxy.execute_in_thread(move |_| {
self.thread_executor.execute_in_thread(move || {
let client_rect = util::get_client_rect(window.0).expect("get client rect failed!");
WindowState::set_window_flags(
window_state.lock().unwrap(),
window_state.lock(),
window.0,
Some(client_rect),
|f| f.set(WindowFlags::DECORATIONS, decorations),
@ -435,9 +479,9 @@ impl Window {
let window = self.window.clone();
let window_state = Arc::clone(&self.window_state);
self.events_loop_proxy.execute_in_thread(move |_| {
self.thread_executor.execute_in_thread(move || {
WindowState::set_window_flags(
window_state.lock().unwrap(),
window_state.lock(),
window.0,
None,
|f| f.set(WindowFlags::ALWAYS_ON_TOP, always_on_top),
@ -446,9 +490,9 @@ impl Window {
}
#[inline]
pub fn get_current_monitor(&self) -> RootMonitorId {
RootMonitorId {
inner: EventsLoop::get_current_monitor(self.window.0),
pub fn get_current_monitor(&self) -> RootMonitorHandle {
RootMonitorHandle {
inner: monitor::get_current_monitor(self.window.0),
}
}
@ -462,7 +506,7 @@ impl Window {
} else {
icon::unset_for_window(self.window.0, IconType::Small);
}
self.window_state.lock().unwrap().window_icon = window_icon;
self.window_state.lock().window_icon = window_icon;
}
#[inline]
@ -475,7 +519,7 @@ impl Window {
} else {
icon::unset_for_window(self.window.0, IconType::Big);
}
self.window_state.lock().unwrap().taskbar_icon = taskbar_icon;
self.window_state.lock().taskbar_icon = taskbar_icon;
}
#[inline]
@ -523,11 +567,10 @@ pub unsafe fn adjust_size(
(rect.right - rect.left, rect.bottom - rect.top)
}
unsafe fn init(
unsafe fn init<T: 'static>(
mut attributes: WindowAttributes,
mut pl_attribs: PlatformSpecificWindowBuilderAttributes,
inserter: events_loop::Inserter,
events_loop_proxy: events_loop::EventsLoopProxy,
event_loop: &EventLoopWindowTarget<T>,
) -> Result<Window, CreationError> {
let title = OsStr::new(&attributes.title)
.encode_wide()
@ -563,7 +606,7 @@ unsafe fn init(
let class_name = register_window_class(&window_icon, &taskbar_icon);
let guessed_dpi_factor = {
let monitors = get_available_monitors();
let monitors = monitor::get_available_monitors();
let dpi_factor = if !monitors.is_empty() {
let mut dpi_factor = Some(monitors[0].get_hidpi_factor());
for monitor in &monitors {
@ -698,7 +741,7 @@ unsafe fn init(
);
let window_state = Arc::new(Mutex::new(window_state));
WindowState::set_window_flags(
window_state.lock().unwrap(),
window_state.lock(),
real_window.0,
None,
|f| *f = window_flags,
@ -709,7 +752,7 @@ unsafe fn init(
let win = Window {
window: real_window,
window_state,
events_loop_proxy,
thread_executor: event_loop.create_thread_executor(),
};
if let Some(_) = attributes.fullscreen {
@ -721,8 +764,6 @@ unsafe fn init(
win.set_inner_size(dimensions);
}
inserter.insert(win.window.0, win.window_state.clone());
Ok(win)
}
@ -747,7 +788,7 @@ unsafe fn register_window_class(
let class = winuser::WNDCLASSEXW {
cbSize: mem::size_of::<winuser::WNDCLASSEXW>() as UINT,
style: winuser::CS_HREDRAW | winuser::CS_VREDRAW | winuser::CS_OWNDC,
lpfnWndProc: Some(events_loop::callback),
lpfnWndProc: Some(winuser::DefWindowProcW),
cbClsExtra: 0,
cbWndExtra: 0,
hInstance: libloaderapi::GetModuleHandleW(ptr::null()),
@ -778,7 +819,7 @@ impl Drop for ComInitialized {
thread_local!{
static COM_INITIALIZED: ComInitialized = {
unsafe {
combaseapi::CoInitializeEx(ptr::null_mut(), COINIT_MULTITHREADED);
combaseapi::CoInitializeEx(ptr::null_mut(), COINIT_APARTMENTTHREADED);
ComInitialized(ptr::null_mut())
}
};

View file

@ -1,9 +1,10 @@
use {MouseCursor, WindowAttributes};
use monitor::MonitorHandle;
use window::{MouseCursor, WindowAttributes};
use std::{io, ptr};
use std::sync::MutexGuard;
use parking_lot::MutexGuard;
use dpi::LogicalSize;
use platform::platform::{util, events_loop};
use platform::platform::icon::WinIcon;
use platform_impl::platform::{util, event_loop};
use platform_impl::platform::icon::WinIcon;
use winapi::shared::windef::{RECT, HWND};
use winapi::shared::minwindef::DWORD;
use winapi::um::winuser;
@ -23,7 +24,7 @@ pub struct WindowState {
pub saved_window: Option<SavedWindow>,
pub dpi_factor: f64,
pub fullscreen: Option<::MonitorId>,
pub fullscreen: Option<MonitorHandle>,
window_flags: WindowFlags,
}
@ -36,6 +37,7 @@ pub struct SavedWindow {
#[derive(Clone)]
pub struct MouseProperties {
pub cursor: MouseCursor,
pub buttons_down: u32,
cursor_flags: CursorFlags,
}
@ -89,6 +91,7 @@ impl WindowState {
WindowState {
mouse: MouseProperties {
cursor: MouseCursor::default(),
buttons_down: 0,
cursor_flags: CursorFlags::empty(),
},
@ -265,7 +268,7 @@ impl WindowFlags {
let (style, style_ex) = new.to_window_styles();
unsafe {
winuser::SendMessageW(window, *events_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, 1, 0);
winuser::SendMessageW(window, *event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, 1, 0);
winuser::SetWindowLongW(window, winuser::GWL_STYLE, style as _);
winuser::SetWindowLongW(window, winuser::GWL_EXSTYLE, style_ex as _);
@ -299,7 +302,7 @@ impl WindowFlags {
);
}
}
winuser::SendMessageW(window, *events_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, 0, 0);
winuser::SendMessageW(window, *event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, 0, 0);
}
}
}

View file

@ -1,20 +1,172 @@
use std::collections::vec_deque::IntoIter as VecDequeIter;
//! The `Window` struct and associated types.
use std::{fmt, error};
use {
CreationError,
EventsLoop,
Icon,
LogicalPosition,
LogicalSize,
MouseCursor,
PhysicalPosition,
PhysicalSize,
platform,
Window,
WindowBuilder,
WindowId,
};
use platform_impl;
use event_loop::EventLoopWindowTarget;
use monitor::{AvailableMonitorsIter, MonitorHandle};
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 event_loop = EventLoop::new();
/// let window = Window::new(&event_loop).unwrap();
///
/// event_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 fmt::Debug for Window {
fn fmt(&self, fmtr: &mut fmt::Formatter) -> 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);
impl WindowId {
/// Returns a dummy `WindowId`, useful for unit testing. The only guarantee made about the return
/// value of this function is that it will always be equal to itself and to future values returned
/// by this function. No other guarantees are made. This may be equal to a real `WindowId`.
///
/// **Passing this into a winit function will result in undefined behavior.**
pub unsafe fn dummy() -> Self {
WindowId(platform_impl::WindowId::dummy())
}
}
/// 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 fmt::Debug for WindowBuilder {
fn fmt(&self, fmtr: &mut fmt::Formatter) -> 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<MonitorHandle>,
/// 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 {
/// Initializes a new `WindowBuilder` with default values.
#[inline]
@ -69,10 +221,10 @@ impl WindowBuilder {
self
}
/// Sets the window fullscreen state. None means a normal window, Some(MonitorId)
/// Sets the window fullscreen state. None means a normal window, Some(MonitorHandle)
/// means a fullscreen window on that specific monitor
#[inline]
pub fn with_fullscreen(mut self, monitor: Option<MonitorId>) -> WindowBuilder {
pub fn with_fullscreen(mut self, monitor: Option<MonitorHandle>) -> WindowBuilder {
self.window.fullscreen = monitor;
self
}
@ -142,7 +294,7 @@ impl WindowBuilder {
/// Error should be very rare and only occur in case of permission denied, incompatible system,
/// out of memory, etc.
#[inline]
pub fn build(mut self, events_loop: &EventsLoop) -> Result<Window, CreationError> {
pub fn build<T: 'static>(mut self, window_target: &EventLoopWindowTarget<T>) -> Result<Window, CreationError> {
self.window.dimensions = Some(self.window.dimensions.unwrap_or_else(|| {
if let Some(ref monitor) = self.window.fullscreen {
// resizing the window to the dimensions of the monitor when fullscreen
@ -154,8 +306,8 @@ impl WindowBuilder {
}));
// building
platform::Window::new(
&events_loop.events_loop,
platform_impl::Window::new(
&window_target.p,
self.window,
self.platform_specific,
).map(|window| Window { window })
@ -165,14 +317,14 @@ impl WindowBuilder {
impl Window {
/// Creates a new Window for platforms where this is appropriate.
///
/// This function is equivalent to `WindowBuilder::new().build(events_loop)`.
/// This function is equivalent to `WindowBuilder::new().build(event_loop)`.
///
/// Error should be very rare and only occur in case of permission denied, incompatible system,
/// out of memory, etc.
#[inline]
pub fn new(events_loop: &EventsLoop) -> Result<Window, CreationError> {
pub fn new<T: 'static>(event_loop: &EventLoopWindowTarget<T>) -> Result<Window, CreationError> {
let builder = WindowBuilder::new();
builder.build(events_loop)
builder.build(event_loop)
}
/// Modifies the title of the window.
@ -205,6 +357,21 @@ impl Window {
self.window.hide()
}
/// Emits a `WindowEvent::RedrawRequested` event in the associated event loop after all OS
/// events have been processed by the event loop.
///
/// This is the **strongly encouraged** method of redrawing windows, as it can integrates with
/// OS-requested redraws (e.g. when a window gets resized).
///
/// This function can cause `RedrawRequested` events to be emitted after `Event::EventsCleared`
/// but before `Event::NewEvents` if called in the following circumstances:
/// * While processing `EventsCleared`.
/// * While processing a `RedrawRequested` event that was sent during `EventsCleared` or any
/// directly subsequent `RedrawRequested` event.
pub fn request_redraw(&self) {
self.window.request_redraw()
}
/// Returns the position of the top-left hand corner of the window relative to the
/// top-left hand corner of the desktop.
///
@ -365,7 +532,7 @@ impl Window {
/// Sets the window to fullscreen or back
#[inline]
pub fn set_fullscreen(&self, monitor: Option<MonitorId>) {
pub fn set_fullscreen(&self, monitor: Option<MonitorHandle>) {
self.window.set_fullscreen(monitor)
}
@ -402,13 +569,13 @@ impl Window {
/// Returns the monitor on which the window currently resides
#[inline]
pub fn get_current_monitor(&self) -> MonitorId {
pub fn get_current_monitor(&self) -> MonitorHandle {
self.window.get_current_monitor()
}
/// Returns the list of all the monitors available on the system.
///
/// This is the same as `EventsLoop::get_available_monitors`, and is provided for convenience.
/// This is the same as `EventLoop::get_available_monitors`, and is provided for convenience.
#[inline]
pub fn get_available_monitors(&self) -> AvailableMonitorsIter {
let data = self.window.get_available_monitors();
@ -417,78 +584,107 @@ impl Window {
/// Returns the primary monitor of the system.
///
/// This is the same as `EventsLoop::get_primary_monitor`, and is provided for convenience.
/// This is the same as `EventLoop::get_primary_monitor`, and is provided for convenience.
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId { inner: self.window.get_primary_monitor() }
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle { inner: self.window.get_primary_monitor() }
}
/// Returns an identifier unique to the window.
#[inline]
pub fn id(&self) -> WindowId {
WindowId(self.window.id())
}
}
/// 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::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.
/// Error that can happen while creating a window or a headless renderer.
#[derive(Debug, Clone)]
pub struct MonitorId {
pub(crate) inner: platform::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<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()
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
}
}

View file

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

View file

@ -3,8 +3,8 @@
extern crate serde;
extern crate winit;
use winit::{ControlFlow, MouseCursor};
use winit::{
use winit::window::{MouseCursor};
use winit::event::{
KeyboardInput, TouchPhase, ElementState, MouseButton, MouseScrollDelta, VirtualKeyCode,
ModifiersState
};
@ -14,8 +14,7 @@ use serde::{Serialize, Deserialize};
fn needs_serde<S: Serialize + Deserialize<'static>>() {}
#[test]
fn root_serde() {
needs_serde::<ControlFlow>();
fn window_serde() {
needs_serde::<MouseCursor>();
}

View file

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