rich_sdl2_rust/video/window/
cursor.rs1use static_assertions::assert_not_impl_all;
4use std::marker::PhantomData;
5use std::ptr::NonNull;
6
7use crate::{bind, geo::Point, surface::Surface, Result, Sdl, SdlError};
8
9use super::Window;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13#[non_exhaustive]
14pub enum SystemCursorKind {
15 Arrow,
17 IBeam,
19 Wait,
21 Crosshair,
23 WaitArrow,
25 SizeNwse,
27 SizeNesw,
29 SizeWe,
31 SizeNs,
33 SizeAll,
35 No,
37 Hand,
39}
40
41impl SystemCursorKind {
42 pub(crate) fn as_raw(self) -> bind::SDL_SystemCursor {
43 match self {
44 SystemCursorKind::Arrow => bind::SDL_SYSTEM_CURSOR_ARROW,
45 SystemCursorKind::IBeam => bind::SDL_SYSTEM_CURSOR_IBEAM,
46 SystemCursorKind::Wait => bind::SDL_SYSTEM_CURSOR_WAIT,
47 SystemCursorKind::Crosshair => bind::SDL_SYSTEM_CURSOR_CROSSHAIR,
48 SystemCursorKind::WaitArrow => bind::SDL_SYSTEM_CURSOR_WAITARROW,
49 SystemCursorKind::SizeNwse => bind::SDL_SYSTEM_CURSOR_SIZENWSE,
50 SystemCursorKind::SizeNesw => bind::SDL_SYSTEM_CURSOR_SIZENESW,
51 SystemCursorKind::SizeWe => bind::SDL_SYSTEM_CURSOR_SIZEWE,
52 SystemCursorKind::SizeNs => bind::SDL_SYSTEM_CURSOR_SIZENS,
53 SystemCursorKind::SizeAll => bind::SDL_SYSTEM_CURSOR_SIZEALL,
54 SystemCursorKind::No => bind::SDL_SYSTEM_CURSOR_NO,
55 SystemCursorKind::Hand => bind::SDL_SYSTEM_CURSOR_HAND,
56 }
57 }
58}
59
60pub struct Cursor<'window> {
62 cursor: NonNull<bind::SDL_Cursor>,
63 window: PhantomData<&'window ()>,
64}
65
66impl std::fmt::Debug for Cursor<'_> {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.debug_struct("Cursor").finish_non_exhaustive()
69 }
70}
71
72assert_not_impl_all!(Cursor: Send, Sync);
73
74impl<'window> Cursor<'window> {
75 pub fn system(_: &'window Window, kind: SystemCursorKind) -> Result<Self> {
81 let cursor = unsafe { bind::SDL_CreateSystemCursor(kind.as_raw()) };
82 let cursor = NonNull::new(cursor).ok_or(SdlError::UnsupportedFeature)?;
83 Ok(Self {
84 cursor,
85 window: PhantomData,
86 })
87 }
88
89 pub fn colored(_: &'window Window, surface: &impl Surface, hot_spot: Point) -> Result<Self> {
95 let cursor = unsafe {
96 bind::SDL_CreateColorCursor(surface.as_ptr().as_ptr(), hot_spot.x, hot_spot.y)
97 };
98 let cursor = NonNull::new(cursor).ok_or_else(|| SdlError::Others { msg: Sdl::error() })?;
99 Ok(Self {
100 cursor,
101 window: PhantomData,
102 })
103 }
104
105 pub fn customized(
111 _: &'window Window,
112 data: &[u8],
113 mask: &[u8],
114 hot_spot: Point,
115 ) -> Result<Self> {
116 debug_assert_eq!(data.len(), mask.len());
117 let width_height = (data.len() / 4) as i32;
118 let cursor = unsafe {
119 bind::SDL_CreateCursor(
120 data.as_ptr(),
121 mask.as_ptr(),
122 width_height,
123 width_height,
124 hot_spot.x,
125 hot_spot.y,
126 )
127 };
128 let cursor = NonNull::new(cursor).ok_or_else(|| SdlError::Others { msg: Sdl::error() })?;
129 Ok(Self {
130 cursor,
131 window: PhantomData,
132 })
133 }
134
135 #[must_use]
137 pub fn default(_: &'window Window) -> Option<Self> {
138 NonNull::new(unsafe { bind::SDL_GetDefaultCursor() }).map(|cursor| Self {
139 cursor,
140 window: PhantomData,
141 })
142 }
143
144 pub fn set(&self) {
146 unsafe { bind::SDL_SetCursor(self.cursor.as_ptr()) }
147 }
148
149 pub fn redraw(&self) {
151 unsafe { bind::SDL_SetCursor(std::ptr::null_mut()) }
152 }
153}
154
155impl Drop for Cursor<'_> {
156 fn drop(&mut self) {
157 unsafe { bind::SDL_FreeCursor(self.cursor.as_ptr()) }
158 }
159}