Doubleclick

Hello,

I’d like to know how you usually implement a double click detection.
I made a quick search and then made this function :

Code:
int DoubleClickDetected (void)
{
static Uint32 LastClickTicks;
Uint32 CurrentClickTicks;
/* The first time this function is called, LastClickTicks has not been initialised yet. /
if (! LastClickTicks)
{
LastClickTicks = SDL_GetTicks ();
return FALSE;
}
else
{
CurrentClickTicks = SDL_GetTicks ();
/
If the period between the two clicks is smaller or equal to a pre-defined number, we report a DoubleClick event. /
if (CurrentClickTicks - LastClickTicks <= DOUBLE_CLICK_MAX_DELAY)
{
/
Update LastClickTicks and signal a DoubleClick. /
LastClickTicks = CurrentClickTicks;
return TRUE;
}
else
{
/
Update LastClickTicks and signal a SingleClick. */
LastClickTicks = CurrentClickTicks;
return FALSE;
}
}
}

The problem about this function is that a click followed by an unrelated event (such as a mouse move) and followed by another click will be considered as a double-click (if the events are fast enough), which is not usual.
If I were to declare a global boolean LastEventWasALeftClick I think it would work, but I’d have to reinitialize it to 0 for all other events, which is not handy, and besides I thought it was best not to use global variables.
So what’s the best solution to detect a double-click ?

Thanks.

What if you have an integer “LastEventWas” and mark it with the
SDL_Event.type? Then you can check if the last event was a click. To make
the difference between left, right and middle button, you can keep another
"LastMousePressed" integer…

just a though.

Leonardo

2010/3/17 Lilly > Hello,

I’d like to know how you usually implement a double click detection.
I made a quick search and then made this function :

Code:

int DoubleClickDetected (void)
{
static Uint32 LastClickTicks;
Uint32 CurrentClickTicks;
/* The first time this function is called, LastClickTicks has not been
initialised yet. /
if (! LastClickTicks)
{
LastClickTicks = SDL_GetTicks ();
return FALSE;
}
else
{
CurrentClickTicks = SDL_GetTicks ();
/
If the period between the two clicks is smaller or equal to a
pre-defined number, we report a DoubleClick event. /
if (CurrentClickTicks - LastClickTicks <= DOUBLE_CLICK_MAX_DELAY)
{
/
Update LastClickTicks and signal a DoubleClick. /
LastClickTicks = CurrentClickTicks;
return TRUE;
}
else
{
/
Update LastClickTicks and signal a SingleClick. */
LastClickTicks = CurrentClickTicks;
return FALSE;
}
}
}

The problem about this function is that a click followed by an unrelated
event (such as a mouse move) and followed by another click will be
considered as a double-click (if the events are fast enough), which is not
usual.
If I were to declare a global boolean LastEventWasALeftClick I think it
would work, but I’d have to reinitialize it to 0 for all other events, which
is not handy, and besides I thought it was best not to use global variables.
So what’s the best solution to detect a double-click ?

Thanks.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Hello,

I’d like to know how you usually implement a double click detection.
I made a quick search and then made this function :

[…]

The problem about this function is that a click followed by an unrelated event (such as a mouse move) and followed by another click will be considered as a double-click (if the events are fast enough), which is not usual.

Only call it if the current event you’re processing is a left-click. I.
e. "case SDL_MOUSBUTTONDOWN: { if(event.button.type==LEFTBUTTON)
CheckDoubleClick(); }"On Tue, 16 Mar 2010 23:57:42 -0700 “Lilly” wrote:

“The problem about this function is that a click followed by an unrelated
event (such as a mouse move) and followed by another click will be
considered as a double-click (if the events are fast enough), which is not
usual.”

I would think that this is desirable. You don’t want random unrelated
events messing with your double-click at all. You might want to make sure
that the first click was on the same object (button or whatever) by saving
the position data as well.

Jonny DOn Wed, Mar 17, 2010 at 8:46 AM, Johannes Kroll wrote:

On Tue, 16 Mar 2010 23:57:42 -0700 “Lilly” wrote:

Hello,

I’d like to know how you usually implement a double click detection.
I made a quick search and then made this function :

[…]

The problem about this function is that a click followed by an unrelated
event (such as a mouse move) and followed by another click will be
considered as a double-click (if the events are fast enough), which is not
usual.

