11 #include <AppKit/AppKit.h>
12 #include <AvailabilityMacros.h>
14 #ifndef MAC_OS_X_VERSION_10_10_3
24 @property (readonly) NSInteger
stage;
57 __block NSSize displayPixelSize;
58 dispatch_sync(dispatch_get_main_queue(), ^{
59 NSDictionary *description = [[NSScreen mainScreen] deviceDescription];
60 displayPixelSize = [description[NSDeviceSize] sizeValue];
63 *width = (int)displayPixelSize.width;
64 *height = (
int)displayPixelSize.height;
72 return event.pressure +
MAX(0., event.stage - 1.);
117 NSRect rectInWindow = NSMakeRect(pointInWindow.x, pointInWindow.y, 0, 0);
118 NSPoint pointInScreen =
window ? [window convertRectToScreen:rectInWindow].origin : pointInWindow;
121 NSInteger windowNumberForPoint = [NSWindow windowNumberAtPoint:pointInScreen belowWindowWithWindowNumber:0];
122 for (NSWindow *w in [NSApp windows])
124 NSRect windowRectInScreen = [w convertRectToScreen:[[w contentView] frame]];
133 ++windowRectInScreen.size.width;
134 ++windowRectInScreen.size.height;
136 if ([w windowNumber] == windowNumberForPoint
138 && NSPointInRect(pointInScreen, windowRectInScreen))
145 pointInScreen.y = [[NSScreen mainScreen] frame].size.height - pointInScreen.y;
157 __block NSRect bounds;
160 bounds = [view convertRectFromBacking:((VuoGraphicsView *)view).viewport];
167 NSPoint windowOrigin = [w frameRectForContentRect:w.frame].origin;
168 NSPoint screenOrigin = w.screen.frame.origin;
169 bounds.origin.x += windowOrigin.x - screenOrigin.x;
170 bounds.origin.y += windowOrigin.y - screenOrigin.y;
173 VuoPoint2d pointInVuo;
174 double viewMaxX = NSWidth(bounds) - 1;
175 double viewMaxY = NSHeight(bounds) - 1;
176 pointInVuo.x = ((pointInView.x - NSMinX(bounds) - viewMaxX /2.) * 2.) / viewMaxX;
177 pointInVuo.y = ((pointInView.y - NSMinY(bounds) - viewMaxY/2.) * 2.) / viewMaxX;
178 pointInVuo.y /= (NSWidth(bounds)/viewMaxX) * (viewMaxY/NSHeight(bounds));
187 NSRect fullScreenFrame = [[window screen] frame];
193 pointInScreen.x =
VuoReal_snap(pointInScreen.x * fullScreenFrame.size.width / (fullScreenFrame.size.width+1), 0, 1);
194 pointInScreen.y =
VuoReal_snap(pointInScreen.y * fullScreenFrame.size.height / (fullScreenFrame.size.height+1), 0, 1);
196 NSView *view = [window contentView];
197 NSPoint pointInView = NSMakePoint(pointInScreen.x - fullScreenFrame.origin.x,
198 pointInScreen.y - fullScreenFrame.origin.y);
199 *isInScreen = NSPointInRect(pointInScreen, fullScreenFrame);
222 __block NSView *view;
223 __block NSPoint pointInView;
224 __block NSRect frame;
226 view =
window.contentView;
227 pointInView = [view convertPoint:pointInWindow fromView:nil];
230 *shouldFire = NSPointInRect(pointInView, frame);
239 NSView *view = [window contentView];
240 NSRect bounds = [view bounds];
241 VuoPoint2d deltaInVuo;
242 deltaInVuo.x = (delta.x * 2.) / bounds.size.width;
243 deltaInVuo.y = -(delta.y * 2.) / bounds.size.width;
260 return !NSEqualPoints([[NSCursor currentCursor] hotSpot], [[NSCursor currentSystemCursor] hotSpot]);
272 if (fabs(delta.x) < 0.00001 && fabs(delta.y) < 0.00001)
275 bool shouldFire =
false;
276 NSWindow *targetWindow = (NSWindow *)windowRef;
279 if (targetWindow == [event
window])
302 bool shouldFire =
false;
303 VuoPoint2d convertedPoint;
304 NSPoint pointInWindowOrScreen = [event locationInWindow];
305 NSWindow *targetWindow = (NSWindow *)windowRef;
308 __block
bool isKeyWindow;
310 isKeyWindow = targetWindow.isKeyWindow;
317 pointInWindowOrScreen = fullscreenPoint;
320 else if (targetWindow == [event
window])
322 else if ((! [event
window] && isKeyWindow) || fireRegardlessOfWindow)
326 NSRect rectInWindowOrScreen = NSMakeRect(pointInWindowOrScreen.x, pointInWindowOrScreen.y, 0, 0);
327 __block NSPoint pointInWindow;
329 pointInWindow = [targetWindow convertRectFromScreen:rectInWindowOrScreen].origin;
338 if (!fireRegardlessOfPosition)
344 if (shouldFire || fireRegardlessOfPosition)
345 fire(convertedPoint);
361 bool shouldFire =
false;
362 VuoPoint2d convertedDelta;
363 NSPoint deltaInScreen = NSMakePoint([event deltaX], [event deltaY]);
364 if (fabs(deltaInScreen.x) < 0.0001
365 && fabs(deltaInScreen.y) < 0.0001)
368 NSWindow *targetWindow = (NSWindow *)windowRef;
376 NSPoint pointInWindowOrScreen = [NSEvent mouseLocation];
380 else if (targetWindow == [event
window] || (! [event
window] && [targetWindow isKeyWindow]))
395 fire(convertedDelta);
407 void (*singleClicked)(VuoPoint2d),
void (*doubleClicked)(VuoPoint2d),
void (*tripleClicked)(VuoPoint2d))
412 NSInteger clickCount = [event clickCount];
413 NSPoint fullscreenPoint = [NSEvent mouseLocation];
414 NSTimeInterval clickIntervalInSeconds = [NSEvent doubleClickInterval];
415 dispatch_time_t clickInterval = dispatch_time(DISPATCH_TIME_NOW, clickIntervalInSeconds * NSEC_PER_SEC);
418 void (*fired)(VuoPoint2d) = NULL;
420 fired = singleClicked;
421 else if (clickCount == 2)
422 fired = doubleClicked;
423 else if (clickCount >= 3)
424 fired = tripleClicked;
429 dispatch_after(clickInterval, context->
clickQueue, ^{
430 if (context->pendingClickCount == clickCount)
432 VuoMouse_fireMousePositionIfNeeded(event, fullscreenPoint, windowRef, modifierKey, false, false, ^(VuoPoint2d point){ fired(point); });
433 context->pendingClickCount = 0;
447 id monitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel handler:^(NSEvent *event) {
448 VuoMouse_fireScrollDeltaIfNeeded(event, window, modifierKey, ^(VuoPoint2d point){ scrolled(point); });
463 id monitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel handler:^(NSEvent *event) {
464 VuoMouse_fireScrollDeltaIfNeeded(event, window, modifierKey, scrolled);
477 if (
window && (modifierKey == VuoModifierKey_Any || modifierKey == VuoModifierKey_None))
499 id monitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskMouseMoved|NSEventMaskLeftMouseDragged|NSEventMaskRightMouseDragged|NSEventMaskOtherMouseDragged handler:^(NSEvent *event) {
500 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, modifierKey, true, false, ^(VuoPoint2d point){ movedTo(point); });
508 context->
globalMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskMouseMoved|NSEventMaskLeftMouseDragged|NSEventMaskRightMouseDragged|NSEventMaskOtherMouseDragged handler:^(NSEvent *event) {
509 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, modifierKey, true, true, ^(VuoPoint2d point){ movedTo(point); });
525 id monitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskMouseMoved|NSEventMaskLeftMouseDragged|NSEventMaskRightMouseDragged|NSEventMaskOtherMouseDragged handler:^(NSEvent *event) {
526 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, modifierKey, true, false, movedTo);
543 id monitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskMouseMoved|NSEventMaskLeftMouseDragged|NSEventMaskRightMouseDragged|NSEventMaskOtherMouseDragged handler:^(NSEvent *event) {
544 VuoMouse_fireMouseDeltaIfNeeded(event, window, modifierKey, movedBy);
562 NSEventMask eventMask = 0;
565 case VuoMouseButton_Left:
566 eventMask = NSEventMaskLeftMouseDragged;
568 case VuoMouseButton_Middle:
569 eventMask = NSEventMaskOtherMouseDragged;
571 case VuoMouseButton_Right:
572 eventMask = NSEventMaskRightMouseDragged;
575 context->
monitor2 = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDragged handler:^(NSEvent *event) {
576 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, VuoModifierKey_Control, fireRegardlessOfPosition, false, dragMovedTo);
581 case VuoMouseButton_Any:
582 eventMask = NSEventMaskLeftMouseDragged | NSEventMaskOtherMouseDragged | NSEventMaskRightMouseDragged;
586 context->
monitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent *event) {
587 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, modifierKey, fireRegardlessOfPosition, false, dragMovedTo);
614 NSEventMask eventMask = 0;
617 case VuoMouseButton_Left:
618 eventMask = NSEventMaskLeftMouseDown;
620 case VuoMouseButton_Middle:
621 eventMask = NSEventMaskOtherMouseDown;
623 case VuoMouseButton_Right:
624 eventMask = NSEventMaskRightMouseDown;
627 context->
monitor2 = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown handler:^(NSEvent *event) {
628 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, VuoModifierKey_Control, false, false, pressed);
633 case VuoMouseButton_Any:
634 eventMask = NSEventMaskLeftMouseDown | NSEventMaskOtherMouseDown | NSEventMaskRightMouseDown;
640 context->
monitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent *event) {
641 if (event.type == NSEventTypePressure)
643 if (context->priorPressureStage == 1 && event.stage == 2 && forcePressed)
644 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, modifierKey, false, false, forcePressed);
645 context->priorPressureStage = event.stage;
648 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, modifierKey, false, false, pressed);
664 ^(VuoPoint2d point){ pressed(point); },
665 ^(VuoPoint2d point){ forcePressed(point); },
666 button,
window, modifierKey);
679 context->
monitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskPressure handler:^(NSEvent *event) {
680 if (VuoModifierKey_doMacEventFlagsMatch(CGEventGetFlags([event CGEvent]), modifierKey)
681 && (button == VuoMouseButton_Any
682 || (button == VuoMouseButton_Left && NSEvent.pressedMouseButtons & 1)
683 || (button == VuoMouseButton_Right && NSEvent.pressedMouseButtons & 2)
684 || (button == VuoMouseButton_Middle && NSEvent.pressedMouseButtons & 4)))
685 pressureChanged(VuoMouse_getPressure(event));
700 NSEventMask eventMask = 0;
703 case VuoMouseButton_Left:
704 eventMask = NSEventMaskLeftMouseUp;
706 case VuoMouseButton_Middle:
707 eventMask = NSEventMaskOtherMouseUp;
709 case VuoMouseButton_Right:
710 eventMask = NSEventMaskRightMouseUp;
713 context->
monitor2 = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseUp handler:^(NSEvent *event) {
714 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, VuoModifierKey_Control, fireRegardlessOfPosition, false, released);
719 case VuoMouseButton_Any:
720 eventMask = NSEventMaskLeftMouseUp | NSEventMaskOtherMouseUp | NSEventMaskRightMouseUp;
724 context->
monitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent *event) {
725 VuoMouse_fireMousePositionIfNeeded(event, [NSEvent mouseLocation], window, modifierKey, fireRegardlessOfPosition, false, released);
749 context->
clickQueue = dispatch_queue_create(
"vuo.mouse.click", 0);
750 context->
clickGroup = dispatch_group_create();
753 NSEventMask eventMask = 0;
756 case VuoMouseButton_Left:
757 eventMask = NSEventMaskLeftMouseUp;
759 case VuoMouseButton_Middle:
760 eventMask = NSEventMaskOtherMouseUp;
762 case VuoMouseButton_Right:
763 eventMask = NSEventMaskRightMouseUp;
766 context->
monitor2 = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseUp handler:^(NSEvent *event) {
767 VuoMouse_fireMouseClickIfNeeded(context, event, window, VuoModifierKey_Control, singleClicked, doubleClicked, tripleClicked);
772 case VuoMouseButton_Any:
773 eventMask = NSEventMaskLeftMouseUp | NSEventMaskOtherMouseUp | NSEventMaskRightMouseUp;
777 context->
monitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent *event) {
778 VuoMouse_fireMouseClickIfNeeded(context, event, window, modifierKey, singleClicked, doubleClicked, tripleClicked);
802 context->
window = windowRef;
822 [NSEvent removeMonitor:context->monitor];
827 [NSEvent removeMonitor:context->monitor2];
833 [NSEvent removeMonitor:context->globalMonitor];
841 dispatch_group_wait(context->
clickGroup, DISPATCH_TIME_FOREVER);
852 [view removeTouchesMovedTrigger:context->touchesMoved zoomed:context->zoomed swipedLeft:context->swipedLeft swipedRight:context->swipedRight];
890 NSEventMaskMouseMoved
891 |NSEventMaskLeftMouseDragged|NSEventMaskRightMouseDragged|NSEventMaskOtherMouseDragged
892 |NSEventMaskLeftMouseDown|NSEventMaskOtherMouseDown|NSEventMaskRightMouseDown
893 |NSEventMaskLeftMouseUp|NSEventMaskOtherMouseUp|NSEventMaskRightMouseUp
894 handler:^(NSEvent *event) {
896 NSPoint p = [event locationInWindow];
897 NSWindow *window = [event window];
900 NSRect rectInWindow = NSMakeRect(p.x, p.y, 0, 0);
901 VuoMouseStatus_position = [window convertRectToScreen:rectInWindow].origin;
904 VuoMouseStatus_position = p;
906 switch ([event type])
908 case NSEventTypeLeftMouseDown: if (!VuoMouse_isResizing()) VuoMouseStatus_leftButton = true; break;
909 case NSEventTypeLeftMouseUp: VuoMouseStatus_leftButton = false; break;
910 case NSEventTypeOtherMouseDown: if (!VuoMouse_isResizing()) VuoMouseStatus_middleButton = true; break;
911 case NSEventTypeOtherMouseUp: VuoMouseStatus_middleButton = false; break;
912 case NSEventTypeRightMouseDown: if (!VuoMouse_isResizing()) VuoMouseStatus_rightButton = true; break;
913 case NSEventTypeRightMouseUp: VuoMouseStatus_rightButton = false; break;
931 [NSEvent removeMonitor:VuoMouseStatus_monitor];
953 bool onlyUpdateWhenActive)
955 if (onlyUpdateWhenActive)
957 __block
bool isActive;
959 isActive = [NSApp isActive];
965 bool shouldTrackPresses;
975 NSRect rectInScreen = NSMakeRect(pointInScreen.x, pointInScreen.y, 0, 0);
976 __block NSPoint pointInWindow;
977 __block
bool isKeyWindow;
979 pointInWindow = [targetWindow convertRectFromScreen:rectInScreen].origin;
980 isKeyWindow = targetWindow.isKeyWindow;
983 shouldTrackPresses = shouldTrackPresses && isKeyWindow;
989 pointInScreen.y = CGDisplayPixelsHigh(CGMainDisplayID()) - pointInScreen.y;
992 shouldTrackPresses =
true;
995 if ( !shouldTrackPresses)
1010 case VuoMouseButton_Left:
1013 case VuoMouseButton_Right:
1024 case VuoMouseButton_Middle:
1027 case VuoMouseButton_Any: