aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/api/x11/window.rs90
1 files changed, 60 insertions, 30 deletions
diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs
index b524795..dc7fa62 100644
--- a/src/api/x11/window.rs
+++ b/src/api/x11/window.rs
@@ -840,20 +840,14 @@ impl Window {
pub fn set_cursor(&self, cursor: MouseCursor) {
unsafe {
- use std::ffi::CString;
- let load = |name :&str| {
- let c_string = CString::new(name.as_bytes().to_vec()).unwrap();
- return (self.x.display.xcursor.XcursorLibraryLoadCursor)(self.x.display.display, c_string.as_ptr());
+ let load = |name: &str| {
+ self.load_cursor(name)
};
- let loadn = |names :&[&str]| {
- for name in names.iter() {
- let xcursor = load(*name);
- if xcursor != 0 {
- return xcursor;
- }
- }
- return 0;
+
+ let loadn = |names: &[&str]| {
+ self.load_first_existing_cursor(names)
};
+
// Try multiple names in some cases where the name
// differs on the desktop environments or themes.
//
@@ -902,8 +896,7 @@ impl Window {
MouseCursor::ZoomIn => load("zoom-in"),
MouseCursor::ZoomOut => load("zoom-out"),
- // TODO: Hide cursor
- MouseCursor::NoneCursor => 0,
+ MouseCursor::NoneCursor => self.create_empty_cursor(),
};
(self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, xcursor);
@@ -914,6 +907,51 @@ impl Window {
}
}
+ fn load_cursor(&self, name: &str) -> ffi::Cursor {
+ use std::ffi::CString;
+ unsafe {
+ let c_string = CString::new(name.as_bytes()).unwrap();
+ (self.x.display.xcursor.XcursorLibraryLoadCursor)(self.x.display.display, c_string.as_ptr())
+ }
+ }
+
+ fn load_first_existing_cursor(&self, names :&[&str]) -> ffi::Cursor {
+ for name in names.iter() {
+ let xcursor = self.load_cursor(name);
+ if xcursor != 0 {
+ return xcursor;
+ }
+ }
+ 0
+ }
+
+ // TODO: This could maybe be cached. I don't think it's worth
+ // the complexity, since cursor changes are not so common,
+ // and this is just allocating a 1x1 pixmap...
+ fn create_empty_cursor(&self) -> ffi::Cursor {
+ use std::mem;
+
+ let data = 0;
+ unsafe {
+ let pixmap = (self.x.display.xlib.XCreateBitmapFromData)(self.x.display.display, self.x.window, &data, 1, 1);
+ if pixmap == 0 {
+ // Failed to allocate
+ return 0;
+ }
+
+ // We don't care about this color, since it only fills bytes
+ // in the pixmap which are not 0 in the mask.
+ let dummy_color: ffi::XColor = mem::uninitialized();
+ let cursor = (self.x.display.xlib.XCreatePixmapCursor)(self.x.display.display,
+ pixmap,
+ pixmap,
+ &dummy_color as *const _ as *mut _,
+ &dummy_color as *const _ as *mut _, 0, 0);
+ (self.x.display.xlib.XFreePixmap)(self.x.display.display, pixmap);
+ cursor
+ }
+ }
+
pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
use CursorState::{ Grab, Normal, Hide };
@@ -932,13 +970,10 @@ impl Window {
},
Normal => {},
Hide => {
+ // NB: Calling XDefineCursor with None (aka 0)
+ // as a value resets the cursor to the default.
unsafe {
- let xcursor = (self.x.display.xlib.XCreateFontCursor)(self.x.display.display, 68/*XC_left_ptr*/);
- self.x.display.check_errors().expect("Failed to call XCreateFontCursor");
- (self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, xcursor);
- self.x.display.check_errors().expect("Failed to call XDefineCursor");
- (self.x.display.xlib.XFlush)(self.x.display.display);
- (self.x.display.xlib.XFreeCursor)(self.x.display.display, xcursor);
+ (self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, 0);
}
},
}
@@ -947,18 +982,13 @@ impl Window {
match state {
Normal => Ok(()),
Hide => {
- let data = &[0, 0, 0, 0, 0, 0, 0, 0];
unsafe {
- let mut black = ffi::XColor {
- red: 0, green: 0, blue: 0,
- pad: 0, pixel: 0, flags: 0,
- };
- let bitmap = (self.x.display.xlib.XCreateBitmapFromData)(self.x.display.display, self.x.window, data.as_ptr(), 8, 8);
- let cursor = (self.x.display.xlib.XCreatePixmapCursor)(self.x.display.display, bitmap, bitmap, &mut black, &mut black, 0, 0);
+ let cursor = self.create_empty_cursor();
(self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, cursor);
- self.x.display.check_errors().expect("Failed to call XDefineCursor");
- (self.x.display.xlib.XFreeCursor)(self.x.display.display, cursor);
- (self.x.display.xlib.XFreePixmap)(self.x.display.display, bitmap);
+ if cursor != 0 {
+ (self.x.display.xlib.XFreeCursor)(self.x.display.display, cursor);
+ }
+ self.x.display.check_errors().expect("Failed to call XDefineCursor or free the empty cursor");
}
Ok(())
},