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