Only call it if the current event you’re processing is a left-click. I.
e. “case SDL_MOUSBUTTONDOWN: { if(event.button.type==LEFTBUTTON)
CheckDoubleClick(); }”


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Johnny,

As I understood, the way it is, the double-click “event” can be messed
with another event, as Lilly said. Other events like mouse move or
keyboard press should deactivate the “waiting second-click for
double-click” state, and that’s not happening.

Leonardo

2010/3/17 Jonathan Dearborn :> "The problem about this function is that a click followed by an unrelated

event (such as a mouse move) and followed by another click will be
considered as a double-click (if the events are fast enough), which is not
usual."
I would think that this is desirable. ?You don’t want random unrelated
events messing with your double-click at all. ?You might want to make sure
that the first click was on the same object (button or whatever) by saving
the position data as well.
Jonny D

On Wed, Mar 17, 2010 at 8:46 AM, Johannes Kroll wrote:

On Tue, 16 Mar 2010 23:57:42 -0700 “Lilly” wrote:

Hello,

I’d like to know how you usually implement a double click detection.
I made a quick search and then made this function :

[…]

The problem about this function is that a click followed by an unrelated
event (such as a mouse move) and followed by another click will be
considered as a double-click (if the events are fast enough), which is not
usual.

Only call it if the current event you’re processing is a left-click. I.
e. “case SDL_MOUSBUTTONDOWN: { if(event.button.type==LEFTBUTTON)
CheckDoubleClick(); }”


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Hello,

thanks for all these answers.

I’ve been thinking and trying to find a solution. I didn’t.
Leonardo, I don’t understand how I can ‘mark it with the SDL_Event.type’. Can you show me how you would do it ?

Johannes Kroll, I’m already calling it only if the current event I’m processing is a left-click, but this doesn’t change anything : a left-click followed by a mouse move followed by another left click would be interpreted as a double left click, which is not desirable.

Jonny D, I don’t exactly know all kind of events so I wouldn’t know if there could be random events that might mess with my double click, but at least I know that a mouse move or a keypress is supposed to annihilate the double click, at least I think it’s the way my OS (windows) behaves.

So I still don’t know how to do it properly…

Lilly wrote:

Johannes Kroll, I’m already calling it only if the current event I’m
processing is a left-click, but this doesn’t change anything : a
left-click followed by a mouse move followed by another left click would
be interpreted as a double left click, which is not desirable.

Then your code has to take that into account, Lilly.

DoubleClickDetected needs to know what events happen between the two
mouse-clicked events. If you won’t tell it and you just call DoubleClickDetected
whenever a MouseClicked event happens, then you’ll be able to move the mouse
between the first click and the second click and it will still register it as a
double click. The mouse move event has to invalidate the effect of the first
mouse clicked event.

So, somewhere in your code:

switch (event->type) {
/* … /
case SDL_MOUSEBUTTONDOWN:
DoubleClickDetected(SDL_MOUSEBUTTONDOWN);
break;
/
/
case SDL_MOUSEMOTION:
DoubelClickDetected(SDL_MOUSEMOTION);
break;
/
… */
}

and then DoubleClickDetected becomes:

int DoubleClickDetected(Uint8 event_type)
{
static Uint32 PrevClickMs;

if (PrevClickMs == 0) {
PrevClickMs = SDL_GetTicks();
return FALSE;
}
if (event_type == SDL_MOUSEMOTION) {
PrevClickMs = 0;
return FALSE;
}

Uint32 CurClickMs = SDL_GetTicks();
Uint32 ClickDeltaMs = CurClickMs - PrevClickMs;
PrevClickMs = CurClickMs;

return ClickDeltaMs <= DOUBLE_CLICK_MAX_DELAY;
}

CE

Lilly, I was thinking of someone like this:

int LastEventType = 0;
int doubleclicked = 0;
/* other code /
switch (event->type) {
case SDL_MOUSEBUTTONDOWN:
if (LastEventType == SDL_MOUSEBUTTONDOWN) {
doubleclicked = DoubleClickDetected()
}
break;
case /
other events */
}
LastEventType = event->type;

/* do your double-click things */

doubleclicked = 0;

Leonardo

