Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Sync and Clone from EventsLoop. Add EventsLoopProxy. #191

Merged
merged 20 commits into from
Jun 21, 2017
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
06a5ec3
[WIP] Remove Sync and Clone from EventsLoop. Add EventsLoopProxy.
mitchmindtree May 24, 2017
c8e791b
Add a test that checks that EventsLoopProxy impls Send
mitchmindtree May 25, 2017
f6587ae
[WIP] Have EventsLoopProxy::wakeup return a Result. Begin linux impl.
mitchmindtree May 25, 2017
9ca2f83
Call flush so that the wayland eventsloop correctly breaks from dispa…
mitchmindtree May 27, 2017
339318f
Update macOS backend to removal of Send+Sync and addition of EventsLo…
mitchmindtree May 31, 2017
647a172
Attempt to update api_transition to addition of EventsLoopProxy
mitchmindtree May 31, 2017
8f0ef51
Fix incorred Awakened import in windows backend
mitchmindtree May 31, 2017
2b55b2e
Temporarily remove windows window-specific awakened event. Needs to b…
mitchmindtree May 31, 2017
38856b1
X11 - Move event insertion from interrupt to proxy wakeup.
mitchmindtree May 31, 2017
f2dd2f0
WIP - Make poll_events and run_forever take &mut self
mitchmindtree Jun 2, 2017
db9e80b
Update examples and tests to addition of ControlFlow
mitchmindtree Jun 7, 2017
c5b9bd3
Update macos backend to addition of ControlFlow (untested)
mitchmindtree Jun 9, 2017
0237526
Complete macos backend update to addition of ControlFlow
mitchmindtree Jun 9, 2017
0af3c04
Update api transition to use ControlFlow
mitchmindtree Jun 9, 2017
4b42af9
Make x11 backend take &mut self in poll_events method
mitchmindtree Jun 9, 2017
cd71271
Fix api_transition ControlFlow update compile errors
mitchmindtree Jun 9, 2017
24d6f8d
Update README to addition of ControlFlow
mitchmindtree Jun 10, 2017
df1276d
Fix x11 EventsLoopProxy::wakeup implementation using a dummy, InputOn…
mitchmindtree Jun 17, 2017
04ccad1
Rename ControlFlow variant from Complete to Break
mitchmindtree Jun 20, 2017
fe61d81
Change Complete to Break in the README
mitchmindtree Jun 20, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ another library.
extern crate winit;

fn main() {
let events_loop = winit::EventsLoop::new();
let mut events_loop = winit::EventsLoop::new();
let window = winit::Window::new(&events_loop).unwrap();

events_loop.run_forever(|event| {
match event {
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => {
events_loop.interrupt();
winit::ControlFlow::Complete
},
_ => ()
_ => winit::ControlFlow::Continue,
}
});
}
Expand Down
7 changes: 4 additions & 3 deletions examples/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
extern crate winit;

use winit::{Event, ElementState, MouseCursor, WindowEvent, KeyboardInput};
use winit::{Event, ElementState, MouseCursor, WindowEvent, KeyboardInput, ControlFlow};

fn main() {
let events_loop = winit::EventsLoop::new();
let mut events_loop = winit::EventsLoop::new();

let window = winit::WindowBuilder::new().build(&events_loop).unwrap();
window.set_title("A fantastic window!");
Expand All @@ -23,9 +23,10 @@ fn main() {
}
},
Event::WindowEvent { event: WindowEvent::Closed, .. } => {
events_loop.interrupt()
return ControlFlow::Complete;
},
_ => ()
}
ControlFlow::Continue
});
}
13 changes: 8 additions & 5 deletions examples/fullscreen.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
extern crate winit;

use std::io::{self, Write};
use winit::{ControlFlow, Event, WindowEvent};

fn main() {
// enumerating monitors
Expand All @@ -22,7 +23,7 @@ fn main() {
monitor
};

let events_loop = winit::EventsLoop::new();
let mut events_loop = winit::EventsLoop::new();

let _window = winit::WindowBuilder::new()
.with_title("Hello world!")
Expand All @@ -34,16 +35,18 @@ fn main() {
println!("{:?}", event);

match event {
winit::Event::WindowEvent { event, .. } => {
Event::WindowEvent { event, .. } => {
match event {
winit::WindowEvent::Closed => events_loop.interrupt(),
winit::WindowEvent::KeyboardInput {
WindowEvent::Closed => return ControlFlow::Complete,
WindowEvent::KeyboardInput {
input: winit::KeyboardInput { virtual_keycode: Some(winit::VirtualKeyCode::Escape), .. }, ..
} => events_loop.interrupt(),
} => return ControlFlow::Complete,
_ => ()
}
},
_ => {}
}

ControlFlow::Continue
});
}
8 changes: 5 additions & 3 deletions examples/grabbing.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
extern crate winit;

