// See LICENSE file for copyright and license details. use x11::xlib::{ XEvent, XKeyEvent, XButtonEvent, XMotionEvent, XCrossingEvent, XCreateWindowEvent, XDestroyWindowEvent, XUnmapEvent, XMapEvent, XConfigureEvent, XExposeEvent, XPending, }; use x11::xlib; use x11::xlib::Display; use std::os::unix::net::{UnixStream,UnixListener}; use libc::c_int; use libc::{ FD_SET, FD_ZERO, FD_ISSET, select, fd_set, }; use std::fmt; use std::ptr; use std::mem::uninitialized; use std::cmp::max; use std::os::unix::io::AsRawFd; use safe_x11::next_xevent; pub enum Event { Key(XKeyEvent, bool), Button(XButtonEvent, bool), Drag(XMotionEvent), Enter(XCrossingEvent), Leave(XCrossingEvent), Generic(XEvent), Create(XCreateWindowEvent), Destroy(XDestroyWindowEvent), Unmap(XUnmapEvent), Map(XMapEvent), Configure(XConfigureEvent), Expose(XExposeEvent), Socket(UnixStream), NoEvent } impl fmt::Debug for Event { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = match *self { Event::Key(ev, pressed) => format!("Key({}, {})", XEvent::from(ev).get_type(), pressed), Event::Button(ev, pressed) => format!("Button({}, {})", XEvent::from(ev).get_type(), pressed), Event::Drag(ev) => format!("Drag({})", XEvent::from(ev).get_type()), Event::Generic(ev) => format!("Generic({})", XEvent::from(ev).get_type()), Event::Enter(ev) => format!("Enter({})", XEvent::from(ev).get_type()), Event::Leave(ev) => format!("Leave({})", XEvent::from(ev).get_type()), Event::Create(ev) => format!("Create({})", XEvent::from(ev).get_type()), Event::Destroy(ev) => format!("Destroy({})", XEvent::from(ev).get_type()), Event::Unmap(ev) => format!("Unmap({})", XEvent::from(ev).get_type()), Event::Map(ev) => format!("Map({})", XEvent::from(ev).get_type()), Event::Configure(ev) => format!("Configure({})", XEvent::from(ev).get_type()), Event::Expose(ev) => format!("Expose({})", XEvent::from(ev).get_type()), Event::Socket(ref ev) => format!("Socket({:?})", ev), Event::NoEvent => String::from("NoEvent"), }; write!(f, "{}", s) } } pub unsafe fn select_event(display: *mut Display, x11fd: c_int, listener: &UnixListener) -> Event { // Return right now if there're some XEvent on the queue if XPending(display) > 0 { return next_event(display); } let socket_fd = listener.as_raw_fd(); let mut read_fdset: fd_set = uninitialized(); FD_ZERO(&mut read_fdset); FD_SET(x11fd, &mut read_fdset); FD_SET(socket_fd, &mut read_fdset); select(max(x11fd, socket_fd) + 1, &mut read_fdset, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()); if FD_ISSET(x11fd, &mut read_fdset) { next_event(display) } else if FD_ISSET(socket_fd, &mut read_fdset) { let mut listener_iter = listener.incoming(); if let Some(Ok(stream)) = listener_iter.nth(0) { return Event::Socket(stream) } else { Event::NoEvent } } else { Event::NoEvent } } pub fn next_event(display: *mut Display) -> Event { let ev = next_xevent(display); match ev.get_type() { 2 => Event::Key(xlib::XKeyEvent::from(ev), true), 3 => Event::Key(xlib::XKeyEvent::from(ev), false), 4 => Event::Button(xlib::XButtonEvent::from(ev), true), 5 => Event::Button(xlib::XButtonEvent::from(ev), false), 6 => Event::Drag(XMotionEvent::from(ev)), 7 => Event::Enter(XCrossingEvent::from(ev)), 8 => Event::Leave(XCrossingEvent::from(ev)), 12 => Event::Expose(XExposeEvent::from(ev)), 16 => Event::Create(XCreateWindowEvent::from(ev)), 17 => Event::Destroy(XDestroyWindowEvent::from(ev)), 18 => Event::Unmap(XUnmapEvent::from(ev)), 19 => Event::Map(XMapEvent::from(ev)), 22 => Event::Configure(XConfigureEvent::from(ev)), e => { println!("Unknown event {}", e); Event::NoEvent }, } }