aboutsummaryrefslogtreecommitdiffstats
path: root/src/x11
diff options
context:
space:
mode:
Diffstat (limited to 'src/x11')
-rw-r--r--src/x11/ffi.rs10
-rw-r--r--src/x11/headless.rs32
-rw-r--r--src/x11/mod.rs5
-rw-r--r--src/x11/window/mod.rs161
-rw-r--r--src/x11/window/monitor.rs19
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