Added support for double-clicks, through a new "clicks" field in the mouse button event.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
diff --git a/include/SDL_events.h b/include/SDL_events.h
index c089030..81ff4dd 100644
--- a/include/SDL_events.h
+++ b/include/SDL_events.h
@@ -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;
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 0bb0b18..742802a 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -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);
}
diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h
index a8faa2e..fd34c66 100644
--- a/src/events/SDL_mouse_c.h
+++ b/src/events/SDL_mouse_c.h
@@ -35,6 +35,13 @@ struct SDL_Cursor
typedef struct
{
+ int last_x, last_y;
+ Uint32 last_timestamp;
+ Uint8 click_count;
+} SDL_MouseClickState;
+
+typedef struct
+{
/* Create a cursor from a surface */
SDL_Cursor *(*CreateCursor) (SDL_Surface * surface, int hot_x, int hot_y);
@@ -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);
diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c
index 3b4d332..ee65b3f 100644
--- a/src/test/SDL_test_common.c
+++ b/src/test/SDL_test_common.c
@@ -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:
diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c
index f75b8da..2298dc8 100644
--- a/src/video/windows/SDL_windowsmouse.c
+++ b/src/video/windows/SDL_windowsmouse.c
@@ -250,6 +250,8 @@ WIN_InitMouse(_THIS)
mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
+
+ SDL_SetDoubleClickTime(GetDoubleClickTime());
}
void