Mercurial > sdl-ios-xcode
comparison src/events/SDL_mouse.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | 23a347cfbed8 |
children | 5f6550e5184f |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
23 | 23 |
24 /* General mouse handling code for SDL */ | 24 /* General mouse handling code for SDL */ |
25 | 25 |
26 #include "SDL_events.h" | 26 #include "SDL_events.h" |
27 #include "SDL_events_c.h" | 27 #include "SDL_events_c.h" |
28 #include "../video/SDL_cursor_c.h" | 28 #include "default_cursor.h" |
29 #include "../video/SDL_sysvideo.h" | 29 |
30 | 30 |
31 | 31 static int SDL_num_mice; |
32 /* These are static for our mouse handling code */ | 32 static int SDL_current_mouse; |
33 static Sint16 SDL_MouseX = 0; | 33 static SDL_Mouse **SDL_mice; |
34 static Sint16 SDL_MouseY = 0; | |
35 static Sint16 SDL_DeltaX = 0; | |
36 static Sint16 SDL_DeltaY = 0; | |
37 static Uint8 SDL_ButtonState = 0; | |
38 | 34 |
39 | 35 |
40 /* Public functions */ | 36 /* Public functions */ |
41 int SDL_MouseInit(void) | 37 int |
42 { | 38 SDL_MouseInit(void) |
43 /* The mouse is at (0,0) */ | 39 { |
44 SDL_MouseX = 0; | 40 return (0); |
45 SDL_MouseY = 0; | 41 } |
46 SDL_DeltaX = 0; | 42 |
47 SDL_DeltaY = 0; | 43 SDL_Mouse * |
48 SDL_ButtonState = 0; | 44 SDL_GetMouse(int index) |
49 | 45 { |
50 /* That's it! */ | 46 if (index < 0 || index >= SDL_num_mice) { |
51 return(0); | 47 return NULL; |
52 } | 48 } |
53 void SDL_MouseQuit(void) | 49 return SDL_mice[index]; |
54 { | 50 } |
55 } | 51 |
56 | 52 int |
57 /* We lost the mouse, so post button up messages for all pressed buttons */ | 53 SDL_AddMouse(const SDL_Mouse * mouse, int index) |
58 void SDL_ResetMouse(void) | 54 { |
59 { | 55 SDL_Mouse **mice; |
60 Uint8 i; | 56 int selected_mouse; |
61 for ( i = 0; i < sizeof(SDL_ButtonState)*8; ++i ) { | 57 |
62 if ( SDL_ButtonState & SDL_BUTTON(i) ) { | 58 /* Add the mouse to the list of mice */ |
63 SDL_PrivateMouseButton(SDL_RELEASED, i, 0, 0); | 59 if (index < 0 || index >= SDL_num_mice || SDL_mice[index]) { |
64 } | 60 mice = |
65 } | 61 (SDL_Mouse **) SDL_realloc(SDL_mice, |
66 } | 62 (SDL_num_mice + 1) * sizeof(*mice)); |
67 | 63 if (!mice) { |
68 Uint8 SDL_GetMouseState (int *x, int *y) | 64 SDL_OutOfMemory(); |
69 { | 65 return -1; |
70 if ( x ) { | 66 } |
71 *x = SDL_MouseX; | 67 |
72 } | 68 SDL_mice = mice; |
73 if ( y ) { | 69 index = SDL_num_mice++; |
74 *y = SDL_MouseY; | 70 } |
75 } | 71 SDL_mice[index] = (SDL_Mouse *) SDL_malloc(sizeof(*SDL_mice[index])); |
76 return(SDL_ButtonState); | 72 if (!SDL_mice[index]) { |
77 } | 73 SDL_OutOfMemory(); |
78 | 74 return -1; |
79 Uint8 SDL_GetRelativeMouseState (int *x, int *y) | 75 } |
80 { | 76 *SDL_mice[index] = *mouse; |
81 if ( x ) | 77 |
82 *x = SDL_DeltaX; | 78 /* Create the default cursor for the mouse */ |
83 if ( y ) | 79 SDL_mice[index]->cursor_shown = SDL_TRUE; |
84 *y = SDL_DeltaY; | 80 selected_mouse = SDL_SelectMouse(index); |
85 SDL_DeltaX = 0; | 81 SDL_mice[index]->cur_cursor = NULL; |
86 SDL_DeltaY = 0; | 82 SDL_mice[index]->def_cursor = |
87 return(SDL_ButtonState); | 83 SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, |
88 } | 84 DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY); |
89 | 85 SDL_SetCursor(SDL_mice[index]->def_cursor); |
90 static void ClipOffset(Sint16 *x, Sint16 *y) | 86 SDL_SelectMouse(selected_mouse); |
91 { | 87 |
92 /* This clips absolute mouse coordinates when the apparent | 88 return index; |
93 display surface is smaller than the real display surface. | 89 } |
94 */ | 90 |
95 if ( SDL_VideoSurface->offset ) { | 91 void |
96 *y -= SDL_VideoSurface->offset/SDL_VideoSurface->pitch; | 92 SDL_DelMouse(int index) |
97 *x -= (SDL_VideoSurface->offset%SDL_VideoSurface->pitch)/ | 93 { |
98 SDL_VideoSurface->format->BytesPerPixel; | 94 SDL_Mouse *mouse = SDL_GetMouse(index); |
99 } | 95 |
100 } | 96 if (!mouse) { |
101 | 97 return; |
102 /* These are global for SDL_eventloop.c */ | 98 } |
103 int SDL_PrivateMouseMotion(Uint8 buttonstate, int relative, Sint16 x, Sint16 y) | 99 |
104 { | 100 mouse->def_cursor = NULL; |
105 int posted; | 101 while (mouse->cursors) { |
106 Uint16 X, Y; | 102 SDL_FreeCursor(mouse->cursors); |
107 Sint16 Xrel; | 103 } |
108 Sint16 Yrel; | 104 |
109 | 105 if (mouse->FreeMouse) { |
110 /* Don't handle mouse motion if there's no cursor surface */ | 106 mouse->FreeMouse(mouse); |
111 if ( SDL_VideoSurface == NULL ) { | 107 } |
112 return(0); | 108 SDL_free(mouse); |
113 } | 109 |
114 | 110 SDL_mice[index] = NULL; |
115 /* Default buttonstate is the current one */ | 111 } |
116 if ( ! buttonstate ) { | 112 |
117 buttonstate = SDL_ButtonState; | 113 void |
118 } | 114 SDL_ResetMouse(int index) |
119 | 115 { |
120 Xrel = x; | 116 SDL_Mouse *mouse = SDL_GetMouse(index); |
121 Yrel = y; | 117 |
122 if ( relative ) { | 118 if (!mouse) { |
123 /* Push the cursor around */ | 119 return; |
124 x = (SDL_MouseX+x); | 120 } |
125 y = (SDL_MouseY+y); | 121 |
126 } else { | 122 /* FIXME */ |
127 /* Do we need to clip {x,y} ? */ | 123 } |
128 ClipOffset(&x, &y); | 124 |
129 } | 125 void |
130 | 126 SDL_MouseQuit(void) |
131 /* Mouse coordinates range from 0 - width-1 and 0 - height-1 */ | 127 { |
132 if ( x < 0 ) | 128 int i; |
133 X = 0; | 129 |
134 else | 130 for (i = 0; i < SDL_num_mice; ++i) { |
135 if ( x >= SDL_VideoSurface->w ) | 131 SDL_DelMouse(i); |
136 X = SDL_VideoSurface->w-1; | 132 } |
137 else | 133 SDL_num_mice = 0; |
138 X = (Uint16)x; | 134 SDL_current_mouse = 0; |
139 | 135 |
140 if ( y < 0 ) | 136 if (SDL_mice) { |
141 Y = 0; | 137 SDL_free(SDL_mice); |
142 else | 138 SDL_mice = NULL; |
143 if ( y >= SDL_VideoSurface->h ) | 139 } |
144 Y = SDL_VideoSurface->h-1; | 140 } |
145 else | 141 |
146 Y = (Uint16)y; | 142 int |
147 | 143 SDL_GetNumMice(void) |
148 /* If not relative mode, generate relative motion from clamped X/Y. | 144 { |
149 This prevents lots of extraneous large delta relative motion when | 145 return SDL_num_mice; |
150 the screen is windowed mode and the mouse is outside the window. | 146 } |
151 */ | 147 |
152 if ( ! relative ) { | 148 int |
153 Xrel = X-SDL_MouseX; | 149 SDL_SelectMouse(int index) |
154 Yrel = Y-SDL_MouseY; | 150 { |
155 } | 151 if (index >= 0 && index < SDL_num_mice) { |
156 | 152 SDL_current_mouse = index; |
157 /* Drop events that don't change state */ | 153 } |
158 if ( ! Xrel && ! Yrel ) { | 154 return SDL_current_mouse; |
155 } | |
156 | |
157 SDL_WindowID | |
158 SDL_GetMouseFocusWindow() | |
159 { | |
160 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
161 | |
162 if (!mouse) { | |
163 return 0; | |
164 } | |
165 return mouse->focus; | |
166 } | |
167 | |
168 static int | |
169 FlushMouseMotion(void *param, SDL_Event * event) | |
170 { | |
171 if (event->type == SDL_MOUSEMOTION | |
172 && event->motion.which == (Uint8) SDL_current_mouse) { | |
173 return 0; | |
174 } else { | |
175 return 1; | |
176 } | |
177 } | |
178 | |
179 int | |
180 SDL_SetRelativeMouseMode(SDL_bool enabled) | |
181 { | |
182 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
183 | |
184 if (!mouse) { | |
185 return -1; | |
186 } | |
187 | |
188 /* Flush pending mouse motion */ | |
189 mouse->flush_motion = SDL_TRUE; | |
190 SDL_PumpEvents(); | |
191 mouse->flush_motion = SDL_FALSE; | |
192 SDL_FilterEvents(FlushMouseMotion, mouse); | |
193 | |
194 /* Set the relative mode */ | |
195 mouse->relative_mode = enabled; | |
196 | |
197 /* Update cursor visibility */ | |
198 SDL_SetCursor(NULL); | |
199 | |
200 if (!enabled) { | |
201 /* Restore the expected mouse position */ | |
202 SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y); | |
203 } | |
204 return 0; | |
205 } | |
206 | |
207 SDL_bool | |
208 SDL_GetRelativeMouseMode() | |
209 { | |
210 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
211 | |
212 if (!mouse) { | |
213 return SDL_FALSE; | |
214 } | |
215 return mouse->relative_mode; | |
216 } | |
217 | |
218 Uint8 | |
219 SDL_GetMouseState(int *x, int *y) | |
220 { | |
221 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
222 | |
223 if (!mouse) { | |
224 if (x) { | |
225 *x = 0; | |
226 } | |
227 if (y) { | |
228 *y = 0; | |
229 } | |
230 return 0; | |
231 } | |
232 | |
233 if (x) { | |
234 *x = mouse->x; | |
235 } | |
236 if (y) { | |
237 *y = mouse->y; | |
238 } | |
239 return mouse->buttonstate; | |
240 } | |
241 | |
242 Uint8 | |
243 SDL_GetRelativeMouseState(int *x, int *y) | |
244 { | |
245 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
246 | |
247 if (!mouse) { | |
248 if (x) { | |
249 *x = 0; | |
250 } | |
251 if (y) { | |
252 *y = 0; | |
253 } | |
254 return 0; | |
255 } | |
256 | |
257 if (x) { | |
258 *x = mouse->xdelta; | |
259 } | |
260 if (y) { | |
261 *y = mouse->ydelta; | |
262 } | |
263 mouse->xdelta = 0; | |
264 mouse->ydelta = 0; | |
265 return mouse->buttonstate; | |
266 } | |
267 | |
268 void | |
269 SDL_SetMouseFocus(int index, SDL_WindowID windowID) | |
270 { | |
271 SDL_Mouse *mouse = SDL_GetMouse(index); | |
272 int i; | |
273 SDL_bool focus; | |
274 | |
275 if (!mouse || (mouse->focus == windowID)) { | |
276 return; | |
277 } | |
278 | |
279 /* See if the current window has lost focus */ | |
280 if (mouse->focus) { | |
281 focus = SDL_FALSE; | |
282 for (i = 0; i < SDL_num_mice; ++i) { | |
283 SDL_Mouse *check; | |
284 if (i != index) { | |
285 check = SDL_GetMouse(i); | |
286 if (check && check->focus == mouse->focus) { | |
287 focus = SDL_TRUE; | |
288 break; | |
289 } | |
290 } | |
291 } | |
292 if (!focus) { | |
293 SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0); | |
294 } | |
295 } | |
296 | |
297 mouse->focus = windowID; | |
298 | |
299 if (mouse->focus) { | |
300 focus = SDL_FALSE; | |
301 for (i = 0; i < SDL_num_mice; ++i) { | |
302 SDL_Mouse *check; | |
303 if (i != index) { | |
304 check = SDL_GetMouse(i); | |
305 if (check && check->focus == mouse->focus) { | |
306 focus = SDL_TRUE; | |
307 break; | |
308 } | |
309 } | |
310 } | |
311 if (!focus) { | |
312 SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0); | |
313 } | |
314 } | |
315 } | |
316 | |
317 int | |
318 SDL_SendMouseMotion(int index, int relative, int x, int y) | |
319 { | |
320 SDL_Mouse *mouse = SDL_GetMouse(index); | |
321 int posted; | |
322 int xrel; | |
323 int yrel; | |
324 | |
325 if (!mouse || mouse->flush_motion) { | |
326 return 0; | |
327 } | |
328 | |
329 if (relative) { | |
330 /* Push the cursor around */ | |
331 xrel = x; | |
332 yrel = y; | |
333 x = (mouse->x + xrel); | |
334 y = (mouse->y + yrel); | |
335 } else { | |
336 xrel = x - mouse->x; | |
337 yrel = y - mouse->y; | |
338 } | |
339 | |
340 /* Drop events that don't change state */ | |
341 if (!xrel && !yrel) { | |
159 #if 0 | 342 #if 0 |
160 printf("Mouse event didn't change state - dropped!\n"); | 343 printf("Mouse event didn't change state - dropped!\n"); |
161 #endif | 344 #endif |
162 return(0); | 345 return 0; |
163 } | 346 } |
164 | 347 |
165 /* Update internal mouse state */ | 348 /* Update internal mouse state */ |
166 SDL_ButtonState = buttonstate; | 349 if (!mouse->relative_mode) { |
167 SDL_MouseX = X; | 350 mouse->x = x; |
168 SDL_MouseY = Y; | 351 mouse->y = y; |
169 SDL_DeltaX += Xrel; | 352 } |
170 SDL_DeltaY += Yrel; | 353 mouse->xdelta += xrel; |
171 SDL_MoveCursor(SDL_MouseX, SDL_MouseY); | 354 mouse->ydelta += yrel; |
172 | 355 |
173 /* Post the event, if desired */ | 356 /* Move the mouse cursor, if needed */ |
174 posted = 0; | 357 if (mouse->cursor_shown && !mouse->relative_mode && |
175 if ( SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE ) { | 358 mouse->MoveCursor && mouse->cur_cursor) { |
176 SDL_Event event; | 359 mouse->MoveCursor(mouse->cur_cursor); |
177 SDL_memset(&event, 0, sizeof(event)); | 360 } |
178 event.type = SDL_MOUSEMOTION; | 361 |
179 event.motion.state = buttonstate; | 362 /* Post the event, if desired */ |
180 event.motion.x = X; | 363 posted = 0; |
181 event.motion.y = Y; | 364 if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE) { |
182 event.motion.xrel = Xrel; | 365 SDL_Event event; |
183 event.motion.yrel = Yrel; | 366 event.motion.type = SDL_MOUSEMOTION; |
184 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | 367 event.motion.which = (Uint8) index; |
185 posted = 1; | 368 event.motion.state = mouse->buttonstate; |
186 SDL_PushEvent(&event); | 369 event.motion.x = mouse->x; |
187 } | 370 event.motion.y = mouse->y; |
188 } | 371 event.motion.xrel = xrel; |
189 return(posted); | 372 event.motion.yrel = yrel; |
190 } | 373 event.motion.windowID = mouse->focus; |
191 | 374 posted = (SDL_PushEvent(&event) > 0); |
192 int SDL_PrivateMouseButton(Uint8 state, Uint8 button, Sint16 x, Sint16 y) | 375 } |
193 { | 376 return posted; |
194 SDL_Event event; | 377 } |
195 int posted; | 378 |
196 int move_mouse; | 379 int |
197 Uint8 buttonstate; | 380 SDL_SendMouseButton(int index, Uint8 state, Uint8 button) |
198 | 381 { |
199 SDL_memset(&event, 0, sizeof(event)); | 382 SDL_Mouse *mouse = SDL_GetMouse(index); |
200 | 383 int posted; |
201 /* Check parameters */ | 384 Uint8 type; |
202 if ( x || y ) { | 385 |
203 ClipOffset(&x, &y); | 386 if (!mouse) { |
204 move_mouse = 1; | 387 return 0; |
205 /* Mouse coordinates range from 0 - width-1 and 0 - height-1 */ | 388 } |
206 if ( x < 0 ) | 389 |
207 x = 0; | 390 /* Figure out which event to perform */ |
208 else | 391 switch (state) { |
209 if ( x >= SDL_VideoSurface->w ) | 392 case SDL_PRESSED: |
210 x = SDL_VideoSurface->w-1; | 393 if (mouse->buttonstate & SDL_BUTTON(button)) { |
211 | 394 /* Ignore this event, no state change */ |
212 if ( y < 0 ) | 395 return 0; |
213 y = 0; | 396 } |
214 else | 397 type = SDL_MOUSEBUTTONDOWN; |
215 if ( y >= SDL_VideoSurface->h ) | 398 mouse->buttonstate |= SDL_BUTTON(button); |
216 y = SDL_VideoSurface->h-1; | 399 break; |
217 } else { | 400 case SDL_RELEASED: |
218 move_mouse = 0; | 401 if (!(mouse->buttonstate & SDL_BUTTON(button))) { |
219 } | 402 /* Ignore this event, no state change */ |
220 if ( ! x ) | 403 return 0; |
221 x = SDL_MouseX; | 404 } |
222 if ( ! y ) | 405 type = SDL_MOUSEBUTTONUP; |
223 y = SDL_MouseY; | 406 mouse->buttonstate &= ~SDL_BUTTON(button); |
224 | 407 break; |
225 /* Figure out which event to perform */ | 408 default: |
226 buttonstate = SDL_ButtonState; | 409 /* Invalid state -- bail */ |
227 switch ( state ) { | 410 return 0; |
228 case SDL_PRESSED: | 411 } |
229 event.type = SDL_MOUSEBUTTONDOWN; | 412 |
230 buttonstate |= SDL_BUTTON(button); | 413 /* Post the event, if desired */ |
231 break; | 414 posted = 0; |
232 case SDL_RELEASED: | 415 if (SDL_ProcessEvents[type] == SDL_ENABLE) { |
233 event.type = SDL_MOUSEBUTTONUP; | 416 SDL_Event event; |
234 buttonstate &= ~SDL_BUTTON(button); | 417 event.type = type; |
235 break; | 418 event.button.which = (Uint8) index; |
236 default: | 419 event.button.state = state; |
237 /* Invalid state -- bail */ | 420 event.button.button = button; |
238 return(0); | 421 event.button.x = mouse->x; |
239 } | 422 event.button.y = mouse->y; |
240 | 423 event.button.windowID = mouse->focus; |
241 /* Update internal mouse state */ | 424 posted = (SDL_PushEvent(&event) > 0); |
242 SDL_ButtonState = buttonstate; | 425 } |
243 if ( move_mouse ) { | 426 return posted; |
244 SDL_MouseX = x; | 427 } |
245 SDL_MouseY = y; | 428 |
246 SDL_MoveCursor(SDL_MouseX, SDL_MouseY); | 429 int |
247 } | 430 SDL_SendMouseWheel(int index, int motion) |
248 | 431 { |
249 /* Post the event, if desired */ | 432 SDL_Mouse *mouse = SDL_GetMouse(index); |
250 posted = 0; | 433 int posted; |
251 if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) { | 434 |
252 event.button.state = state; | 435 if (!mouse || !motion) { |
253 event.button.button = button; | 436 return 0; |
254 event.button.x = x; | 437 } |
255 event.button.y = y; | 438 |
256 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | 439 /* Post the event, if desired */ |
257 posted = 1; | 440 posted = 0; |
258 SDL_PushEvent(&event); | 441 if (SDL_ProcessEvents[SDL_MOUSEWHEEL] == SDL_ENABLE) { |
259 } | 442 SDL_Event event; |
260 } | 443 event.type = SDL_MOUSEWHEEL; |
261 return(posted); | 444 event.wheel.which = (Uint8) index; |
262 } | 445 event.wheel.motion = motion; |
263 | 446 event.wheel.windowID = mouse->focus; |
447 posted = (SDL_PushEvent(&event) > 0); | |
448 } | |
449 return posted; | |
450 } | |
451 | |
452 void | |
453 SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y) | |
454 { | |
455 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
456 | |
457 if (!mouse) { | |
458 return; | |
459 } | |
460 | |
461 if (mouse->WarpMouse) { | |
462 mouse->WarpMouse(mouse, windowID, x, y); | |
463 } else { | |
464 SDL_SetMouseFocus(SDL_current_mouse, windowID); | |
465 SDL_SendMouseMotion(SDL_current_mouse, 0, x, y); | |
466 } | |
467 } | |
468 | |
469 SDL_Cursor * | |
470 SDL_CreateCursor(const Uint8 * data, const Uint8 * mask, | |
471 int w, int h, int hot_x, int hot_y) | |
472 { | |
473 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
474 SDL_Surface *surface; | |
475 SDL_Cursor *cursor; | |
476 int x, y; | |
477 Uint32 *pixel; | |
478 Uint8 datab, maskb; | |
479 const Uint32 black = 0xFF000000; | |
480 const Uint32 white = 0xFFFFFFFF; | |
481 const Uint32 transparent = 0x00000000; | |
482 | |
483 if (!mouse) { | |
484 SDL_SetError("No mice are initialized"); | |
485 return NULL; | |
486 } | |
487 | |
488 if (!mouse->CreateCursor) { | |
489 SDL_SetError("Current mouse doesn't have cursor support"); | |
490 return NULL; | |
491 } | |
492 | |
493 /* Sanity check the hot spot */ | |
494 if ((hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h)) { | |
495 SDL_SetError("Cursor hot spot doesn't lie within cursor"); | |
496 return NULL; | |
497 } | |
498 | |
499 /* Make sure the width is a multiple of 8 */ | |
500 w = ((w + 7) & ~7); | |
501 | |
502 /* Create the surface from a bitmap */ | |
503 surface = | |
504 SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, | |
505 0xFF000000); | |
506 if (!surface) { | |
507 return NULL; | |
508 } | |
509 for (y = 0; y < h; ++y) { | |
510 pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch); | |
511 for (x = 0; x < w; ++x) { | |
512 if ((x % 8) == 0) { | |
513 datab = *data++; | |
514 maskb = *mask++; | |
515 } | |
516 if (maskb & 0x80) { | |
517 *pixel++ = (datab & 0x80) ? black : white; | |
518 } else { | |
519 *pixel++ = (datab & 0x80) ? black : transparent; | |
520 } | |
521 datab <<= 1; | |
522 maskb <<= 1; | |
523 } | |
524 } | |
525 | |
526 cursor = mouse->CreateCursor(surface, hot_x, hot_y); | |
527 if (cursor) { | |
528 cursor->mouse = mouse; | |
529 cursor->next = mouse->cursors; | |
530 mouse->cursors = cursor; | |
531 } | |
532 | |
533 SDL_FreeSurface(surface); | |
534 | |
535 return cursor; | |
536 } | |
537 | |
538 /* SDL_SetCursor(NULL) can be used to force the cursor redraw, | |
539 if this is desired for any reason. This is used when setting | |
540 the video mode and when the SDL window gains the mouse focus. | |
541 */ | |
542 void | |
543 SDL_SetCursor(SDL_Cursor * cursor) | |
544 { | |
545 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
546 | |
547 if (!mouse) { | |
548 SDL_SetError("No mice are initialized"); | |
549 return; | |
550 } | |
551 | |
552 /* Set the new cursor */ | |
553 if (cursor) { | |
554 /* Make sure the cursor is still valid for this mouse */ | |
555 SDL_Cursor *found; | |
556 for (found = mouse->cursors; found; found = found->next) { | |
557 if (found == cursor) { | |
558 break; | |
559 } | |
560 } | |
561 if (!found) { | |
562 SDL_SetError("Cursor not associated with the current mouse"); | |
563 return; | |
564 } | |
565 mouse->cur_cursor = cursor; | |
566 } else { | |
567 cursor = mouse->cur_cursor; | |
568 } | |
569 | |
570 if (cursor && mouse->cursor_shown && !mouse->relative_mode) { | |
571 if (mouse->ShowCursor) { | |
572 mouse->ShowCursor(cursor); | |
573 } | |
574 } else { | |
575 if (mouse->ShowCursor) { | |
576 mouse->ShowCursor(NULL); | |
577 } | |
578 } | |
579 } | |
580 | |
581 SDL_Cursor * | |
582 SDL_GetCursor(void) | |
583 { | |
584 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
585 | |
586 if (!mouse) { | |
587 return NULL; | |
588 } | |
589 return mouse->cur_cursor; | |
590 } | |
591 | |
592 void | |
593 SDL_FreeCursor(SDL_Cursor * cursor) | |
594 { | |
595 SDL_Mouse *mouse; | |
596 SDL_Cursor *curr, *prev; | |
597 | |
598 if (!cursor) { | |
599 return; | |
600 } | |
601 mouse = cursor->mouse; | |
602 | |
603 if (cursor == mouse->def_cursor) { | |
604 return; | |
605 } | |
606 if (cursor == mouse->cur_cursor) { | |
607 SDL_SetCursor(mouse->def_cursor); | |
608 } | |
609 | |
610 for (prev = NULL, curr = mouse->cursors; curr; | |
611 prev = curr, curr = curr->next) { | |
612 if (curr == cursor) { | |
613 if (prev) { | |
614 prev->next = curr->next; | |
615 } else { | |
616 mouse->cursors = curr->next; | |
617 } | |
618 | |
619 if (mouse->FreeCursor) { | |
620 mouse->FreeCursor(curr); | |
621 } | |
622 return; | |
623 } | |
624 } | |
625 } | |
626 | |
627 int | |
628 SDL_ShowCursor(int toggle) | |
629 { | |
630 SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); | |
631 SDL_bool shown; | |
632 | |
633 if (!mouse) { | |
634 return 0; | |
635 } | |
636 | |
637 shown = mouse->cursor_shown; | |
638 if (toggle >= 0) { | |
639 if (toggle) { | |
640 mouse->cursor_shown = SDL_TRUE; | |
641 } else { | |
642 mouse->cursor_shown = SDL_FALSE; | |
643 } | |
644 if (mouse->cursor_shown != shown) { | |
645 SDL_SetCursor(NULL); | |
646 } | |
647 } | |
648 return shown; | |
649 } | |
650 | |
651 /* vi: set ts=4 sw=4 expandtab: */ |