1 //! Xlib calls related to a mouse. 2 use super::{XlibError, MOUSEMASK}; 3 use crate::display_servers::xlib_display_server::xwrap::BUTTONMASK; 4 use crate::XWrap; 5 use std::os::raw::{c_int, c_ulong}; 6 use x11_dl::xlib; 7 8 impl XWrap { 9 /// Grabs the mouse clicks of a window. grab_mouse_clicks(&self, handle: xlib::Window, is_focused: bool)10 pub fn grab_mouse_clicks(&self, handle: xlib::Window, is_focused: bool) { 11 self.ungrab_buttons(handle); 12 if !is_focused { 13 self.grab_buttons(handle, xlib::Button1, xlib::AnyModifier, xlib::GrabModeSync); 14 self.grab_buttons(handle, xlib::Button3, xlib::AnyModifier, xlib::GrabModeSync); 15 } 16 self.grab_buttons( 17 handle, 18 xlib::Button1, 19 self.mouse_key_mask, 20 xlib::GrabModeAsync, 21 ); 22 self.grab_buttons( 23 handle, 24 xlib::Button1, 25 self.mouse_key_mask | xlib::ShiftMask, 26 xlib::GrabModeAsync, 27 ); 28 self.grab_buttons( 29 handle, 30 xlib::Button3, 31 self.mouse_key_mask, 32 xlib::GrabModeAsync, 33 ); 34 self.grab_buttons( 35 handle, 36 xlib::Button3, 37 self.mouse_key_mask | xlib::ShiftMask, 38 xlib::GrabModeAsync, 39 ); 40 } 41 42 /// Grabs the button with the modifier for a window. 43 // `XGrabButton`: https://tronche.com/gui/x/xlib/input/XGrabButton.html grab_buttons( &self, window: xlib::Window, button: u32, modifiers: u32, pointer_mode: i32, )44 pub fn grab_buttons( 45 &self, 46 window: xlib::Window, 47 button: u32, 48 modifiers: u32, 49 pointer_mode: i32, 50 ) { 51 // Grab the buttons with and without numlock (Mod2). 52 let mods: Vec<u32> = vec![ 53 modifiers, 54 modifiers | xlib::Mod2Mask, 55 modifiers | xlib::LockMask, 56 ]; 57 for m in mods { 58 unsafe { 59 (self.xlib.XGrabButton)( 60 self.display, 61 button, 62 m, 63 window, 64 0, 65 BUTTONMASK as u32, 66 pointer_mode, 67 xlib::GrabModeAsync, 68 self.root, 69 0, 70 ); 71 } 72 } 73 } 74 75 /// Cleans all currently grabbed buttons of a window. 76 // `XUngrabButton`: https://tronche.com/gui/x/xlib/input/XUngrabButton.html ungrab_buttons(&self, handle: xlib::Window)77 pub fn ungrab_buttons(&self, handle: xlib::Window) { 78 unsafe { 79 (self.xlib.XUngrabButton)( 80 self.display, 81 xlib::AnyButton as u32, 82 xlib::AnyModifier, 83 handle, 84 ); 85 } 86 } 87 88 /// Grabs the cursor and sets its visual. 89 // `XGrabPointer`: https://tronche.com/gui/x/xlib/input/XGrabPointer.html grab_pointer(&self, cursor: c_ulong)90 pub fn grab_pointer(&self, cursor: c_ulong) { 91 unsafe { 92 //grab the mouse 93 (self.xlib.XGrabPointer)( 94 self.display, 95 self.root, 96 0, 97 MOUSEMASK as u32, 98 xlib::GrabModeAsync, 99 xlib::GrabModeAsync, 100 0, 101 cursor, 102 xlib::CurrentTime, 103 ); 104 } 105 } 106 107 /// Ungrab the cursor. 108 // `XUngrabPointer`: https://tronche.com/gui/x/xlib/input/XUngrabPointer.html ungrab_pointer(&self)109 pub fn ungrab_pointer(&self) { 110 unsafe { 111 //release the mouse grab 112 (self.xlib.XUngrabPointer)(self.display, xlib::CurrentTime); 113 } 114 } 115 116 /// Move the cursor to a window. 117 /// # Errors 118 /// 119 /// Will error if unable to obtain window attributes. See `get_window_attrs`. move_cursor_to_window(&self, window: xlib::Window) -> Result<(), XlibError>120 pub fn move_cursor_to_window(&self, window: xlib::Window) -> Result<(), XlibError> { 121 let attrs = self.get_window_attrs(window)?; 122 let point = (attrs.x + (attrs.width / 2), attrs.y + (attrs.height / 2)); 123 self.move_cursor_to_point(point) 124 } 125 126 /// Move the cursor to a point. 127 /// # Errors 128 /// 129 /// Error indicates `XlibError`. 130 // `XWarpPointer`: https://tronche.com/gui/x/xlib/input/XWarpPointer.html 131 // TODO: Verify that Error is unreachable or specify conditions that may result 132 // in an error. move_cursor_to_point(&self, point: (i32, i32)) -> Result<(), XlibError>133 pub fn move_cursor_to_point(&self, point: (i32, i32)) -> Result<(), XlibError> { 134 if point.0 >= 0 && point.1 >= 0 { 135 let none: c_int = 0; 136 unsafe { 137 (self.xlib.XWarpPointer)( 138 self.display, 139 none as c_ulong, 140 self.root, 141 none, 142 none, 143 none as u32, 144 none as u32, 145 point.0, 146 point.1, 147 ); 148 } 149 } 150 Ok(()) 151 } 152 153 /// Replay a click on a window. 154 // `XAllowEvents`: https://linux.die.net/man/3/xallowevents 155 // `XSync`: https://tronche.com/gui/x/xlib/event-handling/XSync.html replay_click(&self)156 pub fn replay_click(&self) { 157 unsafe { 158 (self.xlib.XAllowEvents)(self.display, xlib::ReplayPointer, xlib::CurrentTime); 159 (self.xlib.XSync)(self.display, xlib::False); 160 } 161 } 162 } 163