It feels/behaves (ms)windows like:
The first click will always fire a EMIE_LMOUSE_PRESSED_DOWN. If the button is pressed down again within the timeout (speed) then also a EMIE_LMOUSE_DOUBLE_CLICKED (new event!) will be fired.
If the mouse was moved within the two clicks, then a normal EMIE_LMOUSE_PRESSED_DOWN will be fired instead of the EMIE_LMOUSE_DOUBLE_CLICKED at the second click, even if it was within the speed. This means the mouse has to stand still while double-clicking (just like in windows).
Default speed is 300 (milliseconds). This means every two clicks within 300 milliseconds will fire a EMIE_LMOUSE_DOUBLE_CLICKED. The speed can be adjusted with CGUIEnvironment::setDoubleClickSpeed(u32 speed).
Next step will be to integrate this into some GUI elements. For example have a listbox fire a EGET_LISTBOX_DOUBLE_CLICKED when it gets double-clicked. Also usefull would be if a textbox's text gets all selected with a doubleclick. etc.
The Linux part should work but is not tested. I would appreciate if someone could test it for me! A goot way to quickly test it is to cach the EMIE_LMOUSE_DOUBLE_CLICKED in the user event receiver and print some message to the console.
The following files have to be modified:
include/IEventReceiver.h
include/IGUIEnvironment.h
CGUIEnvironment.h
CGUIEnvironment.cpp
CIrrDeviceWin32.cpp
CIrrDeviceLinux.cpp
Here are the code changes. Lines starting with "+" have to be added and lines starting with "-" removed.
include/IEventReceiver.h
Code: Select all
enum EMOUSE_INPUT_EVENT
{
.
.
.
EMIE_MOUSE_WHEEL,
+ //! Left mouse button was double-clicked.
+ EMIE_LMOUSE_DOUBLE_CLICKED
}
Code: Select all
public:
+ //! Used internaly by the IrrDevices to check if a double-click has occured.
+ virtual bool isDoubleClick(const SEvent& event, u32 time) = 0;
+
+ //! Sets the double-click speed in milliseconds.
+ //! Every two left mouse button clicks within this time will fire
+ //! a EMIE_LMOUSE_DOUBLE_CLICKED event (if the mouse has not moved
+ //! within the two clicks).
+ virtual void setDoubleClickSpeed(u32 speed) = 0;
CGUIEnvironment.h
Code: Select all
public:
+ //! Used internaly by the IrrDevices to check if a double-click has occured.
+ virtual bool isDoubleClick(const SEvent& event, u32 time);
+
+ //! Sets the double-click speed in milliseconds.
+ virtual void setDoubleClickSpeed(u32 speed);
Code: Select all
private:
+ struct SDoubleClick {
+ SDoubleClick():Speed(300),Time(0),X(0),Y(0){};
+ u32 Speed; // speed in milliseconds
+ u32 Time; // time of last click
+ s32 X, Y; // mouse coordinates of last click
+ };
+ SDoubleClick DoubleClick;
CGUIEnvironment.cpp
Code: Select all
+ //! Used internaly by the IrrDevices to check if a double-click has occured.
+ bool CGUIEnvironment::isDoubleClick(const SEvent& event, u32 time)
+ {
+ bool result = false;
+ if (time - DoubleClick.Time < DoubleClick.Speed
+ && event.MouseInput.X == DoubleClick.X
+ && event.MouseInput.Y == DoubleClick.Y)
+ {
+ result = true;
+ DoubleClick.Time = 0; // reset
+ } else {
+ DoubleClick.Time = time;
+ }
+
+ DoubleClick.X = event.MouseInput.X;
+ DoubleClick.Y = event.MouseInput.Y;
+
+ return result;
+ }
+
+ //! Sets the double-click speed in milliseconds.
+ void CGUIEnvironment::setDoubleClickSpeed(u32 speed) {
+ DoubleClick.Speed = speed;
+ }
CIrrDeviceWin32.cpp
The patch for this file has been updated! Please use the code that you find 3 posts later!
Code: Select all
case WM_MBUTTONDOWN:
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
- event.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN;
event.MouseInput.X = LOWORD(lParam);
event.MouseInput.Y = HIWORD(lParam);
dev = getDeviceFromHWnd(hWnd);
- if (dev)
- dev->postEventFromUser(event);
+ if (dev) {
+ if (dev->getGUIEnvironment()->isDoubleClick(event, dev->getTimer()->getTime()))
+ event.MouseInput.Event = irr::EMIE_LMOUSE_DOUBLE_CLICKED;
+ else
+ event.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN;
+ dev->postEventFromUser(event);
+ }
return 0;
CIrrDeviceLinux.cpp
The patch for this file has been updated! Please use the code that you find 3 posts later!
Code: Select all
case Button5:
irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL;
irrevent.MouseInput.Wheel = -1.0f;
break;
}
+ if (irrevent.MouseInput.Event == irr::EMIE_LMOUSE_PRESSED_DOWN
+ && getGUIEnvironment()->isDoubleClick(event, getTimer()->getTime()))
+ irrevent.MouseInput.Event = irr::EMIE_LMOUSE_DOUBLE_CLICKED;
if (irrevent.MouseInput.Event != irr::EMIE_MOUSE_MOVED)
postEventFromUser(irrevent);
break;