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 */
Uint8 button; /**< The mouse button index */
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
Uint8 padding1;
Uint8 padding2;
Sint32 x; /**< X coordinate, relative to window */
Sint32 y; /**< Y coordinate, relative to window */
} SDL_MouseButtonEvent;

View File

@ -23,6 +23,7 @@
/* General mouse handling code for SDL */
#include "SDL_assert.h"
#include "SDL_timer.h"
#include "SDL_events.h"
#include "SDL_events_c.h"
#include "default_cursor.h"
@ -32,6 +33,8 @@
/* 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);
@ -64,6 +67,12 @@ SDL_GetMouse(void)
return &SDL_mouse;
}
void
SDL_SetDoubleClickTime(Uint32 interval)
{
SDL_double_click_time = interval;
}
SDL_Window *
SDL_GetMouseFocus(void)
{
@ -272,6 +281,23 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
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
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;
Uint32 type;
Uint32 buttonstate = mouse->buttonstate;
SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
Uint8 click_count;
/* Figure out which event to perform */
switch (state) {
@ -306,6 +334,27 @@ SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8
}
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 */
posted = 0;
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.state = state;
event.button.button = button;
event.button.clicks = click_count;
event.button.x = mouse->x;
event.button.y = mouse->y;
posted = (SDL_PushEvent(&event) > 0);
@ -376,6 +426,10 @@ SDL_MouseQuit(void)
mouse->FreeCursor(mouse->def_cursor);
}
if (mouse->clickstate) {
SDL_free(mouse->clickstate);
}
SDL_zerop(mouse);
}

View File

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

View File

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

View File

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