WIP - Make poll_events and run_forever take &mut self
This removes the need for the EventsLoop::interrupt method by inroducing a ControlFlow type. This new type is to be returned by the user's callback and indicates whether the `EventsLoop` should continue waiting for events or break from the loop. Only the wayland, x11 and api_transition backends have been updated so far, and only the wayland backend has actually been tested.
This commit is contained in:
parent
38856b1c60
commit
f2dd2f0752
7 changed files with 103 additions and 95 deletions
|
|
@ -7,7 +7,8 @@ pub use self::xdisplay::{XConnection, XNotSupported, XError};
|
|||
pub mod ffi;
|
||||
|
||||
use platform::PlatformSpecificWindowBuilderAttributes;
|
||||
use {CreationError, Event, EventsLoopClosed, WindowEvent, DeviceEvent, AxisId, ButtonId, KeyboardInput};
|
||||
use {CreationError, Event, EventsLoopClosed, WindowEvent, DeviceEvent, AxisId, ButtonId,
|
||||
KeyboardInput, ControlFlow};
|
||||
|
||||
use std::{mem, ptr, slice};
|
||||
use std::sync::{Arc, Mutex, Weak};
|
||||
|
|
@ -30,10 +31,9 @@ mod xdisplay;
|
|||
// the one generated by the macro.
|
||||
|
||||
pub struct EventsLoop {
|
||||
interrupted: AtomicBool,
|
||||
display: Arc<XConnection>,
|
||||
wm_delete_window: ffi::Atom,
|
||||
windows: Mutex<HashMap<WindowId, WindowData>>,
|
||||
windows: Arc<Mutex<HashMap<WindowId, WindowData>>>,
|
||||
devices: Mutex<HashMap<DeviceId, Device>>,
|
||||
xi2ext: XExtension,
|
||||
pending_wakeup: Arc<AtomicBool>,
|
||||
|
|
@ -81,11 +81,10 @@ impl EventsLoop {
|
|||
let root = unsafe { (display.xlib.XDefaultRootWindow)(display.display) };
|
||||
|
||||
let result = EventsLoop {
|
||||
interrupted: AtomicBool::new(false),
|
||||
pending_wakeup: Arc::new(AtomicBool::new(false)),
|
||||
display: display,
|
||||
wm_delete_window: wm_delete_window,
|
||||
windows: Mutex::new(HashMap::new()),
|
||||
windows: Arc::new(Mutex::new(HashMap::new())),
|
||||
devices: Mutex::new(HashMap::new()),
|
||||
xi2ext: xi2ext,
|
||||
root: root,
|
||||
|
|
@ -118,14 +117,9 @@ impl EventsLoop {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn interrupt(&self) {
|
||||
self.interrupted.store(true, atomic::Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn poll_events<F>(&self, mut callback: F)
|
||||
where F: FnMut(Event)
|
||||
{
|
||||
self.interrupted.store(false, atomic::Ordering::Relaxed);
|
||||
let xlib = &self.display.xlib;
|
||||
|
||||
let mut xev = unsafe { mem::uninitialized() };
|
||||
|
|
@ -141,16 +135,12 @@ impl EventsLoop {
|
|||
(xlib.XNextEvent)(self.display.display, &mut xev);
|
||||
}
|
||||
self.process_event(&mut xev, &mut callback);
|
||||
if self.interrupted.load(atomic::Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, atomic::Ordering::Relaxed);
|
||||
self.pending_wakeup.store(false, atomic::Ordering::Relaxed);
|
||||
|
||||
let xlib = &self.display.xlib;
|
||||
|
|
@ -160,13 +150,25 @@ impl EventsLoop {
|
|||
loop {
|
||||
unsafe { (xlib.XNextEvent)(self.display.display, &mut xev) }; // Blocks as necessary
|
||||
|
||||
let mut control_flow = ControlFlow::Continue;
|
||||
|
||||
if self.pending_wakeup.load(atomic::Ordering::Relaxed) {
|
||||
self.pending_wakeup.store(false, atomic::Ordering::Relaxed);
|
||||
callback(Event::Awakened);
|
||||
control_flow = callback(Event::Awakened);
|
||||
}
|
||||
|
||||
self.process_event(&mut xev, &mut callback);
|
||||
if self.interrupted.load(atomic::Ordering::Relaxed) {
|
||||
// Track whether or not `Complete` was returned when processing the event.
|
||||
{
|
||||
let mut cb = |event| {
|
||||
if let ControlFlow::Complete = callback(event) {
|
||||
control_flow = ControlFlow::Complete;
|
||||
}
|
||||
};
|
||||
|
||||
self.process_event(&mut xev, &mut cb);
|
||||
}
|
||||
|
||||
if let ControlFlow::Complete = control_flow {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -178,7 +180,7 @@ impl EventsLoop {
|
|||
device.name.clone()
|
||||
}
|
||||
|
||||
fn process_event<F>(&self, xev: &mut ffi::XEvent, callback: &mut F)
|
||||
fn process_event<F>(&self, xev: &mut ffi::XEvent, mut callback: F)
|
||||
where F: FnMut(Event)
|
||||
{
|
||||
let xlib = &self.display.xlib;
|
||||
|
|
@ -312,7 +314,11 @@ impl EventsLoop {
|
|||
};
|
||||
|
||||
for chr in written.chars() {
|
||||
callback(Event::WindowEvent { window_id: wid, event: WindowEvent::ReceivedCharacter(chr) })
|
||||
let event = Event::WindowEvent {
|
||||
window_id: wid,
|
||||
event: WindowEvent::ReceivedCharacter(chr),
|
||||
};
|
||||
callback(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -603,7 +609,8 @@ pub struct DeviceId(c_int);
|
|||
|
||||
pub struct Window2 {
|
||||
pub window: Arc<Window>,
|
||||
events_loop: Weak<::platform::EventsLoop>,
|
||||
display: Weak<XConnection>,
|
||||
windows: Weak<Mutex<HashMap<WindowId, WindowData>>>,
|
||||
}
|
||||
|
||||
impl ::std::ops::Deref for Window2 {
|
||||
|
|
@ -620,9 +627,10 @@ lazy_static! { // TODO: use a static mutex when that's possible, and put me
|
|||
}
|
||||
|
||||
impl Window2 {
|
||||
pub fn new(events_loop: Arc<::platform::EventsLoop>,
|
||||
window: &::WindowAttributes, pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
||||
-> Result<Window2, CreationError>
|
||||
pub fn new(events_loop: &::platform::EventsLoop,
|
||||
window: &::WindowAttributes,
|
||||
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
||||
-> Result<Self, CreationError>
|
||||
{
|
||||
let x_events_loop = if let ::platform::EventsLoop::X(ref e) = *events_loop { e } else { unreachable!() };
|
||||
let win = ::std::sync::Arc::new(try!(Window::new(&x_events_loop, window, pl_attribs)));
|
||||
|
|
@ -662,7 +670,8 @@ impl Window2 {
|
|||
|
||||
Ok(Window2 {
|
||||
window: win,
|
||||
events_loop: Arc::downgrade(&events_loop),
|
||||
windows: Arc::downgrade(&x_events_loop.windows),
|
||||
display: Arc::downgrade(&x_events_loop.display),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -674,17 +683,13 @@ impl Window2 {
|
|||
|
||||
impl Drop for Window2 {
|
||||
fn drop(&mut self) {
|
||||
if let Some(ev) = self.events_loop.upgrade() {
|
||||
if let ::platform::EventsLoop::X(ref ev) = *ev {
|
||||
let mut windows = ev.windows.lock().unwrap();
|
||||
|
||||
|
||||
let w = windows.remove(&self.window.id()).unwrap();
|
||||
let _lock = GLOBAL_XOPENIM_LOCK.lock().unwrap();
|
||||
unsafe {
|
||||
(ev.display.xlib.XDestroyIC)(w.ic);
|
||||
(ev.display.xlib.XCloseIM)(w.im);
|
||||
}
|
||||
if let (Some(windows), Some(display)) = (self.windows.upgrade(), self.display.upgrade()) {
|
||||
let mut windows = windows.lock().unwrap();
|
||||
let w = windows.remove(&self.window.id()).unwrap();
|
||||
let _lock = GLOBAL_XOPENIM_LOCK.lock().unwrap();
|
||||
unsafe {
|
||||
(display.xlib.XDestroyIC)(w.ic);
|
||||
(display.xlib.XCloseIM)(w.im);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue