void SDL_MouseQuit(void) { SDL_Cursor *cursor, *next; SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->CaptureMouse) { SDL_CaptureMouse(SDL_FALSE); } SDL_SetRelativeMouseMode(SDL_FALSE); SDL_ShowCursor(1); cursor = mouse->cursors; while (cursor) { next = cursor->next; SDL_FreeCursor(cursor); cursor = next; } if (mouse->def_cursor && mouse->FreeCursor) { mouse->FreeCursor(mouse->def_cursor); } if (mouse->clickstate) { SDL_free(mouse->clickstate); } SDL_zerop(mouse); }
int SDL_CaptureMouse(SDL_bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *focusWindow; SDL_bool isCaptured; if (!mouse->CaptureMouse) { return SDL_Unsupported(); } focusWindow = SDL_GetKeyboardFocus(); isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE); if (isCaptured == enabled) { return 0; /* already done! */ } if (enabled) { if (!focusWindow) { return SDL_SetError("No window has focus"); } else if (mouse->CaptureMouse(focusWindow) == -1) { return -1; /* CaptureMouse() should call SetError */ } focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE; } else { if (mouse->CaptureMouse(NULL) == -1) { return -1; /* CaptureMouse() should call SetError */ } focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE; } return 0; }
/* SDL_SetCursor(NULL) can be used to force the cursor redraw, if this is desired for any reason. This is used when setting the video mode and when the SDL window gains the mouse focus. */ void SDL_SetCursor(SDL_Cursor * cursor) { SDL_Mouse *mouse = &SDL_mouse; /* Set the new cursor */ if (cursor) { /* Make sure the cursor is still valid for this mouse */ SDL_Cursor *found; for (found = mouse->cursors; found; found = found->next) { if (found == cursor) { break; } } if (!found) { SDL_SetError("Cursor not associated with the current mouse"); return; } mouse->cur_cursor = cursor; } else { cursor = mouse->cur_cursor; } if (cursor && mouse->cursor_shown && !mouse->relative_mode) { if (mouse->ShowCursor) { mouse->ShowCursor(cursor); } } else { if (mouse->ShowCursor) { mouse->ShowCursor(NULL); } } }
void SDL_MouseQuit(void) { SDL_Cursor *cursor, *next; SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->CaptureMouse) { SDL_CaptureMouse(SDL_FALSE); } SDL_SetRelativeMouseMode(SDL_FALSE); SDL_ShowCursor(1); cursor = mouse->cursors; while (cursor) { next = cursor->next; SDL_FreeCursor(cursor); cursor = next; } if (mouse->def_cursor && mouse->FreeCursor) { mouse->FreeCursor(mouse->def_cursor); } if (mouse->clickstate) { SDL_free(mouse->clickstate); } SDL_zerop(mouse); SDL_DelHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE, SDL_MouseNormalSpeedScaleChanged, mouse); SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, SDL_MouseRelativeSpeedScaleChanged, mouse); }
void SDL_FreeCursor(SDL_Cursor * cursor) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Cursor *curr, *prev; if (!cursor) { return; } if (cursor == mouse->def_cursor) { return; } if (cursor == mouse->cur_cursor) { SDL_SetCursor(mouse->def_cursor); } for (prev = NULL, curr = mouse->cursors; curr; prev = curr, curr = curr->next) { if (curr == cursor) { if (prev) { prev->next = curr->next; } else { mouse->cursors = curr->next; } if (mouse->FreeCursor) { mouse->FreeCursor(curr); } return; } } }
void SDL_WarpMouseGlobal(int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->WarpMouseGlobal) { mouse->WarpMouseGlobal(x, y); } }
void SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) { SDL_Mouse *mouse = &SDL_mouse; if (mouse->WarpMouse) { mouse->WarpMouse(mouse, window, x, y); } else { SDL_SendMouseMotion(window, 0, x, y); } }
int SDL_WarpMouseGlobal(int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->WarpMouseGlobal) { return mouse->WarpMouseGlobal(x, y); } return SDL_Unsupported(); }
int SDL_SetRelativeMouseMode(SDL_bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *focusWindow = SDL_GetKeyboardFocus(); if (enabled == mouse->relative_mode) { return 0; } if (enabled && focusWindow) { /* Center it in the focused window to prevent clicks from going through * to background windows. */ SDL_SetMouseFocus(focusWindow); SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2); } /* Set the relative mode */ if (!enabled && mouse->relative_mode_warp) { mouse->relative_mode_warp = SDL_FALSE; } else if (enabled && ShouldUseRelativeModeWarp(mouse)) { mouse->relative_mode_warp = SDL_TRUE; } else if (mouse->SetRelativeMouseMode(enabled) < 0) { if (enabled) { /* Fall back to warp mode if native relative mode failed */ if (!mouse->WarpMouse) { return SDL_SetError("No relative mode implementation available"); } mouse->relative_mode_warp = SDL_TRUE; } } mouse->relative_mode = enabled; mouse->scale_accum_x = 0.0f; mouse->scale_accum_y = 0.0f; if (mouse->focus) { SDL_UpdateWindowGrab(mouse->focus); /* Put the cursor back to where the application expects it */ if (!enabled) { SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y); } } /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */ SDL_FlushEvent(SDL_MOUSEMOTION); /* Update cursor visibility */ SDL_SetCursor(NULL); return 0; }
void SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); if (!mouse) { return; } if (mouse->WarpMouse) { mouse->WarpMouse(mouse, window, x, y); } else { SDL_SetMouseFocus(SDL_current_mouse, window); SDL_SendMouseMotion(SDL_current_mouse, 0, x, y, 0); } }
void SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->WarpMouse) { mouse->WarpMouse(window, x, y); // Urho3D: update the internal position mouse->x = x; mouse->y = y; mouse->last_x = x; mouse->last_y = y; } else { SDL_SendMouseMotion(window, 0, x, y); } }
int SDL_SetRelativeMouseMode(SDL_bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *focusWindow = SDL_GetKeyboardFocus(); int original_x = mouse->x, original_y = mouse->y; if (enabled == mouse->relative_mode) { return 0; } if (!mouse->SetRelativeMouseMode) { return SDL_Unsupported(); } if (enabled && focusWindow) { /* Center it in the focused window to prevent clicks from going through * to background windows. */ SDL_SetMouseFocus(focusWindow); SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2); } if (mouse->SetRelativeMouseMode(enabled) < 0) { return -1; } /* Set the relative mode */ mouse->relative_mode = enabled; if (enabled) { /* Save the expected mouse position */ mouse->original_x = original_x; mouse->original_y = original_y; } else if (mouse->focus) { /* Restore the expected mouse position */ SDL_WarpMouseInWindow(mouse->focus, mouse->original_x, mouse->original_y); } /* Flush pending mouse motion */ SDL_FlushEvent(SDL_MOUSEMOTION); /* Update cursor visibility */ SDL_SetCursor(NULL); return 0; }
void SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); if ( window == NULL ) window = mouse->focus; if ( window == NULL ) return; if (mouse->WarpMouse) { mouse->WarpMouse(window, x, y); } else { SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y); } }
SDL_Cursor * SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Surface *temp = NULL; SDL_Cursor *cursor; if (!surface) { SDL_SetError("Passed NULL cursor surface"); return NULL; } if (!mouse->CreateCursor) { SDL_SetError("Cursors are not currently supported"); return NULL; } /* Sanity check the hot spot */ if ((hot_x < 0) || (hot_y < 0) || (hot_x >= surface->w) || (hot_y >= surface->h)) { SDL_SetError("Cursor hot spot doesn't lie within cursor"); return NULL; } if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) { temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0); if (!temp) { return NULL; } surface = temp; } cursor = mouse->CreateCursor(surface, hot_x, hot_y); if (cursor) { cursor->next = mouse->cursors; mouse->cursors = cursor; } if (temp) { SDL_FreeSurface(temp); } return cursor; }
SDL_Cursor * SDL_CreateSystemCursor(SDL_SystemCursor id) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Cursor *cursor; if (!mouse->CreateSystemCursor) { SDL_SetError("CreateSystemCursor is not currently supported"); return NULL; } cursor = mouse->CreateSystemCursor(id); if (cursor) { cursor->next = mouse->cursors; mouse->cursors = cursor; } return cursor; }
void SDL_MouseQuit(void) { SDL_Cursor *cursor, *next; SDL_Mouse *mouse = SDL_GetMouse(); SDL_ShowCursor(1); cursor = mouse->cursors; while (cursor) { next = cursor->next; SDL_FreeCursor(cursor); cursor = next; } if (mouse->def_cursor && mouse->FreeCursor) { mouse->FreeCursor(mouse->def_cursor); } SDL_zerop(mouse); }
void SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); if ( window == NULL ) window = mouse->focus; if ( window == NULL ) return; if (mouse->WarpMouse) { mouse->WarpMouse(window, x, y); } else { SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y); } // Urho3D: update mouse internal state immediately mouse->last_x = mouse->x = x; mouse->last_y = mouse->y = y; }
void SDL_MouseQuit(void) { // Urho3D: free default cursor on exit SDL_Mouse *mouse = SDL_GetMouse(); if (!mouse) { return; } if(!mouse->def_cursor) { return; } if(!mouse->FreeCursor) { return; } mouse->FreeCursor(mouse->def_cursor); mouse->def_cursor = 0; }
Uint32 SDL_GetGlobalMouseState(int *x, int *y) { SDL_Mouse *mouse = SDL_GetMouse(); int tmpx, tmpy; /* make sure these are never NULL for the backend implementations... */ if (!x) { x = &tmpx; } if (!y) { y = &tmpy; } *x = *y = 0; if (!mouse->GetGlobalMouseState) { return 0; } return mouse->GetGlobalMouseState(x, y); }
void SDL_DelMouse(int index) { SDL_Mouse *mouse = SDL_GetMouse(index); if (!mouse) { return; } mouse->def_cursor = NULL; SDL_free(mouse->name); while (mouse->cursors) { SDL_FreeCursor(mouse->cursors); } if (mouse->FreeMouse) { mouse->FreeMouse(mouse); } SDL_free(mouse); SDL_mice[index] = NULL; }
int SDL_SetRelativeMouseMode(SDL_bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); if (enabled == mouse->relative_mode) { return 0; } if (!mouse->SetRelativeMouseMode) { SDL_Unsupported(); return -1; } if (mouse->SetRelativeMouseMode(enabled) < 0) { return -1; } /* Set the relative mode */ mouse->relative_mode = enabled; if (enabled) { /* Save the expected mouse position */ mouse->original_x = mouse->x; mouse->original_y = mouse->y; } else if (mouse->focus) { /* Restore the expected mouse position */ SDL_WarpMouseInWindow(mouse->focus, mouse->original_x, mouse->original_y); } /* Flush pending mouse motion */ SDL_FlushEvent(SDL_MOUSEMOTION); /* Update cursor visibility */ SDL_SetCursor(NULL); return 0; }
Uint32 SDL_GetGlobalMouseState(int *x, int *y) { SDL_Mouse *mouse = SDL_GetMouse(); int tmpx, tmpy; /* make sure these are never NULL for the backend implementations... */ if (!x) { x = &tmpx; } if (!y) { y = &tmpy; } *x = *y = 0; if (!mouse->GetGlobalMouseState) { SDL_assert(0 && "This should really be implemented for every target."); return 0; } return mouse->GetGlobalMouseState(x, y); }
int SDL_SendMouseMotion(SDL_Window * window, int relative, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; int xrel; int yrel; int x_max = 0, y_max = 0; if (window) { SDL_SetMouseFocus(window); } /* the relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; yrel = y; x = (mouse->last_x + x); y = (mouse->last_y + y); } else { xrel = x - mouse->last_x; yrel = y - mouse->last_y; } /* Drop events that don't change state */ if (!xrel && !yrel) { #if 0 printf("Mouse event didn't change state - dropped!\n"); #endif return 0; } /* Update internal mouse coordinates */ if (mouse->relative_mode == SDL_FALSE) { mouse->x = x; mouse->y = y; } else { mouse->x += xrel; mouse->y += yrel; } SDL_GetWindowSize(mouse->focus, &x_max, &y_max); --x_max; --y_max; /* make sure that the pointers find themselves inside the windows */ /* only check if mouse->xmax is set ! */ if (mouse->x > x_max) { mouse->x = x_max; } if (mouse->x < 0) { mouse->x = 0; } if (mouse->y > y_max) { mouse->y = y_max; } if (mouse->y < 0) { mouse->y = 0; } mouse->xdelta += xrel; mouse->ydelta += yrel; #if 0 /* FIXME */ /* Move the mouse cursor, if needed */ if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { mouse->MoveCursor(mouse->cur_cursor); } #endif /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) { SDL_Event event; event.motion.type = SDL_MOUSEMOTION; event.motion.windowID = mouse->focus ? mouse->focus->id : 0; event.motion.state = mouse->buttonstate; event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.xrel = xrel; event.motion.yrel = yrel; posted = (SDL_PushEvent(&event) > 0); } mouse->last_x = mouse->x; mouse->last_y = mouse->y; return posted; }
SDL_Cursor * SDL_CreateCursor(const Uint8 * data, const Uint8 * mask, int w, int h, int hot_x, int hot_y) { SDL_Mouse *mouse = &SDL_mouse; SDL_Surface *surface; SDL_Cursor *cursor; int x, y; Uint32 *pixel; Uint8 datab = 0, maskb = 0; const Uint32 black = 0xFF000000; const Uint32 white = 0xFFFFFFFF; const Uint32 transparent = 0x00000000; if (!mouse->CreateCursor) { SDL_SetError("Cursors are not currently supported"); return NULL; } /* Sanity check the hot spot */ if ((hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h)) { SDL_SetError("Cursor hot spot doesn't lie within cursor"); return NULL; } /* Make sure the width is a multiple of 8 */ w = ((w + 7) & ~7); /* Create the surface from a bitmap */ surface = SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); if (!surface) { return NULL; } for (y = 0; y < h; ++y) { pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch); for (x = 0; x < w; ++x) { if ((x % 8) == 0) { datab = *data++; maskb = *mask++; } if (maskb & 0x80) { *pixel++ = (datab & 0x80) ? black : white; } else { *pixel++ = (datab & 0x80) ? black : transparent; } datab <<= 1; maskb <<= 1; } } cursor = mouse->CreateCursor(surface, hot_x, hot_y); if (cursor) { cursor->next = mouse->cursors; mouse->cursors = cursor; } SDL_FreeSurface(surface); return cursor; }
int SDL_SendMouseMotion(int id, int relative, int x, int y, int pressure) { int index = SDL_GetMouseIndexId(id); SDL_Mouse *mouse = SDL_GetMouse(index); int posted; int xrel; int yrel; int x_max = 0, y_max = 0; if (!mouse || mouse->flush_motion) { return 0; } /* if the mouse is out of proximity we don't to want to have any motion from it */ if (mouse->proximity == SDL_FALSE) { mouse->last_x = x; mouse->last_y = y; return 0; } /* the relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; yrel = y; x = (mouse->last_x + x); y = (mouse->last_y + y); } else { xrel = x - mouse->last_x; yrel = y - mouse->last_y; } /* Drop events that don't change state */ if (!xrel && !yrel) { #if 0 printf("Mouse event didn't change state - dropped!\n"); #endif return 0; } /* Update internal mouse coordinates */ if (mouse->relative_mode == SDL_FALSE) { mouse->x = x; mouse->y = y; } else { mouse->x += xrel; mouse->y += yrel; } SDL_GetWindowSize(mouse->focus, &x_max, &y_max); /* make sure that the pointers find themselves inside the windows */ /* only check if mouse->xmax is set ! */ if (x_max && mouse->x > x_max) { mouse->x = x_max; } else if (mouse->x < 0) { mouse->x = 0; } if (y_max && mouse->y > y_max) { mouse->y = y_max; } else if (mouse->y < 0) { mouse->y = 0; } mouse->xdelta += xrel; mouse->ydelta += yrel; mouse->pressure = pressure; /* Move the mouse cursor, if needed */ if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { mouse->MoveCursor(mouse->cur_cursor); } /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE && mouse->proximity == SDL_TRUE) { SDL_Event event; event.motion.type = SDL_MOUSEMOTION; event.motion.which = (Uint8) index; event.motion.state = mouse->buttonstate; event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.z = mouse->z; event.motion.pressure = mouse->pressure; event.motion.pressure_max = mouse->pressure_max; event.motion.pressure_min = mouse->pressure_min; event.motion.rotation = 0; event.motion.tilt_x = 0; event.motion.tilt_y = 0; event.motion.cursor = mouse->current_end; event.motion.xrel = xrel; event.motion.yrel = yrel; event.motion.windowID = mouse->focus ? mouse->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } mouse->last_x = mouse->x; mouse->last_y = mouse->y; return posted; }
/* Check to see if we need to synthesize focus events */ static SDL_bool SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate) { SDL_Mouse *mouse = SDL_GetMouse(); int w, h; SDL_bool inWindow; SDL_GetWindowSize(window, &w, &h); if (x < 0 || y < 0 || x >= w || y >= h) { inWindow = SDL_FALSE; } else { inWindow = SDL_TRUE; } /* Linux doesn't give you mouse events outside your window unless you grab the pointer. Windows doesn't give you mouse events outside your window unless you call SetCapture(). Both of these are slightly scary changes, so for now we'll punt and if the mouse leaves the window you'll lose mouse focus and reset button state. */ #ifdef SUPPORT_DRAG_OUTSIDE_WINDOW if (!inWindow && !buttonstate) { #else if (!inWindow) { #endif if (window == mouse->focus) { #ifdef DEBUG_MOUSE printf("Mouse left window, synthesizing move & focus lost event\n"); #endif SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); SDL_SetMouseFocus(NULL); } return SDL_FALSE; } if (window != mouse->focus) { #ifdef DEBUG_MOUSE printf("Mouse entered window, synthesizing focus gain & move event\n"); #endif SDL_SetMouseFocus(window); SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); } return SDL_TRUE; } int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { if (window && !relative) { SDL_Mouse *mouse = SDL_GetMouse(); if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) { return 0; } } return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y); } static int SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; int xrel; int yrel; int x_max = 0, y_max = 0; /* relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; yrel = y; x = (mouse->last_x + x); y = (mouse->last_y + y); } else { xrel = x - mouse->last_x; yrel = y - mouse->last_y; } /* Drop events that don't change state */ if (!xrel && !yrel) { #ifdef DEBUG_MOUSE printf("Mouse event didn't change state - dropped!\n"); #endif return 0; } /* Update internal mouse coordinates */ if (mouse->relative_mode == SDL_FALSE) { mouse->x = x; mouse->y = y; } else { mouse->x += xrel; mouse->y += yrel; } SDL_GetWindowSize(mouse->focus, &x_max, &y_max); --x_max; --y_max; /* make sure that the pointers find themselves inside the windows */ if (mouse->x > x_max) { mouse->x = x_max; } if (mouse->x < 0) { mouse->x = 0; } if (mouse->y > y_max) { mouse->y = y_max; } if (mouse->y < 0) { mouse->y = 0; } mouse->xdelta += xrel; mouse->ydelta += yrel; #if 0 /* FIXME */ /* Move the mouse cursor, if needed */ if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { mouse->MoveCursor(mouse->cur_cursor); } #endif /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) { SDL_Event event; event.motion.type = SDL_MOUSEMOTION; event.motion.windowID = mouse->focus ? mouse->focus->id : 0; event.motion.which = mouseID; event.motion.state = mouse->buttonstate; event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.xrel = xrel; event.motion.yrel = yrel; posted = (SDL_PushEvent(&event) > 0); } /* Use unclamped values if we're getting events outside the window */ mouse->last_x = x; mouse->last_y = y; return posted; }
/* Check to see if we need to synthesize focus events */ static SDL_bool SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_bool inWindow = SDL_TRUE; if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) { int w, h; SDL_GetWindowSize(window, &w, &h); if (x < 0 || y < 0 || x >= w || y >= h) { inWindow = SDL_FALSE; } } /* Linux doesn't give you mouse events outside your window unless you grab the pointer. Windows doesn't give you mouse events outside your window unless you call SetCapture(). Both of these are slightly scary changes, so for now we'll punt and if the mouse leaves the window you'll lose mouse focus and reset button state. */ #ifdef SUPPORT_DRAG_OUTSIDE_WINDOW if (!inWindow && !buttonstate) { #else if (!inWindow) { #endif if (window == mouse->focus) { #ifdef DEBUG_MOUSE printf("Mouse left window, synthesizing move & focus lost event\n"); #endif SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); SDL_SetMouseFocus(NULL); } return SDL_FALSE; } if (window != mouse->focus) { #ifdef DEBUG_MOUSE printf("Mouse entered window, synthesizing focus gain & move event\n"); #endif SDL_SetMouseFocus(window); SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); } return SDL_TRUE; } int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { if (window && !relative) { SDL_Mouse *mouse = SDL_GetMouse(); if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) { return 0; } } return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y); } static int GetScaledMouseDelta(float scale, int value, float *accum) { if (scale != 1.0f) { *accum += scale * value; if (*accum >= 0.0f) { value = (int)SDL_floor(*accum); } else { value = (int)SDL_ceil(*accum); } *accum -= value; } return value; } static int SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; int xrel; int yrel; /* SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events */ if (mouse->mouse_touch_events) { if (mouseID != SDL_TOUCH_MOUSEID && !relative && track_mouse_down) { if (window) { float fx = (float)x / (float)window->w; float fy = (float)y / (float)window->h; SDL_SendTouchMotion(SDL_MOUSE_TOUCHID, 0, fx, fy, 1.0f); } } } if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) { int center_x = 0, center_y = 0; SDL_GetWindowSize(window, ¢er_x, ¢er_y); center_x /= 2; center_y /= 2; if (x == center_x && y == center_y) { mouse->last_x = center_x; mouse->last_y = center_y; return 0; } SDL_WarpMouseInWindow(window, center_x, center_y); } if (relative) { if (mouse->relative_mode) { x = GetScaledMouseDelta(mouse->relative_speed_scale, x, &mouse->scale_accum_x); y = GetScaledMouseDelta(mouse->relative_speed_scale, y, &mouse->scale_accum_y); } else { x = GetScaledMouseDelta(mouse->normal_speed_scale, x, &mouse->scale_accum_x); y = GetScaledMouseDelta(mouse->normal_speed_scale, y, &mouse->scale_accum_y); } xrel = x; yrel = y; x = (mouse->last_x + xrel); y = (mouse->last_y + yrel); } else { xrel = x - mouse->last_x; yrel = y - mouse->last_y; } /* Drop events that don't change state */ if (!xrel && !yrel) { #ifdef DEBUG_MOUSE printf("Mouse event didn't change state - dropped!\n"); #endif return 0; } /* Ignore relative motion when first positioning the mouse */ if (!mouse->has_position) { xrel = 0; yrel = 0; mouse->has_position = SDL_TRUE; } /* Ignore relative motion positioning the first touch */ if (mouseID == SDL_TOUCH_MOUSEID && !mouse->buttonstate) { xrel = 0; yrel = 0; } /* Update internal mouse coordinates */ if (!mouse->relative_mode) { mouse->x = x; mouse->y = y; } else { mouse->x += xrel; mouse->y += yrel; } /* make sure that the pointers find themselves inside the windows, unless we have the mouse captured. */ if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) { int x_max = 0, y_max = 0; /* !!! FIXME: shouldn't this be (window) instead of (mouse->focus)? */ SDL_GetWindowSize(mouse->focus, &x_max, &y_max); --x_max; --y_max; if (mouse->x > x_max) { mouse->x = x_max; } if (mouse->x < 0) { mouse->x = 0; } if (mouse->y > y_max) { mouse->y = y_max; } if (mouse->y < 0) { mouse->y = 0; } } mouse->xdelta += xrel; mouse->ydelta += yrel; /* Move the mouse cursor, if needed */ if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { mouse->MoveCursor(mouse->cur_cursor); } /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) { SDL_Event event; event.motion.type = SDL_MOUSEMOTION; event.motion.windowID = mouse->focus ? mouse->focus->id : 0; event.motion.which = mouseID; event.motion.state = mouse->buttonstate; event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.xrel = xrel; event.motion.yrel = yrel; posted = (SDL_PushEvent(&event) > 0); } if (relative) { mouse->last_x = mouse->x; mouse->last_y = mouse->y; } else { /* Use unclamped values if we're getting events outside the window */ mouse->last_x = x; mouse->last_y = y; } return posted; }