MacOSX Double / Triple Click Fix
This patch corrects issues with double click and adds triple click to MacOSX. Double click was functioning but double clicking and then dragging would not work.
This commit is contained in:
parent
ecd51d231b
commit
1bbd086a17
|
@ -105,8 +105,8 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso
|
||||||
m_activeModifierHotKeyMask(0),
|
m_activeModifierHotKeyMask(0),
|
||||||
m_eventTapPort(nullptr),
|
m_eventTapPort(nullptr),
|
||||||
m_eventTapRLSR(nullptr),
|
m_eventTapRLSR(nullptr),
|
||||||
m_lastSingleClick(0),
|
m_lastClickTime(0),
|
||||||
m_lastDoubleClick(0),
|
m_clickState(1),
|
||||||
m_lastSingleClickXCursor(0),
|
m_lastSingleClickXCursor(0),
|
||||||
m_lastSingleClickYCursor(0),
|
m_lastSingleClickYCursor(0),
|
||||||
m_autoShowHideCursor(autoShowHideCursor),
|
m_autoShowHideCursor(autoShowHideCursor),
|
||||||
|
@ -524,6 +524,10 @@ OSXScreen::postMouseEvent(CGPoint& pos) const
|
||||||
}
|
}
|
||||||
|
|
||||||
CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, button);
|
CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, button);
|
||||||
|
|
||||||
|
// Dragging events also need the click state
|
||||||
|
CGEventSetIntegerValueField(event, kCGMouseEventClickState, m_clickState);
|
||||||
|
|
||||||
CGEventPost(kCGHIDEventTap, event);
|
CGEventPost(kCGHIDEventTap, event);
|
||||||
|
|
||||||
CFRelease(event);
|
CFRelease(event);
|
||||||
|
@ -532,20 +536,6 @@ OSXScreen::postMouseEvent(CGPoint& pos) const
|
||||||
void
|
void
|
||||||
OSXScreen::fakeMouseButton(ButtonID id, bool press)
|
OSXScreen::fakeMouseButton(ButtonID id, bool press)
|
||||||
{
|
{
|
||||||
NXEventHandle handle = NXOpenEventStatus();
|
|
||||||
double clickTime = NXClickTime(handle);
|
|
||||||
|
|
||||||
if ((ARCH->time() - m_lastDoubleClick) <= clickTime) {
|
|
||||||
// drop all down and up fakes immedately after a double click.
|
|
||||||
// TODO: perhaps there is a better way to do this, usually in
|
|
||||||
// finder, if you tripple click a folder, it will open it and
|
|
||||||
// then select a folder under the cursor -- and perhaps other
|
|
||||||
// strange behaviour might happen?
|
|
||||||
LOG((CLOG_DEBUG1 "dropping mouse button %s",
|
|
||||||
press ? "press" : "release"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buttons are indexed from one, but the button down array is indexed from zero
|
// Buttons are indexed from one, but the button down array is indexed from zero
|
||||||
UInt32 index = id - kButtonLeft;
|
UInt32 index = id - kButtonLeft;
|
||||||
if (index >= NumButtonIDs) {
|
if (index >= NumButtonIDs) {
|
||||||
|
@ -569,61 +559,47 @@ OSXScreen::fakeMouseButton(ButtonID id, bool press)
|
||||||
// since we don't have double click distance in NX APIs
|
// since we don't have double click distance in NX APIs
|
||||||
// we define our own defaults.
|
// we define our own defaults.
|
||||||
const double maxDiff = sqrt(2) + 0.0001;
|
const double maxDiff = sqrt(2) + 0.0001;
|
||||||
|
|
||||||
if (press && (id == kButtonLeft) &&
|
|
||||||
((ARCH->time() - m_lastSingleClick) <= clickTime) &&
|
NXEventHandle handle = NXOpenEventStatus();
|
||||||
diff <= maxDiff) {
|
double clickTime = NXClickTime(handle);
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1 "faking mouse left double click"));
|
// As long as the click is within the time window and distance window
|
||||||
|
// increase clickState (double click, triple click, etc)
|
||||||
// finder does not seem to detect double clicks from two separate
|
// This will allow for higher than triple click but the quartz documenation
|
||||||
// CGEventCreateMouseEvent calls. so, if we detect a double click we
|
// does not specify that this should be limited to triple click
|
||||||
// use CGEventSetIntegerValueField to tell the OS.
|
if(press) {
|
||||||
//
|
if((ARCH->time() - m_lastClickTime) <= clickTime && diff <= maxDiff){
|
||||||
// the caveat here is that findor will see this as a single click
|
m_clickState++;
|
||||||
// followed by a double click (even though there should be only a
|
}
|
||||||
// double click). this may cause weird behaviour in other apps.
|
else {
|
||||||
//
|
m_clickState = 1;
|
||||||
// for some reason using the old CGPostMouseEvent function, doesn't
|
}
|
||||||
// cause double clicks (though i'm sure it did work at some point).
|
|
||||||
|
m_lastClickTime = ARCH->time();
|
||||||
CGEventRef event = CGEventCreateMouseEvent(
|
}
|
||||||
NULL, kCGEventLeftMouseDown, pos, kCGMouseButtonLeft);
|
|
||||||
|
if(m_clickState == 1){
|
||||||
CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2);
|
m_lastSingleClickXCursor = m_xCursor;
|
||||||
m_buttonState.set(index, kMouseButtonDown);
|
m_lastSingleClickYCursor = m_yCursor;
|
||||||
CGEventPost(kCGHIDEventTap, event);
|
}
|
||||||
|
|
||||||
CGEventSetType(event, kCGEventLeftMouseUp);
|
EMouseButtonState state = press ? kMouseButtonDown : kMouseButtonUp;
|
||||||
m_buttonState.set(index, kMouseButtonUp);
|
|
||||||
CGEventPost(kCGHIDEventTap, event);
|
LOG((CLOG_DEBUG1 "faking mouse button id: %d press: %s", id, press ? "pressed" : "released"));
|
||||||
|
|
||||||
CFRelease(event);
|
MouseButtonEventMapType thisButtonMap = MouseButtonEventMap[index];
|
||||||
|
CGEventType type = thisButtonMap[state];
|
||||||
m_lastDoubleClick = ARCH->time();
|
|
||||||
}
|
CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, index);
|
||||||
else {
|
|
||||||
|
CGEventSetIntegerValueField(event, kCGMouseEventClickState, m_clickState);
|
||||||
// ... otherwise, perform a single press or release as normal.
|
|
||||||
|
m_buttonState.set(index, state);
|
||||||
EMouseButtonState state = press ? kMouseButtonDown : kMouseButtonUp;
|
CGEventPost(kCGHIDEventTap, event);
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1 "faking mouse button id: %d press: %s", id, press ? "pressed" : "released"));
|
CFRelease(event);
|
||||||
|
|
||||||
MouseButtonEventMapType thisButtonMap = MouseButtonEventMap[index];
|
|
||||||
CGEventType type = thisButtonMap[state];
|
|
||||||
|
|
||||||
CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, index);
|
|
||||||
|
|
||||||
m_buttonState.set(index, state);
|
|
||||||
CGEventPost(kCGHIDEventTap, event);
|
|
||||||
|
|
||||||
CFRelease(event);
|
|
||||||
|
|
||||||
m_lastSingleClick = ARCH->time();
|
|
||||||
m_lastSingleClickXCursor = m_xCursor;
|
|
||||||
m_lastSingleClickYCursor = m_yCursor;
|
|
||||||
}
|
|
||||||
if (!press && (id == kButtonLeft)) {
|
if (!press && (id == kButtonLeft)) {
|
||||||
if (m_fakeDraggingStarted) {
|
if (m_fakeDraggingStarted) {
|
||||||
m_getDropTargetThread = new Thread(new TMethodJob<OSXScreen>(
|
m_getDropTargetThread = new Thread(new TMethodJob<OSXScreen>(
|
||||||
|
|
|
@ -335,8 +335,8 @@ private:
|
||||||
CFRunLoopSourceRef m_eventTapRLSR;
|
CFRunLoopSourceRef m_eventTapRLSR;
|
||||||
|
|
||||||
// for double click coalescing.
|
// for double click coalescing.
|
||||||
double m_lastSingleClick;
|
double m_lastClickTime;
|
||||||
double m_lastDoubleClick;
|
int m_clickState;
|
||||||
SInt32 m_lastSingleClickXCursor;
|
SInt32 m_lastSingleClickXCursor;
|
||||||
SInt32 m_lastSingleClickYCursor;
|
SInt32 m_lastSingleClickYCursor;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue