1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 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 (at) 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 } 759