Add set_mouse_cursor method to X11 Window
This commit is contained in:
parent
c24d12c453
commit
d84a1fde44
|
@ -16,8 +16,9 @@ raw-window-handle = "0.3.3"
|
|||
|
||||
[target.'cfg(target_os="linux")'.dependencies]
|
||||
xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] }
|
||||
x11 = { version = "2.18", features = ["xlib"] }
|
||||
x11 = { version = "2.18", features = ["xlib", "xcursor"] }
|
||||
xcb-util = { version = "0.3", features = ["icccm"] }
|
||||
maybe-uninit = "2.0"
|
||||
libc = "0.2"
|
||||
nix = "0.18"
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@ impl WindowHandler for MyProgram {
|
|||
|
||||
fn on_event(&mut self, _window: &mut Window, event: Event) {
|
||||
match event {
|
||||
Event::Mouse(e) => println!("Mouse event: {:?}", e),
|
||||
Event::Mouse(e) => {
|
||||
println!("Mouse event: {:?}", e);
|
||||
},
|
||||
Event::Keyboard(e) => println!("Keyboard event: {:?}", e),
|
||||
Event::Window(e) => println!("Window event: {:?}", e),
|
||||
}
|
||||
|
|
|
@ -1,19 +1,49 @@
|
|||
#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Hash)]
|
||||
pub enum MouseCursor {
|
||||
Idle,
|
||||
Pointer,
|
||||
Grab,
|
||||
Text,
|
||||
Crosshair,
|
||||
Working,
|
||||
Grabbing,
|
||||
ResizingHorizontally,
|
||||
ResizingVertically,
|
||||
Default,
|
||||
Hand,
|
||||
HandGrabbing,
|
||||
Help,
|
||||
|
||||
Hidden,
|
||||
|
||||
Text,
|
||||
VerticalText,
|
||||
|
||||
Working,
|
||||
PtrWorking,
|
||||
|
||||
NotAllowed,
|
||||
PtrNotAllowed,
|
||||
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
|
||||
Alias,
|
||||
Copy,
|
||||
Move,
|
||||
AllScroll,
|
||||
Cell,
|
||||
Crosshair,
|
||||
|
||||
EResize,
|
||||
NResize,
|
||||
NeResize,
|
||||
NwResize,
|
||||
SResize,
|
||||
SeResize,
|
||||
SwResize,
|
||||
WResize,
|
||||
EwResize,
|
||||
NsResize,
|
||||
NwseResize,
|
||||
NeswResize,
|
||||
ColResize,
|
||||
RowResize,
|
||||
}
|
||||
|
||||
impl Default for MouseCursor {
|
||||
fn default() -> Self {
|
||||
Self::Idle
|
||||
Self::Default
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::os::raw::{c_ulong, c_void};
|
||||
use std::sync::mpsc;
|
||||
use std::os::raw::{c_ulong, c_void, c_char};
|
||||
use std::sync::{mpsc, Mutex};
|
||||
use std::time::*;
|
||||
use std::thread;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use raw_window_handle::{
|
||||
unix::XlibHandle,
|
||||
|
@ -20,6 +21,7 @@ pub struct Window {
|
|||
window_id: u32,
|
||||
window_info: WindowInfo,
|
||||
mouse_cursor: MouseCursor,
|
||||
cursor_cache: HashMap<MouseCursor, c_ulong>,
|
||||
|
||||
frame_interval: Duration,
|
||||
event_loop_running: bool,
|
||||
|
@ -157,6 +159,7 @@ impl Window {
|
|||
window_id,
|
||||
window_info,
|
||||
mouse_cursor: MouseCursor::default(),
|
||||
cursor_cache: HashMap::new(),
|
||||
|
||||
frame_interval: Duration::from_millis(15),
|
||||
event_loop_running: false,
|
||||
|
@ -176,32 +179,25 @@ impl Window {
|
|||
&self.window_info
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn set_mouse_cursor(&mut self, mouse_cursor: MouseCursor) {
|
||||
if self.mouse_cursor != mouse_cursor {
|
||||
if mouse_cursor == MouseCursor::Hidden {
|
||||
xcb::change_cursor(&self.xcb_connection.conn, xcb::CW_CURSOR, xcb::CURSOR_NONE);
|
||||
} else {
|
||||
let cursor_name = match mouse_cursor {
|
||||
MouseCursor::Idle => "pointer",
|
||||
MouseCursor::Pointer => "pointer",
|
||||
MouseCursor::Grab => "hand1",
|
||||
MouseCursor::Text => "xterm",
|
||||
MouseCursor::Crosshair => "crosshair",
|
||||
MouseCursor::Working => "watch",
|
||||
MouseCursor::Grabbing => "hand2",
|
||||
MouseCursor::ResizingHorizontally => "sizing",
|
||||
MouseCursor::ResizingVertically => "sizing",
|
||||
_ => "pointer",
|
||||
};
|
||||
}
|
||||
let display = self.xcb_connection.conn.get_raw_dpy();
|
||||
|
||||
|
||||
let cursor = *self
|
||||
.cursor_cache
|
||||
.entry(mouse_cursor)
|
||||
.or_insert_with(|| get_cursor(display, mouse_cursor));
|
||||
|
||||
unsafe {
|
||||
if cursor != 0 {
|
||||
x11::xlib::XDefineCursor(display, self.window_id as c_ulong, cursor);
|
||||
}
|
||||
x11::xlib::XFlush(display);
|
||||
}
|
||||
|
||||
self.mouse_cursor = mouse_cursor;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[inline]
|
||||
fn drain_xcb_events<H: WindowHandler>(&mut self, handler: &mut H) {
|
||||
|
@ -430,3 +426,104 @@ fn mouse_id(id: u8) -> MouseButton {
|
|||
id => MouseButton::Other(id),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_cursor(display: *mut x11::xlib::Display, name: &[u8]) -> c_ulong {
|
||||
unsafe {
|
||||
x11::xcursor::XcursorLibraryLoadCursor(display, name.as_ptr() as *const c_char)
|
||||
}
|
||||
}
|
||||
|
||||
fn load_first_existing_cursor(display: *mut x11::xlib::Display, names: &[&[u8]]) -> c_ulong {
|
||||
for name in names.iter() {
|
||||
let xcursor = load_cursor(display, name);
|
||||
if xcursor != 0 {
|
||||
return xcursor;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn get_cursor(display: *mut x11::xlib::Display, cursor: MouseCursor) -> c_ulong {
|
||||
let load = |name: &[u8]| load_cursor(display, name);
|
||||
let loadn = |names: &[&[u8]]| load_first_existing_cursor(display, names);
|
||||
|
||||
let mut cursor = match cursor {
|
||||
MouseCursor::Default => load(b"left_ptr\0"),
|
||||
MouseCursor::Hand => loadn(&[b"hand2\0", b"hand1\0"]),
|
||||
MouseCursor::HandGrabbing => loadn(&[b"closedhand\0", b"grabbing\0"]),
|
||||
MouseCursor::Help => load(b"question_arrow\0"),
|
||||
|
||||
MouseCursor::Hidden => create_empty_cursor(display),
|
||||
|
||||
MouseCursor::Text => loadn(&[b"text\0", b"xterm\0"]),
|
||||
MouseCursor::VerticalText => load(b"vertical-text\0"),
|
||||
|
||||
MouseCursor::Working => load(b"watch\0"),
|
||||
MouseCursor::PtrWorking => load(b"left_ptr_watch\0"),
|
||||
|
||||
MouseCursor::NotAllowed => load(b"crossed_circle\0"),
|
||||
MouseCursor::PtrNotAllowed => loadn(&[b"no-drop\0", b"crossed_circle\0"]),
|
||||
|
||||
MouseCursor::ZoomIn => load(b"zoom-in\0"),
|
||||
MouseCursor::ZoomOut => load(b"zoom-out\0"),
|
||||
|
||||
MouseCursor::Alias => load(b"link\0"),
|
||||
MouseCursor::Copy => load(b"copy\0"),
|
||||
MouseCursor::Move => load(b"move\0"),
|
||||
MouseCursor::AllScroll => load(b"all-scroll\0"),
|
||||
MouseCursor::Cell => load(b"plus\0"),
|
||||
MouseCursor::Crosshair => load(b"crosshair\0"),
|
||||
|
||||
MouseCursor::EResize => load(b"right_side\0"),
|
||||
MouseCursor::NResize => load(b"top_side\0"),
|
||||
MouseCursor::NeResize => load(b"top_right_corner\0"),
|
||||
MouseCursor::NwResize => load(b"top_left_corner\0"),
|
||||
MouseCursor::SResize => load(b"bottom_side\0"),
|
||||
MouseCursor::SeResize => load(b"bottom_right_corner\0"),
|
||||
MouseCursor::SwResize => load(b"bottom_left_corner\0"),
|
||||
MouseCursor::WResize => load(b"left_side\0"),
|
||||
MouseCursor::EwResize => load(b"h_double_arrow\0"),
|
||||
MouseCursor::NsResize => load(b"v_double_arrow\0"),
|
||||
MouseCursor::NwseResize => loadn(&[b"bd_double_arrow\0", b"size_bdiag\0"]),
|
||||
MouseCursor::NeswResize => loadn(&[b"fd_double_arrow\0", b"size_fdiag\0"]),
|
||||
MouseCursor::ColResize => loadn(&[b"split_h\0", b"h_double_arrow\0"]),
|
||||
MouseCursor::RowResize => loadn(&[b"split_v\0", b"v_double_arrow\0"]),
|
||||
};
|
||||
|
||||
if cursor == 0 {
|
||||
cursor = load(b"left_ptr\0")
|
||||
}
|
||||
|
||||
cursor
|
||||
}
|
||||
|
||||
fn create_empty_cursor(display: *mut x11::xlib::Display,) -> c_ulong {
|
||||
let data = 0;
|
||||
let pixmap = unsafe {
|
||||
let screen = x11::xlib::XDefaultScreen(display);
|
||||
let window = x11::xlib::XRootWindow(display, screen);
|
||||
x11::xlib::XCreateBitmapFromData(display, window, &data, 1, 1)
|
||||
};
|
||||
|
||||
if pixmap == 0 {
|
||||
panic!("failed to allocate pixmap for cursor");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// We don't care about this color, since it only fills bytes
|
||||
// in the pixmap which are not 0 in the mask.
|
||||
let mut dummy_color = maybe_uninit::MaybeUninit::uninit();
|
||||
let cursor = x11::xlib::XCreatePixmapCursor(
|
||||
display,
|
||||
pixmap,
|
||||
pixmap,
|
||||
dummy_color.as_mut_ptr(),
|
||||
dummy_color.as_mut_ptr(),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
x11::xlib::XFreePixmap(display, pixmap);
|
||||
|
||||
cursor
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue