Added support for double-clicks, through a new "clicks" field in the mouse button event.
authorSam Lantinga <slouken@libsdl.org>
Mon, 23 Dec 2013 12:17:52 -0800
changeset 8066658b461d81be
parent 8065 fcca53e02c81
child 8067 8314a9008bf1
Added support for double-clicks, through a new "clicks" field in the mouse button event.
include/SDL_events.h
src/events/SDL_mouse.c
src/events/SDL_mouse_c.h
src/test/SDL_test_common.c
src/video/windows/SDL_windowsmouse.c
     1.1 --- a/include/SDL_events.h	Mon Dec 23 10:54:27 2013 -0800
     1.2 +++ b/include/SDL_events.h	Mon Dec 23 12:17:52 2013 -0800
     1.3 @@ -239,8 +239,8 @@
     1.4      Uint32 which;       /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
     1.5      Uint8 button;       /**< The mouse button index */
     1.6      Uint8 state;        /**< ::SDL_PRESSED or ::SDL_RELEASED */
     1.7 +    Uint8 clicks;       /**< 1 for single-click, 2 for double-click, etc. */
     1.8      Uint8 padding1;
     1.9 -    Uint8 padding2;
    1.10      Sint32 x;           /**< X coordinate, relative to window */
    1.11      Sint32 y;           /**< Y coordinate, relative to window */
    1.12  } SDL_MouseButtonEvent;
     2.1 --- a/src/events/SDL_mouse.c	Mon Dec 23 10:54:27 2013 -0800
     2.2 +++ b/src/events/SDL_mouse.c	Mon Dec 23 12:17:52 2013 -0800
     2.3 @@ -23,6 +23,7 @@
     2.4  /* General mouse handling code for SDL */
     2.5  
     2.6  #include "SDL_assert.h"
     2.7 +#include "SDL_timer.h"
     2.8  #include "SDL_events.h"
     2.9  #include "SDL_events_c.h"
    2.10  #include "default_cursor.h"
    2.11 @@ -32,6 +33,8 @@
    2.12  
    2.13  /* The mouse state */
    2.14  static SDL_Mouse SDL_mouse;
    2.15 +static Uint32 SDL_double_click_time = 500;
    2.16 +static int SDL_double_click_radius = 1;
    2.17  
    2.18  static int
    2.19  SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);
    2.20 @@ -64,6 +67,12 @@
    2.21      return &SDL_mouse;
    2.22  }
    2.23  
    2.24 +void
    2.25 +SDL_SetDoubleClickTime(Uint32 interval)
    2.26 +{
    2.27 +    SDL_double_click_time = interval;
    2.28 +}
    2.29 +
    2.30  SDL_Window *
    2.31  SDL_GetMouseFocus(void)
    2.32  {
    2.33 @@ -272,6 +281,23 @@
    2.34      return posted;
    2.35  }
    2.36  
    2.37 +static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
    2.38 +{
    2.39 +    if (button >= mouse->num_clickstates) {
    2.40 +        int i, count = button + 1;
    2.41 +        mouse->clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
    2.42 +        if (!mouse->clickstate) {
    2.43 +            return NULL;
    2.44 +        }
    2.45 +
    2.46 +        for (i = mouse->num_clickstates; i < count; ++i) {
    2.47 +            SDL_zero(mouse->clickstate[i]);
    2.48 +        }
    2.49 +        mouse->num_clickstates = count;
    2.50 +    }
    2.51 +    return &mouse->clickstate[button];
    2.52 +}
    2.53 +
    2.54  int
    2.55  SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
    2.56  {
    2.57 @@ -279,6 +305,8 @@
    2.58      int posted;
    2.59      Uint32 type;
    2.60      Uint32 buttonstate = mouse->buttonstate;
    2.61 +    SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
    2.62 +    Uint8 click_count;
    2.63  
    2.64      /* Figure out which event to perform */
    2.65      switch (state) {
    2.66 @@ -306,6 +334,27 @@
    2.67      }
    2.68      mouse->buttonstate = buttonstate;
    2.69  
    2.70 +    if (clickstate) {
    2.71 +        if (state == SDL_PRESSED) {
    2.72 +            Uint32 now = SDL_GetTicks();
    2.73 +
    2.74 +            if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + SDL_double_click_time) ||
    2.75 +                SDL_abs(mouse->x - clickstate->last_x) > SDL_double_click_radius ||
    2.76 +                SDL_abs(mouse->y - clickstate->last_y) > SDL_double_click_radius) {
    2.77 +                clickstate->click_count = 0;
    2.78 +            }
    2.79 +            clickstate->last_timestamp = now;
    2.80 +            clickstate->last_x = mouse->x;
    2.81 +            clickstate->last_y = mouse->y;
    2.82 +            if (clickstate->click_count < 255) {
    2.83 +                ++clickstate->click_count;
    2.84 +            }
    2.85 +        }
    2.86 +        click_count = clickstate->click_count;
    2.87 +    } else {
    2.88 +        click_count = 1;
    2.89 +    }
    2.90 +
    2.91      /* Post the event, if desired */
    2.92      posted = 0;
    2.93      if (SDL_GetEventState(type) == SDL_ENABLE) {
    2.94 @@ -315,6 +364,7 @@
    2.95          event.button.which = mouseID;
    2.96          event.button.state = state;
    2.97          event.button.button = button;
    2.98 +        event.button.clicks = click_count;
    2.99          event.button.x = mouse->x;
   2.100          event.button.y = mouse->y;
   2.101          posted = (SDL_PushEvent(&event) > 0);
   2.102 @@ -376,6 +426,10 @@
   2.103          mouse->FreeCursor(mouse->def_cursor);
   2.104      }
   2.105  
   2.106 +    if (mouse->clickstate) {
   2.107 +        SDL_free(mouse->clickstate);
   2.108 +    }
   2.109 +
   2.110      SDL_zerop(mouse);
   2.111  }
   2.112  
     3.1 --- a/src/events/SDL_mouse_c.h	Mon Dec 23 10:54:27 2013 -0800
     3.2 +++ b/src/events/SDL_mouse_c.h	Mon Dec 23 12:17:52 2013 -0800
     3.3 @@ -35,6 +35,13 @@
     3.4  
     3.5  typedef struct
     3.6  {
     3.7 +    int last_x, last_y;
     3.8 +    Uint32 last_timestamp;
     3.9 +    Uint8 click_count;
    3.10 +} SDL_MouseClickState;
    3.11 +
    3.12 +typedef struct
    3.13 +{
    3.14      /* Create a cursor from a surface */
    3.15      SDL_Cursor *(*CreateCursor) (SDL_Surface * surface, int hot_x, int hot_y);
    3.16  
    3.17 @@ -69,6 +76,10 @@
    3.18      /* the x and y coordinates when relative mode was activated */
    3.19      int original_x, original_y;
    3.20  
    3.21 +    /* Data for double-click tracking */
    3.22 +    int num_clickstates;
    3.23 +    SDL_MouseClickState *clickstate;
    3.24 +
    3.25      SDL_Cursor *cursors;
    3.26      SDL_Cursor *def_cursor;
    3.27      SDL_Cursor *cur_cursor;
    3.28 @@ -85,6 +96,9 @@
    3.29  /* Get the mouse state structure */
    3.30  SDL_Mouse *SDL_GetMouse(void);
    3.31  
    3.32 +/* Set the default double-click interval */
    3.33 +extern void SDL_SetDoubleClickTime(Uint32 interval);
    3.34 +
    3.35  /* Set the default mouse cursor */
    3.36  extern void SDL_SetDefaultCursor(SDL_Cursor * cursor);
    3.37  
     4.1 --- a/src/test/SDL_test_common.c	Mon Dec 23 10:54:27 2013 -0800
     4.2 +++ b/src/test/SDL_test_common.c	Mon Dec 23 12:17:52 2013 -0800
     4.3 @@ -1042,13 +1042,13 @@
     4.4                  event->motion.windowID);
     4.5          break;
     4.6      case SDL_MOUSEBUTTONDOWN:
     4.7 -        fprintf(stderr, "Mouse: button %d pressed at %d,%d in window %d",
     4.8 -                event->button.button, event->button.x, event->button.y,
     4.9 +        fprintf(stderr, "Mouse: button %d pressed at %d,%d with click count %d in window %d",
    4.10 +                event->button.button, event->button.x, event->button.y, event->button.clicks,
    4.11                  event->button.windowID);
    4.12          break;
    4.13      case SDL_MOUSEBUTTONUP:
    4.14 -        fprintf(stderr, "Mouse: button %d released at %d,%d in window %d",
    4.15 -                event->button.button, event->button.x, event->button.y,
    4.16 +        fprintf(stderr, "Mouse: button %d released at %d,%d with click count %d in window %d",
    4.17 +                event->button.button, event->button.x, event->button.y, event->button.clicks,
    4.18                  event->button.windowID);
    4.19          break;
    4.20      case SDL_MOUSEWHEEL:
     5.1 --- a/src/video/windows/SDL_windowsmouse.c	Mon Dec 23 10:54:27 2013 -0800
     5.2 +++ b/src/video/windows/SDL_windowsmouse.c	Mon Dec 23 12:17:52 2013 -0800
     5.3 @@ -250,6 +250,8 @@
     5.4      mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
     5.5  
     5.6      SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
     5.7 +
     5.8 +    SDL_SetDoubleClickTime(GetDoubleClickTime());
     5.9  }
    5.10  
    5.11  void