use winit::{WindowEvent, ElementState, KeyboardInput};
use winit::{ControlFlow, WindowEvent, ElementState, KeyboardInput};

fn main() {
let events_loop = winit::EventsLoop::new();
let mut events_loop = winit::EventsLoop::new();

let window = winit::WindowBuilder::new().build(&events_loop).unwrap();
window.set_title("winit - Cursor grabbing test");
Expand All @@ -28,7 +28,7 @@ fn main() {
}
},

WindowEvent::Closed => events_loop.interrupt(),
WindowEvent::Closed => return ControlFlow::Complete,

a @ WindowEvent::MouseMoved { .. } => {
println!("{:?}", a);
Expand All @@ -39,5 +39,7 @@ fn main() {
}
_ => {}
}

ControlFlow::Continue
});
}
6 changes: 3 additions & 3 deletions examples/min_max_size.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate winit;

fn main() {
let events_loop = winit::EventsLoop::new();
let mut events_loop = winit::EventsLoop::new();

let _window = winit::WindowBuilder::new()
.with_min_dimensions(400, 200)
Expand All @@ -13,8 +13,8 @@ fn main() {
println!("{:?}", event);

match event {
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => events_loop.interrupt(),
_ => ()
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => winit::ControlFlow::Complete,
_ => winit::ControlFlow::Continue,
}
});
}
5 changes: 3 additions & 2 deletions examples/multiwindow.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate winit;

fn main() {
let events_loop = winit::EventsLoop::new();
let mut events_loop = winit::EventsLoop::new();

let window1 = winit::Window::new(&events_loop).unwrap();
let window2 = winit::Window::new(&events_loop).unwrap();
Expand All @@ -24,10 +24,11 @@ fn main() {

num_windows -= 1;
if num_windows == 0 {
events_loop.interrupt();
return winit::ControlFlow::Complete;
}
},
_ => (),
}
winit::ControlFlow::Continue
})
}
29 changes: 29 additions & 0 deletions examples/proxy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
extern crate winit;

fn main() {
let mut events_loop = winit::EventsLoop::new();

let _window = winit::WindowBuilder::new()
.with_title("A fantastic window!")
.build(&events_loop)
.unwrap();

let proxy = events_loop.create_proxy();

std::thread::spawn(move || {
// Wake up the `events_loop` once every second.
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
proxy.wakeup().unwrap();
}
});

events_loop.run_forever(|event| {
println!("{:?}", event);
match event {
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } =>
winit::ControlFlow::Complete,
_ => winit::ControlFlow::Continue,
}
});
}
6 changes: 3 additions & 3 deletions examples/transparent.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate winit;

fn main() {
let events_loop = winit::EventsLoop::new();
let mut events_loop = winit::EventsLoop::new();

let window = winit::WindowBuilder::new().with_decorations(false)
.with_transparency(true)
Expand All @@ -13,8 +13,8 @@ fn main() {
println!("{:?}", event);

match event {
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => events_loop.interrupt(),
_ => ()
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => winit::ControlFlow::Complete,
_ => winit::ControlFlow::Continue,
}
});
}
10 changes: 6 additions & 4 deletions examples/window.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
extern crate winit;

