diff options
Diffstat (limited to 'src/x11')
-rw-r--r-- | src/x11/ffi.rs | 10 | ||||
-rw-r--r-- | src/x11/headless.rs | 32 | ||||
-rw-r--r-- | src/x11/mod.rs | 5 | ||||
-rw-r--r-- | src/x11/window/mod.rs | 161 | ||||
-rw-r--r-- | src/x11/window/monitor.rs | 19 |
5 files changed, 152 insertions, 75 deletions
diff --git a/src/x11/ffi.rs b/src/x11/ffi.rs index 5610eee..5e7b5a1 100644 --- a/src/x11/ffi.rs +++ b/src/x11/ffi.rs @@ -1241,7 +1241,7 @@ pub struct XSetWindowAttributes { #[repr(C)] pub struct XEvent { pub type_: libc::c_int, - pad: [libc::c_long, ..24], + pad: [libc::c_long; 24], } #[repr(C)] @@ -1253,7 +1253,7 @@ pub struct XClientMessageEvent { pub window: Window, pub message_type: Atom, pub format: libc::c_int, - pub l: [libc::c_long, ..5], + pub l: [libc::c_long; 5], } #[repr(C)] @@ -1384,6 +1384,7 @@ extern "C" { #[link(name = "GL")] #[link(name = "X11")] #[link(name = "Xxf86vm")] +#[link(name = "Xcursor")] extern "C" { pub fn XCloseDisplay(display: *mut Display); pub fn XCheckMaskEvent(display: *mut Display, event_mask: libc::c_long, @@ -1435,7 +1436,7 @@ extern "C" { res_class: *mut libc::c_char) -> XIM; // TODO: this is a vararg function - //pub fn XCreateIC(im: XIM, ...) -> XIC; + //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); @@ -1454,6 +1455,9 @@ extern "C" { x: libc::c_int, y: libc::c_int) -> Bool; pub fn XF86VidModeGetAllModeLines(dpy: *mut Display, screen: libc::c_int, modecount_return: *mut libc::c_int, modesinfo: *mut *mut *mut XF86VidModeModeInfo) -> Bool; + + pub fn XcursorLibraryLoadCursor(dpy: *mut Display, name: *const libc::c_char) -> Cursor; + pub fn XDefineCursor(dby: *mut Display, w: Window, cursor: Cursor); } /* diff --git a/src/x11/headless.rs b/src/x11/headless.rs index 95f5233..7692832 100644 --- a/src/x11/headless.rs +++ b/src/x11/headless.rs @@ -1,23 +1,32 @@ -use HeadlessRendererBuilder; +use BuilderAttribs; use CreationError; use CreationError::OsError; use libc; use std::{mem, ptr}; use super::ffi; +fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const i8) -> T { + use std::ffi::CString; + let c_str = CString::from_slice(s.as_bytes()); + f(c_str.as_slice_with_nul().as_ptr()) +} + pub struct HeadlessContext { context: ffi::OSMesaContext, buffer: Vec<u32>, - width: uint, - height: uint, + width: u32, + height: u32, } impl HeadlessContext { - pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> { + pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> { + let dimensions = builder.dimensions.unwrap(); + Ok(HeadlessContext { - width: builder.dimensions.0, - height: builder.dimensions.1, - buffer: Vec::from_elem(builder.dimensions.0 * builder.dimensions.1, unsafe { mem::uninitialized() }), + width: dimensions.0, + height: dimensions.1, + buffer: ::std::iter::repeat(unsafe { mem::uninitialized() }) + .take((dimensions.0 * dimensions.1) as usize).collect(), context: unsafe { let ctxt = ffi::OSMesaCreateContext(0x1908, ptr::null()); if ctxt.is_null() { @@ -39,10 +48,8 @@ impl HeadlessContext { } pub fn get_proc_address(&self, addr: &str) -> *const () { - use std::c_str::ToCStr; - unsafe { - addr.with_c_str(|s| { + with_c_str(addr, |s| { ffi::OSMesaGetProcAddress(mem::transmute(s)) as *const () }) } @@ -53,7 +60,7 @@ impl HeadlessContext { ::Api::OpenGl } - pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) { + pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) { } } @@ -62,3 +69,6 @@ impl Drop for HeadlessContext { unsafe { ffi::OSMesaDestroyContext(self.context) } } } + +unsafe impl Send for HeadlessContext {} +unsafe impl Sync for HeadlessContext {} diff --git a/src/x11/mod.rs b/src/x11/mod.rs index 9ce789f..22184a9 100644 --- a/src/x11/mod.rs +++ b/src/x11/mod.rs @@ -11,3 +11,8 @@ mod headless; #[cfg(feature = "window")] mod window; + +#[cfg(not(feature = "window"))] +pub type Window = (); // TODO: hack to make things work +#[cfg(not(feature = "window"))] +pub type MonitorID = (); // TODO: hack to make things work diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs index 422b5b6..5b70a19 100644 --- a/src/x11/window/mod.rs +++ b/src/x11/window/mod.rs @@ -1,10 +1,11 @@ -use {Event, WindowBuilder}; +use {Event, BuilderAttribs, MouseCursor}; use CreationError; use CreationError::OsError; use libc; use std::{mem, ptr}; use std::cell::Cell; use std::sync::atomic::AtomicBool; +use std::collections::RingBuf; use super::ffi; use std::sync::{Arc, Once, ONCE_INIT}; @@ -16,13 +17,19 @@ mod monitor; static THREAD_INIT: Once = ONCE_INIT; fn ensure_thread_init() { - THREAD_INIT.doit(|| { + THREAD_INIT.call_once(|| { unsafe { ffi::XInitThreads(); } }); } +fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const i8) -> T { + use std::ffi::CString; + let c_str = CString::from_slice(s.as_bytes()); + f(c_str.as_slice_with_nul().as_ptr()) +} + struct XWindow { display: *mut ffi::Display, window: ffi::Window, @@ -34,6 +41,9 @@ struct XWindow { im: ffi::XIM, } +unsafe impl Send for Window {} +unsafe impl Sync for Window {} + impl Drop for XWindow { fn drop(&mut self) { unsafe { @@ -53,7 +63,7 @@ impl Drop for XWindow { } } -#[deriving(Clone)] +#[derive(Clone)] pub struct WindowProxy { x: Arc<XWindow>, } @@ -86,7 +96,7 @@ pub struct Window { } impl Window { - pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> { + pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> { ensure_thread_init(); let dimensions = builder.dimensions.unwrap_or((800, 600)); @@ -150,7 +160,7 @@ impl Window { } for i in range(0, mode_num) { - let mode: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as int) as *const _); + let mode: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); if mode.hdisplay == dimensions.0 as u16 && mode.vdisplay == dimensions.1 as u16 { best_mode = i; } @@ -159,7 +169,7 @@ impl Window { return Err(OsError(format!("Could not find a suitable graphics mode"))); } - modes + modes }; let xf86_desk_mode = unsafe { @@ -205,7 +215,7 @@ impl Window { if builder.monitor.is_some() { window_attributes |= ffi::CWOverrideRedirect; unsafe { - ffi::XF86VidModeSwitchToMode(display, screen_id, *modes.offset(best_mode as int)); + ffi::XF86VidModeSwitchToMode(display, screen_id, *modes.offset(best_mode as isize)); ffi::XF86VidModeSetViewPort(display, screen_id, 0, 0); set_win_attr.override_redirect = 1; } @@ -230,13 +240,13 @@ impl Window { // creating window, step 2 let wm_delete_window = unsafe { - use std::c_str::ToCStr; - - let delete_window = "WM_DELETE_WINDOW".to_c_str(); - let mut wm_delete_window = ffi::XInternAtom(display, delete_window.as_ptr(), 0); + let mut wm_delete_window = with_c_str("WM_DELETE_WINDOW", |delete_window| + ffi::XInternAtom(display, delete_window, 0) + ); ffi::XSetWMProtocols(display, window, &mut wm_delete_window, 1); - let c_title = builder.title.to_c_str(); - ffi::XStoreName(display, window, c_title.as_ptr()); + with_c_str(&*builder.title, |title| {; + ffi::XStoreName(display, window, title); + }); ffi::XFlush(display); wm_delete_window @@ -253,13 +263,15 @@ impl Window { // creating input context let ic = unsafe { - use std::c_str::ToCStr; - - let input_style = "inputStyle".to_c_str(); - let client_window = "clientWindow".to_c_str(); - let ic = ffi::XCreateIC(im, input_style.as_ptr(), - ffi::XIMPreeditNothing | ffi::XIMStatusNothing, client_window.as_ptr(), - window, ptr::null()); + let ic = with_c_str("inputStyle", |input_style| + with_c_str("clientWindow", |client_window| + ffi::XCreateIC( + im, input_style, + ffi::XIMPreeditNothing | ffi::XIMStatusNothing, client_window, + window, ptr::null() + ) + ) + ); if ic.is_null() { return Err(OsError(format!("XCreateIC failed"))); } @@ -298,14 +310,14 @@ impl Window { // loading the extra GLX functions let extra_functions = ffi::glx_extra::Glx::load_with(|addr| { - addr.with_c_str(|s| { + with_c_str(addr, |s| { use libc; ffi::glx::GetProcAddress(s as *const u8) as *const libc::c_void }) }); let share = if let Some(win) = builder.sharing { - win.window.x.context + win.x.context } else { ptr::null() }; @@ -346,16 +358,15 @@ impl Window { } pub fn is_closed(&self) -> bool { - use std::sync::atomic::Relaxed; + use std::sync::atomic::Ordering::Relaxed; self.is_closed.load(Relaxed) } pub fn set_title(&self, title: &str) { - let c_title = title.to_c_str(); - unsafe { - ffi::XStoreName(self.x.display, self.x.window, c_title.as_ptr()); + with_c_str(title, |title| unsafe { + ffi::XStoreName(self.x.display, self.x.window, title); ffi::XFlush(self.x.display); - } + }) } pub fn show(&self) { @@ -372,7 +383,7 @@ impl Window { } } - fn get_geometry(&self) -> Option<(int, int, uint, uint)> { + fn get_geometry(&self) -> Option<(i32, i32, u32, u32)> { unsafe { use std::mem; @@ -391,27 +402,27 @@ impl Window { return None; } - Some((x as int, y as int, width as uint, height as uint)) + Some((x as i32, y as i32, width as u32, height as u32)) } } - pub fn get_position(&self) -> Option<(int, int)> { + pub fn get_position(&self) -> Option<(i32, i32)> { self.get_geometry().map(|(x, y, _, _)| (x, y)) } - pub fn set_position(&self, x: int, y: int) { + pub fn set_position(&self, x: i32, y: i32) { unsafe { ffi::XMoveWindow(self.x.display, self.x.window, x as libc::c_int, y as libc::c_int) } } - pub fn get_inner_size(&self) -> Option<(uint, uint)> { + pub fn get_inner_size(&self) -> Option<(u32, u32)> { self.get_geometry().map(|(_, _, w, h)| (w, h)) } - pub fn get_outer_size(&self) -> Option<(uint, uint)> { + pub fn get_outer_size(&self) -> Option<(u32, u32)> { unimplemented!() } - pub fn set_inner_size(&self, _x: uint, _y: uint) { + pub fn set_inner_size(&self, _x: u32, _y: u32) { unimplemented!() } @@ -421,10 +432,10 @@ impl Window { } } - pub fn poll_events(&self) -> Vec<Event> { + pub fn poll_events(&self) -> RingBuf<Event> { use std::mem; - let mut events = Vec::new(); + let mut events = RingBuf::new(); loop { use std::num::Int; @@ -447,15 +458,15 @@ impl Window { ffi::ClientMessage => { use events::Event::{Closed, Awakened}; - use std::sync::atomic::Relaxed; + 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(Closed); + events.push_back(Closed); } else { - events.push(Awakened); + events.push_back(Awakened); } }, @@ -465,14 +476,14 @@ impl Window { 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(Resized(cfg_event.width as uint, cfg_event.height as uint)); + 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(MouseMoved((event.x as int, event.y as int))); + events.push_back(MouseMoved((event.x as i32, event.y as i32))); }, ffi::KeyPress | ffi::KeyRelease => { @@ -490,18 +501,18 @@ impl Window { let written = unsafe { use std::str; - let mut buffer: [u8, ..16] = [mem::uninitialized(), ..16]; + 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().slice_to(count as uint)) + str::from_utf8(buffer.as_slice().slice_to(count as usize)) .unwrap_or("").to_string() }; for chr in written.as_slice().chars() { - events.push(ReceivedCharacter(chr)); + events.push_back(ReceivedCharacter(chr)); } let keysym = unsafe { @@ -510,7 +521,7 @@ impl Window { let vkey = events::keycode_to_element(keysym as libc::c_uint); - events.push(KeyboardInput(state, event.keycode as u8, vkey)); + events.push_back(KeyboardInput(state, event.keycode as u8, vkey)); }, ffi::ButtonPress | ffi::ButtonRelease => { @@ -527,11 +538,11 @@ impl Window { ffi::Button2 => Some(MiddleMouseButton), ffi::Button3 => Some(RightMouseButton), ffi::Button4 => { - events.push(MouseWheel(1)); + events.push_back(MouseWheel(1)); None } ffi::Button5 => { - events.push(MouseWheel(-1)); + events.push_back(MouseWheel(-1)); None } _ => None @@ -539,7 +550,7 @@ impl Window { match button { Some(button) => - events.push(MouseInput(state, button)), + events.push_back(MouseInput(state, button)), None => () }; }, @@ -551,7 +562,7 @@ impl Window { events } - pub fn wait_events(&self) -> Vec<Event> { + pub fn wait_events(&self) -> RingBuf<Event> { use std::mem; loop { @@ -576,11 +587,10 @@ impl Window { } pub fn get_proc_address(&self, addr: &str) -> *const () { - use std::c_str::ToCStr; use std::mem; unsafe { - addr.with_c_str(|s| { + with_c_str(addr, |s| { ffi::glx::GetProcAddress(mem::transmute(s)) as *const () }) } @@ -599,6 +609,53 @@ impl Window { ::Api::OpenGl } - pub fn set_window_resize_callback(&mut self, _: Option<fn(uint, uint)>) { + pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) { + } + + pub fn set_cursor(&self, cursor: MouseCursor) { + unsafe { + use std::ffi::CString; + let cursor_name = match cursor { + MouseCursor::Alias => "link", + MouseCursor::Arrow => "arrow", + MouseCursor::Cell => "plus", + MouseCursor::Copy => "copy", + MouseCursor::Crosshair => "crosshair", + MouseCursor::Default => "left_ptr", + MouseCursor::Grabbing => "grabbing", + MouseCursor::Hand | MouseCursor::Grab => "hand", + MouseCursor::Help => "question_arrow", + MouseCursor::Move => "move", + MouseCursor::NoDrop => "circle", + MouseCursor::NotAllowed => "crossed_circle", + MouseCursor::Progress => "left_ptr_watch", + + /// Resize cursors + MouseCursor::EResize => "right_side", + MouseCursor::NResize => "top_side", + MouseCursor::NeResize => "top_right_corner", + MouseCursor::NwResize => "top_left_corner", + MouseCursor::SResize => "bottom_side", + MouseCursor::SeResize => "bottom_right_corner", + MouseCursor::SwResize => "bottom_left_corner", + MouseCursor::WResize => "left_side", + MouseCursor::EwResize | MouseCursor::ColResize => "h_double_arrow", + MouseCursor::NsResize | MouseCursor::RowResize => "v_double_arrow", + MouseCursor::NwseResize => "bd_double_arrow", + MouseCursor::NeswResize => "fd_double_arrow", + + MouseCursor::Text | MouseCursor::VerticalText => "xterm", + MouseCursor::Wait => "watch", + + /// TODO: Find matching X11 cursors + MouseCursor::ContextMenu | MouseCursor::NoneCursor | + MouseCursor::AllScroll | MouseCursor::ZoomIn | + MouseCursor::ZoomOut => "left_ptr", + }; + let c_string = CString::from_slice(cursor_name.as_bytes()); + let xcursor = ffi::XcursorLibraryLoadCursor(self.x.display, c_string.as_ptr()); + ffi::XDefineCursor (self.x.display, self.x.window, xcursor); + ffi::XFlush(self.x.display); + } } } diff --git a/src/x11/window/monitor.rs b/src/x11/window/monitor.rs index f62a8ef..3c188b6 100644 --- a/src/x11/window/monitor.rs +++ b/src/x11/window/monitor.rs @@ -1,10 +1,11 @@ -use std::{ptr}; +use std::ptr; +use std::collections::RingBuf; use super::super::ffi; use super::ensure_thread_init; -pub struct MonitorID(pub uint); +pub struct MonitorID(pub u32); -pub fn get_available_monitors() -> Vec<MonitorID> { +pub fn get_available_monitors() -> RingBuf<MonitorID> { ensure_thread_init(); let nb_monitors = unsafe { let display = ffi::XOpenDisplay(ptr::null()); @@ -16,9 +17,9 @@ pub fn get_available_monitors() -> Vec<MonitorID> { nb_monitors }; - let mut vec = Vec::new(); - vec.grow_fn(nb_monitors as uint, |i| MonitorID(i)); - vec + let mut monitors = RingBuf::new(); + monitors.extend(range(0, nb_monitors).map(|i| MonitorID(i as u32))); + monitors } pub fn get_primary_monitor() -> MonitorID { @@ -33,7 +34,7 @@ pub fn get_primary_monitor() -> MonitorID { primary_monitor }; - MonitorID(primary_monitor as uint) + MonitorID(primary_monitor as u32) } impl MonitorID { @@ -42,7 +43,7 @@ impl MonitorID { Some(format!("Monitor #{}", screen_num)) } - pub fn get_dimensions(&self) -> (uint, uint) { + pub fn get_dimensions(&self) -> (u32, u32) { let dimensions = unsafe { let display = ffi::XOpenDisplay(ptr::null()); let MonitorID(screen_num) = *self; @@ -50,7 +51,7 @@ impl MonitorID { let width = ffi::XWidthOfScreen(screen); let height = ffi::XHeightOfScreen(screen); ffi::XCloseDisplay(display); - (width as uint, height as uint) + (width as u32, height as u32) }; dimensions |