SDL_mouse.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../SDL_internal.h"
/* General mouse handling code for SDL */
#include "SDL_assert.h"
#include "SDL_hints.h"
#include "SDL_timer.h"
#include "SDL_events.h"
#include "SDL_events_c.h"
#include "../video/SDL_sysvideo.h"
/* #define DEBUG_MOUSE */
/* The mouse state */
static SDL_Mouse SDL_mouse;
static Uint32 SDL_double_click_time = 500;
static int SDL_double_click_radius = 1;
static int
SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);
static void SDLCALL
SDL_MouseNormalSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
if (hint && *hint) {
mouse->normal_speed_scale = (float)SDL_atof(hint);
} else {
mouse->normal_speed_scale = 1.0f;
}
}
static void SDLCALL
SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
if (hint && *hint) {
mouse->relative_speed_scale = (float)SDL_atof(hint);
} else {
mouse->relative_speed_scale = 1.0f;
}
}
static void SDLCALL
SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
if (hint && (*hint == '0' || SDL_strcasecmp(hint, "false") == 0)) {
mouse->touch_mouse_events = SDL_FALSE;
} else {
mouse->touch_mouse_events = SDL_TRUE;
}
}
/* Public functions */
int
SDL_MouseInit(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
SDL_zerop(mouse);
SDL_AddHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
SDL_MouseNormalSpeedScaleChanged, mouse);
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
SDL_MouseRelativeSpeedScaleChanged, mouse);
SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
SDL_TouchMouseEventsChanged, mouse);
mouse->cursor_shown = SDL_TRUE;
return (0);
}
void
SDL_SetDefaultCursor(SDL_Cursor * cursor)
{
SDL_Mouse *mouse = SDL_GetMouse();
mouse->def_cursor = cursor;
if (!mouse->cur_cursor) {
SDL_SetCursor(cursor);
}
}
SDL_Mouse *
SDL_GetMouse(void)
{
return &SDL_mouse;
}
void
SDL_SetDoubleClickTime(Uint32 interval)
{
SDL_double_click_time = interval;
}
SDL_Window *
SDL_GetMouseFocus(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
return mouse->focus;
}
#if 0
void
SDL_ResetMouse(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
Uint8 i;
#ifdef DEBUG_MOUSE
printf("Resetting mouse\n");
#endif
for (i = 1; i <= sizeof(mouse->buttonstate)*8; ++i) {
if (mouse->buttonstate & SDL_BUTTON(i)) {
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, i);
}
}
SDL_assert(mouse->buttonstate == 0);
}
#endif
void
SDL_SetMouseFocus(SDL_Window * window)
{
SDL_Mouse *mouse = SDL_GetMouse();
if (mouse->focus == window) {
return;
}
/* Actually, this ends up being a bad idea, because most operating
systems have an implicit grab when you press the mouse button down
so you can drag things out of the window and then get the mouse up
when it happens. So, #if 0...
*/
#if 0
if (mouse->focus && !window) {
/* We won't get anymore mouse messages, so reset mouse state */
SDL_ResetMouse();
}
#endif
/* See if the current window has lost focus */
if (mouse->focus) {
SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
}
mouse->focus = window;
mouse->has_position = SDL_FALSE;
if (mouse->focus) {
SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
}
/* Update cursor visibility */
SDL_SetCursor(NULL);
}
/* 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;
if (mouseID == SDL_TOUCH_MOUSEID && !mouse->touch_mouse_events) {
return 0;
}
if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) {
int center_x = 0, center_y = 0;
SDL_GetWindowSize(window, &center_x, &center_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;
}
static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
{
if (button >= mouse->num_clickstates) {
int i, count = button + 1;
SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
if (!clickstate) {
return NULL;
}
mouse->clickstate = clickstate;
for (i = mouse->num_clickstates; i < count; ++i) {
SDL_zero(mouse->clickstate[i]);
}
mouse->num_clickstates = count;
}
return &mouse->clickstate[button];
}
static int
SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
{
SDL_Mouse *mouse = SDL_GetMouse();
int posted;
Uint32 type;
Uint32 buttonstate = mouse->buttonstate;
if (mouseID == SDL_TOUCH_MOUSEID && !mouse->touch_mouse_events) {
return 0;
}
/* Figure out which event to perform */
switch (state) {
case SDL_PRESSED:
type = SDL_MOUSEBUTTONDOWN;
buttonstate |= SDL_BUTTON(button);
break;
case SDL_RELEASED:
type = SDL_MOUSEBUTTONUP;
buttonstate &= ~SDL_BUTTON(button);
break;
default:
/* Invalid state -- bail */
return 0;
}
/* We do this after calculating buttonstate so button presses gain focus */
if (window && state == SDL_PRESSED) {
SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
}
if (buttonstate == mouse->buttonstate) {
/* Ignore this event, no state change */
return 0;
}
mouse->buttonstate = buttonstate;
if (clicks < 0) {
SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
if (clickstate) {
if (state == SDL_PRESSED) {
Uint32 now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + SDL_double_click_time) ||
SDL_abs(mouse->x - clickstate->last_x) > SDL_double_click_radius ||
SDL_abs(mouse->y - clickstate->last_y) > SDL_double_click_radius) {
clickstate->click_count = 0;
}
clickstate->last_timestamp = now;
clickstate->last_x = mouse->x;
clickstate->last_y = mouse->y;
if (clickstate->click_count < 255) {
++clickstate->click_count;
}
}
clicks = clickstate->click_count;
} else {
clicks = 1;
}
}
/* Post the event, if desired */
posted = 0;
if (SDL_GetEventState(type) == SDL_ENABLE) {
SDL_Event event;
event.type = type;
event.button.windowID = mouse->focus ? mouse->focus->id : 0;
event.button.which = mouseID;
event.button.state = state;
event.button.button = button;
event.button.clicks = (Uint8) SDL_min(clicks, 255);
event.button.x = mouse->x;
event.button.y = mouse->y;
posted = (SDL_PushEvent(&event) > 0);
}
/* We do this after dispatching event so button releases can lose focus */
if (window && state == SDL_RELEASED) {
SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
}
return posted;
}
int
SDL_SendMouseButtonClicks(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
{
clicks = SDL_max(clicks, 0);
return SDL_PrivateSendMouseButton(window, mouseID, state, button, clicks);
}
int
SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
{
return SDL_PrivateSendMouseButton(window, mouseID, state, button, -1);
}
int
SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
{
SDL_Mouse *mouse = SDL_GetMouse();
int posted;
int integral_x, integral_y;
if (window) {
SDL_SetMouseFocus(window);
}
if (!x && !y) {
return 0;
}
mouse->accumulated_wheel_x += x;
if (mouse->accumulated_wheel_x > 0) {
integral_x = (int)SDL_floor(mouse->accumulated_wheel_x);
} else if (mouse->accumulated_wheel_x < 0) {
integral_x = (int)SDL_ceil(mouse->accumulated_wheel_x);
} else {
integral_x = 0;
}
mouse->accumulated_wheel_x -= integral_x;
mouse->accumulated_wheel_y += y;
if (mouse->accumulated_wheel_y > 0) {
integral_y = (int)SDL_floor(mouse->accumulated_wheel_y);
} else if (mouse->accumulated_wheel_y < 0) {
integral_y = (int)SDL_ceil(mouse->accumulated_wheel_y);
} else {
integral_y = 0;
}
mouse->accumulated_wheel_y -= integral_y;
/* Post the event, if desired */
posted = 0;
if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) {
SDL_Event event;
event.type = SDL_MOUSEWHEEL;
event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
event.wheel.which = mouseID;
#if 0 /* Uncomment this when it goes in for SDL 2.1 */
event.wheel.preciseX = x;
event.wheel.preciseY = y;
#endif
event.wheel.x = integral_x;
event.wheel.y = integral_y;
event.wheel.direction = (Uint32)direction;
posted = (SDL_PushEvent(&event) > 0);
}
return posted;
}
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;
}
mouse->cursors = NULL;
if (mouse->def_cursor && mouse->FreeCursor) {
mouse->FreeCursor(mouse->def_cursor);
mouse->def_cursor = NULL;
}
if (mouse->clickstate) {
SDL_free(mouse->clickstate);
mouse->clickstate = NULL;
}
SDL_DelHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
SDL_MouseNormalSpeedScaleChanged, mouse);
SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
SDL_MouseRelativeSpeedScaleChanged, mouse);
}
Uint32
SDL_GetMouseState(int *x, int *y)
{
SDL_Mouse *mouse = SDL_GetMouse();
if (x) {
*x = mouse->x;
}
if (y) {
*y = mouse->y;
}
return mouse->buttonstate;
}
Uint32
SDL_GetRelativeMouseState(int *x, int *y)
{
SDL_Mouse *mouse = SDL_GetMouse();
if (x) {
*x = mouse->xdelta;
}
if (y) {
*y = mouse->ydelta;
}
mouse->xdelta = 0;
mouse->ydelta = 0;
return mouse->buttonstate;
}
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_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);
}
}
int
SDL_WarpMouseGlobal(int x, int y)
{
SDL_Mouse *mouse = SDL_GetMouse();
if (mouse->WarpMouseGlobal) {
return mouse->WarpMouseGlobal(x, y);
}
return SDL_Unsupported();
}
static SDL_bool
ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
{
if (!mouse->SetRelativeMouseMode) {
return SDL_TRUE;
}
return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, SDL_FALSE);
}
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 */
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;
}
SDL_bool
SDL_GetRelativeMouseMode()
{
SDL_Mouse *mouse = SDL_GetMouse();
return mouse->relative_mode;
}
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_Cursor *
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
int w, int h, int hot_x, int hot_y)
{
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;
/* 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 = SDL_CreateColorCursor(surface, hot_x, hot_y);
SDL_FreeSurface(surface);
return cursor;
}
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;
}
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;
}
/* 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_GetMouse();
/* Set the new cursor */
if (cursor) {
/* Make sure the cursor is still valid for this mouse */
if (cursor != mouse->def_cursor) {
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 {
if (mouse->focus) {
cursor = mouse->cur_cursor;
} else {
cursor = mouse->def_cursor;
}
}
if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
if (mouse->ShowCursor) {
mouse->ShowCursor(cursor);
}
} else {
if (mouse->ShowCursor) {
mouse->ShowCursor(NULL);
}
}
}
SDL_Cursor *
SDL_GetCursor(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse) {
return NULL;
}
return mouse->cur_cursor;
}
SDL_Cursor *
SDL_GetDefaultCursor(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse) {
return NULL;
}
return mouse->def_cursor;
}
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;
}
}
}
int
SDL_ShowCursor(int toggle)
{
SDL_Mouse *mouse = SDL_GetMouse();
SDL_bool shown;
if (!mouse) {
return 0;
}
shown = mouse->cursor_shown;
if (toggle >= 0) {
if (toggle) {
mouse->cursor_shown = SDL_TRUE;
} else {
mouse->cursor_shown = SDL_FALSE;
}
if (mouse->cursor_shown != shown) {
SDL_SetCursor(NULL);
}
}
return shown;
}
/* vi: set ts=4 sw=4 expandtab: */
SDL_SetDoubleClickTime
void SDL_SetDoubleClickTime(Uint32 interval)
Definition: SDL_mouse.c:118
SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE
#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE
A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode...
Definition: SDL_hints.h:273
scale
GLenum GLenum GLenum GLenum GLenum scale
Definition: SDL_opengl_glext.h:9375
SDL_UpdateWindowGrab
void SDL_UpdateWindowGrab(SDL_Window *window)
Definition: SDL_video.c:2427
SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
SDL_abs
#define SDL_abs
Definition: SDL_dynapi_overrides.h:381
SDL_ConvertSurfaceFormat
#define SDL_ConvertSurfaceFormat
Definition: SDL_dynapi_overrides.h:464
SDL_Mouse::y
int y
Definition: SDL_mouse_c.h:79
SDL_Mouse::last_y
int last_y
Definition: SDL_mouse_c.h:82
SDL_GetMouse
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:112
SDL_GetCursor
SDL_Cursor * SDL_GetCursor(void)
Return the active cursor.
Definition: SDL_mouse.c:948
SDL_PrivateSendMouseButton
static int SDL_PrivateSendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
Definition: SDL_mouse.c:414
SDL_min
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_Mouse::ShowCursor
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:52
SDL_HINT_TOUCH_MOUSE_EVENTS
#define SDL_HINT_TOUCH_MOUSE_EVENTS
A variable controlling whether touch events should generate synthetic mouse events.
Definition: SDL_hints.h:306
button
SDL_Texture * button
Definition: testgamecontroller.c:67
SDL_ceil
#define SDL_ceil
Definition: SDL_dynapi_overrides.h:426
SDL_TRUE
Definition: SDL_stdinc.h:142
SDL_Mouse::has_position
SDL_bool has_position
Definition: SDL_mouse_c.h:86
SDL_PrivateSendMouseMotion
static int SDL_PrivateSendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:265
SDL_MOUSEBUTTONUP
Definition: SDL_events.h:104
SDL_Mouse::last_x
int last_x
Definition: SDL_mouse_c.h:82
SDL_CreateColorCursor
SDL_Cursor * SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
Create a color cursor.
Definition: SDL_mouse.c:841
SDL_Window::w
int w
Definition: SDL_sysvideo.h:80
SDL_Surface::h
int h
Definition: SDL_surface.h:73
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
SDL_MouseClickState::last_timestamp
Uint32 last_timestamp
Definition: SDL_mouse_c.h:39
SDL_Mouse::buttonstate
Uint32 buttonstate
Definition: SDL_mouse_c.h:85
SDL_Mouse::relative_mode_warp
SDL_bool relative_mode_warp
Definition: SDL_mouse_c.h:88
SDL_Mouse::focus
SDL_Window * focus
Definition: SDL_mouse_c.h:77
SDL_FlushEvent
#define SDL_FlushEvent
Definition: SDL_dynapi_overrides.h:120
count
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Mouse::SetRelativeMouseMode
int(* SetRelativeMouseMode)(SDL_bool enabled)
Definition: SDL_mouse_c.h:67
SDL_FALSE
Definition: SDL_stdinc.h:141
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1946
state
struct xkb_state * state
Definition: SDL_waylandsym.h:113
SDL_Mouse::scale_accum_y
float scale_accum_y
Definition: SDL_mouse_c.h:92
surface
EGLSurface surface
Definition: eglext.h:248
SDL_MOUSEBUTTONDOWN
Definition: SDL_events.h:103
SDL_GetMouseState
Uint32 SDL_GetMouseState(int *x, int *y)
Retrieve the current state of the mouse.
Definition: SDL_mouse.c:603
SDL_Mouse::clickstate
SDL_MouseClickState * clickstate
Definition: SDL_mouse_c.h:97
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
SDL_TouchMouseEventsChanged
static void SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:67
SDL_events.h
SDL_Cursor
Definition: SDL_mouse_c.h:30
SDL_SendMouseButtonClicks
int SDL_SendMouseButtonClicks(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
Definition: SDL_mouse.c:499
SDL_ENABLE
#define SDL_ENABLE
Definition: SDL_events.h:722
SDL_Mouse::num_clickstates
int num_clickstates
Definition: SDL_mouse_c.h:96
SDL_MouseNormalSpeedScaleChanged
static void SDL_MouseNormalSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:43
f
GLfloat f
Definition: SDL_opengl_glext.h:1870
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_SetCursor
void SDL_SetCursor(SDL_Cursor *cursor)
Set the active cursor.
Definition: SDL_mouse.c:908
SDL_Mouse::GetGlobalMouseState
Uint32(* GetGlobalMouseState)(int *x, int *y)
Definition: SDL_mouse_c.h:73
SDL_WarpMouseGlobal
int SDL_WarpMouseGlobal(int x, int y)
Moves the mouse to the given position in global screen space.
Definition: SDL_mouse.c:676
SDL_Mouse::ydelta
int ydelta
Definition: SDL_mouse_c.h:81
SDL_ShowCursor
int SDL_ShowCursor(int toggle)
Toggle whether or not the cursor is shown.
Definition: SDL_mouse.c:1004
SDL_SendWindowEvent
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
Definition: SDL_windowevents.c:88
SDL_SetMouseFocus
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:151
SDL_GetKeyboardFocus
#define SDL_GetKeyboardFocus
Definition: SDL_dynapi_overrides.h:216
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:181
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
SDL_strcasecmp
#define SDL_strcasecmp
Definition: SDL_dynapi_overrides.h:419
SDL_TOUCH_MOUSEID
#define SDL_TOUCH_MOUSEID
Definition: SDL_touch.h:53
SDL_Surface::w
int w
Definition: SDL_surface.h:73
SDL_MOUSEWHEEL
Definition: SDL_events.h:105
SDL_floor
#define SDL_floor
Definition: SDL_dynapi_overrides.h:431
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
SDL_MouseQuit
void SDL_MouseQuit(void)
Definition: SDL_mouse.c:566
SDL_max
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
SDL_CreateCursor
SDL_Cursor * SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, int hot_x, int hot_y)
Create a cursor, using the specified bitmap data and mask (in MSB format).
Definition: SDL_mouse.c:792
SDL_Mouse::cursors
SDL_Cursor * cursors
Definition: SDL_mouse_c.h:99
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_Mouse::mouseID
SDL_MouseID mouseID
Definition: SDL_mouse_c.h:76
SDL_double_click_radius
static int SDL_double_click_radius
Definition: SDL_mouse.c:37
SDL_CaptureMouse
int SDL_CaptureMouse(SDL_bool enabled)
Capture the mouse, to track input outside an SDL window.
Definition: SDL_mouse.c:757
SDL_MouseID
Uint32 SDL_MouseID
Definition: SDL_mouse_c.h:28
SDL_WarpMouseInWindow
void SDL_WarpMouseInWindow(SDL_Window *window, int x, int y)
Moves the mouse to the given position within the window.
Definition: SDL_mouse.c:656
SDL_MouseInit
int SDL_MouseInit(void)
Definition: SDL_mouse.c:80
SDL_GetHintBoolean
#define SDL_GetHintBoolean
Definition: SDL_dynapi_overrides.h:608
SDL_MouseClickState::click_count
Uint8 click_count
Definition: SDL_mouse_c.h:40
SDL_Mouse::CaptureMouse
int(* CaptureMouse)(SDL_Window *window)
Definition: SDL_mouse_c.h:70
SDL_GetWindowSize
#define SDL_GetWindowSize
Definition: SDL_dynapi_overrides.h:527
SDL_WINDOW_MOUSE_CAPTURE
Definition: SDL_video.h:116
SDL_mouse
static SDL_Mouse SDL_mouse
Definition: SDL_mouse.c:35
SDL_Mouse::CreateCursor
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:46
SDL_GetDefaultCursor
SDL_Cursor * SDL_GetDefaultCursor(void)
Return the default cursor.
Definition: SDL_mouse.c:959
SDL_GetRelativeMouseMode
SDL_bool SDL_GetRelativeMouseMode()
Query whether relative mouse mode is enabled.
Definition: SDL_mouse.c:749
SDL_GetEventState
#define SDL_GetEventState(type)
Definition: SDL_events.h:735
GetScaledMouseDelta
static int GetScaledMouseDelta(float scale, int value, float *accum)
Definition: SDL_mouse.c:250
SDL_atof
#define SDL_atof
Definition: SDL_dynapi_overrides.h:411
SDL_SendMouseMotion
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:237
SDL_GetTicks
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:75
SDL_CreateSystemCursor
SDL_Cursor * SDL_CreateSystemCursor(SDL_SystemCursor id)
Create a system cursor.
Definition: SDL_mouse.c:884
SDL_Mouse::touch_mouse_events
SDL_bool touch_mouse_events
Definition: SDL_mouse_c.h:93
SDL_FreeSurface
#define SDL_FreeSurface
Definition: SDL_dynapi_overrides.h:446
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_Mouse::accumulated_wheel_y
float accumulated_wheel_y
Definition: SDL_mouse_c.h:84
SDL_Mouse::cursor_shown
SDL_bool cursor_shown
Definition: SDL_mouse_c.h:102
SDL_Mouse::relative_mode
SDL_bool relative_mode
Definition: SDL_mouse_c.h:87
SDL_PushEvent
#define SDL_PushEvent
Definition: SDL_dynapi_overrides.h:125
mask
GLenum GLint GLuint mask
Definition: SDL_opengl_glext.h:657
SDL_MouseClickState::last_x
int last_x
Definition: SDL_mouse_c.h:38
SDL_hints.h
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:698
SDL_SystemCursor
SDL_SystemCursor
Cursor types for SDL_CreateSystemCursor().
Definition: SDL_mouse.h:46
GetMouseClickState
static SDL_MouseClickState * GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
Definition: SDL_mouse.c:395
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_Mouse::scale_accum_x
float scale_accum_x
Definition: SDL_mouse_c.h:91
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
SDL_WINDOWEVENT_LEAVE
Definition: SDL_video.h:164
SDL_SetDefaultCursor
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:101
SDL_UpdateMouseFocus
static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, int x, int y, Uint32 buttonstate)
Definition: SDL_mouse.c:189
SDL_Mouse::WarpMouseGlobal
int(* WarpMouseGlobal)(int x, int y)
Definition: SDL_mouse_c.h:64
enabled
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: SDL_opengl_glext.h:2479
cursor
SDL_Cursor * cursor
Definition: testcustomcursor.c:119
SDL_Window::h
int h
Definition: SDL_sysvideo.h:80
SDL_MouseRelativeSpeedScaleChanged
static void SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:55
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_Mouse::x
int x
Definition: SDL_mouse_c.h:78
SDL_Mouse::FreeCursor
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:58
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_Mouse::normal_speed_scale
float normal_speed_scale
Definition: SDL_mouse_c.h:89
SDL_events_c.h
NULL
#define NULL
Definition: begin_code.h:164
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:139
SDL_SendMouseWheel
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
Definition: SDL_mouse.c:512
SDL_Surface::format
SDL_PixelFormat * format
Definition: SDL_surface.h:72
SDL_Cursor::next
struct SDL_Cursor * next
Definition: SDL_mouse_c.h:32
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_MOUSEMOTION
Definition: SDL_events.h:102
SDL_HINT_MOUSE_NORMAL_SPEED_SCALE
#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE
A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in rela...
Definition: SDL_hints.h:268
SDL_CreateRGBSurface
#define SDL_CreateRGBSurface
Definition: SDL_dynapi_overrides.h:444
SDL_Mouse::xdelta
int xdelta
Definition: SDL_mouse_c.h:80
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_SetRelativeMouseMode
int SDL_SetRelativeMouseMode(SDL_bool enabled)
Set relative mouse mode.
Definition: SDL_mouse.c:698
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_AddHintCallback
#define SDL_AddHintCallback
Definition: SDL_dynapi_overrides.h:192
SDL_Window::id
Uint32 id
Definition: SDL_sysvideo.h:76
SDL_DelHintCallback
#define SDL_DelHintCallback
Definition: SDL_dynapi_overrides.h:193
SDL_WINDOWEVENT_ENTER
Definition: SDL_video.h:163
SDL_Mouse::WarpMouse
void(* WarpMouse)(SDL_Window *window, int x, int y)
Definition: SDL_mouse_c.h:61
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:74
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
SDL_BUTTON
#define SDL_BUTTON(X)
Definition: SDL_mouse.h:281
SDL_Event
General event structure.
Definition: SDL_events.h:525
SDL_Mouse
Definition: SDL_mouse_c.h:43
SDL_MouseClickState::last_y
int last_y
Definition: SDL_mouse_c.h:38
SDL_MouseClickState
Definition: SDL_mouse_c.h:36
SDL_PRESSED
#define SDL_PRESSED
Definition: SDL_events.h:50
SDL_PixelFormat::format
Uint32 format
Definition: SDL_pixels.h:317
SDL_Mouse::accumulated_wheel_x
float accumulated_wheel_x
Definition: SDL_mouse_c.h:83
SDL_GetMouseFocus
SDL_Window * SDL_GetMouseFocus(void)
Get the window which currently has mouse focus.
Definition: SDL_mouse.c:124
SDL_Mouse::cur_cursor
SDL_Cursor * cur_cursor
Definition: SDL_mouse_c.h:101
SDL_FreeCursor
void SDL_FreeCursor(SDL_Cursor *cursor)
Frees a cursor created with SDL_CreateCursor() or similar functions.
Definition: SDL_mouse.c:970
SDL_timer.h
SDL_double_click_time
static Uint32 SDL_double_click_time
Definition: SDL_mouse.c:36
SDL_Window::flags
Uint32 flags
Definition: SDL_sysvideo.h:83
SDL_TICKS_PASSED
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_Mouse::MoveCursor
void(* MoveCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:55
SDL_Mouse::CreateSystemCursor
SDL_Cursor *(* CreateSystemCursor)(SDL_SystemCursor id)
Definition: SDL_mouse_c.h:49
SDL_Mouse::relative_speed_scale
float relative_speed_scale
Definition: SDL_mouse_c.h:90
SDLCALL
#define SDLCALL
Definition: SDL_internal.h:45
SDL_MouseWheelDirection
SDL_MouseWheelDirection
Scroll direction types for the Scroll event.
Definition: SDL_mouse.h:66
SDL_SendMouseButton
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:506
SDL_Unsupported
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_HINT_MOUSE_RELATIVE_MODE_WARP
#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP
A variable controlling whether relative mouse mode is implemented using mouse warping.
Definition: SDL_hints.h:284
ShouldUseRelativeModeWarp
static SDL_bool ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
Definition: SDL_mouse.c:688
SDL_GetRelativeMouseState
Uint32 SDL_GetRelativeMouseState(int *x, int *y)
Retrieve the relative state of the mouse.
Definition: SDL_mouse.c:617
SDL_GetGlobalMouseState
Uint32 SDL_GetGlobalMouseState(int *x, int *y)
Get the current state of the mouse, in relation to the desktop.
Definition: SDL_mouse.c:633
SDL_assert.h
hot_x
int uint32_t uint32_t uint32_t uint32_t uint32_t int drmModeModeInfoPtr mode int uint32_t uint32_t uint32_t uint32_t int32_t hot_x
Definition: SDL_kmsdrmsym.h:55
SDL_Mouse::def_cursor
SDL_Cursor * def_cursor
Definition: SDL_mouse_c.h:100