comparison src/video/SDL_cursor.c @ 1670:eef792d31de8 SDL-1.3

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