From 14e292709d022b124f9e7398f75ab82e115584b6 Mon Sep 17 00:00:00 2001 From: John Galvin <96908304+Johnnyg63@users.noreply.github.com> Date: Thu, 24 Sep 2026 20:04:49 +0100 Subject: [PATCH] 311-various-macos-issues-mostly-to-do-with-mouse-inputs --- dev/src/api_macos.cpp | 71 ++++++++++------------------ dev/src/host_apple_macos.cpp | 14 ++++-- dev/src/host_apple_macos.h | 5 +- olcPixelGameEngine3.h | 90 ++++++++++++++++-------------------- 4 files changed, 78 insertions(+), 102 deletions(-) diff --git a/dev/src/api_macos.cpp b/dev/src/api_macos.cpp index cdad635b..a0e3ce75 100644 --- a/dev/src/api_macos.cpp +++ b/dev/src/api_macos.cpp @@ -147,6 +147,7 @@ static constexpr const char* kSetContentViewSel = "setContentVie static constexpr const char* kContentViewSel = "contentView"; static constexpr const char* kBoundsSel = "bounds"; static constexpr const char* kConvertRectToBackingSel = "convertRectToBacking:"; // Thank you - Ben the Ultimate Guru +static constexpr const char* kConvertRectFromBackingSel = "convertRectFromBacking:"; // Thank you - Mr B the Ultimate Teacher!!! static constexpr const char* kConvertPointToBackingSel = "convertPointToBacking:"; static constexpr const char* kConvertPointFromBackingSel = "convertPointFromBacking:"; static constexpr const char* kConvertPointFromViewSel = "convertPoint:fromView:"; @@ -330,6 +331,7 @@ namespace ObjectiveCSEL { static SEL contentViewSel = nullptr; static SEL boundsSel = nullptr; static SEL convertRectToBackingSel = nullptr; // Thank you - Ben the Ultimate Guru + static SEL convertRectFromBackingSel = nullptr; // Thank you - Mr B the Ultimate Teacher!!! static SEL convertPointToBackingSel = nullptr; static SEL convertPointFromBackingSel = nullptr; static SEL convertPointFromViewSel = nullptr; @@ -479,6 +481,7 @@ namespace ObjectiveCSEL { contentViewSel = sel_registerName(kContentViewSel); boundsSel = sel_registerName(kBoundsSel); convertRectToBackingSel = sel_registerName(kConvertRectToBackingSel); // Thank you - Ben the Ultimate Guru + convertRectFromBackingSel = sel_registerName(kConvertRectFromBackingSel); // Thank you - Mr B the Ultimate Teacher!!! convertPointToBackingSel = sel_registerName(kConvertPointToBackingSel); convertPointFromBackingSel = sel_registerName(kConvertPointFromBackingSel); convertPointFromViewSel = sel_registerName(kConvertPointFromViewSel); @@ -1365,8 +1368,8 @@ void view_mouseDown(id self, SEL _cmd, id event) { CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? - if (nPointerEventType == 0) [[likely]] { + // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? Thanks Mr B + if (nPointerEventType != kCGEventMouseSubtypeTabletPoint && nPointerEventType != kCGEventMouseSubtypeTabletProximity) [[likely]] { if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->mouseDownCallback) [[likely]] { MouseEventData data = extractMouseEventData(event); @@ -1397,8 +1400,8 @@ void view_mouseUp(id self, SEL _cmd, id event) { CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? - if (nPointerEventType == 0) [[likely]] { + // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? Thanks Mr B + if (nPointerEventType != kCGEventMouseSubtypeTabletPoint && nPointerEventType != kCGEventMouseSubtypeTabletProximity) [[likely]] { MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->mouseUpCallback) [[likely]] { @@ -1429,8 +1432,8 @@ void view_mouseDragged(id self, SEL _cmd, id event) { CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? - if (nPointerEventType == 0) [[likely]] { + // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? Thanks Mr B + if (nPointerEventType != kCGEventMouseSubtypeTabletPoint && nPointerEventType != kCGEventMouseSubtypeTabletProximity) [[likely]] { if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->mouseDraggedCallback) [[likely]] { MouseEventData data = extractMouseEventData(event); @@ -1456,12 +1459,7 @@ void view_mouseDragged(id self, SEL _cmd, id event) { // Handle mouse movement events void view_mouseMoved(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - // if it is a trackpad event, ignore it. - if (nPointerEventType > 2) return; - + // a Mouse move event and Stlus roximity Event have the same properties. NSPoint location = ((NSPoint(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::locationInWindowSel); NSUInteger modifierFlags = ((NSUInteger(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::modifierFlagsSel); @@ -1476,12 +1474,7 @@ void view_mouseMoved(id self, SEL _cmd, id event) { // Handle right mouse down events void view_rightMouseDown(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events - + MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->rightMouseDownCallback) [[likely]] { gptrNSWindowEvents->rightMouseDownCallback(data.location.x, data.location.y, (int)data.buttonNumber, (unsigned int)data.modifierFlags, gptrNSWindowEvents->eventUserData); @@ -1492,11 +1485,6 @@ void view_rightMouseDown(id self, SEL _cmd, id event) { void view_rightMouseUp(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events - MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->rightMouseUpCallback) [[likely]] { gptrNSWindowEvents->rightMouseUpCallback(data.location.x, data.location.y, (int)data.buttonNumber, (unsigned int)data.modifierFlags, gptrNSWindowEvents->eventUserData); @@ -1506,11 +1494,6 @@ void view_rightMouseUp(id self, SEL _cmd, id event) { // Handle right mouse drag events void view_rightMouseDragged(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->rightMouseDraggedCallback) [[likely]] { @@ -1523,11 +1506,6 @@ void view_rightMouseDragged(id self, SEL _cmd, id event) { void view_otherMouseDown(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events - MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->otherMouseDownCallback) [[likely]] { gptrNSWindowEvents->otherMouseDownCallback(data.location.x, data.location.y, (int)data.buttonNumber, (unsigned int)data.modifierFlags, gptrNSWindowEvents->eventUserData); @@ -1538,11 +1516,6 @@ void view_otherMouseDown(id self, SEL _cmd, id event) { void view_otherMouseUp(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events - MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->otherMouseUpCallback) { gptrNSWindowEvents->otherMouseUpCallback(data.location.x, data.location.y, (int)data.buttonNumber, (unsigned int)data.modifierFlags, gptrNSWindowEvents->eventUserData); @@ -1551,11 +1524,6 @@ void view_otherMouseUp(id self, SEL _cmd, id event) { void view_otherMouseDragged(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->otherMouseDraggedCallback) [[likely]] { @@ -2100,7 +2068,17 @@ extern "C" { // Destroy the window void window_destroy(Window* self) { - (void)self; + + // Thanks Mr B! + if (self) { + self->acceptsInputEvents = NO; + if (gptrNSWindowEvents == self) { + gptrNSWindowEvents = NULL; + } + if (gptrWindowDelegate == self) { + gptrWindowDelegate = NULL; + } + } // NSWindow will be cleaned up by autorelease pool } @@ -2411,8 +2389,9 @@ extern "C" { // Make context current ((void(*)(id, SEL))objc_msgSend)(self->glContext, ObjectiveCSEL::makeCurrentContextSel); - // Update the view frame - NSRect newFrame = {0.0, 0.0, width, height}; + // Update the view frame Without folks like Mr B the Ultimate Teacher, this would have been tricky + NSRect pixelFrame = {0.0, 0.0, width, height}; + NSRect newFrame = ((NSRect(*)(id, SEL, NSRect))objc_msgSend)(self->glView, ObjectiveCSEL::convertRectFromBackingSel, pixelFrame); ((void(*)(id, SEL, NSRect))objc_msgSend)(self->glView, ObjectiveCSEL::setFrameSel, newFrame); // Force context to reshape diff --git a/dev/src/host_apple_macos.cpp b/dev/src/host_apple_macos.cpp index b4759995..a79b86af 100644 --- a/dev/src/host_apple_macos.cpp +++ b/dev/src/host_apple_macos.cpp @@ -212,16 +212,15 @@ namespace olc::host { bool Host_Apple_MacOS::SetMousePosition(olc::Window* pWindow, const olc::vi2d& vPos) { olc_IgnoreUnused(pWindow); - dispatch_sync(dispatch_get_main_queue(), ^{ - pMacOSWindow->setCursorPosition(vPos.x, vPos.y); - }); + vPositionMouse = vPos; + this->vPendingMainThreadTasks.push_back(SET_MOUSE_POSITION); return false; } bool Host_Apple_MacOS::SetMouseVisible(olc::Window* pWindow, const bool bVisible) { olc_IgnoreUnused(pWindow); - dispatch_sync(dispatch_get_main_queue(), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ pMacOSWindow->setCursorVisibility(bVisible); }); return true; @@ -555,6 +554,13 @@ namespace olc::host { pPGEwindow->olc_OnFocus(false); break; } + case SET_MOUSE_POSITION: + { + // Set mouse position on main thread + pMacOSWindow->setCursorPosition(vPositionMouse.x, vPositionMouse.y); + res = false; // No need to skip frame + break; + } case NONE: default: { diff --git a/dev/src/host_apple_macos.h b/dev/src/host_apple_macos.h index 303ffd10..3d510bf2 100644 --- a/dev/src/host_apple_macos.h +++ b/dev/src/host_apple_macos.h @@ -109,7 +109,8 @@ namespace olc BECOME_ACTIVE, RESIGN_ACTIVE, MINIMIZE_WINDOW, - DEMINIMIZE_WINDOW + DEMINIMIZE_WINDOW, + SET_MOUSE_POSITION }; // Internal Mac OS functions @@ -149,6 +150,8 @@ namespace olc void KeyboardEventHandler(const olc::apis::macos::KeyEvent& event, bool isPressed); bool bNumLockActive = true; // Num Lock state, we assume it's active at start uint16_t ConvertPGE2WindowStyle(); + + olc::vi2d vPositionMouse = {0, 0}; // Stores the desired mouse position for SET_MOUSE_POSITION task }; diff --git a/olcPixelGameEngine3.h b/olcPixelGameEngine3.h index a5edfe02..3725ed03 100644 --- a/olcPixelGameEngine3.h +++ b/olcPixelGameEngine3.h @@ -6016,7 +6016,8 @@ namespace olc BECOME_ACTIVE, RESIGN_ACTIVE, MINIMIZE_WINDOW, - DEMINIMIZE_WINDOW + DEMINIMIZE_WINDOW, + SET_MOUSE_POSITION }; // Internal Mac OS functions @@ -6056,6 +6057,8 @@ namespace olc void KeyboardEventHandler(const olc::apis::macos::KeyEvent& event, bool isPressed); bool bNumLockActive = true; // Num Lock state, we assume it's active at start uint16_t ConvertPGE2WindowStyle(); + + olc::vi2d vPositionMouse = {0, 0}; // Stores the desired mouse position for SET_MOUSE_POSITION task }; @@ -7746,6 +7749,7 @@ static constexpr const char* kSetContentViewSel = "setContentVie static constexpr const char* kContentViewSel = "contentView"; static constexpr const char* kBoundsSel = "bounds"; static constexpr const char* kConvertRectToBackingSel = "convertRectToBacking:"; // Thank you - Ben the Ultimate Guru +static constexpr const char* kConvertRectFromBackingSel = "convertRectFromBacking:"; // Thank you - Mr B the Ultimate Teacher!!! static constexpr const char* kConvertPointToBackingSel = "convertPointToBacking:"; static constexpr const char* kConvertPointFromBackingSel = "convertPointFromBacking:"; static constexpr const char* kConvertPointFromViewSel = "convertPoint:fromView:"; @@ -7929,6 +7933,7 @@ namespace ObjectiveCSEL { static SEL contentViewSel = nullptr; static SEL boundsSel = nullptr; static SEL convertRectToBackingSel = nullptr; // Thank you - Ben the Ultimate Guru + static SEL convertRectFromBackingSel = nullptr; // Thank you - Mr B the Ultimate Teacher!!! static SEL convertPointToBackingSel = nullptr; static SEL convertPointFromBackingSel = nullptr; static SEL convertPointFromViewSel = nullptr; @@ -8078,6 +8083,7 @@ namespace ObjectiveCSEL { contentViewSel = sel_registerName(kContentViewSel); boundsSel = sel_registerName(kBoundsSel); convertRectToBackingSel = sel_registerName(kConvertRectToBackingSel); // Thank you - Ben the Ultimate Guru + convertRectFromBackingSel = sel_registerName(kConvertRectFromBackingSel); // Thank you - Mr B the Ultimate Teacher!!! convertPointToBackingSel = sel_registerName(kConvertPointToBackingSel); convertPointFromBackingSel = sel_registerName(kConvertPointFromBackingSel); convertPointFromViewSel = sel_registerName(kConvertPointFromViewSel); @@ -8964,8 +8970,8 @@ void view_mouseDown(id self, SEL _cmd, id event) { CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? - if (nPointerEventType == 0) [[likely]] { + // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? Thanks Mr B + if (nPointerEventType != kCGEventMouseSubtypeTabletPoint && nPointerEventType != kCGEventMouseSubtypeTabletProximity) [[likely]] { if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->mouseDownCallback) [[likely]] { MouseEventData data = extractMouseEventData(event); @@ -8996,8 +9002,8 @@ void view_mouseUp(id self, SEL _cmd, id event) { CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? - if (nPointerEventType == 0) [[likely]] { + // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? Thanks Mr B + if (nPointerEventType != kCGEventMouseSubtypeTabletPoint && nPointerEventType != kCGEventMouseSubtypeTabletProximity) [[likely]] { MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->mouseUpCallback) [[likely]] { @@ -9028,8 +9034,8 @@ void view_mouseDragged(id self, SEL _cmd, id event) { CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? - if (nPointerEventType == 0) [[likely]] { + // Is it a mouse drag event (subtype 0) or a tablet pointer event (subtype 1 or 2)? Thanks Mr B + if (nPointerEventType != kCGEventMouseSubtypeTabletPoint && nPointerEventType != kCGEventMouseSubtypeTabletProximity) [[likely]] { if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->mouseDraggedCallback) [[likely]] { MouseEventData data = extractMouseEventData(event); @@ -9055,12 +9061,7 @@ void view_mouseDragged(id self, SEL _cmd, id event) { // Handle mouse movement events void view_mouseMoved(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - // if it is a trackpad event, ignore it. - if (nPointerEventType > 2) return; - + // a Mouse move event and Stlus roximity Event have the same properties. NSPoint location = ((NSPoint(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::locationInWindowSel); NSUInteger modifierFlags = ((NSUInteger(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::modifierFlagsSel); @@ -9075,12 +9076,7 @@ void view_mouseMoved(id self, SEL _cmd, id event) { // Handle right mouse down events void view_rightMouseDown(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events - + MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->rightMouseDownCallback) [[likely]] { gptrNSWindowEvents->rightMouseDownCallback(data.location.x, data.location.y, (int)data.buttonNumber, (unsigned int)data.modifierFlags, gptrNSWindowEvents->eventUserData); @@ -9091,11 +9087,6 @@ void view_rightMouseDown(id self, SEL _cmd, id event) { void view_rightMouseUp(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events - MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->rightMouseUpCallback) [[likely]] { gptrNSWindowEvents->rightMouseUpCallback(data.location.x, data.location.y, (int)data.buttonNumber, (unsigned int)data.modifierFlags, gptrNSWindowEvents->eventUserData); @@ -9105,11 +9096,6 @@ void view_rightMouseUp(id self, SEL _cmd, id event) { // Handle right mouse drag events void view_rightMouseDragged(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->rightMouseDraggedCallback) [[likely]] { @@ -9122,11 +9108,6 @@ void view_rightMouseDragged(id self, SEL _cmd, id event) { void view_otherMouseDown(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events - MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->otherMouseDownCallback) [[likely]] { gptrNSWindowEvents->otherMouseDownCallback(data.location.x, data.location.y, (int)data.buttonNumber, (unsigned int)data.modifierFlags, gptrNSWindowEvents->eventUserData); @@ -9137,11 +9118,6 @@ void view_otherMouseDown(id self, SEL _cmd, id event) { void view_otherMouseUp(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events - MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->otherMouseUpCallback) { gptrNSWindowEvents->otherMouseUpCallback(data.location.x, data.location.y, (int)data.buttonNumber, (unsigned int)data.modifierFlags, gptrNSWindowEvents->eventUserData); @@ -9150,11 +9126,6 @@ void view_otherMouseUp(id self, SEL _cmd, id event) { void view_otherMouseDragged(id self, SEL _cmd, id event) { (void)self;(void)_cmd; - - CGEventRef cgEvent = ((CGEventRef(*)(id, SEL))objc_msgSend)(event, ObjectiveCSEL::cgEventSel); - uint8_t nPointerEventType = CGEventGetIntegerValueField(cgEvent, kCGMouseEventSubtype); - if(nPointerEventType > 2) [[unlikely]] - return; // Ignore mouse events that are not mouse drag or tablet pointer events MouseEventData data = extractMouseEventData(event); if (gptrNSWindowEvents && gptrNSWindowEvents->acceptsInputEvents && gptrNSWindowEvents->otherMouseDraggedCallback) [[likely]] { @@ -9699,7 +9670,17 @@ extern "C" { // Destroy the window void window_destroy(Window* self) { - (void)self; + + // Thanks Mr B! + if (self) { + self->acceptsInputEvents = NO; + if (gptrNSWindowEvents == self) { + gptrNSWindowEvents = NULL; + } + if (gptrWindowDelegate == self) { + gptrWindowDelegate = NULL; + } + } // NSWindow will be cleaned up by autorelease pool } @@ -10010,8 +9991,9 @@ extern "C" { // Make context current ((void(*)(id, SEL))objc_msgSend)(self->glContext, ObjectiveCSEL::makeCurrentContextSel); - // Update the view frame - NSRect newFrame = {0.0, 0.0, width, height}; + // Update the view frame Without folks like Mr B the Ultimate Teacher, this would have been tricky + NSRect pixelFrame = {0.0, 0.0, width, height}; + NSRect newFrame = ((NSRect(*)(id, SEL, NSRect))objc_msgSend)(self->glView, ObjectiveCSEL::convertRectFromBackingSel, pixelFrame); ((void(*)(id, SEL, NSRect))objc_msgSend)(self->glView, ObjectiveCSEL::setFrameSel, newFrame); // Force context to reshape @@ -11742,16 +11724,15 @@ namespace olc::host { bool Host_Apple_MacOS::SetMousePosition(olc::Window* pWindow, const olc::vi2d& vPos) { olc_IgnoreUnused(pWindow); - dispatch_sync(dispatch_get_main_queue(), ^{ - pMacOSWindow->setCursorPosition(vPos.x, vPos.y); - }); + vPositionMouse = vPos; + this->vPendingMainThreadTasks.push_back(SET_MOUSE_POSITION); return false; } bool Host_Apple_MacOS::SetMouseVisible(olc::Window* pWindow, const bool bVisible) { olc_IgnoreUnused(pWindow); - dispatch_sync(dispatch_get_main_queue(), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ pMacOSWindow->setCursorVisibility(bVisible); }); return true; @@ -12085,6 +12066,13 @@ namespace olc::host { pPGEwindow->olc_OnFocus(false); break; } + case SET_MOUSE_POSITION: + { + // Set mouse position on main thread + pMacOSWindow->setCursorPosition(vPositionMouse.x, vPositionMouse.y); + res = false; // No need to skip frame + break; + } case NONE: default: {