fn main() {
let events_loop = winit::EventsLoop::new();
let mut events_loop = winit::EventsLoop::new();

let window = winit::WindowBuilder::new()
let _window = winit::WindowBuilder::new()
.with_title("A fantastic window!")
.build(&events_loop)
.unwrap();
Expand All @@ -12,8 +12,10 @@ fn main() {
println!("{:?}", event);

match event {
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => events_loop.interrupt(),
_ => ()
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => {
winit::ControlFlow::Complete
},
_ => winit::ControlFlow::Continue,
}
});
}
71 changes: 50 additions & 21 deletions src/api_transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,31 @@
macro_rules! gen_api_transition {
() => {
pub struct EventsLoop {
windows: ::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>,
interrupted: ::std::sync::atomic::AtomicBool,
windows: ::std::sync::Arc<::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>>,
awakened: ::std::sync::Arc<::std::sync::atomic::AtomicBool>,
}

pub struct EventsLoopProxy {
awakened: ::std::sync::Weak<::std::sync::atomic::AtomicBool>,
}

impl EventsLoop {
pub fn new() -> EventsLoop {
EventsLoop {
windows: ::std::sync::Mutex::new(vec![]),
interrupted: ::std::sync::atomic::AtomicBool::new(false),
windows: ::std::sync::Arc::new(::std::sync::Mutex::new(vec![])),
awakened: ::std::sync::Arc::new(::std::sync::atomic::AtomicBool::new(false)),
}
}

pub fn interrupt(&self) {
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed);
}

pub fn poll_events<F>(&self, mut callback: F)
pub fn poll_events<F>(&mut self, mut callback: F)
where F: FnMut(::Event)
{
let mut windows = self.windows.lock().unwrap();
if self.awakened.load(::std::sync::atomic::Ordering::Relaxed) {
self.awakened.store(false, ::std::sync::atomic::Ordering::Relaxed);
callback(::Event::Awakened);
}

let windows = self.windows.lock().unwrap();
for window in windows.iter() {
for event in window.poll_events() {
callback(::Event::WindowEvent {
Expand All @@ -38,18 +43,41 @@ macro_rules! gen_api_transition {
}
}

pub fn run_forever<F>(&self, mut callback: F)
where F: FnMut(::Event)
pub fn run_forever<F>(&mut self, mut callback: F)
where F: FnMut(::Event) -> ::ControlFlow,
{
self.interrupted.store(false, ::std::sync::atomic::Ordering::Relaxed);
self.awakened.store(false, ::std::sync::atomic::Ordering::Relaxed);

// Yeah that's a very bad implementation.
loop {
self.poll_events(|e| callback(e));
::std::thread::sleep_ms(5);
if self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
let mut control_flow = ::ControlFlow::Continue;
self.poll_events(|e| {
if let ::ControlFlow::Complete = callback(e) {
control_flow = ::ControlFlow::Complete;
}
});
if let ::ControlFlow::Complete = control_flow {
break;
}
::std::thread::sleep(::std::time::Duration::from_millis(5));
}
}

pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy {
awakened: ::std::sync::Arc::downgrade(&self.awakened),
}
}
}

impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
match self.awakened.upgrade() {
None => Err(::EventsLoopClosed),
Some(awakened) => {
awakened.store(true, ::std::sync::atomic::Ordering::Relaxed);
Ok(())
},
}
}
}
Expand All @@ -62,7 +90,7 @@ macro_rules! gen_api_transition {

pub struct Window2 {
pub window: ::std::sync::Arc<Window>,
events_loop: ::std::sync::Weak<EventsLoop>,
windows: ::std::sync::Weak<::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>>
}

impl ::std::ops::Deref for Window2 {
Expand All @@ -74,15 +102,16 @@ macro_rules! gen_api_transition {
}

impl Window2 {
pub fn new(events_loop: ::std::sync::Arc<EventsLoop>, window: &::WindowAttributes,
pub fn new(events_loop: &EventsLoop,
window: &::WindowAttributes,
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
-> Result<Window2, CreationError>
{
let win = ::std::sync::Arc::new(try!(Window::new(window, pl_attribs)));
events_loop.windows.lock().unwrap().push(win.clone());
Ok(Window2 {
window: win,
events_loop: ::std::sync::Arc::downgrade(&events_loop),
windows: ::std::sync::Arc::downgrade(&events_loop.windows),
})
}

Expand All @@ -94,8 +123,8 @@ macro_rules! gen_api_transition {

impl Drop for Window2 {
fn drop(&mut self) {
if let Some(ev) = self.events_loop.upgrade() {
let mut windows = ev.windows.lock().unwrap();
if let Some(windows) = self.windows.upgrade() {
let mut windows = windows.lock().unwrap();
windows.retain(|w| &**w as *const Window != &*self.window as *const _);
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ pub enum Event {
device_id: DeviceId,
event: DeviceEvent,
},
Awakened,
}

#[derive(Clone, Debug)]
pub enum WindowEvent {
// TODO: remove ; can break the lib internally so be careful
Awakened,

/// The size of the window has changed.
Resized(u32, u32),
Expand Down
Loading