diff options
Diffstat (limited to 'src/x11')
| -rw-r--r-- | src/x11/ffi.rs | 45 | ||||
| -rw-r--r-- | src/x11/mod.rs | 68 | 
2 files changed, 96 insertions, 17 deletions
diff --git a/src/x11/ffi.rs b/src/x11/ffi.rs index 2c94820..ec5b69c 100644 --- a/src/x11/ffi.rs +++ b/src/x11/ffi.rs @@ -9,7 +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 Drawable = XID;    // TODO: not sure  pub type GLXContext = *const ();  pub type GLXContextID = XID;  pub type GLXDrawable = XID; @@ -25,7 +25,10 @@ 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; @@ -201,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; @@ -1333,11 +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; +        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, @@ -1346,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 c2b2044..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, @@ -199,6 +226,10 @@ impl Window {              }              match xev.type_ { +                ffi::KeymapNotify => { +                    unsafe { ffi::XRefreshKeyboardMapping(&xev) } +                }, +                  ffi::ClientMessage => {                      use Closed;                      use std::sync::atomics::Relaxed; @@ -224,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)); @@ -257,7 +309,7 @@ impl Window {                      if elem.is_some() {                          let elem = elem.unwrap(); -                         +                          if xev.type_ == ffi::ButtonPress {                              events.push(Pressed(elem));                          } else if xev.type_ == ffi::ButtonRelease { @@ -318,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); }      }  }  | 