2010/3/18 Chris Eineke :> switch (event->type) {

/* … /
case SDL_MOUSEBUTTONDOWN:
? ?DoubleClickDetected(SDL_MOUSEBUTTONDOWN);
? ?break;
/
/
case SDL_MOUSEMOTION:
? ?DoubelClickDetected(SDL_MOUSEMOTION);
? ?break;
/
… */
}

something like this sorry :slight_smile:

Leonardo

2010/3/18 Leonardo Guilherme <@Leonardo_Guilherme>:> Lilly, I was thinking of someone like this:

int LastEventType = 0;
int doubleclicked = 0;
/* other code /
switch (event->type) {
? ?case SDL_MOUSEBUTTONDOWN:
? ? ? ?if (LastEventType == SDL_MOUSEBUTTONDOWN) {
? ? ? ? ? ?doubleclicked = DoubleClickDetected()
? ? ? ?}
? ? ? ?break;
? ? case /
other events */
}
LastEventType = event->type;

/* do your double-click things */

doubleclicked = 0;

Leonardo

2010/3/18 Chris Eineke :

switch (event->type) {
/* … /
case SDL_MOUSEBUTTONDOWN:
? ?DoubleClickDetected(SDL_MOUSEBUTTONDOWN);
? ?break;
/
/
case SDL_MOUSEMOTION:
? ?DoubelClickDetected(SDL_MOUSEMOTION);
? ?break;
/
… */
}

I think most GUIs like GTK and MSWindows are permissible about what
constitutes an interruption to a double click, so I wouldn’t just use
"LastEventWasALeftClick" if you didn’t want a one pixel movement of the
mouse to kill a double click. You’ll have to decide what works best for your
application and what your users expect. You could also extend the SDL_event
union with an extended SDL_MouseButtonEvent:

/* Mouse EXPANDED button event structure /
typedef struct SDL_MouseButtonEventX {
Uint8 type; /
SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP /
Uint8 which; /
The mouse device index /
Uint8 button; /
The mouse button index /
Uint8 state; /
SDL_PRESSED or SDL_RELEASED /
Uint16 x, y; /
The X/Y coordinates of the mouse at press time /
Uint8 counter; /
double? triple? quadruple click? the sky’s the limit!
*/
} SDL_MouseButtonEventX;

/* Make sure our expansion doesn’t overrun the length of the SDL_Event union
*/
#if sizeof(SDL_Event) < sizeof(SDL_MouseButtonEventX)
#error SDL_MouseButtonEventX is too big!
#endif

/* Make sure our new struct expands properly on the old mouse button struct
/
#define offsetOf(struct,member) (size_t)(((struct
)NULL)->member)
#if offsetOf(SDL_MouseButtonEvent, type) != offsetOf(SDL_MouseButtonX, type)
||
offsetOf(SDL_MouseButtonEvent, which) != offsetOf(SDL_MouseButtonX,
which) ||
offsetOf(SDL_MouseButtonEvent, button) != offsetOf(SDL_MouseButtonX,
button) ||
offsetOf(SDL_MouseButtonEvent, state) != offsetOf(SDL_MouseButtonX,
state) ||
offsetOf(SDL_MouseButtonEvent, x != offsetOf(SDL_MouseButtonX, x) ||
offsetOf(SDL_MouseButtonEvent, y != offsetOf(SDL_MouseButtonX, y)
#error SDL_MouseButtonEventX is discontiguous with SDL_MouseButtonEvent!
#endif

/* This might be useful if your event filter uses SDL_PeepEvents() */
#define EVMASK SDL_EVENTMASK(SDL_MOUSEMOTION) |
SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) |
SDL_EVENTMASK(SDL_MOUSEBUTTTONUP) |
SDL_EVENTMASK(SDL_KEYBUTTONDOWN) |
SDL_EVENTMASK(SDL_KEYBUTTTONUP)

static int OurEventFilter(const SDL_Event event) {
/
Do your magic in here, then register OurEventFilter with
SDL_SetEventFilter() /
event->counter = 1; // set this to something more interesting later on,
then in your event loop
// you can cast the SDL_Event
to an SDL_MouseButtonEventX to access the
’counter’ member
}On Wed, Mar 17, 2010 at 2:57 AM, Lilly wrote:

Hello,

