mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-25 23:01:30 +11:00
Merge pull request #70 from tomaka/fix-iterators
Use platform-specific iterators instead
This commit is contained in:
commit
4500702a02
|
@ -74,6 +74,52 @@ unsafe impl Send for HeadlessContext {}
|
||||||
#[cfg(feature = "headless")]
|
#[cfg(feature = "headless")]
|
||||||
unsafe impl Sync for HeadlessContext {}
|
unsafe impl Sync for HeadlessContext {}
|
||||||
|
|
||||||
|
pub struct PollEventsIterator<'a> {
|
||||||
|
window: &'a Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
match self.window.event_rx.try_recv() {
|
||||||
|
Ok(event) => {
|
||||||
|
Some(match event {
|
||||||
|
android_glue::Event::EventDown => MouseInput(Pressed, MouseButton::Left),
|
||||||
|
android_glue::Event::EventUp => MouseInput(Released, MouseButton::Left),
|
||||||
|
android_glue::Event::EventMove(x, y) => MouseMoved((x as i32, y as i32)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WaitEventsIterator<'a> {
|
||||||
|
window: &'a Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for WaitEventsIterator<'a> {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::old_io::timer;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// calling poll_events()
|
||||||
|
if let Some(ev) = self.window.poll_events().next() {
|
||||||
|
return Some(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement a proper way of sleeping on the event queue
|
||||||
|
timer::sleep(Duration::milliseconds(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
|
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
|
@ -242,34 +288,16 @@ impl Window {
|
||||||
WindowProxy
|
WindowProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_events(&self) -> RingBuf<Event> {
|
pub fn poll_events(&self) -> PollEventsIterator {
|
||||||
let mut events = RingBuf::new();
|
PollEventsIterator {
|
||||||
loop {
|
window: self
|
||||||
match self.event_rx.try_recv() {
|
|
||||||
Ok(event) => match event {
|
|
||||||
android_glue::Event::EventDown => {
|
|
||||||
events.push_back(MouseInput(Pressed, MouseButton::Left));
|
|
||||||
},
|
|
||||||
android_glue::Event::EventUp => {
|
|
||||||
events.push_back(MouseInput(Released, MouseButton::Left));
|
|
||||||
},
|
|
||||||
android_glue::Event::EventMove(x, y) => {
|
|
||||||
events.push_back(MouseMoved((x as i32, y as i32)));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
break;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
events
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_events(&self) -> RingBuf<Event> {
|
pub fn wait_events(&self) -> WaitEventsIterator {
|
||||||
use std::time::Duration;
|
WaitEventsIterator {
|
||||||
use std::old_io::timer;
|
window: self
|
||||||
timer::sleep(Duration::milliseconds(16));
|
}
|
||||||
self.poll_events()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_current(&self) {
|
pub fn make_current(&self) {
|
||||||
|
|
262
src/cocoa/mod.rs
262
src/cocoa/mod.rs
|
@ -25,6 +25,7 @@ use std::ptr;
|
||||||
use std::collections::RingBuf;
|
use std::collections::RingBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
|
use std::sync::Mutex;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
|
||||||
use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel};
|
use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput, MouseWheel};
|
||||||
|
@ -164,6 +165,9 @@ pub struct Window {
|
||||||
resize: Option<fn(u32, u32)>,
|
resize: Option<fn(u32, u32)>,
|
||||||
|
|
||||||
is_closed: Cell<bool>,
|
is_closed: Cell<bool>,
|
||||||
|
|
||||||
|
/// Events that have been retreived with XLib but not dispatched with iterators yet
|
||||||
|
pending_events: Mutex<RingBuf<Event>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
|
@ -189,6 +193,146 @@ impl WindowProxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PollEventsIterator<'a> {
|
||||||
|
window: &'a Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
if let Some(ev) = self.window.pending_events.lock().unwrap().pop_front() {
|
||||||
|
return Some(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
||||||
|
NSAnyEventMask.bits(),
|
||||||
|
NSDate::distantPast(nil),
|
||||||
|
NSDefaultRunLoopMode,
|
||||||
|
YES);
|
||||||
|
if event == nil { return None; }
|
||||||
|
{
|
||||||
|
// Create a temporary structure with state that delegates called internally
|
||||||
|
// by sendEvent can read and modify. When that returns, update window state.
|
||||||
|
// This allows the synchronous resize loop to continue issuing callbacks
|
||||||
|
// to the user application, by passing handler through to the delegate state.
|
||||||
|
let mut ds = DelegateState {
|
||||||
|
is_closed: self.window.is_closed.get(),
|
||||||
|
context: self.window.context,
|
||||||
|
window: self.window.window,
|
||||||
|
view: self.window.view,
|
||||||
|
handler: self.window.resize,
|
||||||
|
};
|
||||||
|
self.window.delegate.set_state(&mut ds);
|
||||||
|
NSApp().sendEvent_(event);
|
||||||
|
self.window.delegate.set_state(ptr::null_mut());
|
||||||
|
self.window.is_closed.set(ds.is_closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
let event = match msg_send()(event, selector("type")) {
|
||||||
|
NSLeftMouseDown => { Some(MouseInput(Pressed, MouseButton::Left)) },
|
||||||
|
NSLeftMouseUp => { Some(MouseInput(Released, MouseButton::Left)) },
|
||||||
|
NSRightMouseDown => { Some(MouseInput(Pressed, MouseButton::Right)) },
|
||||||
|
NSRightMouseUp => { Some(MouseInput(Released, MouseButton::Right)) },
|
||||||
|
NSMouseMoved => {
|
||||||
|
let window_point = event.locationInWindow();
|
||||||
|
let window: id = msg_send()(event, selector("window"));
|
||||||
|
let view_point = if window == 0 {
|
||||||
|
let window_rect = self.window.window.convertRectFromScreen_(NSRect::new(window_point, NSSize::new(0.0, 0.0)));
|
||||||
|
self.window.view.convertPoint_fromView_(window_rect.origin, nil)
|
||||||
|
} else {
|
||||||
|
self.window.view.convertPoint_fromView_(window_point, nil)
|
||||||
|
};
|
||||||
|
let view_rect = NSView::frame(self.window.view);
|
||||||
|
let scale_factor = self.window.hidpi_factor();
|
||||||
|
Some(MouseMoved(((scale_factor * view_point.x as f32) as i32,
|
||||||
|
(scale_factor * (view_rect.size.height - view_point.y) as f32) as i32)))
|
||||||
|
},
|
||||||
|
NSKeyDown => {
|
||||||
|
let mut events = RingBuf::new();
|
||||||
|
let received_c_str = event.characters().UTF8String();
|
||||||
|
let received_str = CString::from_slice(c_str_to_bytes(&received_c_str));
|
||||||
|
for received_char in from_utf8(received_str.as_bytes()).unwrap().chars() {
|
||||||
|
if received_char.is_ascii() {
|
||||||
|
events.push_back(ReceivedCharacter(received_char));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let vkey = event::vkeycode_to_element(NSEvent::keyCode(event));
|
||||||
|
events.push_back(KeyboardInput(Pressed, NSEvent::keyCode(event) as u8, vkey));
|
||||||
|
let event = events.pop_front();
|
||||||
|
self.window.pending_events.lock().unwrap().extend(events.into_iter());
|
||||||
|
event
|
||||||
|
},
|
||||||
|
NSKeyUp => {
|
||||||
|
let vkey = event::vkeycode_to_element(NSEvent::keyCode(event));
|
||||||
|
Some(KeyboardInput(Released, NSEvent::keyCode(event) as u8, vkey))
|
||||||
|
},
|
||||||
|
NSFlagsChanged => {
|
||||||
|
let mut events = RingBuf::new();
|
||||||
|
let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask, events::VirtualKeyCode::LShift, shift_pressed);
|
||||||
|
if shift_modifier.is_some() {
|
||||||
|
shift_pressed = !shift_pressed;
|
||||||
|
events.push_back(shift_modifier.unwrap());
|
||||||
|
}
|
||||||
|
let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask, events::VirtualKeyCode::LControl, ctrl_pressed);
|
||||||
|
if ctrl_modifier.is_some() {
|
||||||
|
ctrl_pressed = !ctrl_pressed;
|
||||||
|
events.push_back(ctrl_modifier.unwrap());
|
||||||
|
}
|
||||||
|
let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask, events::VirtualKeyCode::LWin, win_pressed);
|
||||||
|
if win_modifier.is_some() {
|
||||||
|
win_pressed = !win_pressed;
|
||||||
|
events.push_back(win_modifier.unwrap());
|
||||||
|
}
|
||||||
|
let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask, events::VirtualKeyCode::LAlt, alt_pressed);
|
||||||
|
if alt_modifier.is_some() {
|
||||||
|
alt_pressed = !alt_pressed;
|
||||||
|
events.push_back(alt_modifier.unwrap());
|
||||||
|
}
|
||||||
|
let event = events.pop_front();
|
||||||
|
self.window.pending_events.lock().unwrap().extend(events.into_iter());
|
||||||
|
event
|
||||||
|
},
|
||||||
|
NSScrollWheel => { Some(MouseWheel(-event.scrollingDeltaY() as i32)) },
|
||||||
|
_ => { None },
|
||||||
|
};
|
||||||
|
|
||||||
|
event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WaitEventsIterator<'a> {
|
||||||
|
window: &'a Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for WaitEventsIterator<'a> {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
loop {
|
||||||
|
if let Some(ev) = self.window.pending_events.lock().unwrap().pop_front() {
|
||||||
|
return Some(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
||||||
|
NSAnyEventMask.bits(),
|
||||||
|
NSDate::distantFuture(nil),
|
||||||
|
NSDefaultRunLoopMode,
|
||||||
|
NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calling poll_events()
|
||||||
|
if let Some(ev) = self.window.poll_events().next() {
|
||||||
|
return Some(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
|
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
|
||||||
|
@ -234,6 +378,7 @@ impl Window {
|
||||||
resize: None,
|
resize: None,
|
||||||
|
|
||||||
is_closed: Cell::new(false),
|
is_closed: Cell::new(false),
|
||||||
|
pending_events: Mutex::new(RingBuf::new()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(window)
|
Ok(window)
|
||||||
|
@ -403,102 +548,16 @@ impl Window {
|
||||||
WindowProxy
|
WindowProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_events(&self) -> RingBuf<Event> {
|
pub fn poll_events(&self) -> PollEventsIterator {
|
||||||
let mut events = RingBuf::new();
|
PollEventsIterator {
|
||||||
|
window: self
|
||||||
loop {
|
}
|
||||||
unsafe {
|
}
|
||||||
let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
|
||||||
NSAnyEventMask.bits(),
|
pub fn wait_events(&self) -> WaitEventsIterator {
|
||||||
NSDate::distantPast(nil),
|
WaitEventsIterator {
|
||||||
NSDefaultRunLoopMode,
|
window: self
|
||||||
YES);
|
|
||||||
if event == nil { break; }
|
|
||||||
{
|
|
||||||
// Create a temporary structure with state that delegates called internally
|
|
||||||
// by sendEvent can read and modify. When that returns, update window state.
|
|
||||||
// This allows the synchronous resize loop to continue issuing callbacks
|
|
||||||
// to the user application, by passing handler through to the delegate state.
|
|
||||||
let mut ds = DelegateState {
|
|
||||||
is_closed: self.is_closed.get(),
|
|
||||||
context: self.context,
|
|
||||||
window: self.window,
|
|
||||||
view: self.view,
|
|
||||||
handler: self.resize,
|
|
||||||
};
|
|
||||||
self.delegate.set_state(&mut ds);
|
|
||||||
NSApp().sendEvent_(event);
|
|
||||||
self.delegate.set_state(ptr::null_mut());
|
|
||||||
self.is_closed.set(ds.is_closed);
|
|
||||||
}
|
|
||||||
|
|
||||||
match msg_send()(event, selector("type")) {
|
|
||||||
NSLeftMouseDown => { events.push_back(MouseInput(Pressed, MouseButton::Left)); },
|
|
||||||
NSLeftMouseUp => { events.push_back(MouseInput(Released, MouseButton::Left)); },
|
|
||||||
NSRightMouseDown => { events.push_back(MouseInput(Pressed, MouseButton::Right)); },
|
|
||||||
NSRightMouseUp => { events.push_back(MouseInput(Released, MouseButton::Right)); },
|
|
||||||
NSMouseMoved => {
|
|
||||||
let window_point: NSPoint = msg_send()(event, selector("locationInWindow"));
|
|
||||||
// let window_point = event.locationInWindow();
|
|
||||||
let window: id = msg_send()(event, selector("window"));
|
|
||||||
let view_point = if window == 0 {
|
|
||||||
let window_rect = self.window.convertRectFromScreen_(NSRect::new(window_point, NSSize::new(0.0, 0.0)));
|
|
||||||
self.view.convertPoint_fromView_(window_rect.origin, nil)
|
|
||||||
} else {
|
|
||||||
self.view.convertPoint_fromView_(window_point, nil)
|
|
||||||
};
|
|
||||||
let view_rect = NSView::frame(self.view);
|
|
||||||
let scale_factor = self.hidpi_factor();
|
|
||||||
events.push_back(MouseMoved(((scale_factor * view_point.x as f32) as i32,
|
|
||||||
(scale_factor * (view_rect.size.height - view_point.y) as f32) as i32)));
|
|
||||||
},
|
|
||||||
NSKeyDown => {
|
|
||||||
let received_c_str = event.characters().UTF8String();
|
|
||||||
let received_str = CString::from_slice(c_str_to_bytes(&received_c_str));
|
|
||||||
for received_char in from_utf8(received_str.as_bytes()).unwrap().chars() {
|
|
||||||
if received_char.is_ascii() {
|
|
||||||
events.push_back(ReceivedCharacter(received_char));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let vkey = event::vkeycode_to_element(NSEvent::keyCode(event));
|
|
||||||
events.push_back(KeyboardInput(Pressed, NSEvent::keyCode(event) as u8, vkey));
|
|
||||||
},
|
|
||||||
NSKeyUp => {
|
|
||||||
let vkey = event::vkeycode_to_element(NSEvent::keyCode(event));
|
|
||||||
events.push_back(KeyboardInput(Released, NSEvent::keyCode(event) as u8, vkey));
|
|
||||||
},
|
|
||||||
NSFlagsChanged => {
|
|
||||||
let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask, events::VirtualKeyCode::LShift, shift_pressed);
|
|
||||||
if shift_modifier.is_some() {
|
|
||||||
shift_pressed = !shift_pressed;
|
|
||||||
events.push_back(shift_modifier.unwrap());
|
|
||||||
}
|
|
||||||
let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask, events::VirtualKeyCode::LControl, ctrl_pressed);
|
|
||||||
if ctrl_modifier.is_some() {
|
|
||||||
ctrl_pressed = !ctrl_pressed;
|
|
||||||
events.push_back(ctrl_modifier.unwrap());
|
|
||||||
}
|
|
||||||
let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask, events::VirtualKeyCode::LWin, win_pressed);
|
|
||||||
if win_modifier.is_some() {
|
|
||||||
win_pressed = !win_pressed;
|
|
||||||
events.push_back(win_modifier.unwrap());
|
|
||||||
}
|
|
||||||
let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask, events::VirtualKeyCode::LAlt, alt_pressed);
|
|
||||||
if alt_modifier.is_some() {
|
|
||||||
alt_pressed = !alt_pressed;
|
|
||||||
events.push_back(alt_modifier.unwrap());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
NSScrollWheel => { events.push_back(MouseWheel(event.scrollingDeltaY() as i32)); },
|
|
||||||
NSOtherMouseDown => { },
|
|
||||||
NSOtherMouseUp => { },
|
|
||||||
NSOtherMouseDragged => { },
|
|
||||||
_ => { },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
events
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn modifier_event(event: id, keymask: NSEventModifierFlags, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
|
unsafe fn modifier_event(event: id, keymask: NSEventModifierFlags, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
|
||||||
|
@ -511,19 +570,6 @@ impl Window {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_events(&self) -> RingBuf<Event> {
|
|
||||||
unsafe {
|
|
||||||
let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
|
||||||
NSAnyEventMask.bits(),
|
|
||||||
NSDate::distantFuture(nil),
|
|
||||||
NSDefaultRunLoopMode,
|
|
||||||
NO);
|
|
||||||
NSApp().sendEvent_(event);
|
|
||||||
|
|
||||||
self.poll_events()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn make_current(&self) {
|
pub unsafe fn make_current(&self) {
|
||||||
let _: id = msg_send()(self.context, selector("update"));
|
let _: id = msg_send()(self.context, selector("update"));
|
||||||
self.context.makeCurrentContext();
|
self.context.makeCurrentContext();
|
||||||
|
|
34
src/lib.rs
34
src/lib.rs
|
@ -592,7 +592,7 @@ impl Window {
|
||||||
/// Contrary to `wait_events`, this function never blocks.
|
/// Contrary to `wait_events`, this function never blocks.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn poll_events(&self) -> PollEventsIterator {
|
pub fn poll_events(&self) -> PollEventsIterator {
|
||||||
PollEventsIterator { window: self, data: self.window.poll_events().into_iter() }
|
PollEventsIterator(self.window.poll_events())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator that returns events one by one, blocking if necessary until one is
|
/// Returns an iterator that returns events one by one, blocking if necessary until one is
|
||||||
|
@ -601,7 +601,7 @@ impl Window {
|
||||||
/// The iterator never returns `None`.
|
/// The iterator never returns `None`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wait_events(&self) -> WaitEventsIterator {
|
pub fn wait_events(&self) -> WaitEventsIterator {
|
||||||
WaitEventsIterator { window: self, data: self.window.wait_events().into_iter() }
|
WaitEventsIterator(self.window.wait_events())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the context as the current context.
|
/// Sets the context as the current context.
|
||||||
|
@ -754,24 +754,13 @@ impl gl_common::GlFunctionsSource for HeadlessContext {
|
||||||
// Implementation note: we retreive the list once, then serve each element by one by one.
|
// Implementation note: we retreive the list once, then serve each element by one by one.
|
||||||
// This may change in the future.
|
// This may change in the future.
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
pub struct PollEventsIterator<'a> {
|
pub struct PollEventsIterator<'a>(winimpl::PollEventsIterator<'a>);
|
||||||
window: &'a Window,
|
|
||||||
data: RingBufIter<Event>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
impl<'a> Iterator for PollEventsIterator<'a> {
|
impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
type Item = Event;
|
type Item = Event;
|
||||||
fn next(&mut self) -> Option<Event> {
|
fn next(&mut self) -> Option<Event> {
|
||||||
if let Some(ev) = self.data.next() {
|
self.0.next()
|
||||||
return Some(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
let PollEventsIterator { window, data } = self.window.poll_events();
|
|
||||||
self.window = window;
|
|
||||||
self.data = data;
|
|
||||||
|
|
||||||
self.data.next()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,24 +768,13 @@ impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
// Implementation note: we retreive the list once, then serve each element by one by one.
|
// Implementation note: we retreive the list once, then serve each element by one by one.
|
||||||
// This may change in the future.
|
// This may change in the future.
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
pub struct WaitEventsIterator<'a> {
|
pub struct WaitEventsIterator<'a>(winimpl::WaitEventsIterator<'a>);
|
||||||
window: &'a Window,
|
|
||||||
data: RingBufIter<Event>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
impl<'a> Iterator for WaitEventsIterator<'a> {
|
impl<'a> Iterator for WaitEventsIterator<'a> {
|
||||||
type Item = Event;
|
type Item = Event;
|
||||||
fn next(&mut self) -> Option<Event> {
|
fn next(&mut self) -> Option<Event> {
|
||||||
if let Some(ev) = self.data.next() {
|
self.0.next()
|
||||||
return Some(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
let WaitEventsIterator { window, data } = self.window.wait_events();
|
|
||||||
self.window = window;
|
|
||||||
self.data = data;
|
|
||||||
|
|
||||||
self.next()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,50 +201,16 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See the docs in the crate root file.
|
/// See the docs in the crate root file.
|
||||||
// TODO: return iterator
|
pub fn poll_events(&self) -> PollEventsIterator {
|
||||||
pub fn poll_events(&self) -> RingBuf<Event> {
|
PollEventsIterator {
|
||||||
let mut events = RingBuf::new();
|
window: self,
|
||||||
loop {
|
|
||||||
match self.events_receiver.try_recv() {
|
|
||||||
Ok(ev) => events.push_back(ev),
|
|
||||||
Err(_) => break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if one of the received events is `Closed`, setting `is_closed` to true
|
|
||||||
if events.iter().any(|e| match e { &::events::Event::Closed => true, _ => false }) {
|
|
||||||
use std::sync::atomic::Ordering::Relaxed;
|
|
||||||
self.is_closed.store(true, Relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
events
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See the docs in the crate root file.
|
/// See the docs in the crate root file.
|
||||||
// TODO: return iterator
|
pub fn wait_events(&self) -> WaitEventsIterator {
|
||||||
pub fn wait_events(&self) -> RingBuf<Event> {
|
WaitEventsIterator {
|
||||||
match self.events_receiver.recv() {
|
window: self,
|
||||||
Ok(ev) => {
|
|
||||||
// if the received event is `Closed`, setting `is_closed` to true
|
|
||||||
match ev {
|
|
||||||
::events::Event::Closed => {
|
|
||||||
use std::sync::atomic::Ordering::Relaxed;
|
|
||||||
self.is_closed.store(true, Relaxed);
|
|
||||||
},
|
|
||||||
_ => ()
|
|
||||||
};
|
|
||||||
|
|
||||||
// looing for other possible events in the queue
|
|
||||||
let mut result = self.poll_events();
|
|
||||||
result.insert(0, ev);
|
|
||||||
result
|
|
||||||
},
|
|
||||||
|
|
||||||
Err(_) => {
|
|
||||||
use std::sync::atomic::Ordering::Relaxed;
|
|
||||||
self.is_closed.store(true, Relaxed);
|
|
||||||
RingBuf::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,6 +260,50 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PollEventsIterator<'a> {
|
||||||
|
window: &'a Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
use events::Event::Closed;
|
||||||
|
|
||||||
|
match self.window.events_receiver.recv() {
|
||||||
|
Ok(Closed) => {
|
||||||
|
use std::sync::atomic::Ordering::Relaxed;
|
||||||
|
self.window.is_closed.store(true, Relaxed);
|
||||||
|
Some(Closed)
|
||||||
|
},
|
||||||
|
Ok(ev) => Some(ev),
|
||||||
|
Err(_) => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WaitEventsIterator<'a> {
|
||||||
|
window: &'a Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for WaitEventsIterator<'a> {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
use events::Event::Closed;
|
||||||
|
|
||||||
|
match self.window.events_receiver.recv() {
|
||||||
|
Ok(Closed) => {
|
||||||
|
use std::sync::atomic::Ordering::Relaxed;
|
||||||
|
self.window.is_closed.store(true, Relaxed);
|
||||||
|
Some(Closed)
|
||||||
|
},
|
||||||
|
Ok(ev) => Some(ev),
|
||||||
|
Err(_) => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl Drop for Window {
|
impl Drop for Window {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
|
|
@ -3,6 +3,8 @@ pub use self::headless::HeadlessContext;
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
pub use self::window::{Window, WindowProxy, MonitorID, get_available_monitors, get_primary_monitor};
|
pub use self::window::{Window, WindowProxy, MonitorID, get_available_monitors, get_primary_monitor};
|
||||||
|
#[cfg(feature = "window")]
|
||||||
|
pub use self::window::{WaitEventsIterator, PollEventsIterator};
|
||||||
|
|
||||||
mod ffi;
|
mod ffi;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::cell::Cell;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::collections::RingBuf;
|
use std::collections::RingBuf;
|
||||||
use super::ffi;
|
use super::ffi;
|
||||||
use std::sync::{Arc, Once, ONCE_INIT, Weak};
|
use std::sync::{Arc, Mutex, Once, ONCE_INIT, Weak};
|
||||||
use std::sync::{StaticMutex, MUTEX_INIT};
|
use std::sync::{StaticMutex, MUTEX_INIT};
|
||||||
|
|
||||||
pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
|
pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
|
||||||
|
@ -105,11 +105,179 @@ impl WindowProxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PollEventsIterator<'a> {
|
||||||
|
window: &'a Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
use std::num::Int;
|
||||||
|
|
||||||
|
if let Some(ev) = self.window.pending_events.lock().unwrap().pop_front() {
|
||||||
|
return Some(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut xev = unsafe { mem::uninitialized() };
|
||||||
|
let res = unsafe { ffi::XCheckMaskEvent(self.window.x.display, Int::max_value(), &mut xev) };
|
||||||
|
|
||||||
|
if res == 0 {
|
||||||
|
let res = unsafe { ffi::XCheckTypedEvent(self.window.x.display, ffi::ClientMessage, &mut xev) };
|
||||||
|
|
||||||
|
if res == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match xev.type_ {
|
||||||
|
ffi::KeymapNotify => {
|
||||||
|
unsafe { ffi::XRefreshKeyboardMapping(&xev) }
|
||||||
|
},
|
||||||
|
|
||||||
|
ffi::ClientMessage => {
|
||||||
|
use events::Event::{Closed, Awakened};
|
||||||
|
use std::sync::atomic::Ordering::Relaxed;
|
||||||
|
|
||||||
|
let client_msg: &ffi::XClientMessageEvent = unsafe { mem::transmute(&xev) };
|
||||||
|
|
||||||
|
if client_msg.l[0] == self.window.wm_delete_window as libc::c_long {
|
||||||
|
self.window.is_closed.store(true, Relaxed);
|
||||||
|
return Some(Closed);
|
||||||
|
} else {
|
||||||
|
return Some(Awakened);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ffi::ConfigureNotify => {
|
||||||
|
use events::Event::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 {
|
||||||
|
self.window.current_size.set((cfg_event.width, cfg_event.height));
|
||||||
|
return Some(Resized(cfg_event.width as u32, cfg_event.height as u32));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ffi::MotionNotify => {
|
||||||
|
use events::Event::MouseMoved;
|
||||||
|
let event: &ffi::XMotionEvent = unsafe { mem::transmute(&xev) };
|
||||||
|
return Some(MouseMoved((event.x as i32, event.y as i32)));
|
||||||
|
},
|
||||||
|
|
||||||
|
ffi::KeyPress | ffi::KeyRelease => {
|
||||||
|
use events::Event::{KeyboardInput, ReceivedCharacter};
|
||||||
|
use events::ElementState::{Pressed, Released};
|
||||||
|
let event: &mut ffi::XKeyEvent = unsafe { mem::transmute(&xev) };
|
||||||
|
|
||||||
|
if event.type_ == ffi::KeyPress {
|
||||||
|
let raw_ev: *mut ffi::XKeyEvent = event;
|
||||||
|
unsafe { ffi::XFilterEvent(mem::transmute(raw_ev), self.window.x.window) };
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = if xev.type_ == ffi::KeyPress { Pressed } else { Released };
|
||||||
|
|
||||||
|
let written = unsafe {
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
let mut buffer: [u8; 16] = [mem::uninitialized(); 16];
|
||||||
|
let raw_ev: *mut ffi::XKeyEvent = event;
|
||||||
|
let count = ffi::Xutf8LookupString(self.window.x.ic, mem::transmute(raw_ev),
|
||||||
|
mem::transmute(buffer.as_mut_ptr()),
|
||||||
|
buffer.len() as libc::c_int, ptr::null_mut(), ptr::null_mut());
|
||||||
|
|
||||||
|
str::from_utf8(&buffer.as_slice()[..count as usize]).unwrap_or("").to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut pending = self.window.pending_events.lock().unwrap();
|
||||||
|
for chr in written.as_slice().chars() {
|
||||||
|
pending.push_back(ReceivedCharacter(chr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let keysym = unsafe {
|
||||||
|
ffi::XKeycodeToKeysym(self.window.x.display, event.keycode as ffi::KeyCode, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
let vkey = events::keycode_to_element(keysym as libc::c_uint);
|
||||||
|
|
||||||
|
return Some(KeyboardInput(state, event.keycode as u8, vkey));
|
||||||
|
},
|
||||||
|
|
||||||
|
ffi::ButtonPress | ffi::ButtonRelease => {
|
||||||
|
use events::Event::{MouseInput, MouseWheel};
|
||||||
|
use events::ElementState::{Pressed, Released};
|
||||||
|
use events::MouseButton::{Left, Right, Middle};
|
||||||
|
|
||||||
|
let event: &ffi::XButtonEvent = unsafe { mem::transmute(&xev) };
|
||||||
|
|
||||||
|
let state = if xev.type_ == ffi::ButtonPress { Pressed } else { Released };
|
||||||
|
|
||||||
|
let button = match event.button {
|
||||||
|
ffi::Button1 => Some(Left),
|
||||||
|
ffi::Button2 => Some(Middle),
|
||||||
|
ffi::Button3 => Some(Right),
|
||||||
|
ffi::Button4 => {
|
||||||
|
self.window.pending_events.lock().unwrap().push_back(MouseWheel(1));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
ffi::Button5 => {
|
||||||
|
self.window.pending_events.lock().unwrap().push_back(MouseWheel(-1));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
|
||||||
|
match button {
|
||||||
|
Some(button) =>
|
||||||
|
return Some(MouseInput(state, button)),
|
||||||
|
None => ()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => ()
|
||||||
|
};
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WaitEventsIterator<'a> {
|
||||||
|
window: &'a Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for WaitEventsIterator<'a> {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(ev) = self.window.pending_events.lock().unwrap().pop_front() {
|
||||||
|
return Some(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this will block until an event arrives, but doesn't remove
|
||||||
|
// it from the queue
|
||||||
|
let mut xev = unsafe { mem::uninitialized() };
|
||||||
|
unsafe { ffi::XPeekEvent(self.window.x.display, &mut xev) };
|
||||||
|
|
||||||
|
// calling poll_events()
|
||||||
|
if let Some(ev) = self.window.poll_events().next() {
|
||||||
|
return Some(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
x: Arc<XWindow>,
|
x: Arc<XWindow>,
|
||||||
is_closed: AtomicBool,
|
is_closed: AtomicBool,
|
||||||
wm_delete_window: ffi::Atom,
|
wm_delete_window: ffi::Atom,
|
||||||
current_size: Cell<(libc::c_int, libc::c_int)>,
|
current_size: Cell<(libc::c_int, libc::c_int)>,
|
||||||
|
/// Events that have been retreived with XLib but not dispatched with iterators yet
|
||||||
|
pending_events: Mutex<RingBuf<Event>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
@ -419,6 +587,7 @@ impl Window {
|
||||||
is_closed: AtomicBool::new(false),
|
is_closed: AtomicBool::new(false),
|
||||||
wm_delete_window: wm_delete_window,
|
wm_delete_window: wm_delete_window,
|
||||||
current_size: Cell::new((0, 0)),
|
current_size: Cell::new((0, 0)),
|
||||||
|
pending_events: Mutex::new(RingBuf::new()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// returning
|
// returning
|
||||||
|
@ -500,149 +669,15 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_events(&self) -> RingBuf<Event> {
|
pub fn poll_events(&self) -> PollEventsIterator {
|
||||||
use std::mem;
|
PollEventsIterator {
|
||||||
|
window: self
|
||||||
let mut events = RingBuf::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
use std::num::Int;
|
|
||||||
|
|
||||||
let mut xev = unsafe { mem::uninitialized() };
|
|
||||||
let res = unsafe { ffi::XCheckMaskEvent(self.x.display, Int::max_value(), &mut xev) };
|
|
||||||
|
|
||||||
if res == 0 {
|
|
||||||
let res = unsafe { ffi::XCheckTypedEvent(self.x.display, ffi::ClientMessage, &mut xev) };
|
|
||||||
|
|
||||||
if res == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match xev.type_ {
|
|
||||||
ffi::KeymapNotify => {
|
|
||||||
unsafe { ffi::XRefreshKeyboardMapping(&xev) }
|
|
||||||
},
|
|
||||||
|
|
||||||
ffi::ClientMessage => {
|
|
||||||
use events::Event::{Closed, Awakened};
|
|
||||||
use std::sync::atomic::Ordering::Relaxed;
|
|
||||||
|
|
||||||
let client_msg: &ffi::XClientMessageEvent = unsafe { mem::transmute(&xev) };
|
|
||||||
|
|
||||||
if client_msg.l[0] == self.wm_delete_window as libc::c_long {
|
|
||||||
self.is_closed.store(true, Relaxed);
|
|
||||||
events.push_back(Closed);
|
|
||||||
} else {
|
|
||||||
events.push_back(Awakened);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ffi::ConfigureNotify => {
|
|
||||||
use events::Event::Resized;
|
|
||||||
let cfg_event: &ffi::XConfigureEvent = unsafe { mem::transmute(&xev) };
|
|
||||||
let (current_width, current_height) = self.current_size.get();
|
|
||||||
if current_width != cfg_event.width || current_height != cfg_event.height {
|
|
||||||
self.current_size.set((cfg_event.width, cfg_event.height));
|
|
||||||
events.push_back(Resized(cfg_event.width as u32, cfg_event.height as u32));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ffi::MotionNotify => {
|
|
||||||
use events::Event::MouseMoved;
|
|
||||||
let event: &ffi::XMotionEvent = unsafe { mem::transmute(&xev) };
|
|
||||||
events.push_back(MouseMoved((event.x as i32, event.y as i32)));
|
|
||||||
},
|
|
||||||
|
|
||||||
ffi::KeyPress | ffi::KeyRelease => {
|
|
||||||
use events::Event::{KeyboardInput, ReceivedCharacter};
|
|
||||||
use events::ElementState::{Pressed, Released};
|
|
||||||
let event: &mut ffi::XKeyEvent = unsafe { mem::transmute(&xev) };
|
|
||||||
|
|
||||||
if event.type_ == ffi::KeyPress {
|
|
||||||
let raw_ev: *mut ffi::XKeyEvent = event;
|
|
||||||
unsafe { ffi::XFilterEvent(mem::transmute(raw_ev), self.x.window) };
|
|
||||||
}
|
|
||||||
|
|
||||||
let state = if xev.type_ == ffi::KeyPress { Pressed } else { Released };
|
|
||||||
|
|
||||||
let written = unsafe {
|
|
||||||
use std::str;
|
|
||||||
|
|
||||||
let mut buffer: [u8; 16] = [mem::uninitialized(); 16];
|
|
||||||
let raw_ev: *mut ffi::XKeyEvent = event;
|
|
||||||
let count = ffi::Xutf8LookupString(self.x.ic, mem::transmute(raw_ev),
|
|
||||||
mem::transmute(buffer.as_mut_ptr()),
|
|
||||||
buffer.len() as libc::c_int, ptr::null_mut(), ptr::null_mut());
|
|
||||||
|
|
||||||
str::from_utf8(&buffer.as_slice()[..count as usize]).unwrap_or("").to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
for chr in written.as_slice().chars() {
|
|
||||||
events.push_back(ReceivedCharacter(chr));
|
|
||||||
}
|
|
||||||
|
|
||||||
let keysym = unsafe {
|
|
||||||
ffi::XKeycodeToKeysym(self.x.display, event.keycode as ffi::KeyCode, 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
let vkey = events::keycode_to_element(keysym as libc::c_uint);
|
|
||||||
|
|
||||||
events.push_back(KeyboardInput(state, event.keycode as u8, vkey));
|
|
||||||
},
|
|
||||||
|
|
||||||
ffi::ButtonPress | ffi::ButtonRelease => {
|
|
||||||
use events::Event::{MouseInput, MouseWheel};
|
|
||||||
use events::ElementState::{Pressed, Released};
|
|
||||||
use events::MouseButton::{Left, Right, Middle};
|
|
||||||
|
|
||||||
let event: &ffi::XButtonEvent = unsafe { mem::transmute(&xev) };
|
|
||||||
|
|
||||||
let state = if xev.type_ == ffi::ButtonPress { Pressed } else { Released };
|
|
||||||
|
|
||||||
let button = match event.button {
|
|
||||||
ffi::Button1 => Some(Left),
|
|
||||||
ffi::Button2 => Some(Middle),
|
|
||||||
ffi::Button3 => Some(Right),
|
|
||||||
ffi::Button4 => {
|
|
||||||
events.push_back(MouseWheel(1));
|
|
||||||
None
|
|
||||||
}
|
|
||||||
ffi::Button5 => {
|
|
||||||
events.push_back(MouseWheel(-1));
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => None
|
|
||||||
};
|
|
||||||
|
|
||||||
match button {
|
|
||||||
Some(button) =>
|
|
||||||
events.push_back(MouseInput(state, button)),
|
|
||||||
None => ()
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
events
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_events(&self) -> RingBuf<Event> {
|
pub fn wait_events(&self) -> WaitEventsIterator {
|
||||||
use std::mem;
|
WaitEventsIterator {
|
||||||
|
window: self
|
||||||
loop {
|
|
||||||
// this will block until an event arrives, but doesn't remove
|
|
||||||
// it from the queue
|
|
||||||
let mut xev = unsafe { mem::uninitialized() };
|
|
||||||
unsafe { ffi::XPeekEvent(self.x.display, &mut xev) };
|
|
||||||
|
|
||||||
// calling poll_events()
|
|
||||||
let ev = self.poll_events();
|
|
||||||
if ev.len() >= 1 {
|
|
||||||
return ev;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue