comparison src/video/SDL_cursor.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children cf2af46e9e2a
comparison
equal deleted inserted replaced
-1:000000000000 0:74212992fb08
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@devolution.com
21 */
22
23 #ifdef SAVE_RCSID
24 static char rcsid =
25 "@(#) $Id$";
26 #endif
27
28 /* General cursor handling code for SDL */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "SDL_mutex.h"
35 #include "SDL_error.h"
36 #include "SDL_video.h"
37 #include "SDL_mouse.h"
38 #include "SDL_blit.h"
39 #include "SDL_events_c.h"
40 #include "SDL_sysvideo.h"
41 #include "SDL_sysevents.h"
42 #include "SDL_cursor_c.h"
43 #include "SDL_pixels_c.h"
44 #include "default_cursor.h"
45
46 /* These are static for our cursor handling code */
47 volatile int SDL_cursorstate = CURSOR_VISIBLE;
48 SDL_Cursor *SDL_cursor = NULL;
49 static SDL_Cursor *SDL_defcursor = NULL;
50 SDL_mutex *SDL_cursorlock = NULL;
51
52 /* Public functions */
53 void SDL_CursorQuit(void)
54 {
55 if ( SDL_cursor != NULL ) {
56 SDL_Cursor *cursor;
57
58 SDL_cursorstate &= ~CURSOR_VISIBLE;
59 if ( SDL_cursor != SDL_defcursor ) {
60 SDL_FreeCursor(SDL_cursor);
61 }
62 SDL_cursor = NULL;
63 if ( SDL_defcursor != NULL ) {
64 cursor = SDL_defcursor;
65 SDL_defcursor = NULL;
66 SDL_FreeCursor(cursor);
67 }
68 }
69 if ( SDL_cursorlock != NULL ) {
70 SDL_DestroyMutex(SDL_cursorlock);
71 SDL_cursorlock = NULL;
72 }
73 }
74 int SDL_CursorInit(Uint32 multithreaded)
75 {
76 /* We don't have mouse focus, and the cursor isn't drawn yet */
77 SDL_cursorstate = CURSOR_VISIBLE;
78
79 /* Create the default cursor */
80 if ( SDL_defcursor == NULL ) {
81 SDL_defcursor = SDL_CreateCursor(default_cdata, default_cmask,
82 DEFAULT_CWIDTH, DEFAULT_CHEIGHT,
83 DEFAULT_CHOTX, DEFAULT_CHOTY);
84 SDL_SetCursor(SDL_defcursor);
85 }
86
87 /* Create a lock if necessary */
88 if ( multithreaded ) {
89 SDL_cursorlock = SDL_CreateMutex();
90 }
91
92 /* That's it! */
93 return(0);
94 }
95
96 /* Multi-thread support for cursors */
97 #ifndef SDL_LockCursor
98 void SDL_LockCursor(void)
99 {
100 if ( SDL_cursorlock ) {
101 SDL_mutexP(SDL_cursorlock);
102 }
103 }
104 #endif
105 #ifndef SDL_UnlockCursor
106 void SDL_UnlockCursor(void)
107 {
108 if ( SDL_cursorlock ) {
109 SDL_mutexV(SDL_cursorlock);
110 }
111 }
112 #endif
113
114 /* Software cursor drawing support */
115 SDL_Cursor * SDL_CreateCursor (Uint8 *data, Uint8 *mask,
116 int w, int h, int hot_x, int hot_y)
117 {
118 SDL_VideoDevice *video = current_video;
119 int savelen;
120 int i;
121 SDL_Cursor *cursor;
122
123 /* Make sure the width is a multiple of 8 */
124 w = ((w+7)&~7);
125
126 /* Sanity check the hot spot */
127 if ( (hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h) ) {
128 SDL_SetError("Cursor hot spot doesn't lie within cursor");
129 return(NULL);
130 }
131
132 /* Allocate memory for the cursor */
133 cursor = (SDL_Cursor *)malloc(sizeof *cursor);
134 if ( cursor == NULL ) {
135 SDL_OutOfMemory();
136 return(NULL);
137 }
138 savelen = (w*4)*h;
139 cursor->area.x = 0;
140 cursor->area.y = 0;
141 cursor->area.w = w;
142 cursor->area.h = h;
143 cursor->hot_x = hot_x;
144 cursor->hot_y = hot_y;
145 cursor->data = (Uint8 *)malloc((w/8)*h*2);
146 cursor->mask = cursor->data+((w/8)*h);
147 cursor->save[0] = (Uint8 *)malloc(savelen*2);
148 cursor->save[1] = cursor->save[0] + savelen;
149 cursor->wm_cursor = NULL;
150 if ( ! cursor->data || ! cursor->save[0] ) {
151 SDL_FreeCursor(cursor);
152 SDL_OutOfMemory();
153 return(NULL);
154 }
155 for ( i=((w/8)*h)-1; i>=0; --i ) {
156 cursor->data[i] = data[i];
157 cursor->mask[i] = mask[i] | data[i];
158 }
159 memset(cursor->save[0], 0, savelen*2);
160
161 /* If the window manager gives us a good cursor, we're done! */
162 if ( video->CreateWMCursor ) {
163 cursor->wm_cursor = video->CreateWMCursor(video, data, mask,
164 w, h, hot_x, hot_y);
165 } else {
166 cursor->wm_cursor = NULL;
167 }
168 return(cursor);
169 }
170
171 /* SDL_SetCursor(NULL) can be used to force the cursor redraw,
172 if this is desired for any reason. This is used when setting
173 the video mode and when the SDL window gains the mouse focus.
174 */
175 void SDL_SetCursor (SDL_Cursor *cursor)
176 {
177 SDL_VideoDevice *video = current_video;
178 SDL_VideoDevice *this = current_video;
179
180 /* Make sure that the video subsystem has been initialized */
181 if ( ! video ) {
182 return;
183 }
184
185 /* Prevent the event thread from moving the mouse */
186 SDL_LockCursor();
187
188 /* Set the new cursor */
189 if ( cursor && (cursor != SDL_cursor) ) {
190 /* Erase the current mouse position */
191 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
192 SDL_EraseCursor(SDL_VideoSurface);
193 } else if ( video->MoveWMCursor ) {
194 /* If the video driver is moving the cursor directly,
195 it needs to hide the old cursor before (possibly)
196 showing the new one. (But don't erase NULL cursor)
197 */
198 if ( SDL_cursor ) {
199 video->ShowWMCursor(this, NULL);
200 }
201 }
202 SDL_cursor = cursor;
203 }
204
205 /* Draw the new mouse cursor */
206 if ( SDL_cursor && (SDL_cursorstate&CURSOR_VISIBLE) ) {
207 /* Use window manager cursor if possible */
208 if ( SDL_cursor->wm_cursor &&
209 video->ShowWMCursor(this, SDL_cursor->wm_cursor) )
210 SDL_cursorstate &= ~CURSOR_USINGSW;
211 else {
212 SDL_cursorstate |= CURSOR_USINGSW;
213 if ( video->ShowWMCursor ) {
214 video->ShowWMCursor(this, NULL);
215 }
216 { int x, y;
217 SDL_GetMouseState(&x, &y);
218 SDL_cursor->area.x = (x - SDL_cursor->hot_x);
219 SDL_cursor->area.y = (y - SDL_cursor->hot_y);
220 }
221 SDL_DrawCursor(SDL_VideoSurface);
222 }
223 } else {
224 /* Erase window manager mouse (cursor not visible) */
225 if ( SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW) ) {
226 SDL_EraseCursor(SDL_VideoSurface);
227 } else {
228 if ( video ) {
229 video->ShowWMCursor(this, NULL);
230 }
231 }
232 }
233 SDL_UnlockCursor();
234 }
235
236 SDL_Cursor * SDL_GetCursor (void)
237 {
238 return(SDL_cursor);
239 }
240
241 void SDL_FreeCursor (SDL_Cursor *cursor)
242 {
243 if ( cursor ) {
244 if ( cursor == SDL_cursor ) {
245 SDL_SetCursor(SDL_defcursor);
246 }
247 if ( cursor != SDL_defcursor ) {
248 if ( cursor->data ) {
249 free(cursor->data);
250 }
251 if ( cursor->save[0] ) {
252 free(cursor->save[0]);
253 }
254 if ( cursor->wm_cursor ) {
255 SDL_VideoDevice *video = current_video;
256 SDL_VideoDevice *this = current_video;
257 video->FreeWMCursor(this, cursor->wm_cursor);
258 }
259 free(cursor);
260 }
261 }
262 }
263
264 int SDL_ShowCursor (int toggle)
265 {
266 int showing;
267
268 showing = (SDL_cursorstate & CURSOR_VISIBLE);
269 if ( toggle >= 0 ) {
270 SDL_LockCursor();
271 if ( toggle ) {
272 SDL_cursorstate |= CURSOR_VISIBLE;
273 } else {
274 SDL_cursorstate &= ~CURSOR_VISIBLE;
275 }
276 SDL_UnlockCursor();
277 if ( (SDL_cursorstate & CURSOR_VISIBLE) != showing ) {
278 SDL_VideoDevice *video = current_video;
279 SDL_VideoDevice *this = current_video;
280
281 SDL_SetCursor(NULL);
282 if ( video && video->CheckMouseMode ) {
283 video->CheckMouseMode(this);
284 }
285 }
286 } else {
287 /* Query current state */ ;
288 }
289 return(showing ? 1 : 0);
290 }
291
292 void SDL_WarpMouse (Uint16 x, Uint16 y)
293 {
294 SDL_VideoDevice *video = current_video;
295 SDL_VideoDevice *this = current_video;
296
297 /* This generates a mouse motion event */
298 if ( video->WarpWMCursor ) {
299 video->WarpWMCursor(this, x, y);
300 } else {
301 x += (this->screen->offset % this->screen->pitch) /
302 this->screen->format->BytesPerPixel;
303 y += (this->screen->offset / this->screen->pitch);
304 SDL_PrivateMouseMotion(0, 0, x, y);
305 }
306 }
307
308 void SDL_MoveCursor(int x, int y)
309 {
310 SDL_VideoDevice *video = current_video;
311
312 /* Erase and update the current mouse position */
313 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
314 /* Erase and redraw mouse cursor in new position */
315 SDL_LockCursor();
316 SDL_EraseCursor(SDL_VideoSurface);
317 SDL_cursor->area.x = (x - SDL_cursor->hot_x);
318 SDL_cursor->area.y = (y - SDL_cursor->hot_y);
319 SDL_DrawCursor(SDL_VideoSurface);
320 SDL_UnlockCursor();
321 } else if ( video->MoveWMCursor ) {
322 video->MoveWMCursor(video, x, y);
323 }
324 }
325
326 /* Keep track of the current cursor colors */
327 static int palette_changed = 1;
328 static Uint32 pixels8[2];
329
330 void SDL_CursorPaletteChanged(void)
331 {
332 palette_changed = 1;
333 }
334
335 void SDL_MouseRect(SDL_Rect *area)
336 {
337 int clip_diff;
338
339 *area = SDL_cursor->area;
340 if ( area->x < 0 ) {
341 area->w += area->x;
342 area->x = 0;
343 }
344 if ( area->y < 0 ) {
345 area->h += area->y;
346 area->y = 0;
347 }
348 clip_diff = (area->x+area->w)-SDL_VideoSurface->w;
349 if ( clip_diff > 0 ) {
350 area->w -= clip_diff;
351 }
352 clip_diff = (area->y+area->h)-SDL_VideoSurface->h;
353 if ( clip_diff > 0 ) {
354 area->h -= clip_diff;
355 }
356 }
357
358 static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area)
359 {
360 const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
361 int i, w, h;
362 Uint8 *data, datab;
363 Uint8 *mask, maskb;
364
365 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8;
366 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8;
367 switch (screen->format->BytesPerPixel) {
368
369 case 1: {
370 Uint8 *dst;
371 int dstskip;
372
373 if ( palette_changed ) {
374 pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255);
375 pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0);
376 palette_changed = 0;
377 }
378 dst = (Uint8 *)screen->pixels +
379 (SDL_cursor->area.y+area->y)*screen->pitch +
380 SDL_cursor->area.x;
381 dstskip = screen->pitch-area->w;
382
383 for ( h=area->h; h; h-- ) {
384 for ( w=area->w/8; w; w-- ) {
385 maskb = *mask++;
386 datab = *data++;
387 for ( i=0; i<8; ++i ) {
388 if ( maskb & 0x80 ) {
389 *dst = pixels8[datab>>7];
390 }
391 maskb <<= 1;
392 datab <<= 1;
393 dst++;
394 }
395 }
396 dst += dstskip;
397 }
398 }
399 break;
400
401 case 2: {
402 Uint16 *dst;
403 int dstskip;
404
405 dst = (Uint16 *)screen->pixels +
406 (SDL_cursor->area.y+area->y)*screen->pitch/2 +
407 SDL_cursor->area.x;
408 dstskip = (screen->pitch/2)-area->w;
409
410 for ( h=area->h; h; h-- ) {
411 for ( w=area->w/8; w; w-- ) {
412 maskb = *mask++;
413 datab = *data++;
414 for ( i=0; i<8; ++i ) {
415 if ( maskb & 0x80 ) {
416 *dst = pixels[datab>>7];
417 }
418 maskb <<= 1;
419 datab <<= 1;
420 dst++;
421 }
422 }
423 dst += dstskip;
424 }
425 }
426 break;
427
428 case 3: {
429 Uint8 *dst;
430 int dstskip;
431
432 dst = (Uint8 *)screen->pixels +
433 (SDL_cursor->area.y+area->y)*screen->pitch +
434 SDL_cursor->area.x*3;
435 dstskip = screen->pitch-area->w*3;
436
437 for ( h=area->h; h; h-- ) {
438 for ( w=area->w/8; w; w-- ) {
439 maskb = *mask++;
440 datab = *data++;
441 for ( i=0; i<8; ++i ) {
442 if ( maskb & 0x80 ) {
443 memset(dst,pixels[datab>>7],3);
444 }
445 maskb <<= 1;
446 datab <<= 1;
447 dst += 3;
448 }
449 }
450 dst += dstskip;
451 }
452 }
453 break;
454
455 case 4: {
456 Uint32 *dst;
457 int dstskip;
458
459 dst = (Uint32 *)screen->pixels +
460 (SDL_cursor->area.y+area->y)*screen->pitch/4 +
461 SDL_cursor->area.x;
462 dstskip = (screen->pitch/4)-area->w;
463
464 for ( h=area->h; h; h-- ) {
465 for ( w=area->w/8; w; w-- ) {
466 maskb = *mask++;
467 datab = *data++;
468 for ( i=0; i<8; ++i ) {
469 if ( maskb & 0x80 ) {
470 *dst = pixels[datab>>7];
471 }
472 maskb <<= 1;
473 datab <<= 1;
474 dst++;
475 }
476 }
477 dst += dstskip;
478 }
479 }
480 break;
481 }
482 }
483
484 static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area)
485 {
486 const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
487 int h;
488 int x, minx, maxx;
489 Uint8 *data, datab = 0;
490 Uint8 *mask, maskb = 0;
491 Uint8 *dst;
492 int dstbpp, dstskip;
493
494 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8;
495 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8;
496 dstbpp = screen->format->BytesPerPixel;
497 dst = (Uint8 *)screen->pixels +
498 (SDL_cursor->area.y+area->y)*screen->pitch +
499 SDL_cursor->area.x*dstbpp;
500 dstskip = screen->pitch-SDL_cursor->area.w*dstbpp;
501
502 minx = area->x;
503 maxx = area->x+area->w;
504 if ( screen->format->BytesPerPixel == 1 ) {
505 if ( palette_changed ) {
506 pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255);
507 pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0);
508 palette_changed = 0;
509 }
510 for ( h=area->h; h; h-- ) {
511 for ( x=0; x<SDL_cursor->area.w; ++x ) {
512 if ( (x%8) == 0 ) {
513 maskb = *mask++;
514 datab = *data++;
515 }
516 if ( (x >= minx) && (x < maxx) ) {
517 if ( maskb & 0x80 ) {
518 memset(dst, pixels8[datab>>7], dstbpp);
519 }
520 }
521 maskb <<= 1;
522 datab <<= 1;
523 dst += dstbpp;
524 }
525 dst += dstskip;
526 }
527 } else {
528 for ( h=area->h; h; h-- ) {
529 for ( x=0; x<SDL_cursor->area.w; ++x ) {
530 if ( (x%8) == 0 ) {
531 maskb = *mask++;
532 datab = *data++;
533 }
534 if ( (x >= minx) && (x < maxx) ) {
535 if ( maskb & 0x80 ) {
536 memset(dst, pixels[datab>>7], dstbpp);
537 }
538 }
539 maskb <<= 1;
540 datab <<= 1;
541 dst += dstbpp;
542 }
543 dst += dstskip;
544 }
545 }
546 }
547
548 /* This handles the ugly work of converting the saved cursor background from
549 the pixel format of the shadow surface to that of the video surface.
550 This is only necessary when blitting from a shadow surface of a different
551 pixel format than the video surface, and using a software rendered cursor.
552 */
553 static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h)
554 {
555 SDL_BlitInfo info;
556 SDL_loblit RunBlit;
557
558 /* Make sure we can steal the blit mapping */
559 if ( screen->map->dst != SDL_VideoSurface ) {
560 return;
561 }
562
563 /* Set up the blit information */
564 info.s_pixels = SDL_cursor->save[1];
565 info.s_width = w;
566 info.s_height = h;
567 info.s_skip = 0;
568 info.d_pixels = SDL_cursor->save[0];
569 info.d_width = w;
570 info.d_height = h;
571 info.d_skip = 0;
572 info.aux_data = screen->map->sw_data->aux_data;
573 info.src = screen->format;
574 info.table = screen->map->table;
575 info.dst = SDL_VideoSurface->format;
576 RunBlit = screen->map->sw_data->blit;
577
578 /* Run the actual software blit */
579 RunBlit(&info);
580 }
581
582 void SDL_DrawCursorNoLock(SDL_Surface *screen)
583 {
584 SDL_Rect area;
585
586 /* Get the mouse rectangle, clipped to the screen */
587 SDL_MouseRect(&area);
588 if ( (area.w == 0) || (area.h == 0) ) {
589 return;
590 }
591
592 /* Copy mouse background */
593 { int w, h, screenbpp;
594 Uint8 *src, *dst;
595
596 /* Set up the copy pointers */
597 screenbpp = screen->format->BytesPerPixel;
598 if ( (screen == SDL_VideoSurface) ||
599 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) {
600 dst = SDL_cursor->save[0];
601 } else {
602 dst = SDL_cursor->save[1];
603 }
604 src = (Uint8 *)screen->pixels + area.y * screen->pitch +
605 area.x * screenbpp;
606
607 /* Perform the copy */
608 w = area.w*screenbpp;
609 h = area.h;
610 while ( h-- ) {
611 memcpy(dst, src, w);
612 dst += w;
613 src += screen->pitch;
614 }
615 }
616
617 /* Draw the mouse cursor */
618 area.x -= SDL_cursor->area.x;
619 area.y -= SDL_cursor->area.y;
620 if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) {
621 SDL_DrawCursorFast(screen, &area);
622 } else {
623 SDL_DrawCursorSlow(screen, &area);
624 }
625 }
626
627 void SDL_DrawCursor(SDL_Surface *screen)
628 {
629 /* Lock the screen if necessary */
630 if ( screen == NULL ) {
631 return;
632 }
633 if ( SDL_MUSTLOCK(screen) ) {
634 if ( SDL_LockSurface(screen) < 0 ) {
635 return;
636 }
637 }
638
639 SDL_DrawCursorNoLock(screen);
640
641 /* Unlock the screen and update if necessary */
642 if ( SDL_MUSTLOCK(screen) ) {
643 SDL_UnlockSurface(screen);
644 }
645 if ( (screen == SDL_VideoSurface) &&
646 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) {
647 SDL_VideoDevice *video = current_video;
648 SDL_VideoDevice *this = current_video;
649 SDL_Rect area;
650
651 SDL_MouseRect(&area);
652
653 /* This can be called before a video mode is set */
654 if ( video->UpdateRects ) {
655 video->UpdateRects(this, 1, &area);
656 }
657 }
658 }
659
660 void SDL_EraseCursorNoLock(SDL_Surface *screen)
661 {
662 SDL_Rect area;
663
664 /* Get the mouse rectangle, clipped to the screen */
665 SDL_MouseRect(&area);
666 if ( (area.w == 0) || (area.h == 0) ) {
667 return;
668 }
669
670 /* Copy mouse background */
671 { int w, h, screenbpp;
672 Uint8 *src, *dst;
673
674 /* Set up the copy pointers */
675 screenbpp = screen->format->BytesPerPixel;
676 if ( (screen == SDL_VideoSurface) ||
677 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) {
678 src = SDL_cursor->save[0];
679 } else {
680 src = SDL_cursor->save[1];
681 }
682 dst = (Uint8 *)screen->pixels + area.y * screen->pitch +
683 area.x * screenbpp;
684
685 /* Perform the copy */
686 w = area.w*screenbpp;
687 h = area.h;
688 while ( h-- ) {
689 memcpy(dst, src, w);
690 src += w;
691 dst += screen->pitch;
692 }
693
694 /* Perform pixel conversion on cursor background */
695 if ( src > SDL_cursor->save[1] ) {
696 SDL_ConvertCursorSave(screen, area.w, area.h);
697 }
698 }
699 }
700
701 void SDL_EraseCursor(SDL_Surface *screen)
702 {
703 /* Lock the screen if necessary */
704 if ( screen == NULL ) {
705 return;
706 }
707 if ( SDL_MUSTLOCK(screen) ) {
708 if ( SDL_LockSurface(screen) < 0 ) {
709 return;
710 }
711 }
712
713 SDL_EraseCursorNoLock(screen);
714
715 /* Unlock the screen and update if necessary */
716 if ( SDL_MUSTLOCK(screen) ) {
717 SDL_UnlockSurface(screen);
718 }
719 if ( (screen == SDL_VideoSurface) &&
720 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) {
721 SDL_VideoDevice *video = current_video;
722 SDL_VideoDevice *this = current_video;
723 SDL_Rect area;
724
725 SDL_MouseRect(&area);
726 video->UpdateRects(this, 1, &area);
727 }
728 }
729
730 /* Reset the cursor on video mode change
731 FIXME: Keep track of all cursors, and reset them all.
732 */
733 void SDL_ResetCursor(void)
734 {
735 int savelen;
736
737 if ( SDL_cursor ) {
738 savelen = SDL_cursor->area.w*4*SDL_cursor->area.h;
739 SDL_cursor->area.x = 0;
740 SDL_cursor->area.y = 0;
741 memset(SDL_cursor->save[0], 0, savelen);
742 }
743 }