diff options
author | est31 <MTest31@outlook.com> | 2016-04-16 20:37:53 +0200 |
---|---|---|
committer | est31 <MTest31@outlook.com> | 2016-04-17 16:48:27 +0200 |
commit | 7fb6450d17388097619bfb1e675e17c7bc2e3eaa (patch) | |
tree | 494ad68beecf56087b5680ecb828eb474b82a4e9 | |
parent | b9065f56ba0c1fa9c55b6af31d765cc326456548 (diff) | |
download | glutin-7fb6450d17388097619bfb1e675e17c7bc2e3eaa.tar.gz glutin-7fb6450d17388097619bfb1e675e17c7bc2e3eaa.zip |
Improve X11 cursor symbols handling
1. Make it non failing. Before we tried to call XFreeCursor with a
cursor of 0 if we couldn't find a cursor. This has then caused a panic.
2. Introduce a system where multiple special cursors are tried
in order to work with different themes and desktop environments.
This way we get less often into the situation where we have to use a
default cursor.
3. Also set names for some cursors that previously only had a placeholder.
Fixes #765.
Will fix https://github.com/servo/servo/issues/10475 as well.
-rw-r--r-- | src/api/x11/window.rs | 106 |
1 files changed, 66 insertions, 40 deletions
diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs index b84dc09..b524795 100644 --- a/src/api/x11/window.rs +++ b/src/api/x11/window.rs @@ -841,50 +841,76 @@ impl Window { 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", + 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 loadn = |names :&[&str]| { + for name in names.iter() { + let xcursor = load(*name); + if xcursor != 0 { + return xcursor; + } + } + return 0; + }; + // Try multiple names in some cases where the name + // differs on the desktop environments or themes. + // + // Try the better looking (or more suiting) names first. + let mut xcursor = match cursor { + MouseCursor::Alias => load("link"), + MouseCursor::Arrow => load("arrow"), + MouseCursor::Cell => load("plus"), + MouseCursor::Copy => load("copy"), + MouseCursor::Crosshair => load("crosshair"), + MouseCursor::Default => load("left_ptr"), + MouseCursor::Hand => load("hand1"), + MouseCursor::Help => load("question_arrow"), + MouseCursor::Move => load("move"), + MouseCursor::Grab => loadn(&["openhand", "grab"]), + MouseCursor::Grabbing => loadn(&["closedhand", "grabbing"]), + MouseCursor::Progress => load("left_ptr_watch"), + MouseCursor::AllScroll => load("all-scroll"), + MouseCursor::ContextMenu => load("context-menu"), + + MouseCursor::NoDrop => loadn(&["no-drop", "circle"]), + MouseCursor::NotAllowed => load("crossed_circle"), + /// 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", + MouseCursor::EResize => load("right_side"), + MouseCursor::NResize => load("top_side"), + MouseCursor::NeResize => load("top_right_corner"), + MouseCursor::NwResize => load("top_left_corner"), + MouseCursor::SResize => load("bottom_side"), + MouseCursor::SeResize => load("bottom_right_corner"), + MouseCursor::SwResize => load("bottom_left_corner"), + MouseCursor::WResize => load("left_side"), + MouseCursor::EwResize => load("h_double_arrow"), + MouseCursor::NsResize => load("v_double_arrow"), + MouseCursor::NwseResize => loadn(&["bd_double_arrow", "size_bdiag"]), + MouseCursor::NeswResize => loadn(&["fd_double_arrow", "size_fdiag"]), + MouseCursor::ColResize => loadn(&["split_h", "h_double_arrow"]), + MouseCursor::RowResize => loadn(&["split_v", "v_double_arrow"]), + + MouseCursor::Text => loadn(&["text", "xterm"]), + MouseCursor::VerticalText => load("vertical-text"), + + MouseCursor::Wait => load("watch"), + + MouseCursor::ZoomIn => load("zoom-in"), + MouseCursor::ZoomOut => load("zoom-out"), + + // TODO: Hide cursor + MouseCursor::NoneCursor => 0, }; - let c_string = CString::new(cursor_name.as_bytes().to_vec()).unwrap(); - let xcursor = (self.x.display.xcursor.XcursorLibraryLoadCursor)(self.x.display.display, c_string.as_ptr()); - self.x.display.check_errors().expect("Failed to call XcursorLibraryLoadCursor"); + (self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, xcursor); - (self.x.display.xlib.XFlush)(self.x.display.display); - (self.x.display.xlib.XFreeCursor)(self.x.display.display, xcursor); - self.x.display.check_errors().expect("Failed to call XDefineCursor"); + if xcursor != 0 { + (self.x.display.xlib.XFreeCursor)(self.x.display.display, xcursor); + } + self.x.display.check_errors().expect("Failed to set or free the cursor"); } } |