summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJørgen P. Tjernø <jorgen@valvesoftware.com>2013-08-07 16:29:15 -0700
committerJørgen P. Tjernø <jorgen@valvesoftware.com>2013-08-07 16:29:15 -0700
commit3c31b3003ba5b5c46bdfb9c448e69cc02f95ab54 (patch)
tree62a7b9472a809ae301abc161f7a07b8ae7bcf9bd
parentcef724151d841c864ed645394b08d5d026facd85 (diff)
Mac: Better mouse-grab if you define SDL_MAC_NO_SANDBOX.
This uses a better mouse grab if you define SDL_MAC_NO_SANDBOX. This mouse grab uses CGEventTapCreate, which you cannot access if you have sandboxing enabled.
-rwxr-xr-xXcode/SDL/SDL.xcodeproj/project.pbxproj19
-rw-r--r--src/video/cocoa/SDL_cocoamouse.h1
-rw-r--r--src/video/cocoa/SDL_cocoamouse.m9
-rw-r--r--src/video/cocoa/SDL_cocoamousetap.h33
-rw-r--r--src/video/cocoa/SDL_cocoamousetap.m252
-rw-r--r--src/video/cocoa/SDL_cocoawindow.m6
6 files changed, 320 insertions, 0 deletions
diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
index 2fccf0f7c2..fd91642c76 100755
--- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
@@ -516,6 +516,12 @@
AADA5B8716CCAB3000107CF7 /* SDL_bits.h in Headers */ = {isa = PBXBuildFile; fileRef = AADA5B8616CCAB3000107CF7 /* SDL_bits.h */; };
AADA5B8816CCAB3000107CF7 /* SDL_bits.h in Headers */ = {isa = PBXBuildFile; fileRef = AADA5B8616CCAB3000107CF7 /* SDL_bits.h */; };
BBFC088D164C6647003E6A99 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; };
+ D55A1B81179F262300625D7C /* SDL_cocoamousetap.h in Headers */ = {isa = PBXBuildFile; fileRef = D55A1B7F179F262300625D7C /* SDL_cocoamousetap.h */; };
+ D55A1B82179F262300625D7C /* SDL_cocoamousetap.m in Sources */ = {isa = PBXBuildFile; fileRef = D55A1B80179F262300625D7C /* SDL_cocoamousetap.m */; };
+ D55A1B83179F263500625D7C /* SDL_cocoamousetap.m in Sources */ = {isa = PBXBuildFile; fileRef = D55A1B80179F262300625D7C /* SDL_cocoamousetap.m */; };
+ D55A1B84179F263600625D7C /* SDL_cocoamousetap.m in Sources */ = {isa = PBXBuildFile; fileRef = D55A1B80179F262300625D7C /* SDL_cocoamousetap.m */; };
+ D55A1B85179F278E00625D7C /* SDL_cocoamousetap.h in Headers */ = {isa = PBXBuildFile; fileRef = D55A1B7F179F262300625D7C /* SDL_cocoamousetap.h */; };
+ D55A1B86179F278F00625D7C /* SDL_cocoamousetap.h in Headers */ = {isa = PBXBuildFile; fileRef = D55A1B7F179F262300625D7C /* SDL_cocoamousetap.h */; };
DB313F7417554B71006C0E22 /* SDL_diskaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD8912E6671700899322 /* SDL_diskaudio.h */; };
DB313F7517554B71006C0E22 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD9512E6671700899322 /* SDL_dummyaudio.h */; };
DB313F7617554B71006C0E22 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
@@ -1044,6 +1050,8 @@
BECDF66C0761BA81005FE872 /* SDL2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDL2.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BECDF6B30761BA81005FE872 /* libSDL2.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2.a; sourceTree = BUILT_PRODUCTS_DIR; };
BECDF6BE0761BA81005FE872 /* Standard DMG */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Standard DMG"; sourceTree = BUILT_PRODUCTS_DIR; };
+ D55A1B7F179F262300625D7C /* SDL_cocoamousetap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoamousetap.h; sourceTree = "<group>"; };
+ D55A1B80179F262300625D7C /* SDL_cocoamousetap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoamousetap.m; sourceTree = "<group>"; };
DB31407717554B71006C0E22 /* libSDL2.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libSDL2.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
F59C70FF00D5CB5801000001 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ReadMe.txt; sourceTree = "<group>"; };
F59C710000D5CB5801000001 /* Welcome.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Welcome.txt; sourceTree = "<group>"; };
@@ -1534,6 +1542,8 @@
04BDFEC912E6671800899322 /* SDL_cocoamodes.m */,
04BDFECA12E6671800899322 /* SDL_cocoamouse.h */,
04BDFECB12E6671800899322 /* SDL_cocoamouse.m */,
+ D55A1B7F179F262300625D7C /* SDL_cocoamousetap.h */,
+ D55A1B80179F262300625D7C /* SDL_cocoamousetap.m */,
04BDFECC12E6671800899322 /* SDL_cocoaopengl.h */,
04BDFECD12E6671800899322 /* SDL_cocoaopengl.m */,
04BDFECE12E6671800899322 /* SDL_cocoashape.h */,
@@ -1611,8 +1621,11 @@
BEC562FE0761C0E800A33029 /* Linked Frameworks */,
);
comments = "To build Universal Binaries, we have experimented with a variety of different options.\nThe complication is that we must retain compatibility with at least 10.2. \nThe Universal Binary defaults only work for > 10.3.9\n\nSo far, we have found:\ngcc 4.0.0 with Xcode 2.1 always links against libgcc_s. gcc 4.0.1 from Xcode 2.2 fixes this problem.\n\nBut gcc 4.0 will not work with < 10.3.9 because we continue to get an undefined symbol to _fprintf$LDBL128.\nSo we must use gcc 3.3 on PPC to accomplish 10.2 support. (But 4.0 is required for i386.)\n\nSetting the deployment target to 10.4 will disable prebinding, so for PPC, we set it less than 10.4 to preserve prebinding for legacy support.\n\nSetting the PPC SDKROOT to /Developers/SDKs/MacOSX10.2.8.sdk will link to 63.0.0 libSystem.B.dylib. Leaving it at current or 10.4u links to 88.1.2. However, as long as we are using gcc 3.3, it doesn't seem to matter as testing has demonstrated both will run. We have decided not to invoke the 10.2.8 SDK because it is not a default installed component with Xcode which will probably cause most people problems. However, rather than deleting the SDKROOT_ppc entry entirely, we have mapped it to 10.4u in case we decide we need to change this setting.\n\nTo use Altivec or SSE, we needed architecture specific flags:\nOTHER_CFLAGS_ppc\nOTHER_CFLAGS_i386\nOTHER_CFLAGS=$(OTHER_CFLAGS_($CURRENT_ARCH))\n\nThe general OTHER_CFLAGS needed to be manually mapped to architecture specific options because Xcode didn't do this automatically for us.\n\n\n";
+ indentWidth = 4;
name = SDLFramework;
sourceTree = "<group>";
+ tabWidth = 4;
+ usesTabs = 0;
};
089C1665FE841158C02AAC07 /* Resources */ = {
isa = PBXGroup;
@@ -1842,6 +1855,7 @@
AA628AD3159367F2005138DD /* SDL_x11xinput2.h in Headers */,
AABCC38D164063D200AB8930 /* SDL_cocoamessagebox.h in Headers */,
AADA5B8716CCAB3000107CF7 /* SDL_bits.h in Headers */,
+ D55A1B81179F262300625D7C /* SDL_cocoamousetap.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1985,6 +1999,7 @@
AABCC38E164063D200AB8930 /* SDL_cocoamessagebox.h in Headers */,
A77E6EB5167AB0A90010E40B /* SDL_gamecontroller.h in Headers */,
AADA5B8816CCAB3000107CF7 /* SDL_bits.h in Headers */,
+ D55A1B85179F278E00625D7C /* SDL_cocoamousetap.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2128,6 +2143,7 @@
DB313FFA17554B71006C0E22 /* SDL_cocoamessagebox.h in Headers */,
DB313FFB17554B71006C0E22 /* SDL_gamecontroller.h in Headers */,
DB313FFC17554B71006C0E22 /* SDL_bits.h in Headers */,
+ D55A1B86179F278F00625D7C /* SDL_cocoamousetap.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2410,6 +2426,7 @@
AABCC38F164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */,
AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */,
AA0F8491178D5ECC00823F9D /* SDL_systls.c in Sources */,
+ D55A1B82179F262300625D7C /* SDL_cocoamousetap.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2526,6 +2543,7 @@
AA9E4094163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */,
AABCC390164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */,
AA0F8492178D5ECC00823F9D /* SDL_systls.c in Sources */,
+ D55A1B84179F263600625D7C /* SDL_cocoamousetap.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2642,6 +2660,7 @@
DB31406917554B71006C0E22 /* SDL_x11messagebox.c in Sources */,
DB31406A17554B71006C0E22 /* SDL_cocoamessagebox.m in Sources */,
AA0F8493178D5ECC00823F9D /* SDL_systls.c in Sources */,
+ D55A1B83179F263500625D7C /* SDL_cocoamousetap.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/src/video/cocoa/SDL_cocoamouse.h b/src/video/cocoa/SDL_cocoamouse.h
index bff8ef6dd9..eb6f5891f8 100644
--- a/src/video/cocoa/SDL_cocoamouse.h
+++ b/src/video/cocoa/SDL_cocoamouse.h
@@ -33,6 +33,7 @@ extern void Cocoa_QuitMouse(_THIS);
typedef struct {
int deltaXOffset;
int deltaYOffset;
+ void *tapdata;
} SDL_MouseData;
@interface NSCursor (InvisibleCursor)
diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m
index 12e755cf91..faba9618e0 100644
--- a/src/video/cocoa/SDL_cocoamouse.m
+++ b/src/video/cocoa/SDL_cocoamouse.m
@@ -25,6 +25,7 @@
#include "SDL_assert.h"
#include "SDL_events.h"
#include "SDL_cocoamouse.h"
+#include "SDL_cocoamousetap.h"
#include "../../events/SDL_mouse_c.h"
@@ -94,6 +95,8 @@ Cocoa_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
cursor = SDL_calloc(1, sizeof(*cursor));
if (cursor) {
cursor->driverdata = nscursor;
+ } else {
+ [nscursor release];
}
}
@@ -266,6 +269,8 @@ Cocoa_InitMouse(_THIS)
mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
+
+ Cocoa_InitMouseEventTap(mouse->driverdata);
}
void
@@ -313,6 +318,10 @@ Cocoa_QuitMouse(_THIS)
{
SDL_Mouse *mouse = SDL_GetMouse();
if (mouse) {
+ if (mouse->driverdata) {
+ Cocoa_QuitMouseEventTap(((SDL_MouseData*)mouse->driverdata));
+ }
+
SDL_free(mouse->driverdata);
}
}
diff --git a/src/video/cocoa/SDL_cocoamousetap.h b/src/video/cocoa/SDL_cocoamousetap.h
new file mode 100644
index 0000000000..a13d97bb55
--- /dev/null
+++ b/src/video/cocoa/SDL_cocoamousetap.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#ifndef _SDL_cocoamousetap_h
+#define _SDL_cocoamousetap_h
+
+#include "SDL_cocoamouse.h"
+
+extern void Cocoa_InitMouseEventTap(SDL_MouseData *driverdata);
+extern void Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata);
+
+#endif /* _SDL_cocoamousetap_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/cocoa/SDL_cocoamousetap.m b/src/video/cocoa/SDL_cocoamousetap.m
new file mode 100644
index 0000000000..01769b321b
--- /dev/null
+++ b/src/video/cocoa/SDL_cocoamousetap.m
@@ -0,0 +1,252 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#define SDL_MAC_NO_SANDBOX 1
+
+#include "SDL_cocoamousetap.h"
+
+/* Event taps are forbidden in the Mac App Store, so we can only enable this
+ * code if your app doesn't need to ship through the app store.
+ * This code makes it so that a grabbed cursor cannot "leak" a mouse click
+ * past the edge of the window if moving the cursor too fast.
+ */
+#if SDL_MAC_NO_SANDBOX
+
+#include "SDL_keyboard.h"
+#include "SDL_thread.h"
+#include "SDL_cocoavideo.h"
+
+#include "../../events/SDL_mouse_c.h"
+
+typedef struct {
+ CFMachPortRef tap;
+ CFRunLoopRef runloop;
+ CFRunLoopSourceRef runloopSource;
+ SDL_Thread *thread;
+ SDL_sem *runloopStartedSemaphore;
+} SDL_MouseEventTapData;
+
+static const CGEventMask movementEventsMask =
+ CGEventMaskBit(kCGEventLeftMouseDragged)
+ | CGEventMaskBit(kCGEventRightMouseDragged)
+ | CGEventMaskBit(kCGEventMouseMoved);
+
+static const CGEventMask allGrabbedEventsMask =
+ CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp)
+ | CGEventMaskBit(kCGEventRightMouseDown) | CGEventMaskBit(kCGEventRightMouseUp)
+ | CGEventMaskBit(kCGEventOtherMouseDown) | CGEventMaskBit(kCGEventOtherMouseUp)
+ | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged)
+ | CGEventMaskBit(kCGEventMouseMoved);
+
+static CGEventRef
+Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
+{
+ SDL_MouseData *driverdata = (SDL_MouseData*)refcon;
+ SDL_Mouse *mouse = SDL_GetMouse();
+ SDL_Window *window = SDL_GetKeyboardFocus();
+ NSRect windowRect;
+ CGPoint eventLocation;
+
+ switch (type)
+ {
+ case kCGEventTapDisabledByTimeout:
+ case kCGEventTapDisabledByUserInput:
+ {
+ CGEventTapEnable(((SDL_MouseEventTapData*)(driverdata->tapdata))->tap, true);
+ return NULL;
+ }
+ default:
+ break;
+ }
+
+
+ if (!window || !mouse) {
+ return event;
+ }
+
+ if (mouse->relative_mode) {
+ return event;
+ }
+
+ if (!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
+ return event;
+ }
+
+ /* This is the same coordinate system as Cocoa uses. */
+ eventLocation = CGEventGetUnflippedLocation(event);
+ windowRect = [((SDL_WindowData *) window->driverdata)->nswindow frame];
+
+ if (!NSPointInRect(NSPointFromCGPoint(eventLocation), windowRect)) {
+
+ /* This is in CGs global screenspace coordinate system, which has a
+ * flipped Y.
+ */
+ CGPoint newLocation = CGEventGetLocation(event);
+
+ if (eventLocation.x < NSMinX(windowRect)) {
+ newLocation.x = NSMinX(windowRect);
+ } else if (eventLocation.x >= NSMaxX(windowRect)) {
+ newLocation.x = NSMaxX(windowRect) - 1.0;
+ }
+
+ if (eventLocation.y < NSMinY(windowRect)) {
+ newLocation.y -= (NSMinY(windowRect) - eventLocation.y + 1);
+ } else if (eventLocation.y >= NSMaxY(windowRect)) {
+ newLocation.y += (eventLocation.y - NSMaxY(windowRect) + 1);
+ }
+
+ CGSetLocalEventsSuppressionInterval(0);
+ CGWarpMouseCursorPosition(newLocation);
+ CGSetLocalEventsSuppressionInterval(0.25);
+
+ if ((CGEventMaskBit(type) & movementEventsMask) == 0) {
+ /* For click events, we just constrain the event to the window, so
+ * no other app receives the click event. We can't due the same to
+ * movement events, since they mean that our warp cursor above
+ * behaves strangely.
+ */
+ CGEventSetLocation(event, newLocation);
+ }
+ }
+
+ return event;
+}
+
+static int
+Cocoa_MouseTapThread(void *data)
+{
+ SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)data;
+
+ /* Create a tap. */
+ CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
+ kCGEventTapOptionDefault, allGrabbedEventsMask,
+ &Cocoa_MouseTapCallback, tapdata);
+ if (eventTap) {
+ /* Try to create a runloop source we can schedule. */
+ CFRunLoopSourceRef runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
+ if (runloopSource) {
+ tapdata->tap = eventTap;
+ tapdata->runloopSource = runloopSource;
+ } else {
+ CFRelease(eventTap);
+ SDL_SemPost(tapdata->runloopStartedSemaphore);
+ /* TODO: Both here and in the return below, set some state in
+ * tapdata to indicate that initialization failed, which we should
+ * check in InitMouseEventTap, after we move the semaphore check
+ * from Quit to Init.
+ */
+ return 1;
+ }
+ } else {
+ SDL_SemPost(tapdata->runloopStartedSemaphore);
+ return 1;
+ }
+
+ tapdata->runloop = CFRunLoopGetCurrent();
+ CFRunLoopAddSource(tapdata->runloop, tapdata->runloopSource, kCFRunLoopCommonModes);
+ CFRunLoopPerformBlock(tapdata->runloop, kCFRunLoopCommonModes, ^{
+ /* We signal this *after* the run loop has started, indicating it's safe to CFRunLoopStop it. */
+ SDL_SemPost(tapdata->runloopStartedSemaphore);
+ });
+
+ /* Run the event loop to handle events in the event tap. */
+ CFRunLoopRun();
+ /* Make sure this is signaled so that SDL_QuitMouseEventTap knows it can safely SDL_WaitThread for us. */
+ if (SDL_SemValue(tapdata->runloopStartedSemaphore) < 1) {
+ SDL_SemPost(tapdata->runloopStartedSemaphore);
+ }
+ CFRunLoopRemoveSource(tapdata->runloop, tapdata->runloopSource, kCFRunLoopCommonModes);
+
+ /* Clean up. */
+ CGEventTapEnable(tapdata->tap, false);
+ CFRelease(tapdata->runloopSource);
+ CFRelease(tapdata->tap);
+ tapdata->runloopSource = NULL;
+ tapdata->tap = NULL;
+
+ return 0;
+}
+
+void
+Cocoa_InitMouseEventTap(SDL_MouseData* driverdata)
+{
+ SDL_MouseEventTapData *tapdata;
+ driverdata->tapdata = SDL_calloc(1, sizeof(SDL_MouseEventTapData));
+ tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
+
+ tapdata->runloopStartedSemaphore = SDL_CreateSemaphore(0);
+ if (tapdata->runloopStartedSemaphore) {
+ tapdata->thread = SDL_CreateThread(&Cocoa_MouseTapThread, "Event Tap Loop", tapdata);
+ if (!tapdata->thread) {
+ SDL_DestroySemaphore(tapdata->runloopStartedSemaphore);
+ }
+ }
+
+ if (!tapdata->thread) {
+ SDL_free(driverdata->tapdata);
+ driverdata->tapdata = NULL;
+ }
+}
+
+void
+Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
+{
+ SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
+ int status;
+
+ /* Ensure that the runloop has been started first.
+ * TODO: Move this to InitMouseEventTap, check for error conditions that can
+ * happen in Cocoa_MouseTapThread, and fall back to the non-EventTap way of
+ * grabbing the mouse if it fails to Init.
+ */
+ status = SDL_SemWaitTimeout(tapdata->runloopStartedSemaphore, 5000);
+ if (status > -1) {
+ /* Then stop it, which will cause Cocoa_MouseTapThread to return. */
+ CFRunLoopStop(tapdata->runloop);
+ /* And then wait for Cocoa_MouseTapThread to finish cleaning up. It
+ * releases some of the pointers in tapdata. */
+ SDL_WaitThread(tapdata->thread, &status);
+ }
+
+ SDL_free(driverdata->tapdata);
+ driverdata->tapdata = NULL;
+}
+
+#else /* SDL_MAC_NO_SANDBOX */
+
+void
+Cocoa_InitMouseEventTap(SDL_MouseData *unused)
+{
+}
+
+void
+Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
+{
+}
+
+#endif /* !SDL_MAC_NO_SANDBOX */
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index 28a58e4e61..0c37f4de06 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -414,6 +414,11 @@ static __inline__ void ConvertNSRect(NSRect *r)
y = window->h - 1;
}
+#if !SDL_MAC_NO_SANDBOX
+ /* When SDL_MAC_NO_SANDBOX is set, this is handled by
+ * SDL_cocoamousetap.m.
+ */
+
cgpoint.x = window->x + x;
cgpoint.y = window->y + y;
@@ -424,6 +429,7 @@ static __inline__ void ConvertNSRect(NSRect *r)
CGSetLocalEventsSuppressionInterval(0.0);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
CGSetLocalEventsSuppressionInterval(0.25);
+#endif
}
}
SDL_SendMouseMotion(window, 0, 0, x, y);