-
Notifications
You must be signed in to change notification settings - Fork 947
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
Switch to a futures-compatible API #126
Changes from 6 commits
422b332
2c4db6b
e7d4317
0242daa
d86fdb4
bcb2429
c3d2289
7da9612
148f507
5025db2
b5d8d30
9cd0430
b988c17
885b927
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,19 @@ | ||
extern crate winit; | ||
|
||
fn resize_callback(width: u32, height: u32) { | ||
println!("Window resized to {}x{}", width, height); | ||
} | ||
|
||
fn main() { | ||
let events_loop = winit::EventsLoop::new(); | ||
|
||
let window = winit::WindowBuilder::new() | ||
.with_title("A fantastic window!") | ||
.with_window_resize_callback(resize_callback) | ||
.build() | ||
.build(&events_loop) | ||
.unwrap(); | ||
|
||
for event in window.wait_events() { | ||
events_loop.run_forever(|event| { | ||
println!("{:?}", event); | ||
|
||
match event { | ||
winit::Event::Closed => break, | ||
winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => events_loop.interrupt(), | ||
_ => () | ||
} | ||
} | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
|
||
//! This temporary module generates types that wrap around the old API (winit v5 and below) and | ||
//! expose the new API (winit v6 and above). | ||
//! | ||
//! This is temporary so that existing backends can smoothly transition. After all implementations | ||
//! have finished transitionning, this module should disappear. | ||
|
||
macro_rules! gen_api_transition { | ||
() => { | ||
pub struct EventsLoop { | ||
windows: ::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>, | ||
interrupted: ::std::sync::atomic::AtomicBool, | ||
} | ||
|
||
impl EventsLoop { | ||
pub fn new() -> EventsLoop { | ||
EventsLoop { | ||
windows: ::std::sync::Mutex::new(vec![]), | ||
interrupted: ::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) | ||
where F: FnMut(::Event) | ||
{ | ||
let mut windows = self.windows.lock().unwrap(); | ||
for window in windows.iter() { | ||
for event in window.poll_events() { | ||
callback(::Event::WindowEvent { | ||
window_id: &**window as *const Window as usize, | ||
event: event, | ||
}) | ||
} | ||
} | ||
} | ||
|
||
pub fn run_forever<F>(&self, mut callback: F) | ||
where F: FnMut(::Event) | ||
{ | ||
self.interrupted.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) { | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub struct Window2 { | ||
window: ::std::sync::Arc<Window>, | ||
events_loop: ::std::sync::Weak<EventsLoop>, | ||
} | ||
|
||
impl ::std::ops::Deref for Window2 { | ||
type Target = Window; | ||
#[inline] | ||
fn deref(&self) -> &Window { | ||
&*self.window | ||
} | ||
} | ||
|
||
impl Window2 { | ||
pub fn new(events_loop: ::std::sync::Arc<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), | ||
}) | ||
} | ||
|
||
#[inline] | ||
pub fn id(&self) -> usize { | ||
&*self.window as *const Window as usize | ||
} | ||
} | ||
|
||
impl Drop for Window2 { | ||
fn drop(&mut self) { | ||
if let Some(ev) = self.events_loop.upgrade() { | ||
let mut windows = ev.windows.lock().unwrap(); | ||
windows.retain(|w| &**w as *const Window != &*self.window as *const _); | ||
} | ||
} | ||
} | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,17 @@ use std::path::PathBuf; | |
|
||
#[derive(Clone, Debug)] | ||
pub enum Event { | ||
WindowEvent { | ||
window_id: usize, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps this should be it's own |
||
event: WindowEvent, | ||
} | ||
} | ||
|
||
#[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), | ||
|
||
|
@@ -49,9 +60,6 @@ pub enum Event { | |
/// is being pressed) and stage (integer representing the click level). | ||
TouchpadPressure(f32, i64), | ||
|
||
/// The event loop was woken up by another thread. | ||
Awakened, | ||
|
||
/// The window needs to be redrawn. | ||
Refresh, | ||
|
||
|
@@ -60,7 +68,6 @@ pub enum Event { | |
/// The parameter is true if app was suspended, and false if it has been resumed. | ||
Suspended(bool), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we move this variant to the I'm wondering if also the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes, the problem with As for the keyboard events, the windows compositor usually sends the event only to the currently focused window, so sending it to a specific window is how it's designed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I guess it's probably OK to leave for a follow-up PR then. You could do it on another branch and wait for contributors from each backend to do PRs to that branch if you can't do each backend yourself.
Now that you mention it, this also seems to be the way macOS windows work too. |
||
|
||
|
||
/// Touch event has been received | ||
Touch(Touch) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This variant could probably just be
Window
as we already know that it is anEvent
via the enum name, e.g.Event::Window
. Otherwise we end up repeating "Event" twice.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A window is not an event though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already know that it is an
Event
though, it is the name of the type.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big deal, just a suggestion.