|
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 */ |
|
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 } |
|
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 |
|
91 void SDL_LockCursor(void) |
|
92 { |
|
93 if ( SDL_cursorlock ) { |
|
94 SDL_mutexP(SDL_cursorlock); |
|
95 } |
|
96 } |
|
97 #endif |
|
98 #ifndef SDL_UnlockCursor |
|
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 */ |
|
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 */ |
|
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 |
|
234 SDL_Cursor * SDL_GetCursor (void) |
|
235 { |
|
236 return(SDL_cursor); |
|
237 } |
|
238 |
|
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 |
|
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 |
|
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 |
|
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 |
|
343 void SDL_CursorPaletteChanged(void) |
|
344 { |
|
345 palette_changed = 1; |
|
346 } |
|
347 |
|
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 |
|
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 |
|
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 */ |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 */ |
|
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 } |