From 422b332c1b49ce496efcb45d1cc9ec240aa4a20a Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:00:17 +0100 Subject: [PATCH 01/13] Add a transition macro system --- examples/cursor.rs | 2 +- examples/grabbing.rs | 2 +- src/api/ios/delegate.rs | 2 +- src/api/wayland/context.rs | 2 +- src/api/wayland/window.rs | 2 +- src/api/x11/input.rs | 6 +-- src/api/x11/window.rs | 8 ++-- src/api_transition.rs | 64 ++++++++++++++++++++++++++++++++ src/events.rs | 15 ++++++-- src/lib.rs | 34 ++++++++++++++++- src/platform/android/mod.rs | 4 +- src/platform/ios/mod.rs | 2 + src/platform/linux/mod.rs | 4 +- src/platform/macos/mod.rs | 4 +- src/platform/windows/callback.rs | 44 +++++++++++----------- src/platform/windows/mod.rs | 4 +- src/window.rs | 50 +++---------------------- 17 files changed, 162 insertions(+), 87 deletions(-) create mode 100644 src/api_transition.rs diff --git a/examples/cursor.rs b/examples/cursor.rs index 596b2736..937bda1f 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -1,6 +1,6 @@ extern crate winit; -use winit::{Event, ElementState, MouseCursor}; +use winit::{WindowEvent as Event, ElementState, MouseCursor}; fn main() { let window = winit::WindowBuilder::new().build().unwrap(); diff --git a/examples/grabbing.rs b/examples/grabbing.rs index f2d1a800..45500777 100644 --- a/examples/grabbing.rs +++ b/examples/grabbing.rs @@ -1,6 +1,6 @@ extern crate winit; -use winit::{Event, ElementState}; +use winit::{WindowEvent as Event, ElementState}; fn main() { let window = winit::WindowBuilder::new().build().unwrap(); diff --git a/src/api/ios/delegate.rs b/src/api/ios/delegate.rs index 62cd89d1..71eb2e72 100644 --- a/src/api/ios/delegate.rs +++ b/src/api/ios/delegate.rs @@ -1,7 +1,7 @@ use libc; use std::mem; use super::DelegateState; -use Event; +use WindowEvent as Event; use events::{ Touch, TouchPhase }; use objc::runtime::{ Class, Object, Sel, BOOL, YES }; diff --git a/src/api/wayland/context.rs b/src/api/wayland/context.rs index b3bd437a..debd5e6b 100644 --- a/src/api/wayland/context.rs +++ b/src/api/wayland/context.rs @@ -1,4 +1,4 @@ -use {Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase}; +use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase}; use std::collections::VecDeque; use std::sync::{Arc, Mutex}; diff --git a/src/api/wayland/window.rs b/src/api/wayland/window.rs index 30b7365a..f4977451 100644 --- a/src/api/wayland/window.rs +++ b/src/api/wayland/window.rs @@ -4,7 +4,7 @@ use std::sync::{Arc, Mutex}; use wayland_client::{EventQueue, EventQueueHandle, Init}; use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface}; -use {CreationError, MouseCursor, CursorState, Event, WindowAttributes}; +use {CreationError, MouseCursor, CursorState, WindowEvent as Event, WindowAttributes}; use platform::MonitorId as PlatformMonitorId; use super::WaylandContext; diff --git a/src/api/x11/input.rs b/src/api/x11/input.rs index 86ce8577..7185a449 100644 --- a/src/api/x11/input.rs +++ b/src/api/x11/input.rs @@ -7,7 +7,7 @@ use std::slice::from_raw_parts; use WindowAttributes; -use events::Event; +use events::WindowEvent as Event; use super::{events, ffi}; use super::XConnection; @@ -123,7 +123,7 @@ impl XInputEventHandler { } pub fn translate_key_event(&self, event: &mut ffi::XKeyEvent) -> Vec { - use events::Event::{KeyboardInput, ReceivedCharacter}; + use events::WindowEvent::{KeyboardInput, ReceivedCharacter}; use events::ElementState::{Pressed, Released}; let mut translated_events = Vec::new(); @@ -170,7 +170,7 @@ impl XInputEventHandler { } pub fn translate_event(&mut self, cookie: &ffi::XGenericEventCookie) -> Option { - use events::Event::{Focused, MouseEntered, MouseInput, MouseLeft, MouseMoved, MouseWheel}; + use events::WindowEvent::{Focused, MouseEntered, MouseInput, MouseLeft, MouseMoved, MouseWheel}; use events::ElementState::{Pressed, Released}; use events::MouseButton::{Left, Right, Middle}; use events::MouseScrollDelta::LineDelta; diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs index d4ea33d2..f3640183 100644 --- a/src/api/x11/window.rs +++ b/src/api/x11/window.rs @@ -1,4 +1,4 @@ -use {Event, MouseCursor}; +use {WindowEvent as Event, MouseCursor}; use CreationError; use CreationError::OsError; use libc; @@ -178,7 +178,7 @@ impl<'a> Iterator for PollEventsIterator<'a> { }, ffi::ClientMessage => { - use events::Event::{Closed, Awakened}; + use events::WindowEvent::{Closed, Awakened}; use std::sync::atomic::Ordering::Relaxed; let client_msg: &ffi::XClientMessageEvent = unsafe { mem::transmute(&xev) }; @@ -192,7 +192,7 @@ impl<'a> Iterator for PollEventsIterator<'a> { }, ffi::ConfigureNotify => { - use events::Event::Resized; + use events::WindowEvent::Resized; let cfg_event: &ffi::XConfigureEvent = unsafe { mem::transmute(&xev) }; let (current_width, current_height) = self.window.current_size.get(); if current_width != cfg_event.width || current_height != cfg_event.height { @@ -202,7 +202,7 @@ impl<'a> Iterator for PollEventsIterator<'a> { }, ffi::Expose => { - use events::Event::Refresh; + use events::WindowEvent::Refresh; return Some(Refresh); }, diff --git a/src/api_transition.rs b/src/api_transition.rs new file mode 100644 index 00000000..231ee64a --- /dev/null +++ b/src/api_transition.rs @@ -0,0 +1,64 @@ + +//! 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>>, + } + + impl EventsLoop { + pub fn new() -> EventsLoop { + EventsLoop { + windows: ::std::sync::Mutex::new(vec![]), + } + } + + pub fn poll_events(&self, mut callback: F) + where F: FnMut(::Event) + { + unimplemented!() + } + + pub fn run_forever(&self, mut callback: F) + where F: FnMut(::Event) + { + unimplemented!() + } + } + + pub struct Window2 { + window: ::std::sync::Arc, + } + + 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, window: &::WindowAttributes, + pl_attribs: &PlatformSpecificWindowBuilderAttributes) + -> Result + { + let win = ::std::sync::Arc::new(try!(Window::new(window, pl_attribs))); + events_loop.windows.lock().unwrap().push(win.clone()); + Ok(Window2 { + window: win, + }) + } + + #[inline] + pub fn id(&self) -> usize { + &*self.window as *const Window as usize + } + } + }; +} diff --git a/src/events.rs b/src/events.rs index b6fd7732..520a6c8a 100644 --- a/src/events.rs +++ b/src/events.rs @@ -2,6 +2,17 @@ use std::path::PathBuf; #[derive(Clone, Debug)] pub enum Event { + WindowEvent { + // window_id: , + 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), - /// Touch event has been received Touch(Touch) } diff --git a/src/lib.rs b/src/lib.rs index d4d28fe3..b28ea0e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,11 +64,16 @@ extern crate x11_dl; #[macro_use(wayland_env,declare_handler)] extern crate wayland_client; +use std::sync::Arc; + pub use events::*; pub use window::{WindowProxy, PollEventsIterator, WaitEventsIterator}; pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor}; pub use native_monitor::NativeMonitorId; +#[macro_use] +mod api_transition; + mod api; mod platform; mod events; @@ -94,7 +99,34 @@ pub mod os; /// } /// ``` pub struct Window { - window: platform::Window, + window: platform::Window2, +} + +pub struct EventsLoop { + events_loop: Arc, +} + +impl EventsLoop { + /// Builds a new events loop. + pub fn new() -> EventsLoop { + EventsLoop { + events_loop: Arc::new(platform::EventsLoop::new()), + } + } + + #[inline] + pub fn poll_events(&self, callback: F) + where F: FnMut(Event) + { + self.events_loop.poll_events(callback) + } + + #[inline] + pub fn run_forever(&self, callback: F) + where F: FnMut(Event) + { + self.events_loop.run_forever(callback) + } } /// Object that allows you to build windows. diff --git a/src/platform/android/mod.rs b/src/platform/android/mod.rs index d3973481..aa324d2b 100644 --- a/src/platform/android/mod.rs +++ b/src/platform/android/mod.rs @@ -6,7 +6,7 @@ use libc; use std::ffi::{CString}; use std::sync::mpsc::{Receiver, channel}; use std::os::raw::c_void; -use {CreationError, Event, MouseCursor}; +use {CreationError, WindowEvent as Event, MouseCursor}; use CreationError::OsError; use events::ElementState::{Pressed, Released}; use events::{Touch, TouchPhase}; @@ -17,6 +17,8 @@ use CursorState; use WindowAttributes; use native_monitor::NativeMonitorId; +gen_api_transition!(); + pub struct Window { native_window: *const c_void, event_rx: Receiver, diff --git a/src/platform/ios/mod.rs b/src/platform/ios/mod.rs index 0b1a5509..fcfe51f9 100644 --- a/src/platform/ios/mod.rs +++ b/src/platform/ios/mod.rs @@ -8,6 +8,8 @@ use ContextError; pub use api::ios::*; +gen_api_transition!(); + #[derive(Clone, Default)] pub struct PlatformSpecificHeadlessBuilderAttributes; diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 5001787c..029ba7d7 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use CreationError; use CursorState; -use Event; +use WindowEvent as Event; use MouseCursor; use WindowAttributes; use libc; @@ -17,6 +17,8 @@ use api::x11::XError; use api::x11::XNotSupported; use api::x11::ffi::XVisualInfo; +gen_api_transition!(); + #[derive(Clone, Default)] pub struct PlatformSpecificWindowBuilderAttributes { pub visual_infos: Option, diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index 3aadfe76..49bcca4c 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -1,6 +1,6 @@ #![cfg(target_os = "macos")] -use {CreationError, Event, MouseCursor, CursorState}; +use {CreationError, WindowEvent as Event, MouseCursor, CursorState}; use CreationError::OsError; use libc; @@ -29,6 +29,8 @@ use os::macos::WindowExt; use events::ElementState; use events::{self, MouseButton, TouchPhase}; +gen_api_transition!(); + pub use self::monitor::{MonitorId, get_available_monitors, get_primary_monitor}; mod monitor; diff --git a/src/platform/windows/callback.rs b/src/platform/windows/callback.rs index 00296a6a..de611640 100644 --- a/src/platform/windows/callback.rs +++ b/src/platform/windows/callback.rs @@ -7,7 +7,7 @@ use std::ffi::OsString; use std::os::windows::ffi::OsStringExt; use CursorState; -use Event; +use WindowEvent as Event; use super::event; use super::WindowState; @@ -68,7 +68,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, { match msg { winapi::WM_DESTROY => { - use events::Event::Closed; + use events::WindowEvent::Closed; CONTEXT_STASH.with(|context_stash| { let context_stash = context_stash.borrow(); @@ -93,7 +93,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_SIZE => { - use events::Event::Resized; + use events::WindowEvent::Resized; let w = winapi::LOWORD(lparam as winapi::DWORD) as u32; let h = winapi::HIWORD(lparam as winapi::DWORD) as u32; send_event(window, Resized(w, h)); @@ -101,7 +101,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_MOVE => { - use events::Event::Moved; + use events::WindowEvent::Moved; let x = winapi::LOWORD(lparam as winapi::DWORD) as i32; let y = winapi::HIWORD(lparam as winapi::DWORD) as i32; send_event(window, Moved(x, y)); @@ -110,7 +110,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, winapi::WM_CHAR => { use std::mem; - use events::Event::ReceivedCharacter; + use events::WindowEvent::ReceivedCharacter; let chr: char = mem::transmute(wparam as u32); send_event(window, ReceivedCharacter(chr)); 0 @@ -125,7 +125,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, } winapi::WM_MOUSEMOVE => { - use events::Event::{MouseEntered, MouseMoved}; + use events::WindowEvent::{MouseEntered, MouseMoved}; let mouse_outside_window = CONTEXT_STASH.with(|context_stash| { let mut context_stash = context_stash.borrow_mut(); if let Some(context_stash) = context_stash.as_mut() { @@ -159,7 +159,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_MOUSELEAVE => { - use events::Event::MouseLeft; + use events::WindowEvent::MouseLeft; let mouse_in_window = CONTEXT_STASH.with(|context_stash| { let mut context_stash = context_stash.borrow_mut(); if let Some(context_stash) = context_stash.as_mut() { @@ -180,7 +180,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_MOUSEWHEEL => { - use events::Event::MouseWheel; + use events::WindowEvent::MouseWheel; use events::MouseScrollDelta::LineDelta; use events::TouchPhase; @@ -194,7 +194,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_KEYDOWN | winapi::WM_SYSKEYDOWN => { - use events::Event::KeyboardInput; + use events::WindowEvent::KeyboardInput; use events::ElementState::Pressed; if msg == winapi::WM_SYSKEYDOWN && wparam as i32 == winapi::VK_F4 { user32::DefWindowProcW(window, msg, wparam, lparam) @@ -206,7 +206,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_KEYUP | winapi::WM_SYSKEYUP => { - use events::Event::KeyboardInput; + use events::WindowEvent::KeyboardInput; use events::ElementState::Released; let (scancode, vkey) = event::vkeycode_to_element(wparam, lparam); send_event(window, KeyboardInput(Released, scancode, vkey)); @@ -214,7 +214,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_LBUTTONDOWN => { - use events::Event::MouseInput; + use events::WindowEvent::MouseInput; use events::MouseButton::Left; use events::ElementState::Pressed; send_event(window, MouseInput(Pressed, Left)); @@ -222,7 +222,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_LBUTTONUP => { - use events::Event::MouseInput; + use events::WindowEvent::MouseInput; use events::MouseButton::Left; use events::ElementState::Released; send_event(window, MouseInput(Released, Left)); @@ -230,7 +230,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_RBUTTONDOWN => { - use events::Event::MouseInput; + use events::WindowEvent::MouseInput; use events::MouseButton::Right; use events::ElementState::Pressed; send_event(window, MouseInput(Pressed, Right)); @@ -238,7 +238,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_RBUTTONUP => { - use events::Event::MouseInput; + use events::WindowEvent::MouseInput; use events::MouseButton::Right; use events::ElementState::Released; send_event(window, MouseInput(Released, Right)); @@ -246,7 +246,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_MBUTTONDOWN => { - use events::Event::MouseInput; + use events::WindowEvent::MouseInput; use events::MouseButton::Middle; use events::ElementState::Pressed; send_event(window, MouseInput(Pressed, Middle)); @@ -254,7 +254,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_MBUTTONUP => { - use events::Event::MouseInput; + use events::WindowEvent::MouseInput; use events::MouseButton::Middle; use events::ElementState::Released; send_event(window, MouseInput(Released, Middle)); @@ -262,7 +262,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_XBUTTONDOWN => { - use events::Event::MouseInput; + use events::WindowEvent::MouseInput; use events::MouseButton::Other; use events::ElementState::Pressed; let xbutton = winapi::HIWORD(wparam as winapi::DWORD) as winapi::c_int; // waiting on PR for winapi to add GET_XBUTTON_WPARAM @@ -271,7 +271,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_XBUTTONUP => { - use events::Event::MouseInput; + use events::WindowEvent::MouseInput; use events::MouseButton::Other; use events::ElementState::Released; let xbutton = winapi::HIWORD(wparam as winapi::DWORD) as winapi::c_int; @@ -300,13 +300,13 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_SETFOCUS => { - use events::Event::Focused; + use events::WindowEvent::Focused; send_event(window, Focused(true)); 0 }, winapi::WM_KILLFOCUS => { - use events::Event::Focused; + use events::WindowEvent::Focused; send_event(window, Focused(false)); 0 }, @@ -345,7 +345,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_DROPFILES => { - use events::Event::DroppedFile; + use events::WindowEvent::DroppedFile; let hdrop = wparam as winapi::HDROP; let mut pathbuf: [u16; winapi::MAX_PATH] = mem::uninitialized(); @@ -394,7 +394,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, x if x == *super::WAKEUP_MSG_ID => { - use events::Event::Awakened; + use events::WindowEvent::Awakened; send_event(window, Awakened); 0 }, diff --git a/src/platform/windows/mod.rs b/src/platform/windows/mod.rs index ded27376..fe6ac385 100644 --- a/src/platform/windows/mod.rs +++ b/src/platform/windows/mod.rs @@ -10,11 +10,13 @@ use std::sync::{ Mutex }; use std::sync::mpsc::Receiver; -use {CreationError, Event, MouseCursor}; +use {CreationError, WindowEvent as Event, MouseCursor}; use CursorState; use WindowAttributes; +gen_api_transition!(); + #[derive(Clone, Default)] pub struct PlatformSpecificWindowBuilderAttributes { pub parent: Option, diff --git a/src/window.rs b/src/window.rs index a04575d7..96a5cd80 100644 --- a/src/window.rs +++ b/src/window.rs @@ -2,7 +2,8 @@ use std::collections::vec_deque::IntoIter as VecDequeIter; use CreationError; use CursorState; -use Event; +use WindowEvent as Event; +use EventsLoop; use MouseCursor; use Window; use WindowBuilder; @@ -93,20 +94,11 @@ impl WindowBuilder { self } - /// Provides a resize callback that is called by Mac (and potentially other - /// operating systems) during resize operations. This can be used to repaint - /// during window resizing. - #[inline] - pub fn with_window_resize_callback(mut self, cb: fn(u32, u32)) -> WindowBuilder { - self.window.resize_callback = Some(cb); - self - } - /// Builds the window. /// /// Error should be very rare and only occur in case of permission denied, incompatible system, /// out of memory, etc. - pub fn build(mut self) -> Result { + pub fn build(mut self, events_loop: &EventsLoop) -> Result { // resizing the window to the dimensions of the monitor when fullscreen if self.window.dimensions.is_none() && self.window.monitor.is_some() { self.window.dimensions = Some(self.window.monitor.as_ref().unwrap().get_dimensions()) @@ -118,32 +110,10 @@ impl WindowBuilder { } // building - let mut w = try!(platform::Window::new(&self.window, &self.platform_specific)); - - // a window resize callback was given - if let Some(callback) = self.window.resize_callback { - w.set_window_resize_callback(Some(callback)); - } + let w = try!(platform::Window2::new(events_loop.events_loop.clone(), &self.window, &self.platform_specific)); Ok(Window { window: w }) } - - /// Builds the window. - /// - /// The context is build in a *strict* way. That means that if the backend couldn't give - /// you what you requested, an `Err` will be returned. - #[inline] - pub fn build_strict(self) -> Result { - self.build() - } -} - - -impl Default for Window { - #[inline] - fn default() -> Window { - Window::new().unwrap() - } } impl Window { @@ -154,9 +124,9 @@ impl Window { /// Error should be very rare and only occur in case of permission denied, incompatible system, /// out of memory, etc. #[inline] - pub fn new() -> Result { + pub fn new(events_loop: &EventsLoop) -> Result { let builder = WindowBuilder::new(); - builder.build() + builder.build(events_loop) } /// Modifies the title of the window. @@ -321,14 +291,6 @@ impl Window { } } - /// Sets a resize callback that is called by Mac (and potentially other - /// operating systems) during resize operations. This can be used to repaint - /// during window resizing. - #[inline] - pub fn set_window_resize_callback(&mut self, callback: Option) { - self.window.set_window_resize_callback(callback); - } - /// Modifies the mouse cursor of the window. /// Has no effect on Android. pub fn set_cursor(&self, cursor: MouseCursor) { From 2c4db6b16e06d4b6480d839c73642490172830df Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:01:59 +0100 Subject: [PATCH 02/13] Update window example --- examples/window.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/examples/window.rs b/examples/window.rs index fc908233..5578dab1 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -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, .. } => return, _ => () } - } + }); } From e7d43174e766640b2d30bd5f08f3a1f9d07fab8c Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:05:36 +0100 Subject: [PATCH 03/13] Implement the transition API --- src/api_transition.rs | 16 ++++++++++++++-- src/events.rs | 2 +- src/window.rs | 5 +++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/api_transition.rs b/src/api_transition.rs index 231ee64a..48968376 100644 --- a/src/api_transition.rs +++ b/src/api_transition.rs @@ -21,13 +21,25 @@ macro_rules! gen_api_transition { pub fn poll_events(&self, mut callback: F) where F: FnMut(::Event) { - unimplemented!() + 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(&self, mut callback: F) where F: FnMut(::Event) { - unimplemented!() + // Yeah that's a very bad implementation. + loop { + self.poll_events(|e| callback(e)); + ::std::thread::sleep_ms(5); + } } } diff --git a/src/events.rs b/src/events.rs index 520a6c8a..4e664120 100644 --- a/src/events.rs +++ b/src/events.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; #[derive(Clone, Debug)] pub enum Event { WindowEvent { - // window_id: , + window_id: usize, event: WindowEvent, } } diff --git a/src/window.rs b/src/window.rs index 96a5cd80..49ba7a31 100644 --- a/src/window.rs +++ b/src/window.rs @@ -318,6 +318,11 @@ impl Window { pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { self.window.set_cursor_state(state) } + + #[inline] + pub fn id(&self) -> usize { + self.window.id() + } } /// Represents a thread safe subset of operations that can be called From 0242daa242955d65df446580a6a80aa24e373f3d Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:09:01 +0100 Subject: [PATCH 04/13] Add interrupting the events loop --- examples/window.rs | 2 +- src/api_transition.rs | 11 +++++++++++ src/lib.rs | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/examples/window.rs b/examples/window.rs index 5578dab1..c6d9327a 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -12,7 +12,7 @@ fn main() { println!("{:?}", event); match event { - winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => return, + winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => events_loop.interrupt(), _ => () } }); diff --git a/src/api_transition.rs b/src/api_transition.rs index 48968376..09788296 100644 --- a/src/api_transition.rs +++ b/src/api_transition.rs @@ -9,15 +9,21 @@ macro_rules! gen_api_transition { () => { pub struct EventsLoop { windows: ::std::sync::Mutex>>, + 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(&self, mut callback: F) where F: FnMut(::Event) { @@ -35,10 +41,15 @@ macro_rules! gen_api_transition { pub fn run_forever(&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; + } } } } diff --git a/src/lib.rs b/src/lib.rs index b28ea0e3..0797891f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,6 +127,11 @@ impl EventsLoop { { self.events_loop.run_forever(callback) } + + #[inline] + pub fn interrupt(&self) { + self.events_loop.interrupt() + } } /// Object that allows you to build windows. From d86fdb48d1957d2da89c786334c4a99c6825f659 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:14:23 +0100 Subject: [PATCH 05/13] Remove the window from the events loop on destruction --- src/api_transition.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/api_transition.rs b/src/api_transition.rs index 09788296..4841ada6 100644 --- a/src/api_transition.rs +++ b/src/api_transition.rs @@ -56,6 +56,7 @@ macro_rules! gen_api_transition { pub struct Window2 { window: ::std::sync::Arc, + events_loop: ::std::sync::Weak, } impl ::std::ops::Deref for Window2 { @@ -75,6 +76,7 @@ macro_rules! gen_api_transition { events_loop.windows.lock().unwrap().push(win.clone()); Ok(Window2 { window: win, + events_loop: ::std::sync::Arc::downgrade(&events_loop), }) } @@ -83,5 +85,14 @@ macro_rules! gen_api_transition { &*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 _); + } + } + } }; } From bcb242983bd2f48a2a65bc07fe1f86ebfbc923fb Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:33:54 +0100 Subject: [PATCH 06/13] Add documentation for the new API --- src/lib.rs | 99 ++++++++++++++++++++++++++++++++++++++++++--------- src/window.rs | 2 +- 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0797891f..575a498e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,10 +2,18 @@ //! //! # Building a window //! -//! There are two ways to create a window: +//! Before you can build a window, you first need to build an `EventsLoop`. This is done with the +//! `EventsLoop::new()` function. Example: //! -//! - Calling `Window::new()`. -//! - Calling `let builder = WindowBuilder::new()` then `builder.build()`. +//! ```no_run +//! use winit::EventsLoop; +//! let events_loop = EventsLoop::new(); +//! ``` +//! +//! 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)`. //! //! The first way is the simpliest way and will give you default values for everything. //! @@ -14,11 +22,58 @@ //! //! # Events handling //! -//! Once a window has been created, you can handle the events that it generates. There are two ways -//! to do so: with `poll_events` or with `wait_events`. The former returns an iterator that ends -//! when no event is available, and the latter returns an iterator that blocks and waits for events -//! if none is available. Depending on which kind of program you're writing, you usually choose -//! one or the other. +//! 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 retreived from the `EventsLoop` the window was created +//! with. +//! +//! There are two ways to do so. The first is to call `events_loop.poll_events(...)`, which will +//! retreive 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. +//! +//! ```no_run +//! use winit::Event; +//! use winit::WindowEvent; +//! # use winit::EventsLoop; +//! # let events_loop = EventsLoop::new(); +//! +//! loop { +//! events_loop.poll_events(|event| { +//! match event { +//! Event::WindowEvent { event: WindowEvent::Resized(w, h), .. } => { +//! println!("The window was resized to {}x{}", w, h); +//! }, +//! _ => () +//! } +//! }); +//! } +//! ``` +//! +//! The second way is to call `events_loop.run_forever(...)`. As its name tells, it will run +//! forever unless it is stopped by calling `events_loop.interrupt()`. +//! +//! ```no_run +//! use winit::Event; +//! use winit::WindowEvent; +//! # use winit::EventsLoop; +//! # let events_loop = EventsLoop::new(); +//! +//! events_loop.run_forever(|event| { +//! match event { +//! Event::WindowEvent { event: WindowEvent::Closed, .. } => { +//! println!("The window was closed ; stopping"); +//! events_loop.interrupt(); +//! }, +//! _ => () +//! } +//! }); +//! ``` +//! +//! 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. //! //! # Drawing on the window //! @@ -86,22 +141,29 @@ pub mod os; /// # Example /// /// ```no_run +/// use winit::Event; +/// use winit::EventsLoop; /// use winit::Window; -/// let window = Window::new().unwrap(); +/// use winit::WindowEvent; /// -/// loop { -/// for event in window.wait_events() { -/// match event { -/// // process events here -/// _ => () -/// } +/// let events_loop = EventsLoop::new(); +/// let window = Window::new(&events_loop).unwrap(); +/// +/// events_loop.run_forever(|event| { +/// match event { +/// Event::WindowEvent { event: WindowEvent::Closed, .. } => { +/// events_loop.interrupt(); +/// }, +/// _ => () /// } -/// } +/// }); /// ``` pub struct Window { window: platform::Window2, } +/// Provides a way to retreive events from the windows that were registered to it. +// TODO: document usage in multiple threads pub struct EventsLoop { events_loop: Arc, } @@ -114,6 +176,8 @@ impl EventsLoop { } } + /// Fetches all the events that are pending, calls the callback function for each of them, + /// and returns. #[inline] pub fn poll_events(&self, callback: F) where F: FnMut(Event) @@ -121,6 +185,7 @@ impl EventsLoop { self.events_loop.poll_events(callback) } + /// Runs forever until `interrupt()` is called. Whenever an event happens, calls the callback. #[inline] pub fn run_forever(&self, callback: F) where F: FnMut(Event) @@ -128,6 +193,8 @@ impl EventsLoop { self.events_loop.run_forever(callback) } + /// If we called `run_forever()`, stops the process of waiting for events. + // TODO: what if we're waiting from multiple threads? #[inline] pub fn interrupt(&self) { self.events_loop.interrupt() diff --git a/src/window.rs b/src/window.rs index 49ba7a31..77f0016a 100644 --- a/src/window.rs +++ b/src/window.rs @@ -119,7 +119,7 @@ impl WindowBuilder { impl Window { /// Creates a new OpenGL context, and a Window for platforms where this is appropriate. /// - /// This function is equivalent to `WindowBuilder::new().build()`. + /// This function is equivalent to `WindowBuilder::new().build(events_loop)`. /// /// Error should be very rare and only occur in case of permission denied, incompatible system, /// out of memory, etc. From c3d2289b0c9144e938924cfe6ed3623ad4728f49 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:34:15 +0100 Subject: [PATCH 07/13] Remove resize_callback from WindowsAttributes --- src/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 575a498e..1b5a0610 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -361,10 +361,6 @@ pub struct WindowAttributes { /// [iOS only] Enable multitouch, see [UIView#multipleTouchEnabled] /// (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instp/UIView/multipleTouchEnabled) pub multitouch: bool, - - /// A function called upon resizing, necessary to receive resize events on Mac and possibly - /// other systems. - pub resize_callback: Option, } impl Default for WindowAttributes { @@ -380,7 +376,6 @@ impl Default for WindowAttributes { transparent: false, decorations: true, multitouch: false, - resize_callback: None, } } } From 7da96121a235a15f32d0cb71ff7b37e4d103af3c Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:45:01 +0100 Subject: [PATCH 08/13] Fix examples --- examples/cursor.rs | 18 ++++++++------ examples/fullscreen.rs | 19 ++++++++++----- examples/grabbing.rs | 51 +++++++++++++++++++++++----------------- examples/min_max_size.rs | 14 +++++++---- examples/multiwindow.rs | 49 +++++++++++++++++++------------------- examples/transparent.rs | 22 ++++++++--------- 6 files changed, 97 insertions(+), 76 deletions(-) diff --git a/examples/cursor.rs b/examples/cursor.rs index 937bda1f..bba013a9 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -1,17 +1,19 @@ extern crate winit; -use winit::{WindowEvent as Event, ElementState, MouseCursor}; +use winit::{Event, ElementState, MouseCursor, WindowEvent}; fn main() { - let window = winit::WindowBuilder::new().build().unwrap(); + let events_loop = winit::EventsLoop::new(); + + let window = winit::WindowBuilder::new().build(&events_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::NoneCursor, 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; - for event in window.wait_events() { + events_loop.run_forever(|event| { match event { - Event::KeyboardInput(ElementState::Pressed, _, _) => { + Event::WindowEvent { event: WindowEvent::KeyboardInput(ElementState::Pressed, _, _), .. } => { println!("Setting cursor to \"{:?}\"", cursors[cursor_idx]); window.set_cursor(cursors[cursor_idx]); if cursor_idx < cursors.len() - 1 { @@ -20,8 +22,10 @@ fn main() { cursor_idx = 0; } }, - Event::Closed => break, - _ => (), + Event::WindowEvent { event: WindowEvent::Closed, .. } => { + events_loop.interrupt() + }, + _ => () } - } + }); } diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 2d5d6f6b..53910114 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -22,19 +22,26 @@ fn main() { monitor }; - let window = winit::WindowBuilder::new() + let events_loop = winit::EventsLoop::new(); + + let _window = winit::WindowBuilder::new() .with_title("Hello world!") .with_fullscreen(monitor) - .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::KeyboardInput(_, _, Some(winit::VirtualKeyCode::Escape)) => break, + winit::Event::WindowEvent { event, .. } => { + match event { + winit::WindowEvent::Closed => events_loop.interrupt(), + winit::WindowEvent::KeyboardInput(_, _, Some(winit::VirtualKeyCode::Escape)) => events_loop.interrupt(), + _ => () + } + }, _ => () } - } + }); } diff --git a/examples/grabbing.rs b/examples/grabbing.rs index 45500777..b7e58fc7 100644 --- a/examples/grabbing.rs +++ b/examples/grabbing.rs @@ -1,34 +1,43 @@ extern crate winit; -use winit::{WindowEvent as Event, ElementState}; +use winit::{WindowEvent, ElementState}; fn main() { - let window = winit::WindowBuilder::new().build().unwrap(); + let events_loop = winit::EventsLoop::new(); + + let window = winit::WindowBuilder::new().build(&events_loop).unwrap(); window.set_title("winit - Cursor grabbing test"); let mut grabbed = false; - for event in window.wait_events() { + events_loop.run_forever(|event| { + println!("{:?}", event); + match event { - Event::KeyboardInput(ElementState::Pressed, _, _) => { - if grabbed { - grabbed = false; - window.set_cursor_state(winit::CursorState::Normal) - .ok().expect("could not ungrab mouse cursor"); - } else { - grabbed = true; - window.set_cursor_state(winit::CursorState::Grab) - .ok().expect("could not grab mouse cursor"); + winit::Event::WindowEvent { event, .. } => { + match event { + WindowEvent::KeyboardInput(ElementState::Pressed, _, _) => { + if grabbed { + grabbed = false; + window.set_cursor_state(winit::CursorState::Normal) + .ok().expect("could not ungrab mouse cursor"); + } else { + grabbed = true; + window.set_cursor_state(winit::CursorState::Grab) + .ok().expect("could not grab mouse cursor"); + } + }, + + WindowEvent::Closed => events_loop.interrupt(), + + a @ WindowEvent::MouseMoved(_, _) => { + println!("{:?}", a); + }, + + _ => (), } }, - - Event::Closed => break, - - a @ Event::MouseMoved(_, _) => { - println!("{:?}", a); - }, - - _ => (), + _ => () } - } + }); } diff --git a/examples/min_max_size.rs b/examples/min_max_size.rs index 7b626740..fe22f3e9 100644 --- a/examples/min_max_size.rs +++ b/examples/min_max_size.rs @@ -1,16 +1,20 @@ extern crate winit; fn main() { - let window = winit::WindowBuilder::new() + let events_loop = winit::EventsLoop::new(); + + let _window = winit::WindowBuilder::new() .with_min_dimensions(400, 200) .with_max_dimensions(800, 400) - .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(), _ => () } - } + }); } diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 703b6a37..6c92b69e 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -1,34 +1,33 @@ extern crate winit; -use std::thread; - fn main() { - let window1 = winit::WindowBuilder::new().build().unwrap(); - let window2 = winit::WindowBuilder::new().build().unwrap(); - let window3 = winit::WindowBuilder::new().build().unwrap(); + let events_loop = winit::EventsLoop::new(); - let t1 = thread::spawn(move || { - run(window1); - }); + let window1 = winit::Window::new(&events_loop).unwrap(); + let window2 = winit::Window::new(&events_loop).unwrap(); + let window3 = winit::Window::new(&events_loop).unwrap(); - let t2 = thread::spawn(move || { - run(window2); - }); + let mut num_windows = 3; - let t3 = thread::spawn(move || { - run(window3); - }); - - let _ = t1.join(); - let _ = t2.join(); - let _ = t3.join(); -} - -fn run(window: winit::Window) { - for event in window.wait_events() { + events_loop.run_forever(|event| { match event { - winit::Event::Closed => break, - _ => () + winit::Event::WindowEvent { event: winit::WindowEvent::Closed, window_id } => { + if window_id == window1.id() { + println!("Window 1 has been closed") + } else if window_id == window2.id() { + println!("Window 2 has been closed") + } else if window_id == window3.id() { + println!("Window 3 has been closed"); + } else { + unreachable!() + } + + num_windows -= 1; + if num_windows == 0 { + events_loop.interrupt(); + } + }, + _ => (), } - } + }) } diff --git a/examples/transparent.rs b/examples/transparent.rs index 078ca1f6..9e476dee 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -1,22 +1,20 @@ extern crate winit; -fn resize_callback(width: u32, height: u32) { - println!("Window resized to {}x{}", width, height); -} - fn main() { - let mut window = winit::WindowBuilder::new().with_decorations(false) - .with_transparency(true) - .build().unwrap(); - window.set_title("A fantastic window!"); - window.set_window_resize_callback(Some(resize_callback as fn(u32, u32))); + let events_loop = winit::EventsLoop::new(); - for event in window.wait_events() { + let window = winit::WindowBuilder::new().with_decorations(false) + .with_transparency(true) + .build(&events_loop).unwrap(); + + window.set_title("A fantastic window!"); + + events_loop.run_forever(|event| { println!("{:?}", event); match event { - winit::Event::Closed => break, + winit::Event::WindowEvent { event: winit::WindowEvent::Closed, .. } => events_loop.interrupt(), _ => () } - } + }); } From 148f507272b9814c0e1d06c50be5814c0fb33305 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:56:53 +0100 Subject: [PATCH 09/13] Wayland fix attempt --- src/api/wayland/keyboard.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/wayland/keyboard.rs b/src/api/wayland/keyboard.rs index abc3069c..89186579 100644 --- a/src/api/wayland/keyboard.rs +++ b/src/api/wayland/keyboard.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; use std::sync::{Arc, Mutex}; -use {VirtualKeyCode, ElementState, Event}; +use {VirtualKeyCode, ElementState, WindowEvent as Event}; use super::wayland_kbd; use wayland_client::EventQueueHandle; From 5025db2d592d7d675eb1439d1035ac1cb3818a20 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 15:58:14 +0100 Subject: [PATCH 10/13] Unix fix attempt --- src/api_transition.rs | 2 +- src/os/unix.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/api_transition.rs b/src/api_transition.rs index 4841ada6..2d0af294 100644 --- a/src/api_transition.rs +++ b/src/api_transition.rs @@ -55,7 +55,7 @@ macro_rules! gen_api_transition { } pub struct Window2 { - window: ::std::sync::Arc, + pub window: ::std::sync::Arc, events_loop: ::std::sync::Weak, } diff --git a/src/os/unix.rs b/src/os/unix.rs index 7ed56373..63735515 100644 --- a/src/os/unix.rs +++ b/src/os/unix.rs @@ -86,7 +86,7 @@ pub trait WindowExt { impl WindowExt for Window { #[inline] fn get_xlib_window(&self) -> Option<*mut libc::c_void> { - match self.window { + match *self.window.window { LinuxWindow::X(ref w) => Some(w.get_xlib_window()), _ => None } @@ -94,28 +94,28 @@ impl WindowExt for Window { #[inline] fn get_xlib_display(&self) -> Option<*mut libc::c_void> { - match self.window { + match *self.window.window { LinuxWindow::X(ref w) => Some(w.get_xlib_display()), _ => None } } fn get_xlib_screen_id(&self) -> Option<*mut libc::c_void> { - match self.window { + match *self.window.window { LinuxWindow::X(ref w) => Some(w.get_xlib_screen_id()), _ => None } } fn get_xlib_xconnection(&self) -> Option> { - match self.window { + match *self.window.window { LinuxWindow::X(ref w) => Some(w.get_xlib_xconnection()), _ => None } } fn get_xcb_connection(&self) -> Option<*mut libc::c_void> { - match self.window { + match *self.window.window { LinuxWindow::X(ref w) => Some(w.get_xcb_connection()), _ => None } @@ -136,7 +136,7 @@ impl WindowExt for Window { #[inline] fn get_wayland_client_surface(&self) -> Option<&WlSurface> { - match self.window { + match *self.window.window { LinuxWindow::Wayland(ref w) => Some(w.get_surface()), _ => None } @@ -144,7 +144,7 @@ impl WindowExt for Window { #[inline] fn get_wayland_client_display(&self) -> Option<&WlDisplay> { - match self.window { + match *self.window.window { LinuxWindow::Wayland(ref w) => Some(w.get_display()), _ => None } From b5d8d305fc08228e4d0462ba97cf01361392b6b2 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Jan 2017 16:21:41 +0100 Subject: [PATCH 11/13] Fix unreachable patterns --- examples/fullscreen.rs | 1 - examples/grabbing.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 53910114..bfb179e0 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -41,7 +41,6 @@ fn main() { _ => () } }, - _ => () } }); } diff --git a/examples/grabbing.rs b/examples/grabbing.rs index b7e58fc7..ff3afb2a 100644 --- a/examples/grabbing.rs +++ b/examples/grabbing.rs @@ -37,7 +37,6 @@ fn main() { _ => (), } }, - _ => () } }); } From 9cd0430ec73bc21e775044c9d8cc7554fc99d3a4 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 3 Feb 2017 06:48:58 +0100 Subject: [PATCH 12/13] Remove stuff from Window's API --- src/lib.rs | 1 - src/window.rs | 79 --------------------------------------------------- 2 files changed, 80 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1b5a0610..58bbd948 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,7 +122,6 @@ extern crate wayland_client; use std::sync::Arc; pub use events::*; -pub use window::{WindowProxy, PollEventsIterator, WaitEventsIterator}; pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor}; pub use native_monitor::NativeMonitorId; diff --git a/src/window.rs b/src/window.rs index 77f0016a..7f205062 100644 --- a/src/window.rs +++ b/src/window.rs @@ -246,24 +246,6 @@ impl Window { self.window.set_inner_size(x, y) } - /// Returns an iterator that poll for the next event in the window's events queue. - /// Returns `None` if there is no event in the queue. - /// - /// Contrary to `wait_events`, this function never blocks. - #[inline] - pub fn poll_events(&self) -> PollEventsIterator { - PollEventsIterator(self.window.poll_events()) - } - - /// Returns an iterator that returns events one by one, blocking if necessary until one is - /// available. - /// - /// The iterator never returns `None`. - #[inline] - pub fn wait_events(&self) -> WaitEventsIterator { - WaitEventsIterator(self.window.wait_events()) - } - /// DEPRECATED. Gets the native platform specific display for this window. /// This is typically only required when integrating with /// other libraries that need this information. @@ -282,15 +264,6 @@ impl Window { self.window.platform_window() } - /// Create a window proxy for this window, that can be freely - /// passed to different threads. - #[inline] - pub fn create_window_proxy(&self) -> WindowProxy { - WindowProxy { - proxy: self.window.create_window_proxy() - } - } - /// Modifies the mouse cursor of the window. /// Has no effect on Android. pub fn set_cursor(&self, cursor: MouseCursor) { @@ -325,58 +298,6 @@ impl Window { } } -/// Represents a thread safe subset of operations that can be called -/// on a window. This structure can be safely cloned and sent between -/// threads. -#[derive(Clone)] -pub struct WindowProxy { - proxy: platform::WindowProxy, -} - -impl WindowProxy { - /// Triggers a blocked event loop to wake up. This is - /// typically called when another thread wants to wake - /// up the blocked rendering thread to cause a refresh. - #[inline] - pub fn wakeup_event_loop(&self) { - self.proxy.wakeup_event_loop(); - } -} - -/// An iterator for the `poll_events` function. -pub struct PollEventsIterator<'a>(platform::PollEventsIterator<'a>); - -impl<'a> Iterator for PollEventsIterator<'a> { - type Item = Event; - - #[inline] - fn next(&mut self) -> Option { - self.0.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } -} - -/// An iterator for the `wait_events` function. -pub struct WaitEventsIterator<'a>(platform::WaitEventsIterator<'a>); - -impl<'a> Iterator for WaitEventsIterator<'a> { - type Item = Event; - - #[inline] - fn next(&mut self) -> Option { - self.0.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } -} - /// An iterator for the list of available monitors. // Implementation note: we retreive the list once, then serve each element by one by one. // This may change in the future. From b988c174fe1a2b466f3735a027943a25b892628e Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 3 Feb 2017 09:13:11 +0100 Subject: [PATCH 13/13] Add WindowId type --- src/api_transition.rs | 9 ++++++--- src/events.rs | 3 ++- src/lib.rs | 9 +++++++++ src/window.rs | 5 +++-- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/api_transition.rs b/src/api_transition.rs index 2d0af294..464a7f05 100644 --- a/src/api_transition.rs +++ b/src/api_transition.rs @@ -31,7 +31,7 @@ macro_rules! gen_api_transition { for window in windows.iter() { for event in window.poll_events() { callback(::Event::WindowEvent { - window_id: &**window as *const Window as usize, + window_id: ::WindowId(WindowId(&**window as *const Window as usize)), event: event, }) } @@ -54,6 +54,9 @@ macro_rules! gen_api_transition { } } + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct WindowId(usize); + pub struct Window2 { pub window: ::std::sync::Arc, events_loop: ::std::sync::Weak, @@ -81,8 +84,8 @@ macro_rules! gen_api_transition { } #[inline] - pub fn id(&self) -> usize { - &*self.window as *const Window as usize + pub fn id(&self) -> WindowId { + WindowId(&*self.window as *const Window as usize) } } diff --git a/src/events.rs b/src/events.rs index 4e664120..7288ea9e 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,9 +1,10 @@ use std::path::PathBuf; +use WindowId; #[derive(Clone, Debug)] pub enum Event { WindowEvent { - window_id: usize, + window_id: WindowId, event: WindowEvent, } } diff --git a/src/lib.rs b/src/lib.rs index 58bbd948..d0ba5911 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -161,6 +161,15 @@ pub struct Window { window: platform::Window2, } +/// 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); + /// Provides a way to retreive events from the windows that were registered to it. // TODO: document usage in multiple threads pub struct EventsLoop { diff --git a/src/window.rs b/src/window.rs index 7f205062..ae9c8d38 100644 --- a/src/window.rs +++ b/src/window.rs @@ -7,6 +7,7 @@ use EventsLoop; use MouseCursor; use Window; use WindowBuilder; +use WindowId; use native_monitor::NativeMonitorId; use libc; @@ -293,8 +294,8 @@ impl Window { } #[inline] - pub fn id(&self) -> usize { - self.window.id() + pub fn id(&self) -> WindowId { + WindowId(self.window.id()) } }