Skip to content

Commit

Permalink
Added support for double-clicks, through a new "clicks" field in the …
Browse files Browse the repository at this point in the history
…mouse button event.
  • Loading branch information
slouken committed Dec 23, 2013
1 parent 3666c1f commit 7469283
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 5 deletions.
2 changes: 1 addition & 1 deletion include/SDL_events.h
Expand Up @@ -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;
Expand Down
54 changes: 54 additions & 0 deletions src/events/SDL_mouse.c
Expand Up @@ -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"
Expand All @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -272,13 +281,32 @@ 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)
{
SDL_Mouse *mouse = SDL_GetMouse();
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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -376,6 +426,10 @@ SDL_MouseQuit(void)
mouse->FreeCursor(mouse->def_cursor);
}

if (mouse->clickstate) {
SDL_free(mouse->clickstate);
}

SDL_zerop(mouse);
}

Expand Down
14 changes: 14 additions & 0 deletions src/events/SDL_mouse_c.h
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions src/test/SDL_test_common.c
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions src/video/windows/SDL_windowsmouse.c
Expand Up @@ -250,6 +250,8 @@ WIN_InitMouse(_THIS)
mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;

SDL_SetDefaultCursor(WIN_CreateDefaultCursor());

SDL_SetDoubleClickTime(GetDoubleClickTime());
}

void
Expand Down

0 comments on commit 7469283

Please sign in to comment.