mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 21:31:29 +11:00
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
|
@ -12,8 +12,10 @@ fn main() {
|
||||||
println!("{:?}", event);
|
println!("{:?}", event);
|
||||||
|
|
||||||
match 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,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
macro_rules! gen_api_transition {
|
macro_rules! gen_api_transition {
|
||||||
() => {
|
() => {
|
||||||
pub struct EventsLoop {
|
pub struct EventsLoop {
|
||||||
windows: ::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>,
|
windows: ::std::sync::Arc<::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>>,
|
||||||
interrupted: ::std::sync::atomic::AtomicBool,
|
interrupted: ::std::sync::atomic::AtomicBool,
|
||||||
awakened: ::std::sync::Arc<::std::sync::atomic::AtomicBool>,
|
awakened: ::std::sync::Arc<::std::sync::atomic::AtomicBool>,
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ macro_rules! gen_api_transition {
|
||||||
impl EventsLoop {
|
impl EventsLoop {
|
||||||
pub fn new() -> EventsLoop {
|
pub fn new() -> EventsLoop {
|
||||||
EventsLoop {
|
EventsLoop {
|
||||||
windows: ::std::sync::Mutex::new(vec![]),
|
windows: ::std::sync::Arc::new(::std::sync::Mutex::new(vec![])),
|
||||||
interrupted: ::std::sync::atomic::AtomicBool::new(false),
|
interrupted: ::std::sync::atomic::AtomicBool::new(false),
|
||||||
awakened: ::std::sync::Arc::new(::std::sync::atomic::AtomicBool::new(false)),
|
awakened: ::std::sync::Arc::new(::std::sync::atomic::AtomicBool::new(false)),
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ macro_rules! gen_api_transition {
|
||||||
|
|
||||||
pub struct Window2 {
|
pub struct Window2 {
|
||||||
pub window: ::std::sync::Arc<Window>,
|
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 {
|
impl ::std::ops::Deref for Window2 {
|
||||||
|
@ -104,7 +104,8 @@ macro_rules! gen_api_transition {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window2 {
|
impl Window2 {
|
||||||
pub fn new(events_loop: ::std::sync::Arc<EventsLoop>, window: &::WindowAttributes,
|
pub fn new(events_loop: &EventsLoop,
|
||||||
|
window: &::WindowAttributes,
|
||||||
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
||||||
-> Result<Window2, CreationError>
|
-> Result<Window2, CreationError>
|
||||||
{
|
{
|
||||||
|
@ -112,7 +113,7 @@ macro_rules! gen_api_transition {
|
||||||
events_loop.windows.lock().unwrap().push(win.clone());
|
events_loop.windows.lock().unwrap().push(win.clone());
|
||||||
Ok(Window2 {
|
Ok(Window2 {
|
||||||
window: win,
|
window: win,
|
||||||
events_loop: ::std::sync::Arc::downgrade(&events_loop),
|
events_loop: ::std::sync::Arc::downgrade(&events_loop.windows),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +125,8 @@ macro_rules! gen_api_transition {
|
||||||
|
|
||||||
impl Drop for Window2 {
|
impl Drop for Window2 {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(ev) = self.events_loop.upgrade() {
|
if let Some(windows) = self.windows.upgrade() {
|
||||||
let mut windows = ev.windows.lock().unwrap();
|
let mut windows = windows.lock().unwrap();
|
||||||
windows.retain(|w| &**w as *const Window != &*self.window as *const _);
|
windows.retain(|w| &**w as *const Window != &*self.window as *const _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
29
src/lib.rs
29
src/lib.rs
|
@ -119,8 +119,6 @@ extern crate x11_dl;
|
||||||
#[macro_use(wayland_env,declare_handler)]
|
#[macro_use(wayland_env,declare_handler)]
|
||||||
extern crate wayland_client;
|
extern crate wayland_client;
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub use events::*;
|
pub use events::*;
|
||||||
pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor};
|
pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor};
|
||||||
pub use native_monitor::NativeMonitorId;
|
pub use native_monitor::NativeMonitorId;
|
||||||
|
@ -189,21 +187,32 @@ pub struct ButtonId(u32);
|
||||||
///
|
///
|
||||||
/// To wake up an `EventsLoop` from a another thread, see the `EventsLoopProxy` docs.
|
/// To wake up an `EventsLoop` from a another thread, see the `EventsLoopProxy` docs.
|
||||||
pub struct EventsLoop {
|
pub struct EventsLoop {
|
||||||
events_loop: Arc<platform::EventsLoop>,
|
events_loop: platform::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)]
|
||||||
|
pub enum ControlFlow {
|
||||||
|
/// Continue looping and waiting for events.
|
||||||
|
Continue,
|
||||||
|
/// Exit from the event loop.
|
||||||
|
Complete,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventsLoop {
|
impl EventsLoop {
|
||||||
/// Builds a new events loop.
|
/// Builds a new events loop.
|
||||||
pub fn new() -> EventsLoop {
|
pub fn new() -> EventsLoop {
|
||||||
EventsLoop {
|
EventsLoop {
|
||||||
events_loop: Arc::new(platform::EventsLoop::new()),
|
events_loop: platform::EventsLoop::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches all the events that are pending, calls the callback function for each of them,
|
/// Fetches all the events that are pending, calls the callback function for each of them,
|
||||||
/// and returns.
|
/// and returns.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn poll_events<F>(&self, callback: F)
|
pub fn poll_events<F>(&mut self, callback: F)
|
||||||
where F: FnMut(Event)
|
where F: FnMut(Event)
|
||||||
{
|
{
|
||||||
self.events_loop.poll_events(callback)
|
self.events_loop.poll_events(callback)
|
||||||
|
@ -211,18 +220,12 @@ impl EventsLoop {
|
||||||
|
|
||||||
/// Runs forever until `interrupt()` is called. Whenever an event happens, calls the callback.
|
/// Runs forever until `interrupt()` is called. Whenever an event happens, calls the callback.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn run_forever<F>(&self, callback: F)
|
pub fn run_forever<F>(&mut self, callback: F)
|
||||||
where F: FnMut(Event)
|
where F: FnMut(Event) -> ControlFlow
|
||||||
{
|
{
|
||||||
self.events_loop.run_forever(callback)
|
self.events_loop.run_forever(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If we called `run_forever()`, stops the process of waiting for events.
|
|
||||||
#[inline]
|
|
||||||
pub fn interrupt(&self) {
|
|
||||||
self.events_loop.interrupt()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an `EventsLoopProxy` that can be used to wake up the `EventsLoop` from another
|
/// Creates an `EventsLoopProxy` that can be used to wake up the `EventsLoop` from another
|
||||||
/// thread.
|
/// thread.
|
||||||
pub fn create_proxy(&self) -> EventsLoopProxy {
|
pub fn create_proxy(&self) -> EventsLoopProxy {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use {CreationError, CursorState, EventsLoopClosed, MouseCursor};
|
use {CreationError, CursorState, EventsLoopClosed, MouseCursor, ControlFlow};
|
||||||
use libc;
|
use libc;
|
||||||
|
|
||||||
use self::x11::XConnection;
|
use self::x11::XConnection;
|
||||||
|
@ -129,9 +129,10 @@ impl MonitorId {
|
||||||
|
|
||||||
impl Window2 {
|
impl Window2 {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(events_loop: ::std::sync::Arc<EventsLoop>, window: &::WindowAttributes,
|
pub fn new(events_loop: &EventsLoop,
|
||||||
|
window: &::WindowAttributes,
|
||||||
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
||||||
-> Result<Window2, CreationError>
|
-> Result<Self, CreationError>
|
||||||
{
|
{
|
||||||
match *UNIX_BACKEND {
|
match *UNIX_BACKEND {
|
||||||
UnixBackend::Wayland(ref ctxt) => {
|
UnixBackend::Wayland(ref ctxt) => {
|
||||||
|
@ -336,28 +337,21 @@ impl EventsLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interrupt(&self) {
|
pub fn poll_events<F>(&mut self, callback: F)
|
||||||
match *self {
|
|
||||||
EventsLoop::Wayland(ref evlp) => evlp.interrupt(),
|
|
||||||
EventsLoop::X(ref evlp) => evlp.interrupt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn poll_events<F>(&self, callback: F)
|
|
||||||
where F: FnMut(::Event)
|
where F: FnMut(::Event)
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
EventsLoop::Wayland(ref evlp) => evlp.poll_events(callback),
|
EventsLoop::Wayland(ref mut evlp) => evlp.poll_events(callback),
|
||||||
EventsLoop::X(ref evlp) => evlp.poll_events(callback)
|
EventsLoop::X(ref mut evlp) => evlp.poll_events(callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_forever<F>(&self, callback: F)
|
pub fn run_forever<F>(&mut self, callback: F)
|
||||||
where F: FnMut(::Event)
|
where F: FnMut(::Event) -> ControlFlow
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
EventsLoop::Wayland(ref evlp) => evlp.run_forever(callback),
|
EventsLoop::Wayland(ref mut evlp) => evlp.run_forever(callback),
|
||||||
EventsLoop::X(ref evlp) => evlp.run_forever(callback)
|
EventsLoop::X(ref mut evlp) => evlp.run_forever(callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState, KeyboardInput, EventsLoopClosed};
|
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState,
|
||||||
|
KeyboardInput, EventsLoopClosed, ControlFlow};
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex, Weak};
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
use std::sync::atomic::{self, AtomicBool};
|
use std::sync::atomic::{self, AtomicBool};
|
||||||
|
@ -53,7 +54,9 @@ impl EventsLoopSink {
|
||||||
::std::mem::replace(&mut self.callback, cb)
|
::std::mem::replace(&mut self.callback, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_callback<F: FnOnce(&mut FnMut(::Event))>(&mut self, f: F) {
|
fn with_callback<F>(&mut self, f: F)
|
||||||
|
where F: FnOnce(&mut FnMut(::Event)),
|
||||||
|
{
|
||||||
f(&mut *self.callback)
|
f(&mut *self.callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,8 +70,6 @@ pub struct EventsLoop {
|
||||||
decorated_ids: Mutex<Vec<(usize, Arc<wl_surface::WlSurface>)>>,
|
decorated_ids: Mutex<Vec<(usize, Arc<wl_surface::WlSurface>)>>,
|
||||||
// our sink, receiver of callbacks, shared with some handlers
|
// our sink, receiver of callbacks, shared with some handlers
|
||||||
sink: Arc<Mutex<EventsLoopSink>>,
|
sink: Arc<Mutex<EventsLoopSink>>,
|
||||||
// trigger interruption of the run
|
|
||||||
interrupted: AtomicBool,
|
|
||||||
// trigger cleanup of the dead surfaces
|
// trigger cleanup of the dead surfaces
|
||||||
cleanup_needed: Arc<AtomicBool>,
|
cleanup_needed: Arc<AtomicBool>,
|
||||||
// Whether or not there is a pending `Awakened` event to be emitted.
|
// Whether or not there is a pending `Awakened` event to be emitted.
|
||||||
|
@ -115,7 +116,6 @@ impl EventsLoop {
|
||||||
evq: Arc::new(Mutex::new(evq)),
|
evq: Arc::new(Mutex::new(evq)),
|
||||||
decorated_ids: Mutex::new(Vec::new()),
|
decorated_ids: Mutex::new(Vec::new()),
|
||||||
sink: sink,
|
sink: sink,
|
||||||
interrupted: AtomicBool::new(false),
|
|
||||||
pending_wakeup: Arc::new(AtomicBool::new(false)),
|
pending_wakeup: Arc::new(AtomicBool::new(false)),
|
||||||
cleanup_needed: Arc::new(AtomicBool::new(false)),
|
cleanup_needed: Arc::new(AtomicBool::new(false)),
|
||||||
hid: hid
|
hid: hid
|
||||||
|
@ -158,10 +158,6 @@ impl EventsLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interrupt(&self) {
|
|
||||||
self.interrupted.store(true, atomic::Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prune_dead_windows(&self) {
|
fn prune_dead_windows(&self) {
|
||||||
self.decorated_ids.lock().unwrap().retain(|&(_, ref w)| w.is_alive());
|
self.decorated_ids.lock().unwrap().retain(|&(_, ref w)| w.is_alive());
|
||||||
let mut evq_guard = self.evq.lock().unwrap();
|
let mut evq_guard = self.evq.lock().unwrap();
|
||||||
|
@ -175,7 +171,7 @@ impl EventsLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_events<F>(&self, callback: F)
|
pub fn poll_events<F>(&mut self, callback: F)
|
||||||
where F: FnMut(::Event)
|
where F: FnMut(::Event)
|
||||||
{
|
{
|
||||||
// send pending requests to the server...
|
// send pending requests to the server...
|
||||||
|
@ -219,38 +215,45 @@ impl EventsLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_forever<F>(&self, callback: F)
|
pub fn run_forever<F>(&mut self, mut callback: F)
|
||||||
where F: FnMut(::Event)
|
where F: FnMut(::Event) -> ControlFlow,
|
||||||
{
|
{
|
||||||
self.interrupted.store(false, atomic::Ordering::Relaxed);
|
|
||||||
|
|
||||||
// send pending requests to the server...
|
// send pending requests to the server...
|
||||||
self.ctxt.flush();
|
self.ctxt.flush();
|
||||||
|
|
||||||
// first of all, get exclusive access to this event queue
|
// first of all, get exclusive access to this event queue
|
||||||
let mut evq_guard = self.evq.lock().unwrap();
|
let mut evq_guard = self.evq.lock().unwrap();
|
||||||
|
|
||||||
|
// Check for control flow by wrapping the callback.
|
||||||
|
let control_flow = ::std::cell::Cell::new(ControlFlow::Continue);
|
||||||
|
let callback = |event| if let ControlFlow::Complete = callback(event) {
|
||||||
|
control_flow.set(ControlFlow::Complete);
|
||||||
|
};
|
||||||
|
|
||||||
// set the callback into the sink
|
// set the callback into the sink
|
||||||
// we extend the lifetime of the closure to 'static to be able to put it in
|
// we extend the lifetime of the closure to 'static to be able to put it in
|
||||||
// the sink, but we'll explicitly drop it at the end of this function, so it's fine
|
// the sink, but we'll explicitly drop it at the end of this function, so it's fine
|
||||||
let static_cb = unsafe { ::std::mem::transmute(Box::new(callback) as Box<FnMut(_)>) };
|
let static_cb = unsafe { ::std::mem::transmute(Box::new(callback) as Box<FnMut(_)>) };
|
||||||
let old_cb = unsafe { self.sink.lock().unwrap().set_callback(static_cb) };
|
let old_cb = unsafe { self.sink.lock().unwrap().set_callback(static_cb) };
|
||||||
|
|
||||||
while !self.interrupted.load(atomic::Ordering::Relaxed) {
|
loop {
|
||||||
self.ctxt.dispatch();
|
self.ctxt.dispatch();
|
||||||
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
||||||
|
|
||||||
self.emit_pending_wakeup();
|
self.emit_pending_wakeup();
|
||||||
|
|
||||||
let ids_guard = self.decorated_ids.lock().unwrap();
|
let ids_guard = self.decorated_ids.lock().unwrap();
|
||||||
self.sink.lock().unwrap().with_callback(
|
self.sink.lock().unwrap()
|
||||||
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
|
.with_callback(|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb));
|
||||||
);
|
|
||||||
self.ctxt.flush();
|
self.ctxt.flush();
|
||||||
|
|
||||||
if self.cleanup_needed.swap(false, atomic::Ordering::Relaxed) {
|
if self.cleanup_needed.swap(false, atomic::Ordering::Relaxed) {
|
||||||
self.prune_dead_windows()
|
self.prune_dead_windows()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let ControlFlow::Complete = control_flow.get() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace the old noop callback
|
// replace the old noop callback
|
||||||
|
|
|
@ -7,7 +7,8 @@ pub use self::xdisplay::{XConnection, XNotSupported, XError};
|
||||||
pub mod ffi;
|
pub mod ffi;
|
||||||
|
|
||||||
use platform::PlatformSpecificWindowBuilderAttributes;
|
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::{mem, ptr, slice};
|
||||||
use std::sync::{Arc, Mutex, Weak};
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
|
@ -30,10 +31,9 @@ mod xdisplay;
|
||||||
// the one generated by the macro.
|
// the one generated by the macro.
|
||||||
|
|
||||||
pub struct EventsLoop {
|
pub struct EventsLoop {
|
||||||
interrupted: AtomicBool,
|
|
||||||
display: Arc<XConnection>,
|
display: Arc<XConnection>,
|
||||||
wm_delete_window: ffi::Atom,
|
wm_delete_window: ffi::Atom,
|
||||||
windows: Mutex<HashMap<WindowId, WindowData>>,
|
windows: Arc<Mutex<HashMap<WindowId, WindowData>>>,
|
||||||
devices: Mutex<HashMap<DeviceId, Device>>,
|
devices: Mutex<HashMap<DeviceId, Device>>,
|
||||||
xi2ext: XExtension,
|
xi2ext: XExtension,
|
||||||
pending_wakeup: Arc<AtomicBool>,
|
pending_wakeup: Arc<AtomicBool>,
|
||||||
|
@ -81,11 +81,10 @@ impl EventsLoop {
|
||||||
let root = unsafe { (display.xlib.XDefaultRootWindow)(display.display) };
|
let root = unsafe { (display.xlib.XDefaultRootWindow)(display.display) };
|
||||||
|
|
||||||
let result = EventsLoop {
|
let result = EventsLoop {
|
||||||
interrupted: AtomicBool::new(false),
|
|
||||||
pending_wakeup: Arc::new(AtomicBool::new(false)),
|
pending_wakeup: Arc::new(AtomicBool::new(false)),
|
||||||
display: display,
|
display: display,
|
||||||
wm_delete_window: wm_delete_window,
|
wm_delete_window: wm_delete_window,
|
||||||
windows: Mutex::new(HashMap::new()),
|
windows: Arc::new(Mutex::new(HashMap::new())),
|
||||||
devices: Mutex::new(HashMap::new()),
|
devices: Mutex::new(HashMap::new()),
|
||||||
xi2ext: xi2ext,
|
xi2ext: xi2ext,
|
||||||
root: root,
|
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)
|
pub fn poll_events<F>(&self, mut callback: F)
|
||||||
where F: FnMut(Event)
|
where F: FnMut(Event)
|
||||||
{
|
{
|
||||||
self.interrupted.store(false, atomic::Ordering::Relaxed);
|
|
||||||
let xlib = &self.display.xlib;
|
let xlib = &self.display.xlib;
|
||||||
|
|
||||||
let mut xev = unsafe { mem::uninitialized() };
|
let mut xev = unsafe { mem::uninitialized() };
|
||||||
|
@ -141,16 +135,12 @@ impl EventsLoop {
|
||||||
(xlib.XNextEvent)(self.display.display, &mut xev);
|
(xlib.XNextEvent)(self.display.display, &mut xev);
|
||||||
}
|
}
|
||||||
self.process_event(&mut xev, &mut callback);
|
self.process_event(&mut xev, &mut callback);
|
||||||
if self.interrupted.load(atomic::Ordering::Relaxed) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_forever<F>(&self, mut callback: F)
|
pub fn run_forever<F>(&mut self, mut callback: F)
|
||||||
where F: FnMut(Event)
|
where F: FnMut(Event) -> ControlFlow
|
||||||
{
|
{
|
||||||
self.interrupted.store(false, atomic::Ordering::Relaxed);
|
|
||||||
self.pending_wakeup.store(false, atomic::Ordering::Relaxed);
|
self.pending_wakeup.store(false, atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
let xlib = &self.display.xlib;
|
let xlib = &self.display.xlib;
|
||||||
|
@ -160,13 +150,25 @@ impl EventsLoop {
|
||||||
loop {
|
loop {
|
||||||
unsafe { (xlib.XNextEvent)(self.display.display, &mut xev) }; // Blocks as necessary
|
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) {
|
if self.pending_wakeup.load(atomic::Ordering::Relaxed) {
|
||||||
self.pending_wakeup.store(false, 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);
|
// Track whether or not `Complete` was returned when processing the event.
|
||||||
if self.interrupted.load(atomic::Ordering::Relaxed) {
|
{
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +180,7 @@ impl EventsLoop {
|
||||||
device.name.clone()
|
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)
|
where F: FnMut(Event)
|
||||||
{
|
{
|
||||||
let xlib = &self.display.xlib;
|
let xlib = &self.display.xlib;
|
||||||
|
@ -312,7 +314,11 @@ impl EventsLoop {
|
||||||
};
|
};
|
||||||
|
|
||||||
for chr in written.chars() {
|
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 struct Window2 {
|
||||||
pub window: Arc<Window>,
|
pub window: Arc<Window>,
|
||||||
events_loop: Weak<::platform::EventsLoop>,
|
display: Weak<XConnection>,
|
||||||
|
windows: Weak<Mutex<HashMap<WindowId, WindowData>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::ops::Deref for Window2 {
|
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 {
|
impl Window2 {
|
||||||
pub fn new(events_loop: Arc<::platform::EventsLoop>,
|
pub fn new(events_loop: &::platform::EventsLoop,
|
||||||
window: &::WindowAttributes, pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
window: &::WindowAttributes,
|
||||||
-> Result<Window2, CreationError>
|
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
||||||
|
-> Result<Self, CreationError>
|
||||||
{
|
{
|
||||||
let x_events_loop = if let ::platform::EventsLoop::X(ref e) = *events_loop { e } else { unreachable!() };
|
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)));
|
let win = ::std::sync::Arc::new(try!(Window::new(&x_events_loop, window, pl_attribs)));
|
||||||
|
@ -662,7 +670,8 @@ impl Window2 {
|
||||||
|
|
||||||
Ok(Window2 {
|
Ok(Window2 {
|
||||||
window: win,
|
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 {
|
impl Drop for Window2 {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(ev) = self.events_loop.upgrade() {
|
if let (Some(windows), Some(display)) = (self.windows.upgrade(), self.display.upgrade()) {
|
||||||
if let ::platform::EventsLoop::X(ref ev) = *ev {
|
let mut windows = windows.lock().unwrap();
|
||||||
let mut windows = ev.windows.lock().unwrap();
|
|
||||||
|
|
||||||
|
|
||||||
let w = windows.remove(&self.window.id()).unwrap();
|
let w = windows.remove(&self.window.id()).unwrap();
|
||||||
let _lock = GLOBAL_XOPENIM_LOCK.lock().unwrap();
|
let _lock = GLOBAL_XOPENIM_LOCK.lock().unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
(ev.display.xlib.XDestroyIC)(w.ic);
|
(display.xlib.XDestroyIC)(w.ic);
|
||||||
(ev.display.xlib.XCloseIM)(w.im);
|
(display.xlib.XCloseIM)(w.im);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ impl WindowBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// building
|
// building
|
||||||
let w = try!(platform::Window2::new(events_loop.events_loop.clone(), &self.window, &self.platform_specific));
|
let w = try!(platform::Window2::new(&events_loop.events_loop, &self.window, &self.platform_specific));
|
||||||
|
|
||||||
Ok(Window { window: w })
|
Ok(Window { window: w })
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue