Added support for double-clicks, through a new "clicks" field in the mouse button event.

This commit is contained in:
Sam Lantinga 2013-12-23 12:17:52 -08:00
parent 3666c1f7ca
commit 746928350f
5 changed files with 75 additions and 5 deletions

View File

@ -239,8 +239,8 @@ typedef struct SDL_MouseButtonEvent
Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
Uint8 button; /**< The mouse button index */ Uint8 button; /**< The mouse button index */
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
Uint8 padding1; Uint8 padding1;
Uint8 padding2;
Sint32 x; /**< X coordinate, relative to window */ Sint32 x; /**< X coordinate, relative to window */
Sint32 y; /**< Y coordinate, relative to window */ Sint32 y; /**< Y coordinate, relative to window */
} SDL_MouseButtonEvent; } SDL_MouseButtonEvent;

View File

@ -23,6 +23,7 @@
/* General mouse handling code for SDL */ /* General mouse handling code for SDL */
#include "SDL_assert.h" #include "SDL_assert.h"
#include "SDL_timer.h"
#include "SDL_events.h" #include "SDL_events.h"
#include "SDL_events_c.h" #include "SDL_events_c.h"
#include "default_cursor.h" #include "default_cursor.h"
@ -32,6 +33,8 @@
/* The mouse state */ /* The mouse state */
static SDL_Mouse SDL_mouse; static SDL_Mouse SDL_mouse;
static Uint32 SDL_double_click_time = 500;
static int SDL_double_click_radius = 1;
static int static int
SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y); SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);
@ -64,6 +67,12 @@ SDL_GetMouse(void)
return &SDL_mouse; return &SDL_mouse;
} }
void
SDL_SetDoubleClickTime(Uint32 interval)
{
SDL_double_click_time = interval;
}
SDL_Window * SDL_Window *
SDL_GetMouseFocus(void) SDL_GetMouseFocus(void)
{ {
@ -272,6 +281,23 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
return posted; return posted;
} }
static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
{
if (button >= mouse->num_clickstates) {
int i, count = button + 1;
mouse->clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
if (!mouse->clickstate) {
return NULL;
}
for (i = mouse->num_clickstates; i < count; ++i) {
SDL_zero(mouse->clickstate[i]);
}
mouse->num_clickstates = count;
}
return &mouse->clickstate[button];
}
int int
SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button) SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
{ {
@ -279,6 +305,8 @@ SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8
int posted; int posted;
Uint32 type; Uint32 type;
Uint32 buttonstate = mouse->buttonstate; Uint32 buttonstate = mouse->buttonstate;
SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
Uint8 click_count;
/* Figure out which event to perform */ /* Figure out which event to perform */
switch (state) { switch (state) {
@ -306,6 +334,27 @@ SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8
} }
mouse->buttonstate = buttonstate; mouse->buttonstate = buttonstate;
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;
}
}
click_count = clickstate->click_count;
} else {
click_count = 1;
}
/* Post the event, if desired */ /* Post the event, if desired */
posted = 0; posted = 0;
if (SDL_GetEventState(type) == SDL_ENABLE) { if (SDL_GetEventState(type) == SDL_ENABLE) {
@ -315,6 +364,7 @@ SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8
event.button.which = mouseID; event.button.which = mouseID;
event.button.state = state; event.button.state = state;
event.button.button = button; event.button.button = button;
event.button.clicks = click_count;
event.button.x = mouse->x; event.button.x = mouse->x;
event.button.y = mouse->y; event.button.y = mouse->y;
posted = (SDL_PushEvent(&event) > 0); posted = (SDL_PushEvent(&event) > 0);
@ -376,6 +426,10 @@ SDL_MouseQuit(void)
mouse->FreeCursor(mouse->def_cursor); mouse->FreeCursor(mouse->def_cursor);
} }
if (mouse->clickstate) {
SDL_free(mouse->clickstate);
}
SDL_zerop(mouse); SDL_zerop(mouse);
} }

View File

@ -33,6 +33,13 @@ struct SDL_Cursor
void *driverdata; void *driverdata;
}; };
typedef struct
{
int last_x, last_y;
Uint32 last_timestamp;
Uint8 click_count;
} SDL_MouseClickState;
typedef struct typedef struct
{ {
/* Create a cursor from a surface */ /* Create a cursor from a surface */
@ -69,6 +76,10 @@ typedef struct
/* the x and y coordinates when relative mode was activated */ /* the x and y coordinates when relative mode was activated */
int original_x, original_y; int original_x, original_y;
/* Data for double-click tracking */
int num_clickstates;
SDL_MouseClickState *clickstate;
SDL_Cursor *cursors; SDL_Cursor *cursors;
SDL_Cursor *def_cursor; SDL_Cursor *def_cursor;
SDL_Cursor *cur_cursor; SDL_Cursor *cur_cursor;
@ -85,6 +96,9 @@ extern int SDL_MouseInit(void);
/* Get the mouse state structure */ /* Get the mouse state structure */
SDL_Mouse *SDL_GetMouse(void); SDL_Mouse *SDL_GetMouse(void);
/* Set the default double-click interval */
extern void SDL_SetDoubleClickTime(Uint32 interval);
/* Set the default mouse cursor */ /* Set the default mouse cursor */
extern void SDL_SetDefaultCursor(SDL_Cursor * cursor); extern void SDL_SetDefaultCursor(SDL_Cursor * cursor);

View File

@ -1042,13 +1042,13 @@ SDLTest_PrintEvent(SDL_Event * event)
event->motion.windowID); event->motion.windowID);
break; break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
fprintf(stderr, "Mouse: button %d pressed at %d,%d in window %d", fprintf(stderr, "Mouse: button %d pressed at %d,%d with click count %d in window %d",
event->button.button, event->button.x, event->button.y, event->button.button, event->button.x, event->button.y, event->button.clicks,
event->button.windowID); event->button.windowID);
break; break;
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
fprintf(stderr, "Mouse: button %d released at %d,%d in window %d", fprintf(stderr, "Mouse: button %d released at %d,%d with click count %d in window %d",
event->button.button, event->button.x, event->button.y, event->button.button, event->button.x, event->button.y, event->button.clicks,
event->button.windowID); event->button.windowID);
break; break;
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:

View File

@ -250,6 +250,8 @@ WIN_InitMouse(_THIS)
mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode; mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
SDL_SetDefaultCursor(WIN_CreateDefaultCursor()); SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
SDL_SetDoubleClickTime(GetDoubleClickTime());
} }
void void