From b4adefd9d9a84bd344ba3e346e2d8d5888397dae Mon Sep 17 00:00:00 2001 From: Antonino Siena Date: Tue, 21 Apr 2020 15:13:12 +0200 Subject: [PATCH] [WIP] Cursor visibility (#170) * Cursor visibility * Implement cursor visiblity for X11 and Wayland * Implement cursor visibility for Windows * Implement cursor visibility on Redox * Implement cursor visiblity for OSX * Semicolons * Wrong method * Missing argument Co-authored-by: Antonino Siena --- src/lib.rs | 9 +++++++ src/native/macosx/MacMiniFB.m | 10 ++++++++ src/os/macos/mod.rs | 8 ++++++ src/os/redox/mod.rs | 4 +++ src/os/unix/mod.rs | 9 +++++++ src/os/unix/wayland.rs | 47 ++++++++++++++++++++++++++++++++++- src/os/unix/x11.rs | 33 ++++++++++++++++++++++++ src/os/windows/mod.rs | 6 +++++ 8 files changed, 125 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3a58f60..ef68441 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -383,6 +383,15 @@ impl Window { .set_background_color(((r << 16) | (g << 8) | b) as u32); } + /// + /// Changes whether or not the cursor image should be shown or if the cursor image + /// should be invisible inside the window + /// When creating a new window the default is 'false' + #[inline] + pub fn set_cursor_visibility(&mut self, visibility: bool) { + self.0.set_cursor_visibility(visibility); + } + /// /// Limits the update rate of polling for new events in order to reduce CPU usage. /// The problem of having a tight loop that does something like this diff --git a/src/native/macosx/MacMiniFB.m b/src/native/macosx/MacMiniFB.m index 1fd8947..4a335b6 100644 --- a/src/native/macosx/MacMiniFB.m +++ b/src/native/macosx/MacMiniFB.m @@ -423,6 +423,16 @@ void mfb_set_title(void* window, const char* title) [win setTitle: ns_title]; } +void mfb_set_cursor_visibility(void *window, bool visibility) +{ + if (visibility){ + [NSCursor unhide]; + } + else{ + [NSCursor hide]; + } +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void mfb_close(void* win) diff --git a/src/os/macos/mod.rs b/src/os/macos/mod.rs index 6efebc9..ab29490 100644 --- a/src/os/macos/mod.rs +++ b/src/os/macos/mod.rs @@ -182,6 +182,7 @@ extern "C" { ); fn mfb_set_mouse_data(window_handle: *mut c_void, shared_data: *mut SharedData); fn mfb_set_cursor_style(window: *mut c_void, cursor: u32); + fn mfb_set_cursor_visibility(window: *mut c_void, visibility: bool); fn mfb_should_close(window: *mut c_void) -> i32; fn mfb_get_screen_size() -> u32; fn mfb_is_active(window: *mut c_void) -> u32; @@ -351,6 +352,13 @@ impl Window { self.shared_data.bg_color = color; } + #[inline] + pub fn set_cursor_visibility(&mut self, visibility: bool) { + unsafe { + mfb_set_cursor_visibility(self.window_handle, visibility); + } + } + pub fn update_with_buffer_stride( &mut self, buffer: &[u32], diff --git a/src/os/redox/mod.rs b/src/os/redox/mod.rs index b8c9cfd..791c290 100644 --- a/src/os/redox/mod.rs +++ b/src/os/redox/mod.rs @@ -184,6 +184,10 @@ impl Window { // Orbital doesn't support cursor styles yet } + pub fn set_cursor_visibility(&mut self, visibility: bool) { + self.window.set_mouse_cursor(visibility); + } + pub fn get_keys(&self) -> Option> { self.key_handler.get_keys() } diff --git a/src/os/unix/mod.rs b/src/os/unix/mod.rs index 7e111bf..6eb1ed8 100644 --- a/src/os/unix/mod.rs +++ b/src/os/unix/mod.rs @@ -112,6 +112,15 @@ impl Window { } } + pub fn set_cursor_visibility(&mut self, visibility: bool) { + match *self { + #[cfg(feature = "x11")] + Window::X11(ref mut w) => w.set_cursor_visibility(visibility), + #[cfg(feature = "wayland")] + Window::Wayland(ref mut w) => w.set_cursor_visibility(visibility), + } + } + pub fn set_position(&mut self, x: isize, y: isize) { match *self { #[cfg(feature = "x11")] diff --git a/src/os/unix/wayland.rs b/src/os/unix/wayland.rs index f36376f..f13fdce 100644 --- a/src/os/unix/wayland.rs +++ b/src/os/unix/wayland.rs @@ -501,6 +501,7 @@ pub struct Window { buffer: Vec, // Resolution, closed toplevel_info: (ToplevelResolution, ToplevelClosed), + pointer_visibility: bool, } impl Window { @@ -562,6 +563,7 @@ impl Window { resizable: opts.resize, buffer: Vec::with_capacity(width * height * scale as usize * scale as usize), toplevel_info: (resolution, closed), + pointer_visibility: false, }) } @@ -573,6 +575,10 @@ impl Window { self.bg_color = bg_color; } + pub fn set_cursor_visibility(&mut self, visibility: bool) { + self.pointer_visibility = visibility; + } + pub fn is_open(&self) -> bool { !self.should_close } @@ -785,6 +791,17 @@ impl Window { self.display .update_cursor(Self::decode_cursor(self.prev_cursor)) .unwrap(); + + if self.pointer_visibility { + self.input.get_pointer().set_cursor( + serial, + Some(&self.display.cursor_surface), + 0, + 0, + ); + } else { + self.input.get_pointer().set_cursor(serial, None, 0, 0); + } } Event::Motion { surface_x, @@ -794,7 +811,12 @@ impl Window { self.mouse_x = surface_x as f32; self.mouse_y = surface_y as f32; } - Event::Button { button, state, .. } => { + Event::Button { + button, + state, + serial, + .. + } => { use wayland_client::protocol::wl_pointer::ButtonState; let pressed = state == ButtonState::Pressed; @@ -811,6 +833,17 @@ impl Window { // the Linux kernel) } } + + if self.pointer_visibility { + self.input.get_pointer().set_cursor( + serial, + Some(&self.display.cursor_surface), + 0, + 0, + ); + } else { + self.input.get_pointer().set_cursor(serial, None, 0, 0); + } } Event::Axis { axis, value, .. } => { use wayland_client::protocol::wl_pointer::Axis; @@ -841,6 +874,18 @@ impl Window { let _ = (axis, discrete); // TODO } + Event::Leave { serial, .. } => { + if self.pointer_visibility { + self.input.get_pointer().set_cursor( + serial, + Some(&self.display.cursor_surface), + 0, + 0, + ); + } else { + self.input.get_pointer().set_cursor(serial, None, 0, 0); + } + } _ => {} } } diff --git a/src/os/unix/x11.rs b/src/os/unix/x11.rs index c29c451..94bb6b9 100644 --- a/src/os/unix/x11.rs +++ b/src/os/unix/x11.rs @@ -567,6 +567,39 @@ impl Window { self.bg_color = bg_color; } + #[inline] + pub fn set_cursor_visibility(&mut self, visibility: bool) { + unsafe { + if visibility { + (self.d.lib.XDefineCursor)( + self.d.display, + self.handle, + self.d.cursors[self.prev_cursor as usize], + ); + } else { + static empty: [c_char; 8] = [0; 8]; + let mut color = std::mem::zeroed(); + let pixmap = (self.d.lib.XCreateBitmapFromData)( + self.d.display, + self.handle, + empty.as_ptr(), + 8, + 8, + ); + let cursor = (self.d.lib.XCreatePixmapCursor)( + self.d.display, + pixmap, + pixmap, + &mut color as *mut _, + &mut color as *mut _, + 0, + 0, + ); + (self.d.lib.XDefineCursor)(self.d.display, self.handle, cursor); + } + } + } + #[inline] pub fn set_position(&mut self, x: isize, y: isize) { unsafe { diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs index a17f040..ce7e614 100644 --- a/src/os/windows/mod.rs +++ b/src/os/windows/mod.rs @@ -797,6 +797,12 @@ impl Window { } } + pub fn set_cursor_visibility(&mut self, visibility: bool) { + unsafe { + winuser::ShowCursor(visibility as i32); + } + } + pub fn update_with_buffer_stride( &mut self, buffer: &[u32],