I’d like to know how you usually implement a double click detection.
I made a quick search and then made this function :

Code:

int DoubleClickDetected (void)
{
static Uint32 LastClickTicks;
Uint32 CurrentClickTicks;
/* The first time this function is called, LastClickTicks has not been
initialised yet. /
if (! LastClickTicks)
{
LastClickTicks = SDL_GetTicks ();
return FALSE;
}
else
{
CurrentClickTicks = SDL_GetTicks ();
/
If the period between the two clicks is smaller or equal to a
pre-defined number, we report a DoubleClick event. /
if (CurrentClickTicks - LastClickTicks <= DOUBLE_CLICK_MAX_DELAY)
{
/
Update LastClickTicks and signal a DoubleClick. /
LastClickTicks = CurrentClickTicks;
return TRUE;
}
else
{
/
Update LastClickTicks and signal a SingleClick. */
LastClickTicks = CurrentClickTicks;
return FALSE;
}
}
}

The problem about this function is that a click followed by an unrelated
event (such as a mouse move) and followed by another click will be
considered as a double-click (if the events are fast enough), which is not
usual.
If I were to declare a global boolean LastEventWasALeftClick I think it
would work, but I’d have to reinitialize it to 0 for all other events, which
is not handy, and besides I thought it was best not to use global variables.
So what’s the best solution to detect a double-click ?

Thanks.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


http://codebad.com/

Hi Lilly,

While these are good approaches, at this point I might ask “what am I
gaining?” with a double-click in SDL.

It seems like every solution proposed is a nontrivial process and subject to
a risk of missing the double-click.

If you really need a double-click inside your application, have you
considered a proper GUI wrapper around your SDL window?

If that’s not acceptable have you considered adding a new button on your
interface to replace the need for a double-click? Or maybe combining a
keyboard press with the left mousebutton?
(eg. shift key + lmb )?

cheers,
ErikOn Wed, Mar 17, 2010 at 2:57 AM, Lilly wrote:

Hello,

I’d like to know how you usually implement a double click detection.
I made a quick search and then made this function :

Code:

int DoubleClickDetected (void)
{
static Uint32 LastClickTicks;
Uint32 CurrentClickTicks;
/* The first time this function is called, LastClickTicks has not been
initialised yet. /
if (! LastClickTicks)
{
LastClickTicks = SDL_GetTicks ();
return FALSE;
}
else
{
CurrentClickTicks = SDL_GetTicks ();
/
If the period between the two clicks is smaller or equal to a
pre-defined number, we report a DoubleClick event. /
if (CurrentClickTicks - LastClickTicks <= DOUBLE_CLICK_MAX_DELAY)
{
/
Update LastClickTicks and signal a DoubleClick. /
LastClickTicks = CurrentClickTicks;
return TRUE;
}
else
{
/
Update LastClickTicks and signal a SingleClick. */
LastClickTicks = CurrentClickTicks;
return FALSE;
}
}
}

The problem about this function is that a click followed by an unrelated
event (such as a mouse move) and followed by another click will be
considered as a double-click (if the events are fast enough), which is not
usual.
If I were to declare a global boolean LastEventWasALeftClick I think it
would work, but I’d have to reinitialize it to 0 for all other events, which
is not handy, and besides I thought it was best not to use global variables.
So what’s the best solution to detect a double-click ?

Thanks.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


http://codebad.com/


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


Erik Yuzwa
I’d love to help out! Find me on:


http://www.erikyuzwa.com
http://www.twitter.com/eyuzwa

Johannes Kroll, I’m already calling it only if the current event I’m processing is a left-click, but this doesn’t change anything : a left-click followed by a mouse move followed by another left click would be interpreted as a double left click, which is not desirable.

You’re right, I misunderstood your question, sorry.
One solution would be to have a “static bool lastEventWasMouseDown” in
your event processing function. After processing any event, you set
this to true if the event was MOUSEDOWN with button 1, and to false if
it was any other event (except MOUSEUP with button 1). Then you call the
function to check for double click only if lastEventWasMouseDown==true.
So if any event happens after the last mousedown, you wouldn’t get a
double click, if that is what you want.
You could also set the boolean to false only on mouse events, which
would ignore system events, might be better…On Wed, 17 Mar 2010 18:42:41 -0700 “Lilly” wrote: