Mercurial > sdl-ios-xcode
annotate src/video/SDL_cursor.c @ 571:8e3ce997621c
Date: Thu, 16 Jan 2003 13:48:31 +0200
From: "Mike Gorchak"
Subject: All QNX patches
whole patches concerning QNX. Almost all code has been rewritten by Julian
and me. Added initial support for hw overlays in QNX and many many others
fixes.
P.S. This patches has been reviewed by Dave Rempel from QSSL and included in
SDL 1.2.5 distribution, which coming on 3rd party CD for newest 6.2.1
version of QNX, which will be available soon.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 20 Jan 2003 01:38:37 +0000 |
parents | 5c74ac147358 |
children | 591b438ab94a |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 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 | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
113
diff
changeset
|
20 slouken@libsdl.org |
0 | 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 ) { | |
77
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
248 SDL_VideoDevice *video = current_video; |
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
249 SDL_VideoDevice *this = current_video; |
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
250 |
0 | 251 if ( cursor->data ) { |
252 free(cursor->data); | |
253 } | |
254 if ( cursor->save[0] ) { | |
255 free(cursor->save[0]); | |
256 } | |
77
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
257 if ( video && cursor->wm_cursor ) { |
0 | 258 video->FreeWMCursor(this, cursor->wm_cursor); |
259 } | |
260 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 | |
527
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
298 /* If we have an offset video mode, offset the mouse coordinates */ |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
299 x += (this->screen->offset % this->screen->pitch) / |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
300 this->screen->format->BytesPerPixel; |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
301 y += (this->screen->offset / this->screen->pitch); |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
302 |
0 | 303 /* This generates a mouse motion event */ |
304 if ( video->WarpWMCursor ) { | |
305 video->WarpWMCursor(this, x, y); | |
306 } else { | |
307 SDL_PrivateMouseMotion(0, 0, x, y); | |
308 } | |
309 } | |
310 | |
311 void SDL_MoveCursor(int x, int y) | |
312 { | |
313 SDL_VideoDevice *video = current_video; | |
314 | |
315 /* Erase and update the current mouse position */ | |
316 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { | |
317 /* Erase and redraw mouse cursor in new position */ | |
318 SDL_LockCursor(); | |
319 SDL_EraseCursor(SDL_VideoSurface); | |
320 SDL_cursor->area.x = (x - SDL_cursor->hot_x); | |
321 SDL_cursor->area.y = (y - SDL_cursor->hot_y); | |
322 SDL_DrawCursor(SDL_VideoSurface); | |
323 SDL_UnlockCursor(); | |
324 } else if ( video->MoveWMCursor ) { | |
325 video->MoveWMCursor(video, x, y); | |
326 } | |
327 } | |
328 | |
329 /* Keep track of the current cursor colors */ | |
330 static int palette_changed = 1; | |
331 static Uint32 pixels8[2]; | |
332 | |
333 void SDL_CursorPaletteChanged(void) | |
334 { | |
335 palette_changed = 1; | |
336 } | |
337 | |
338 void SDL_MouseRect(SDL_Rect *area) | |
339 { | |
340 int clip_diff; | |
341 | |
342 *area = SDL_cursor->area; | |
343 if ( area->x < 0 ) { | |
344 area->w += area->x; | |
345 area->x = 0; | |
346 } | |
347 if ( area->y < 0 ) { | |
348 area->h += area->y; | |
349 area->y = 0; | |
350 } | |
351 clip_diff = (area->x+area->w)-SDL_VideoSurface->w; | |
352 if ( clip_diff > 0 ) { | |
113
e21ac1dd30f1
Fixed crash if mouse is outside of the screen bounds for some reason
Sam Lantinga <slouken@lokigames.com>
parents:
77
diff
changeset
|
353 area->w = area->w < clip_diff ? 0 : area->w-clip_diff; |
0 | 354 } |
355 clip_diff = (area->y+area->h)-SDL_VideoSurface->h; | |
356 if ( clip_diff > 0 ) { | |
113
e21ac1dd30f1
Fixed crash if mouse is outside of the screen bounds for some reason
Sam Lantinga <slouken@lokigames.com>
parents:
77
diff
changeset
|
357 area->h = area->h < clip_diff ? 0 : area->h-clip_diff; |
0 | 358 } |
359 } | |
360 | |
361 static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area) | |
362 { | |
363 const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 }; | |
364 int i, w, h; | |
365 Uint8 *data, datab; | |
366 Uint8 *mask, maskb; | |
367 | |
368 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; | |
369 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; | |
370 switch (screen->format->BytesPerPixel) { | |
371 | |
372 case 1: { | |
373 Uint8 *dst; | |
374 int dstskip; | |
375 | |
376 if ( palette_changed ) { | |
377 pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255); | |
378 pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0); | |
379 palette_changed = 0; | |
380 } | |
381 dst = (Uint8 *)screen->pixels + | |
382 (SDL_cursor->area.y+area->y)*screen->pitch + | |
383 SDL_cursor->area.x; | |
384 dstskip = screen->pitch-area->w; | |
385 | |
386 for ( h=area->h; h; h-- ) { | |
387 for ( w=area->w/8; w; w-- ) { | |
388 maskb = *mask++; | |
389 datab = *data++; | |
390 for ( i=0; i<8; ++i ) { | |
391 if ( maskb & 0x80 ) { | |
392 *dst = pixels8[datab>>7]; | |
393 } | |
394 maskb <<= 1; | |
395 datab <<= 1; | |
396 dst++; | |
397 } | |
398 } | |
399 dst += dstskip; | |
400 } | |
401 } | |
402 break; | |
403 | |
404 case 2: { | |
405 Uint16 *dst; | |
406 int dstskip; | |
407 | |
408 dst = (Uint16 *)screen->pixels + | |
409 (SDL_cursor->area.y+area->y)*screen->pitch/2 + | |
410 SDL_cursor->area.x; | |
411 dstskip = (screen->pitch/2)-area->w; | |
412 | |
413 for ( h=area->h; h; h-- ) { | |
414 for ( w=area->w/8; w; w-- ) { | |
415 maskb = *mask++; | |
416 datab = *data++; | |
417 for ( i=0; i<8; ++i ) { | |
418 if ( maskb & 0x80 ) { | |
419 *dst = pixels[datab>>7]; | |
420 } | |
421 maskb <<= 1; | |
422 datab <<= 1; | |
423 dst++; | |
424 } | |
425 } | |
426 dst += dstskip; | |
427 } | |
428 } | |
429 break; | |
430 | |
431 case 3: { | |
432 Uint8 *dst; | |
433 int dstskip; | |
434 | |
435 dst = (Uint8 *)screen->pixels + | |
436 (SDL_cursor->area.y+area->y)*screen->pitch + | |
437 SDL_cursor->area.x*3; | |
438 dstskip = screen->pitch-area->w*3; | |
439 | |
440 for ( h=area->h; h; h-- ) { | |
441 for ( w=area->w/8; w; w-- ) { | |
442 maskb = *mask++; | |
443 datab = *data++; | |
444 for ( i=0; i<8; ++i ) { | |
445 if ( maskb & 0x80 ) { | |
446 memset(dst,pixels[datab>>7],3); | |
447 } | |
448 maskb <<= 1; | |
449 datab <<= 1; | |
450 dst += 3; | |
451 } | |
452 } | |
453 dst += dstskip; | |
454 } | |
455 } | |
456 break; | |
457 | |
458 case 4: { | |
459 Uint32 *dst; | |
460 int dstskip; | |
461 | |
462 dst = (Uint32 *)screen->pixels + | |
463 (SDL_cursor->area.y+area->y)*screen->pitch/4 + | |
464 SDL_cursor->area.x; | |
465 dstskip = (screen->pitch/4)-area->w; | |
466 | |
467 for ( h=area->h; h; h-- ) { | |
468 for ( w=area->w/8; w; w-- ) { | |
469 maskb = *mask++; | |
470 datab = *data++; | |
471 for ( i=0; i<8; ++i ) { | |
472 if ( maskb & 0x80 ) { | |
473 *dst = pixels[datab>>7]; | |
474 } | |
475 maskb <<= 1; | |
476 datab <<= 1; | |
477 dst++; | |
478 } | |
479 } | |
480 dst += dstskip; | |
481 } | |
482 } | |
483 break; | |
484 } | |
485 } | |
486 | |
487 static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area) | |
488 { | |
489 const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 }; | |
490 int h; | |
491 int x, minx, maxx; | |
492 Uint8 *data, datab = 0; | |
493 Uint8 *mask, maskb = 0; | |
494 Uint8 *dst; | |
495 int dstbpp, dstskip; | |
496 | |
497 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; | |
498 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; | |
499 dstbpp = screen->format->BytesPerPixel; | |
500 dst = (Uint8 *)screen->pixels + | |
501 (SDL_cursor->area.y+area->y)*screen->pitch + | |
502 SDL_cursor->area.x*dstbpp; | |
503 dstskip = screen->pitch-SDL_cursor->area.w*dstbpp; | |
504 | |
505 minx = area->x; | |
506 maxx = area->x+area->w; | |
507 if ( screen->format->BytesPerPixel == 1 ) { | |
508 if ( palette_changed ) { | |
509 pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255); | |
510 pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0); | |
511 palette_changed = 0; | |
512 } | |
513 for ( h=area->h; h; h-- ) { | |
514 for ( x=0; x<SDL_cursor->area.w; ++x ) { | |
515 if ( (x%8) == 0 ) { | |
516 maskb = *mask++; | |
517 datab = *data++; | |
518 } | |
519 if ( (x >= minx) && (x < maxx) ) { | |
520 if ( maskb & 0x80 ) { | |
521 memset(dst, pixels8[datab>>7], dstbpp); | |
522 } | |
523 } | |
524 maskb <<= 1; | |
525 datab <<= 1; | |
526 dst += dstbpp; | |
527 } | |
528 dst += dstskip; | |
529 } | |
530 } else { | |
531 for ( h=area->h; h; h-- ) { | |
532 for ( x=0; x<SDL_cursor->area.w; ++x ) { | |
533 if ( (x%8) == 0 ) { | |
534 maskb = *mask++; | |
535 datab = *data++; | |
536 } | |
537 if ( (x >= minx) && (x < maxx) ) { | |
538 if ( maskb & 0x80 ) { | |
539 memset(dst, pixels[datab>>7], dstbpp); | |
540 } | |
541 } | |
542 maskb <<= 1; | |
543 datab <<= 1; | |
544 dst += dstbpp; | |
545 } | |
546 dst += dstskip; | |
547 } | |
548 } | |
549 } | |
550 | |
551 /* This handles the ugly work of converting the saved cursor background from | |
552 the pixel format of the shadow surface to that of the video surface. | |
553 This is only necessary when blitting from a shadow surface of a different | |
554 pixel format than the video surface, and using a software rendered cursor. | |
555 */ | |
556 static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h) | |
557 { | |
558 SDL_BlitInfo info; | |
559 SDL_loblit RunBlit; | |
560 | |
561 /* Make sure we can steal the blit mapping */ | |
562 if ( screen->map->dst != SDL_VideoSurface ) { | |
563 return; | |
564 } | |
565 | |
566 /* Set up the blit information */ | |
567 info.s_pixels = SDL_cursor->save[1]; | |
568 info.s_width = w; | |
569 info.s_height = h; | |
570 info.s_skip = 0; | |
571 info.d_pixels = SDL_cursor->save[0]; | |
572 info.d_width = w; | |
573 info.d_height = h; | |
574 info.d_skip = 0; | |
575 info.aux_data = screen->map->sw_data->aux_data; | |
576 info.src = screen->format; | |
577 info.table = screen->map->table; | |
578 info.dst = SDL_VideoSurface->format; | |
579 RunBlit = screen->map->sw_data->blit; | |
580 | |
581 /* Run the actual software blit */ | |
582 RunBlit(&info); | |
583 } | |
584 | |
585 void SDL_DrawCursorNoLock(SDL_Surface *screen) | |
586 { | |
587 SDL_Rect area; | |
588 | |
589 /* Get the mouse rectangle, clipped to the screen */ | |
590 SDL_MouseRect(&area); | |
591 if ( (area.w == 0) || (area.h == 0) ) { | |
592 return; | |
593 } | |
594 | |
595 /* Copy mouse background */ | |
596 { int w, h, screenbpp; | |
597 Uint8 *src, *dst; | |
598 | |
599 /* Set up the copy pointers */ | |
600 screenbpp = screen->format->BytesPerPixel; | |
601 if ( (screen == SDL_VideoSurface) || | |
602 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { | |
603 dst = SDL_cursor->save[0]; | |
604 } else { | |
605 dst = SDL_cursor->save[1]; | |
606 } | |
607 src = (Uint8 *)screen->pixels + area.y * screen->pitch + | |
608 area.x * screenbpp; | |
609 | |
610 /* Perform the copy */ | |
611 w = area.w*screenbpp; | |
612 h = area.h; | |
613 while ( h-- ) { | |
614 memcpy(dst, src, w); | |
615 dst += w; | |
616 src += screen->pitch; | |
617 } | |
618 } | |
619 | |
620 /* Draw the mouse cursor */ | |
621 area.x -= SDL_cursor->area.x; | |
622 area.y -= SDL_cursor->area.y; | |
623 if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) { | |
624 SDL_DrawCursorFast(screen, &area); | |
625 } else { | |
626 SDL_DrawCursorSlow(screen, &area); | |
627 } | |
628 } | |
629 | |
630 void SDL_DrawCursor(SDL_Surface *screen) | |
631 { | |
632 /* Lock the screen if necessary */ | |
633 if ( screen == NULL ) { | |
634 return; | |
635 } | |
636 if ( SDL_MUSTLOCK(screen) ) { | |
637 if ( SDL_LockSurface(screen) < 0 ) { | |
638 return; | |
639 } | |
640 } | |
641 | |
642 SDL_DrawCursorNoLock(screen); | |
643 | |
644 /* Unlock the screen and update if necessary */ | |
645 if ( SDL_MUSTLOCK(screen) ) { | |
646 SDL_UnlockSurface(screen); | |
647 } | |
648 if ( (screen == SDL_VideoSurface) && | |
649 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { | |
650 SDL_VideoDevice *video = current_video; | |
651 SDL_VideoDevice *this = current_video; | |
652 SDL_Rect area; | |
653 | |
654 SDL_MouseRect(&area); | |
655 | |
656 /* This can be called before a video mode is set */ | |
657 if ( video->UpdateRects ) { | |
658 video->UpdateRects(this, 1, &area); | |
659 } | |
660 } | |
661 } | |
662 | |
663 void SDL_EraseCursorNoLock(SDL_Surface *screen) | |
664 { | |
665 SDL_Rect area; | |
666 | |
667 /* Get the mouse rectangle, clipped to the screen */ | |
668 SDL_MouseRect(&area); | |
669 if ( (area.w == 0) || (area.h == 0) ) { | |
670 return; | |
671 } | |
672 | |
673 /* Copy mouse background */ | |
674 { int w, h, screenbpp; | |
675 Uint8 *src, *dst; | |
676 | |
677 /* Set up the copy pointers */ | |
678 screenbpp = screen->format->BytesPerPixel; | |
679 if ( (screen == SDL_VideoSurface) || | |
680 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { | |
681 src = SDL_cursor->save[0]; | |
682 } else { | |
683 src = SDL_cursor->save[1]; | |
684 } | |
685 dst = (Uint8 *)screen->pixels + area.y * screen->pitch + | |
686 area.x * screenbpp; | |
687 | |
688 /* Perform the copy */ | |
689 w = area.w*screenbpp; | |
690 h = area.h; | |
691 while ( h-- ) { | |
692 memcpy(dst, src, w); | |
693 src += w; | |
694 dst += screen->pitch; | |
695 } | |
696 | |
697 /* Perform pixel conversion on cursor background */ | |
698 if ( src > SDL_cursor->save[1] ) { | |
699 SDL_ConvertCursorSave(screen, area.w, area.h); | |
700 } | |
701 } | |
702 } | |
703 | |
704 void SDL_EraseCursor(SDL_Surface *screen) | |
705 { | |
706 /* Lock the screen if necessary */ | |
707 if ( screen == NULL ) { | |
708 return; | |
709 } | |
710 if ( SDL_MUSTLOCK(screen) ) { | |
711 if ( SDL_LockSurface(screen) < 0 ) { | |
712 return; | |
713 } | |
714 } | |
715 | |
716 SDL_EraseCursorNoLock(screen); | |
717 | |
718 /* Unlock the screen and update if necessary */ | |
719 if ( SDL_MUSTLOCK(screen) ) { | |
720 SDL_UnlockSurface(screen); | |
721 } | |
722 if ( (screen == SDL_VideoSurface) && | |
723 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { | |
724 SDL_VideoDevice *video = current_video; | |
725 SDL_VideoDevice *this = current_video; | |
726 SDL_Rect area; | |
727 | |
728 SDL_MouseRect(&area); | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
729 if ( video->UpdateRects ) { |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
730 video->UpdateRects(this, 1, &area); |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
731 } |
0 | 732 } |
733 } | |
734 | |
735 /* Reset the cursor on video mode change | |
736 FIXME: Keep track of all cursors, and reset them all. | |
737 */ | |
738 void SDL_ResetCursor(void) | |
739 { | |
740 int savelen; | |
741 | |
742 if ( SDL_cursor ) { | |
743 savelen = SDL_cursor->area.w*4*SDL_cursor->area.h; | |
744 SDL_cursor->area.x = 0; | |
745 SDL_cursor->area.y = 0; | |
746 memset(SDL_cursor->save[0], 0, savelen); | |
747 } | |
748 } |