0
|
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 }
|