diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/x11/events.rs | 48 | ||||
| -rw-r--r-- | src/x11/ffi.rs | 49 | ||||
| -rw-r--r-- | src/x11/mod.rs | 114 | 
3 files changed, 172 insertions, 39 deletions
| diff --git a/src/x11/events.rs b/src/x11/events.rs index 8b78136..78d310c 100644 --- a/src/x11/events.rs +++ b/src/x11/events.rs @@ -5,14 +5,14 @@ use Element;  pub fn keycode_to_element(scancode: libc::c_uint) -> Option<Element> {      Some(match scancode {          //ffi::XK_BackSpace => events::Backspace, -        //ffi::XK_Tab => events::Tab, +        ffi::XK_Tab => events::Tab,          //ffi::XK_Linefeed => events::Linefeed,          //ffi::XK_Clear => events::Clear, -        //ffi::XK_Return => events::Return, +        ffi::XK_Return => events::Return,          //ffi::XK_Pause => events::Pause,          //ffi::XK_Scroll_Lock => events::Scroll_lock,          //ffi::XK_Sys_Req => events::Sys_req, -        //ffi::XK_Escape => events::Escape, +        ffi::XK_Escape => events::Escape,          //ffi::XK_Delete => events::Delete,          //ffi::XK_Multi_key => events::Multi_key,          //ffi::XK_Kanji => events::Kanji, @@ -33,10 +33,10 @@ pub fn keycode_to_element(scancode: libc::c_uint) -> Option<Element> {          //ffi::XK_Eisu_Shift => events::Eisu_shift,          //ffi::XK_Eisu_toggle => events::Eisu_toggle,          //ffi::XK_Home => events::Home, -        //ffi::XK_Left => events::Left, -        //ffi::XK_Up => events::Up, -        //ffi::XK_Right => events::Right, -        //ffi::XK_Down => events::Down, +        ffi::XK_Left => events::Left, +        ffi::XK_Up => events::Up, +        ffi::XK_Right => events::Right, +        ffi::XK_Down => events::Down,          //ffi::XK_Prior => events::Prior,          //ffi::XK_Page_Up => events::Page_up,          //ffi::XK_Next => events::Next, @@ -49,7 +49,7 @@ pub fn keycode_to_element(scancode: libc::c_uint) -> Option<Element> {          //ffi::XK_Select => events::Select,          //ffi::XK_Print => events::Print,          //ffi::XK_Execute => events::Execute, -        //ffi::XK_Insert => events::Insert, +        ffi::XK_Insert => events::Insert,          //ffi::XK_Undo => events::Undo,          //ffi::XK_Redo => events::Redo,          //ffi::XK_Menu => events::Menu, @@ -97,25 +97,25 @@ pub fn keycode_to_element(scancode: libc::c_uint) -> Option<Element> {          //ffi::XK_KP_7 => events::Kp_7,          //ffi::XK_KP_8 => events::Kp_8,          //ffi::XK_KP_9 => events::Kp_9, -        //ffi::XK_F1 => events::F1, -        //ffi::XK_F2 => events::F2, -        //ffi::XK_F3 => events::F3, -        //ffi::XK_F4 => events::F4, -        //ffi::XK_F5 => events::F5, -        //ffi::XK_F6 => events::F6, -        //ffi::XK_F7 => events::F7, -        //ffi::XK_F8 => events::F8, -        //ffi::XK_F9 => events::F9, -        //ffi::XK_F10 => events::F10, -        //ffi::XK_F11 => events::F11, +        ffi::XK_F1 => events::F1, +        ffi::XK_F2 => events::F2, +        ffi::XK_F3 => events::F3, +        ffi::XK_F4 => events::F4, +        ffi::XK_F5 => events::F5, +        ffi::XK_F6 => events::F6, +        ffi::XK_F7 => events::F7, +        ffi::XK_F8 => events::F8, +        ffi::XK_F9 => events::F9, +        ffi::XK_F10 => events::F10, +        ffi::XK_F11 => events::F11,          //ffi::XK_L1 => events::L1, -        //ffi::XK_F12 => events::F12, +        ffi::XK_F12 => events::F12,          //ffi::XK_L2 => events::L2, -        //ffi::XK_F13 => events::F13, +        ffi::XK_F13 => events::F13,          //ffi::XK_L3 => events::L3, -        //ffi::XK_F14 => events::F14, +        ffi::XK_F14 => events::F14,          //ffi::XK_L4 => events::L4, -        //ffi::XK_F15 => events::F15, +        ffi::XK_F15 => events::F15,          //ffi::XK_L5 => events::L5,          //ffi::XK_F16 => events::F16,          //ffi::XK_L6 => events::L6, @@ -171,7 +171,7 @@ pub fn keycode_to_element(scancode: libc::c_uint) -> Option<Element> {          //ffi::XK_Super_R => events::Super_r,          //ffi::XK_Hyper_L => events::Hyper_l,          //ffi::XK_Hyper_R => events::Hyper_r, -        //ffi::XK_space => events::Space, +        ffi::XK_space => events::Space,          //ffi::XK_exclam => events::Exclam,          //ffi::XK_quotedbl => events::Quotedbl,          //ffi::XK_numbersign => events::Numbersign, diff --git a/src/x11/ffi.rs b/src/x11/ffi.rs index 4a72ca3..ec5b69c 100644 --- a/src/x11/ffi.rs +++ b/src/x11/ffi.rs @@ -9,6 +9,7 @@ pub type Bool = libc::c_int;  pub type Colormap = XID;  pub type Cursor = XID;  pub type Display = (); +pub type Drawable = XID;    // TODO: not sure  pub type GLXContext = *const ();  pub type GLXContextID = XID;  pub type GLXDrawable = XID; @@ -24,11 +25,20 @@ pub type Time = libc::c_ulong;  pub type Visual = ();   // TODO: not sure  pub type VisualID = libc::c_ulong;   // TODO: not sure  pub type Window = XID; +pub type XrmDatabase = *const ();       // TODO: not sure +pub type XIC = *mut ();  pub type XID = uint; +pub type XIM = *mut ();  pub static AllocNone: libc::c_int = 0;  pub static AllocAll: libc::c_int = 1; +pub static Button1: libc::c_uint = 1; +pub static Button2: libc::c_uint = 2; +pub static Button3: libc::c_uint = 3; +pub static Button4: libc::c_uint = 4; +pub static Button5: libc::c_uint = 5; +  pub static InputOutput: libc::c_uint = 1;  pub static InputOnly: libc::c_uint = 2; @@ -158,6 +168,7 @@ pub static GLX_TRANSPARENT_RED_VALUE: libc::c_int = 0x25;  pub static GLX_TRANSPARENT_GREEN_VALUE: libc::c_int = 0x26;  pub static GLX_TRANSPARENT_BLUE_VALUE: libc::c_int = 0x27;  pub static GLX_TRANSPARENT_ALPHA_VALUE: libc::c_int = 0x28; +#[allow(type_overflow)]  pub static GLX_DONT_CARE: libc::c_int = 0xFFFFFFFF;  pub static GLX_NONE: libc::c_int = 0x8000;  pub static GLX_SLOW_CONFIG: libc::c_int = 0x8001; @@ -193,6 +204,16 @@ pub static GLX_PBUFFER: libc::c_int = 0x8023;  pub static GLX_PBUFFER_HEIGHT: libc::c_int = 0x8040;  pub static GLX_PBUFFER_WIDTH: libc::c_int = 0x8041; +pub static XIMPreeditArea: libc::c_long = 0x0001; +pub static XIMPreeditCallbacks: libc::c_long = 0x0002; +pub static XIMPreeditPosition: libc::c_long = 0x0004; +pub static XIMPreeditNothing: libc::c_long = 0x0008; +pub static XIMPreeditNone: libc::c_long = 0x0010; +pub static XIMStatusArea: libc::c_long = 0x0100; +pub static XIMStatusCallbacks: libc::c_long = 0x0200; +pub static XIMStatusNothing: libc::c_long = 0x0400; +pub static XIMStatusNone: libc::c_long = 0x0800; +  pub static XK_BackSpace: libc::c_uint = 0xFF08;  pub static XK_Tab: libc::c_uint = 0xFF09;  pub static XK_Linefeed: libc::c_uint = 0xFF0A; @@ -1325,7 +1346,12 @@ extern "C" {      pub fn XDefaultRootWindow(display: *mut Display) -> Window;      pub fn XDefaultScreen(display: *mut Display) -> libc::c_int;      pub fn XDestroyWindow(display: *mut Display, w: Window); +    pub fn XFilterEvent(event: *mut XEvent, w: Window) -> Bool;      pub fn XFlush(display: *mut Display); +    pub fn XGetGeometry(display: *mut Display, d: Drawable, root_return: *mut Window, +        x_return: *mut libc::c_int, y_return: *mut libc::c_int, +        width_return: *mut libc::c_uint, height_return: *mut libc::c_uint, +        border_width_return: *mut libc::c_uint, depth_return: *mut libc::c_uint) -> Status;      pub fn XInternAtom(display: *mut Display, atom_name: *const libc::c_char,          only_if_exists: Bool) -> Atom;      pub fn XKeycodeToKeysym(display: *mut Display, keycode: KeyCode, @@ -1334,26 +1360,37 @@ extern "C" {      pub fn XNextEvent(display: *mut Display, event_return: *mut XEvent);      pub fn XOpenDisplay(display_name: *const libc::c_char) -> *mut Display;      pub fn XPeekEvent(display: *mut Display, event_return: *mut XEvent); +    pub fn XRefreshKeyboardMapping(event_map: *const XEvent);      pub fn XSetWMProtocols(display: *mut Display, w: Window, protocols: *mut Atom,          count: libc::c_int) -> Status;      pub fn XStoreName(display: *mut Display, w: Window, window_name: *const libc::c_char); +    pub fn XCloseIM(im: XIM) -> Status; +    pub fn XOpenIM(display: *mut Display, db: XrmDatabase, res_name: *mut libc::c_char, +        res_class: *mut libc::c_char) -> XIM; + +    // TODO: this is a vararg function +    //pub fn XCreateIC(im: XIM, ...) -> XIC; +    pub fn XCreateIC(im: XIM, a: *const libc::c_char, b: libc::c_long, c: *const libc::c_char, +        d: Window, e: *const ()) -> XIC; +    pub fn XDestroyIC(ic: XIC); +    pub fn XSetICFocus(ic: XIC); +    pub fn XUnsetICFocus(ic: XIC); + +    pub fn Xutf8LookupString(ic: XIC, event: *mut XKeyEvent, +        buffer_return: *mut libc::c_char, bytes_buffer: libc::c_int, +        keysym_return: *mut KeySym, status_return: *mut Status) -> libc::c_int; +      pub fn glXCreateContext(dpy: *mut Display, vis: *const XVisualInfo,          shareList: GLXContext, direct: Bool) -> GLXContext; -      pub fn glXDestroyContext(dpy: *mut Display, ctx: GLXContext); -      pub fn glXChooseFBConfig(dpy: *mut Display, screen: libc::c_int,          attrib_list: *const libc::c_int, nelements: *mut libc::c_int); -      pub fn glXChooseVisual(dpy: *mut Display, screen: libc::c_int,          attribList: *const libc::c_int) -> *const XVisualInfo; -      pub fn glXGetProcAddress(procName: *const libc::c_uchar) -> *const (); -      pub fn glXMakeCurrent(dpy: *mut Display, drawable: GLXDrawable,          ctx: GLXContext) -> Bool; -      pub fn glXSwapBuffers(dpy: *mut Display, drawable: GLXDrawable);  } diff --git a/src/x11/mod.rs b/src/x11/mod.rs index 61488a1..76339f5 100644 --- a/src/x11/mod.rs +++ b/src/x11/mod.rs @@ -9,6 +9,8 @@ mod ffi;  pub struct Window {      display: *mut ffi::Display,      window: ffi::Window, +    im: ffi::XIM, +    ic: ffi::XIC,      context: ffi::GLXContext,      is_closed: AtomicBool,      wm_delete_window: ffi::Atom, @@ -80,7 +82,7 @@ impl Window {              swa.event_mask = ffi::ExposureMask | ffi::ResizeRedirectMask |                  ffi::VisibilityChangeMask | ffi::KeyPressMask | ffi::PointerMotionMask |                  ffi::KeyPressMask | ffi::KeyReleaseMask | ffi::ButtonPressMask | -                ffi::ButtonReleaseMask; +                ffi::ButtonReleaseMask | ffi::KeymapStateMask;              swa          }; @@ -109,6 +111,29 @@ impl Window {              wm_delete_window          }; +        // creating  +        let im = unsafe { +            let im = ffi::XOpenIM(display, ptr::null(), ptr::mut_null(), ptr::mut_null()); +            if im.is_null() { +                return Err(format!("XOpenIM failed")); +            } +            im +        }; + +        // creating input context +        let ic = unsafe { +            use std::c_str::ToCStr; + +            let ic = ffi::XCreateIC(im, "inputStyle".to_c_str().as_ptr(), +                ffi::XIMPreeditNothing | ffi::XIMStatusNothing, "clientWindow".to_c_str().as_ptr(), +                window, ptr::null()); +            if ic.is_null() { +                return Err(format!("XCreateIC failed")); +            } +            ffi::XSetICFocus(ic); +            ic +        }; +          // creating GL context          let context = unsafe {              ffi::glXCreateContext(display, visual_infos, ptr::null(), 1) @@ -118,6 +143,8 @@ impl Window {          Ok(Window{              display: display,              window: window, +            im: im, +            ic: ic,              context: context,              is_closed: AtomicBool::new(false),              wm_delete_window: wm_delete_window, @@ -136,8 +163,31 @@ impl Window {          }      } +    fn get_geometry(&self) -> Option<(int, int, uint, uint)> { +        unsafe { +            use std::mem; + +            let mut root: ffi::Window = mem::uninitialized(); +            let mut x: libc::c_int = mem::uninitialized(); +            let mut y: libc::c_int = mem::uninitialized(); +            let mut width: libc::c_uint = mem::uninitialized(); +            let mut height: libc::c_uint = mem::uninitialized(); +            let mut border: libc::c_uint = mem::uninitialized(); +            let mut depth: libc::c_uint = mem::uninitialized(); + +            if ffi::XGetGeometry(self.display, self.window, +                &mut root, &mut x, &mut y, &mut width, &mut height, +                &mut border, &mut depth) == 0 +            { +                return None; +            } + +            Some((x as int, y as int, width as uint, height as uint)) +        } +    } +      pub fn get_position(&self) -> Option<(int, int)> { -        unimplemented!() +        self.get_geometry().map(|(x, y, _, _)| (x, y))      }      pub fn set_position(&self, x: uint, y: uint) { @@ -145,7 +195,7 @@ impl Window {      }      pub fn get_inner_size(&self) -> Option<(uint, uint)> { -        unimplemented!() +        self.get_geometry().map(|(_, _, w, h)| (w, h))      }      pub fn get_outer_size(&self) -> Option<(uint, uint)> { @@ -176,6 +226,10 @@ impl Window {              }              match xev.type_ { +                ffi::KeymapNotify => { +                    unsafe { ffi::XRefreshKeyboardMapping(&xev) } +                }, +                  ffi::ClientMessage => {                      use Closed;                      use std::sync::atomics::Relaxed; @@ -201,11 +255,32 @@ impl Window {                  },                  ffi::KeyPress | ffi::KeyRelease => { -                    use {Pressed, Released}; -                    let event: &ffi::XKeyEvent = unsafe { mem::transmute(&xev) }; +                    use {Pressed, Released, ReceivedCharacter}; +                    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) }; +                    }                      let keysym = unsafe { ffi::XKeycodeToKeysym(self.display, event.keycode as ffi::KeyCode, 0) }; +                    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.ic, mem::transmute(raw_ev),  +                            mem::transmute(buffer.as_mut_ptr()), +                            buffer.len() as libc::c_int, ptr::mut_null(), ptr::mut_null()); + +                        str::from_utf8(buffer.as_slice().slice_to(count as uint)).unwrap_or("").to_string() +                    }; + +                    for chr in written.as_slice().chars() { +                        events.push(ReceivedCharacter(chr)); +                    } +                      match events::keycode_to_element(keysym as libc::c_uint) {                          Some(elem) if xev.type_ == ffi::KeyPress => {                              events.push(Pressed(elem)); @@ -220,8 +295,27 @@ impl Window {                  ffi::ButtonPress | ffi::ButtonRelease => {                      use {Pressed, Released}; +                    use events;                      let event: &ffi::XButtonEvent = unsafe { mem::transmute(&xev) }; -                    //events.push(CursorPositionChanged(event.x as uint, event.y as uint)); + +                    let elem = match event.button { +                        ffi::Button1 => Some(events::Button1), +                        ffi::Button2 => Some(events::Button2), +                        ffi::Button3 => Some(events::Button3), +                        ffi::Button4 => Some(events::Button4), +                        ffi::Button5 => Some(events::Button5), +                        _ => None +                    }; + +                    if elem.is_some() { +                        let elem = elem.unwrap(); + +                        if xev.type_ == ffi::ButtonPress { +                            events.push(Pressed(elem)); +                        } else if xev.type_ == ffi::ButtonRelease { +                            events.push(Released(elem)); +                        } +                    }                  },                  _ => () @@ -276,8 +370,10 @@ impl Window {  impl Drop for Window {      fn drop(&mut self) { -        unsafe { ffi::glXDestroyContext(self.display, self.context) } -        unsafe { ffi::XDestroyWindow(self.display, self.window) } -        unsafe { ffi::XCloseDisplay(self.display) } +        unsafe { ffi::glXDestroyContext(self.display, self.context); } +        unsafe { ffi::XDestroyIC(self.ic); } +        unsafe { ffi::XCloseIM(self.im); } +        unsafe { ffi::XDestroyWindow(self.display, self.window); } +        unsafe { ffi::XCloseDisplay(self.display); }      }  } | 
