1use crate::get_error;
2use crate::surface::SurfaceRef;
3use crate::video;
4use crate::EventPump;
5use std::iter::FilterMap;
6use std::mem::transmute;
7
8use crate::sys;
9use crate::sys::SDL_SystemCursor;
10
11mod relative;
12pub use self::relative::RelativeMouseState;
13
14#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
15#[repr(u32)]
16pub enum SystemCursor {
17 Arrow = SDL_SystemCursor::SDL_SYSTEM_CURSOR_ARROW as u32,
18 IBeam = SDL_SystemCursor::SDL_SYSTEM_CURSOR_IBEAM as u32,
19 Wait = SDL_SystemCursor::SDL_SYSTEM_CURSOR_WAIT as u32,
20 Crosshair = SDL_SystemCursor::SDL_SYSTEM_CURSOR_CROSSHAIR as u32,
21 WaitArrow = SDL_SystemCursor::SDL_SYSTEM_CURSOR_WAITARROW as u32,
22 SizeNWSE = SDL_SystemCursor::SDL_SYSTEM_CURSOR_SIZENWSE as u32,
23 SizeNESW = SDL_SystemCursor::SDL_SYSTEM_CURSOR_SIZENESW as u32,
24 SizeWE = SDL_SystemCursor::SDL_SYSTEM_CURSOR_SIZEWE as u32,
25 SizeNS = SDL_SystemCursor::SDL_SYSTEM_CURSOR_SIZENS as u32,
26 SizeAll = SDL_SystemCursor::SDL_SYSTEM_CURSOR_SIZEALL as u32,
27 No = SDL_SystemCursor::SDL_SYSTEM_CURSOR_NO as u32,
28 Hand = SDL_SystemCursor::SDL_SYSTEM_CURSOR_HAND as u32,
29}
30
31pub struct Cursor {
32 raw: *mut sys::SDL_Cursor,
33}
34
35impl Drop for Cursor {
36 #[inline]
37 #[doc(alias = "SDL_FreeCursor")]
38 fn drop(&mut self) {
39 unsafe { sys::SDL_FreeCursor(self.raw) };
40 }
41}
42
43impl Cursor {
44 #[doc(alias = "SDL_CreateCursor")]
45 pub fn new(
46 data: &[u8],
47 mask: &[u8],
48 width: i32,
49 height: i32,
50 hot_x: i32,
51 hot_y: i32,
52 ) -> Result<Cursor, String> {
53 unsafe {
54 let raw =
55 sys::SDL_CreateCursor(data.as_ptr(), mask.as_ptr(), width, height, hot_x, hot_y);
56
57 if raw.is_null() {
58 Err(get_error())
59 } else {
60 Ok(Cursor { raw })
61 }
62 }
63 }
64
65 #[doc(alias = "SDL_CreateColorCursor")]
67 pub fn from_surface<S: AsRef<SurfaceRef>>(
68 surface: S,
69 hot_x: i32,
70 hot_y: i32,
71 ) -> Result<Cursor, String> {
72 unsafe {
73 let raw = sys::SDL_CreateColorCursor(surface.as_ref().raw(), hot_x, hot_y);
74
75 if raw.is_null() {
76 Err(get_error())
77 } else {
78 Ok(Cursor { raw })
79 }
80 }
81 }
82
83 #[doc(alias = "SDL_CreateSystemCursor")]
84 pub fn from_system(cursor: SystemCursor) -> Result<Cursor, String> {
85 unsafe {
86 let raw = sys::SDL_CreateSystemCursor(transmute(cursor as u32));
87
88 if raw.is_null() {
89 Err(get_error())
90 } else {
91 Ok(Cursor { raw })
92 }
93 }
94 }
95
96 #[doc(alias = "SDL_SetCursor")]
97 pub fn set(&self) {
98 unsafe {
99 sys::SDL_SetCursor(self.raw);
100 }
101 }
102}
103
104#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
105pub enum MouseWheelDirection {
106 Normal,
107 Flipped,
108 Unknown(u32),
109}
110
111impl MouseWheelDirection {
129 #[inline]
130 pub fn from_ll(direction: u32) -> MouseWheelDirection {
131 match direction {
132 0 => MouseWheelDirection::Normal,
133 1 => MouseWheelDirection::Flipped,
134 _ => MouseWheelDirection::Unknown(direction),
135 }
136 }
137 #[inline]
138 pub fn to_ll(self) -> u32 {
139 match self {
140 MouseWheelDirection::Normal => 0,
141 MouseWheelDirection::Flipped => 1,
142 MouseWheelDirection::Unknown(direction) => direction,
143 }
144 }
145}
146
147#[repr(u8)]
148#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
149pub enum MouseButton {
150 Unknown = 0,
151 Left = sys::SDL_BUTTON_LEFT as u8,
152 Middle = sys::SDL_BUTTON_MIDDLE as u8,
153 Right = sys::SDL_BUTTON_RIGHT as u8,
154 X1 = sys::SDL_BUTTON_X1 as u8,
155 X2 = sys::SDL_BUTTON_X2 as u8,
156}
157
158impl MouseButton {
159 #[inline]
160 pub fn from_ll(button: u8) -> MouseButton {
161 match button as u32 {
162 sys::SDL_BUTTON_LEFT => MouseButton::Left,
163 sys::SDL_BUTTON_MIDDLE => MouseButton::Middle,
164 sys::SDL_BUTTON_RIGHT => MouseButton::Right,
165 sys::SDL_BUTTON_X1 => MouseButton::X1,
166 sys::SDL_BUTTON_X2 => MouseButton::X2,
167 _ => MouseButton::Unknown,
168 }
169 }
170}
171
172#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
173pub struct MouseState {
174 mouse_state: u32,
175 x: i32,
176 y: i32,
177}
178
179impl MouseState {
180 #[doc(alias = "SDL_GetMouseState")]
181 pub fn new(_e: &EventPump) -> MouseState {
182 let mut x = 0;
183 let mut y = 0;
184 let mouse_state: u32 = unsafe { sys::SDL_GetMouseState(&mut x, &mut y) };
185
186 MouseState { mouse_state, x, y }
187 }
188
189 pub fn from_sdl_state(state: u32) -> MouseState {
190 MouseState {
191 mouse_state: state,
192 x: 0,
193 y: 0,
194 }
195 }
196 pub fn to_sdl_state(&self) -> u32 {
197 self.mouse_state
198 }
199
200 fn button_mask(&self, button: u32) -> u32 {
201 1 << (button - 1)
202 }
203
204 pub fn left(&self) -> bool {
215 (self.mouse_state & self.button_mask(sys::SDL_BUTTON_LEFT)) != 0
216 }
217
218 pub fn middle(&self) -> bool {
220 (self.mouse_state & self.button_mask(sys::SDL_BUTTON_MIDDLE)) != 0
221 }
222
223 pub fn right(&self) -> bool {
225 (self.mouse_state & self.button_mask(sys::SDL_BUTTON_RIGHT)) != 0
226 }
227
228 pub fn x1(&self) -> bool {
230 (self.mouse_state & self.button_mask(sys::SDL_BUTTON_X1)) != 0
231 }
232
233 pub fn x2(&self) -> bool {
235 (self.mouse_state & self.button_mask(sys::SDL_BUTTON_X2)) != 0
236 }
237
238 pub fn x(&self) -> i32 {
240 self.x
241 }
242
243 pub fn y(&self) -> i32 {
245 self.y
246 }
247
248 pub fn is_mouse_button_pressed(&self, mouse_button: MouseButton) -> bool {
259 let mask = 1 << ((mouse_button as u32) - 1);
260 self.mouse_state & mask != 0
261 }
262
263 pub fn mouse_buttons(&self) -> MouseButtonIterator {
283 MouseButtonIterator {
284 cur_button: 1,
285 mouse_state: &self.mouse_state,
286 }
287 }
288
289 pub fn pressed_mouse_buttons(&self) -> PressedMouseButtonIterator {
306 self.mouse_buttons().into_pressed_buttons_iter()
307 }
308}
309
310pub struct MouseButtonIterator<'a> {
311 cur_button: u8,
312 mouse_state: &'a u32,
313}
314
315impl<'a> Iterator for MouseButtonIterator<'a> {
316 type Item = (MouseButton, bool);
317
318 fn next(&mut self) -> Option<(MouseButton, bool)> {
319 if self.cur_button < MouseButton::X2 as u8 + 1 {
320 let mouse_button = self.cur_button;
321 let mask = 1 << ((self.cur_button as u32) - 1);
322 let pressed = self.mouse_state & mask != 0;
323 self.cur_button += 1;
324 Some((MouseButton::from_ll(mouse_button), pressed))
325 } else {
326 None
327 }
328 }
329}
330
331impl<'a> MouseButtonIterator<'a> {
332 fn into_pressed_buttons_iter(self) -> PressedMouseButtonIterator<'a> {
333 self.filter_map(|(mouse_button, pressed)| pressed.then_some(mouse_button))
334 }
335}
336
337pub type PressedMouseButtonIterator<'a> =
338 FilterMap<MouseButtonIterator<'a>, fn((MouseButton, bool)) -> Option<MouseButton>>;
339
340impl crate::Sdl {
341 #[inline]
342 pub fn mouse(&self) -> MouseUtil {
343 MouseUtil {
344 _sdldrop: self.sdldrop(),
345 }
346 }
347}
348
349pub struct MouseUtil {
358 _sdldrop: crate::SdlDrop,
359}
360
361impl MouseUtil {
362 #[doc(alias = "SDL_GetMouseFocus")]
364 pub fn focused_window_id(&self) -> Option<u32> {
365 let raw = unsafe { sys::SDL_GetMouseFocus() };
366 if raw.is_null() {
367 None
368 } else {
369 let id = unsafe { sys::SDL_GetWindowID(raw) };
370 Some(id)
371 }
372 }
373
374 #[doc(alias = "SDL_WarpMouseInWindow")]
375 pub fn warp_mouse_in_window(&self, window: &video::Window, x: i32, y: i32) {
376 unsafe {
377 sys::SDL_WarpMouseInWindow(window.raw(), x, y);
378 }
379 }
380
381 #[doc(alias = "SDL_SetRelativeMouseMode")]
382 pub fn set_relative_mouse_mode(&self, on: bool) {
383 let on = if on {
384 sys::SDL_bool::SDL_TRUE
385 } else {
386 sys::SDL_bool::SDL_FALSE
387 };
388 unsafe {
389 sys::SDL_SetRelativeMouseMode(on);
390 }
391 }
392
393 #[doc(alias = "SDL_GetRelativeMouseMode")]
394 pub fn relative_mouse_mode(&self) -> bool {
395 unsafe { sys::SDL_GetRelativeMouseMode() == sys::SDL_bool::SDL_TRUE }
396 }
397
398 #[doc(alias = "SDL_ShowCursor")]
399 pub fn is_cursor_showing(&self) -> bool {
400 unsafe { sys::SDL_ShowCursor(crate::sys::SDL_QUERY) == 1 }
401 }
402
403 #[doc(alias = "SDL_ShowCursor")]
404 pub fn show_cursor(&self, show: bool) {
405 unsafe {
406 sys::SDL_ShowCursor(show as i32);
407 }
408 }
409
410 #[doc(alias = "SDL_CaptureMouse")]
411 pub fn capture(&self, enable: bool) {
412 let enable = if enable {
413 sys::SDL_bool::SDL_TRUE
414 } else {
415 sys::SDL_bool::SDL_FALSE
416 };
417 unsafe {
418 sys::SDL_CaptureMouse(enable);
419 }
420 }
421}