Mercurial > sdl-ios-xcode
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: */ |