SDL_mouse.c (22199B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../SDL_internal.h" 22 23/* General mouse handling code for SDL */ 24 25#include "SDL_assert.h" 26#include "SDL_hints.h" 27#include "SDL_timer.h" 28#include "SDL_events.h" 29#include "SDL_events_c.h" 30#include "default_cursor.h" 31#include "../video/SDL_sysvideo.h" 32 33/* #define DEBUG_MOUSE */ 34 35/* The mouse state */ 36static SDL_Mouse SDL_mouse; 37static Uint32 SDL_double_click_time = 500; 38static int SDL_double_click_radius = 1; 39 40static int 41SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y); 42 43/* Public functions */ 44int 45SDL_MouseInit(void) 46{ 47 SDL_Mouse *mouse = SDL_GetMouse(); 48 49 mouse->cursor_shown = SDL_TRUE; 50 51 return (0); 52} 53 54void 55SDL_SetDefaultCursor(SDL_Cursor * cursor) 56{ 57 SDL_Mouse *mouse = SDL_GetMouse(); 58 59 mouse->def_cursor = cursor; 60 if (!mouse->cur_cursor) { 61 SDL_SetCursor(cursor); 62 } 63} 64 65SDL_Mouse * 66SDL_GetMouse(void) 67{ 68 return &SDL_mouse; 69} 70 71void 72SDL_SetDoubleClickTime(Uint32 interval) 73{ 74 SDL_double_click_time = interval; 75} 76 77SDL_Window * 78SDL_GetMouseFocus(void) 79{ 80 SDL_Mouse *mouse = SDL_GetMouse(); 81 82 return mouse->focus; 83} 84 85void 86SDL_ResetMouse(void) 87{ 88 SDL_Mouse *mouse = SDL_GetMouse(); 89 Uint8 i; 90 91#ifdef DEBUG_MOUSE 92 printf("Resetting mouse\n"); 93#endif 94 for (i = 1; i <= sizeof(mouse->buttonstate)*8; ++i) { 95 if (mouse->buttonstate & SDL_BUTTON(i)) { 96 SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, i); 97 } 98 } 99 SDL_assert(mouse->buttonstate == 0); 100} 101 102void 103SDL_SetMouseFocus(SDL_Window * window) 104{ 105 SDL_Mouse *mouse = SDL_GetMouse(); 106 107 if (mouse->focus == window) { 108 return; 109 } 110 111 /* Actually, this ends up being a bad idea, because most operating 112 systems have an implicit grab when you press the mouse button down 113 so you can drag things out of the window and then get the mouse up 114 when it happens. So, #if 0... 115 */ 116#if 0 117 if (mouse->focus && !window) { 118 /* We won't get anymore mouse messages, so reset mouse state */ 119 SDL_ResetMouse(); 120 } 121#endif 122 123 /* See if the current window has lost focus */ 124 if (mouse->focus) { 125 SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0); 126 } 127 128 mouse->focus = window; 129 130 if (mouse->focus) { 131 SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0); 132 } 133 134 /* Update cursor visibility */ 135 SDL_SetCursor(NULL); 136} 137 138/* Check to see if we need to synthesize focus events */ 139static SDL_bool 140SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate) 141{ 142 SDL_Mouse *mouse = SDL_GetMouse(); 143 SDL_bool inWindow = SDL_TRUE; 144 145 if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) { 146 int w, h; 147 SDL_GetWindowSize(window, &w, &h); 148 if (x < 0 || y < 0 || x >= w || y >= h) { 149 inWindow = SDL_FALSE; 150 } 151 } 152 153/* Linux doesn't give you mouse events outside your window unless you grab 154 the pointer. 155 156 Windows doesn't give you mouse events outside your window unless you call 157 SetCapture(). 158 159 Both of these are slightly scary changes, so for now we'll punt and if the 160 mouse leaves the window you'll lose mouse focus and reset button state. 161*/ 162#ifdef SUPPORT_DRAG_OUTSIDE_WINDOW 163 if (!inWindow && !buttonstate) { 164#else 165 if (!inWindow) { 166#endif 167 if (window == mouse->focus) { 168#ifdef DEBUG_MOUSE 169 printf("Mouse left window, synthesizing move & focus lost event\n"); 170#endif 171 SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); 172 SDL_SetMouseFocus(NULL); 173 } 174 return SDL_FALSE; 175 } 176 177 if (window != mouse->focus) { 178#ifdef DEBUG_MOUSE 179 printf("Mouse entered window, synthesizing focus gain & move event\n"); 180#endif 181 SDL_SetMouseFocus(window); 182 SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); 183 } 184 return SDL_TRUE; 185} 186 187int 188SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) 189{ 190 if (window && !relative) { 191 SDL_Mouse *mouse = SDL_GetMouse(); 192 if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) { 193 return 0; 194 } 195 } 196 197 return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y); 198} 199 200static int 201SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) 202{ 203 SDL_Mouse *mouse = SDL_GetMouse(); 204 int posted; 205 int xrel; 206 int yrel; 207 208 if (mouse->relative_mode_warp) { 209 int center_x = 0, center_y = 0; 210 SDL_GetWindowSize(window, ¢er_x, ¢er_y); 211 center_x /= 2; 212 center_y /= 2; 213 if (x == center_x && y == center_y) { 214 mouse->last_x = center_x; 215 mouse->last_y = center_y; 216 return 0; 217 } 218 SDL_WarpMouseInWindow(window, center_x, center_y); 219 } 220 221 if (relative) { 222 xrel = x; 223 yrel = y; 224 x = (mouse->last_x + xrel); 225 y = (mouse->last_y + yrel); 226 } else { 227 xrel = x - mouse->last_x; 228 yrel = y - mouse->last_y; 229 } 230 231 /* Drop events that don't change state */ 232 if (!xrel && !yrel) { 233#ifdef DEBUG_MOUSE 234 printf("Mouse event didn't change state - dropped!\n"); 235#endif 236 return 0; 237 } 238 239 /* Update internal mouse coordinates */ 240 if (!mouse->relative_mode) { 241 mouse->x = x; 242 mouse->y = y; 243 } else { 244 mouse->x += xrel; 245 mouse->y += yrel; 246 } 247 248 /* make sure that the pointers find themselves inside the windows, 249 unless we have the mouse captured. */ 250 if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) { 251 int x_max = 0, y_max = 0; 252 253 // !!! FIXME: shouldn't this be (window) instead of (mouse->focus)? 254 SDL_GetWindowSize(mouse->focus, &x_max, &y_max); 255 --x_max; 256 --y_max; 257 258 if (mouse->x > x_max) { 259 mouse->x = x_max; 260 } 261 if (mouse->x < 0) { 262 mouse->x = 0; 263 } 264 265 if (mouse->y > y_max) { 266 mouse->y = y_max; 267 } 268 if (mouse->y < 0) { 269 mouse->y = 0; 270 } 271 } 272 273 mouse->xdelta += xrel; 274 mouse->ydelta += yrel; 275 276 /* Move the mouse cursor, if needed */ 277 if (mouse->cursor_shown && !mouse->relative_mode && 278 mouse->MoveCursor && mouse->cur_cursor) { 279 mouse->MoveCursor(mouse->cur_cursor); 280 } 281 282 /* Post the event, if desired */ 283 posted = 0; 284 if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) { 285 SDL_Event event; 286 event.motion.type = SDL_MOUSEMOTION; 287 event.motion.windowID = mouse->focus ? mouse->focus->id : 0; 288 event.motion.which = mouseID; 289 event.motion.state = mouse->buttonstate; 290 event.motion.x = mouse->x; 291 event.motion.y = mouse->y; 292 event.motion.xrel = xrel; 293 event.motion.yrel = yrel; 294 posted = (SDL_PushEvent(&event) > 0); 295 } 296 /* Use unclamped values if we're getting events outside the window */ 297 mouse->last_x = x; 298 mouse->last_y = y; 299 return posted; 300} 301 302static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button) 303{ 304 if (button >= mouse->num_clickstates) { 305 int i, count = button + 1; 306 mouse->clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate)); 307 if (!mouse->clickstate) { 308 return NULL; 309 } 310 311 for (i = mouse->num_clickstates; i < count; ++i) { 312 SDL_zero(mouse->clickstate[i]); 313 } 314 mouse->num_clickstates = count; 315 } 316 return &mouse->clickstate[button]; 317} 318 319int 320SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button) 321{ 322 SDL_Mouse *mouse = SDL_GetMouse(); 323 int posted; 324 Uint32 type; 325 Uint32 buttonstate = mouse->buttonstate; 326 SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button); 327 Uint8 click_count; 328 329 /* Figure out which event to perform */ 330 switch (state) { 331 case SDL_PRESSED: 332 type = SDL_MOUSEBUTTONDOWN; 333 buttonstate |= SDL_BUTTON(button); 334 break; 335 case SDL_RELEASED: 336 type = SDL_MOUSEBUTTONUP; 337 buttonstate &= ~SDL_BUTTON(button); 338 break; 339 default: 340 /* Invalid state -- bail */ 341 return 0; 342 } 343 344 /* We do this after calculating buttonstate so button presses gain focus */ 345 if (window && state == SDL_PRESSED) { 346 SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate); 347 } 348 349 if (buttonstate == mouse->buttonstate) { 350 /* Ignore this event, no state change */ 351 return 0; 352 } 353 mouse->buttonstate = buttonstate; 354 355 if (clickstate) { 356 if (state == SDL_PRESSED) { 357 Uint32 now = SDL_GetTicks(); 358 359 if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + SDL_double_click_time) || 360 SDL_abs(mouse->x - clickstate->last_x) > SDL_double_click_radius || 361 SDL_abs(mouse->y - clickstate->last_y) > SDL_double_click_radius) { 362 clickstate->click_count = 0; 363 } 364 clickstate->last_timestamp = now; 365 clickstate->last_x = mouse->x; 366 clickstate->last_y = mouse->y; 367 if (clickstate->click_count < 255) { 368 ++clickstate->click_count; 369 } 370 } 371 click_count = clickstate->click_count; 372 } else { 373 click_count = 1; 374 } 375 376 /* Post the event, if desired */ 377 posted = 0; 378 if (SDL_GetEventState(type) == SDL_ENABLE) { 379 SDL_Event event; 380 event.type = type; 381 event.button.windowID = mouse->focus ? mouse->focus->id : 0; 382 event.button.which = mouseID; 383 event.button.state = state; 384 event.button.button = button; 385 event.button.clicks = click_count; 386 event.button.x = mouse->x; 387 event.button.y = mouse->y; 388 posted = (SDL_PushEvent(&event) > 0); 389 } 390 391 /* We do this after dispatching event so button releases can lose focus */ 392 if (window && state == SDL_RELEASED) { 393 SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate); 394 } 395 396 return posted; 397} 398 399int 400SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y) 401{ 402 SDL_Mouse *mouse = SDL_GetMouse(); 403 int posted; 404 405 if (window) { 406 SDL_SetMouseFocus(window); 407 } 408 409 if (!x && !y) { 410 return 0; 411 } 412 413 /* Post the event, if desired */ 414 posted = 0; 415 if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) { 416 SDL_Event event; 417 event.type = SDL_MOUSEWHEEL; 418 event.wheel.windowID = mouse->focus ? mouse->focus->id : 0; 419 event.wheel.which = mouseID; 420 event.wheel.x = x; 421 event.wheel.y = y; 422 posted = (SDL_PushEvent(&event) > 0); 423 } 424 return posted; 425} 426 427void 428SDL_MouseQuit(void) 429{ 430 SDL_Cursor *cursor, *next; 431 SDL_Mouse *mouse = SDL_GetMouse(); 432 433 if (mouse->CaptureMouse) { 434 SDL_CaptureMouse(SDL_FALSE); 435 } 436 SDL_SetRelativeMouseMode(SDL_FALSE); 437 SDL_ShowCursor(1); 438 439 cursor = mouse->cursors; 440 while (cursor) { 441 next = cursor->next; 442 SDL_FreeCursor(cursor); 443 cursor = next; 444 } 445 446 if (mouse->def_cursor && mouse->FreeCursor) { 447 mouse->FreeCursor(mouse->def_cursor); 448 } 449 450 if (mouse->clickstate) { 451 SDL_free(mouse->clickstate); 452 } 453 454 SDL_zerop(mouse); 455} 456 457Uint32 458SDL_GetMouseState(int *x, int *y) 459{ 460 SDL_Mouse *mouse = SDL_GetMouse(); 461 462 if (x) { 463 *x = mouse->x; 464 } 465 if (y) { 466 *y = mouse->y; 467 } 468 return mouse->buttonstate; 469} 470 471Uint32 472SDL_GetRelativeMouseState(int *x, int *y) 473{ 474 SDL_Mouse *mouse = SDL_GetMouse(); 475 476 if (x) { 477 *x = mouse->xdelta; 478 } 479 if (y) { 480 *y = mouse->ydelta; 481 } 482 mouse->xdelta = 0; 483 mouse->ydelta = 0; 484 return mouse->buttonstate; 485} 486 487Uint32 488SDL_GetGlobalMouseState(int *x, int *y) 489{ 490 SDL_Mouse *mouse = SDL_GetMouse(); 491 int tmpx, tmpy; 492 493 /* make sure these are never NULL for the backend implementations... */ 494 if (!x) { 495 x = &tmpx; 496 } 497 if (!y) { 498 y = &tmpy; 499 } 500 501 *x = *y = 0; 502 503 if (!mouse->GetGlobalMouseState) { 504 SDL_assert(0 && "This should really be implemented for every target."); 505 return 0; 506 } 507 508 return mouse->GetGlobalMouseState(x, y); 509} 510 511void 512SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) 513{ 514 SDL_Mouse *mouse = SDL_GetMouse(); 515 516 if (window == NULL) { 517 window = mouse->focus; 518 } 519 520 if (window == NULL) { 521 return; 522 } 523 524 if (mouse->WarpMouse) { 525 mouse->WarpMouse(window, x, y); 526 } else { 527 SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y); 528 } 529} 530 531void 532SDL_WarpMouseGlobal(int x, int y) 533{ 534 SDL_Mouse *mouse = SDL_GetMouse(); 535 536 if (mouse->WarpMouseGlobal) { 537 mouse->WarpMouseGlobal(x, y); 538 } 539} 540 541static SDL_bool 542ShouldUseRelativeModeWarp(SDL_Mouse *mouse) 543{ 544 const char *hint; 545 546 if (!mouse->SetRelativeMouseMode) { 547 return SDL_TRUE; 548 } 549 550 hint = SDL_GetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP); 551 if (hint) { 552 if (*hint == '0') { 553 return SDL_FALSE; 554 } else { 555 return SDL_TRUE; 556 } 557 } 558 return SDL_FALSE; 559} 560 561int 562SDL_SetRelativeMouseMode(SDL_bool enabled) 563{ 564 SDL_Mouse *mouse = SDL_GetMouse(); 565 SDL_Window *focusWindow = SDL_GetKeyboardFocus(); 566 567 if (enabled == mouse->relative_mode) { 568 return 0; 569 } 570 571 if (enabled && focusWindow) { 572 /* Center it in the focused window to prevent clicks from going through 573 * to background windows. 574 */ 575 SDL_SetMouseFocus(focusWindow); 576 SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2); 577 } 578 579 /* Set the relative mode */ 580 if (!enabled && mouse->relative_mode_warp) { 581 mouse->relative_mode_warp = SDL_FALSE; 582 } else if (enabled && ShouldUseRelativeModeWarp(mouse)) { 583 mouse->relative_mode_warp = SDL_TRUE; 584 } else if (mouse->SetRelativeMouseMode(enabled) < 0) { 585 if (enabled) { 586 /* Fall back to warp mode if native relative mode failed */ 587 mouse->relative_mode_warp = SDL_TRUE; 588 } 589 } 590 mouse->relative_mode = enabled; 591 592 if (mouse->focus) { 593 SDL_UpdateWindowGrab(mouse->focus); 594 595 /* Put the cursor back to where the application expects it */ 596 if (!enabled) { 597 SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y); 598 } 599 } 600 601 /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */ 602 SDL_FlushEvent(SDL_MOUSEMOTION); 603 604 /* Update cursor visibility */ 605 SDL_SetCursor(NULL); 606 607 return 0; 608} 609 610SDL_bool 611SDL_GetRelativeMouseMode() 612{ 613 SDL_Mouse *mouse = SDL_GetMouse(); 614 615 return mouse->relative_mode; 616} 617 618int 619SDL_CaptureMouse(SDL_bool enabled) 620{ 621 SDL_Mouse *mouse = SDL_GetMouse(); 622 SDL_Window *focusWindow; 623 SDL_bool isCaptured; 624 625 if (!mouse->CaptureMouse) { 626 return SDL_Unsupported(); 627 } 628 629 focusWindow = SDL_GetKeyboardFocus(); 630 631 isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE); 632 if (isCaptured == enabled) { 633 return 0; /* already done! */ 634 } 635 636 if (enabled) { 637 if (!focusWindow) { 638 return SDL_SetError("No window has focus"); 639 } else if (mouse->CaptureMouse(focusWindow) == -1) { 640 return -1; /* CaptureMouse() should call SetError */ 641 } 642 focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE; 643 } else { 644 if (mouse->CaptureMouse(NULL) == -1) { 645 return -1; /* CaptureMouse() should call SetError */ 646 } 647 focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE; 648 } 649 650 return 0; 651} 652 653SDL_Cursor * 654SDL_CreateCursor(const Uint8 * data, const Uint8 * mask, 655 int w, int h, int hot_x, int hot_y) 656{ 657 SDL_Surface *surface; 658 SDL_Cursor *cursor; 659 int x, y; 660 Uint32 *pixel; 661 Uint8 datab = 0, maskb = 0; 662 const Uint32 black = 0xFF000000; 663 const Uint32 white = 0xFFFFFFFF; 664 const Uint32 transparent = 0x00000000; 665 666 /* Make sure the width is a multiple of 8 */ 667 w = ((w + 7) & ~7); 668 669 /* Create the surface from a bitmap */ 670 surface = SDL_CreateRGBSurface(0, w, h, 32, 671 0x00FF0000, 672 0x0000FF00, 673 0x000000FF, 674 0xFF000000); 675 if (!surface) { 676 return NULL; 677 } 678 for (y = 0; y < h; ++y) { 679 pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch); 680 for (x = 0; x < w; ++x) { 681 if ((x % 8) == 0) { 682 datab = *data++; 683 maskb = *mask++; 684 } 685 if (maskb & 0x80) { 686 *pixel++ = (datab & 0x80) ? black : white; 687 } else { 688 *pixel++ = (datab & 0x80) ? black : transparent; 689 } 690 datab <<= 1; 691 maskb <<= 1; 692 } 693 } 694 695 cursor = SDL_CreateColorCursor(surface, hot_x, hot_y); 696 697 SDL_FreeSurface(surface); 698 699 return cursor; 700} 701 702SDL_Cursor * 703SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y) 704{ 705 SDL_Mouse *mouse = SDL_GetMouse(); 706 SDL_Surface *temp = NULL; 707 SDL_Cursor *cursor; 708 709 if (!surface) { 710 SDL_SetError("Passed NULL cursor surface"); 711 return NULL; 712 } 713 714 if (!mouse->CreateCursor) { 715 SDL_SetError("Cursors are not currently supported"); 716 return NULL; 717 } 718 719 /* Sanity check the hot spot */ 720 if ((hot_x < 0) || (hot_y < 0) || 721 (hot_x >= surface->w) || (hot_y >= surface->h)) { 722 SDL_SetError("Cursor hot spot doesn't lie within cursor"); 723 return NULL; 724 } 725 726 if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) { 727 temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0); 728 if (!temp) { 729 return NULL; 730 } 731 surface = temp; 732 } 733 734 cursor = mouse->CreateCursor(surface, hot_x, hot_y); 735 if (cursor) { 736 cursor->next = mouse->cursors; 737 mouse->cursors = cursor; 738 } 739 740 SDL_FreeSurface(temp); 741 742 return cursor; 743} 744 745SDL_Cursor * 746SDL_CreateSystemCursor(SDL_SystemCursor id) 747{ 748 SDL_Mouse *mouse = SDL_GetMouse(); 749 SDL_Cursor *cursor; 750 751 if (!mouse->CreateSystemCursor) { 752 SDL_SetError("CreateSystemCursor is not currently supported"); 753 return NULL; 754 } 755 756 cursor = mouse->CreateSystemCursor(id); 757 if (cursor) { 758 cursor->next = mouse->cursors; 759 mouse->cursors = cursor; 760 } 761 762 return cursor; 763} 764 765/* SDL_SetCursor(NULL) can be used to force the cursor redraw, 766 if this is desired for any reason. This is used when setting 767 the video mode and when the SDL window gains the mouse focus. 768 */ 769void 770SDL_SetCursor(SDL_Cursor * cursor) 771{ 772 SDL_Mouse *mouse = SDL_GetMouse(); 773 774 /* Set the new cursor */ 775 if (cursor) { 776 /* Make sure the cursor is still valid for this mouse */ 777 if (cursor != mouse->def_cursor) { 778 SDL_Cursor *found; 779 for (found = mouse->cursors; found; found = found->next) { 780 if (found == cursor) { 781 break; 782 } 783 } 784 if (!found) { 785 SDL_SetError("Cursor not associated with the current mouse"); 786 return; 787 } 788 } 789 mouse->cur_cursor = cursor; 790 } else { 791 if (mouse->focus) { 792 cursor = mouse->cur_cursor; 793 } else { 794 cursor = mouse->def_cursor; 795 } 796 } 797 798 if (cursor && mouse->cursor_shown && !mouse->relative_mode) { 799 if (mouse->ShowCursor) { 800 mouse->ShowCursor(cursor); 801 } 802 } else { 803 if (mouse->ShowCursor) { 804 mouse->ShowCursor(NULL); 805 } 806 } 807} 808 809SDL_Cursor * 810SDL_GetCursor(void) 811{ 812 SDL_Mouse *mouse = SDL_GetMouse(); 813 814 if (!mouse) { 815 return NULL; 816 } 817 return mouse->cur_cursor; 818} 819 820SDL_Cursor * 821SDL_GetDefaultCursor(void) 822{ 823 SDL_Mouse *mouse = SDL_GetMouse(); 824 825 if (!mouse) { 826 return NULL; 827 } 828 return mouse->def_cursor; 829} 830 831void 832SDL_FreeCursor(SDL_Cursor * cursor) 833{ 834 SDL_Mouse *mouse = SDL_GetMouse(); 835 SDL_Cursor *curr, *prev; 836 837 if (!cursor) { 838 return; 839 } 840 841 if (cursor == mouse->def_cursor) { 842 return; 843 } 844 if (cursor == mouse->cur_cursor) { 845 SDL_SetCursor(mouse->def_cursor); 846 } 847 848 for (prev = NULL, curr = mouse->cursors; curr; 849 prev = curr, curr = curr->next) { 850 if (curr == cursor) { 851 if (prev) { 852 prev->next = curr->next; 853 } else { 854 mouse->cursors = curr->next; 855 } 856 857 if (mouse->FreeCursor) { 858 mouse->FreeCursor(curr); 859 } 860 return; 861 } 862 } 863} 864 865int 866SDL_ShowCursor(int toggle) 867{ 868 SDL_Mouse *mouse = SDL_GetMouse(); 869 SDL_bool shown; 870 871 if (!mouse) { 872 return 0; 873 } 874 875 shown = mouse->cursor_shown; 876 if (toggle >= 0) { 877 if (toggle) { 878 mouse->cursor_shown = SDL_TRUE; 879 } else { 880 mouse->cursor_shown = SDL_FALSE; 881 } 882 if (mouse->cursor_shown != shown) { 883 SDL_SetCursor(NULL); 884 } 885 } 886 return shown; 887} 888 889/* vi: set ts=4 sw=4 expandtab: */