summaryrefslogtreecommitdiff
path: root/Source/3rdParty/SDL2/src/video/cocoa/SDL_cocoamousetap.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/3rdParty/SDL2/src/video/cocoa/SDL_cocoamousetap.m')
-rw-r--r--Source/3rdParty/SDL2/src/video/cocoa/SDL_cocoamousetap.m286
1 files changed, 0 insertions, 286 deletions
diff --git a/Source/3rdParty/SDL2/src/video/cocoa/SDL_cocoamousetap.m b/Source/3rdParty/SDL2/src/video/cocoa/SDL_cocoamousetap.m
deleted file mode 100644
index aa4f152..0000000
--- a/Source/3rdParty/SDL2/src/video/cocoa/SDL_cocoamousetap.m
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2018 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_internal.h"
-
-#if SDL_VIDEO_DRIVER_COCOA
-
-#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_cocoavideo.h"
-#include "../../thread/SDL_systhread.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_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)refcon;
- SDL_Mouse *mouse = SDL_GetMouse();
- SDL_Window *window = SDL_GetKeyboardFocus();
- NSWindow *nswindow;
- NSRect windowRect;
- CGPoint eventLocation;
-
- switch (type) {
- case kCGEventTapDisabledByTimeout:
- {
- CGEventTapEnable(tapdata->tap, true);
- return NULL;
- }
- case kCGEventTapDisabledByUserInput:
- {
- 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. */
- nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
- eventLocation = CGEventGetUnflippedLocation(event);
- windowRect = [nswindow contentRectForFrameRect:[nswindow frame]];
-
- if (!NSMouseInRect(NSPointFromCGPoint(eventLocation), windowRect, NO)) {
-
- /* 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));
- }
-
- CGWarpMouseCursorPosition(newLocation);
- CGAssociateMouseAndMouseCursorPosition(YES);
-
- 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 void
-SemaphorePostCallback(CFRunLoopTimerRef timer, void *info)
-{
- SDL_SemPost((SDL_sem*)info);
-}
-
-static int
-Cocoa_MouseTapThread(void *data)
-{
- SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)data;
-
- /* Tap was created on main thread but we own it now. */
- CFMachPortRef eventTap = tapdata->tap;
- if (eventTap) {
- /* Try to create a runloop source we can schedule. */
- CFRunLoopSourceRef runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
- if (runloopSource) {
- 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);
- CFRunLoopTimerContext context = {.info = tapdata->runloopStartedSemaphore};
- /* We signal the runloop started semaphore *after* the run loop has started, indicating it's safe to CFRunLoopStop it. */
- CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 0, 0, 0, &SemaphorePostCallback, &context);
- CFRunLoopAddTimer(tapdata->runloop, timer, kCFRunLoopCommonModes);
- CFRelease(timer);
-
- /* 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->tap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
- kCGEventTapOptionDefault, allGrabbedEventsMask,
- &Cocoa_MouseTapCallback, tapdata);
- if (tapdata->tap) {
- /* Tap starts disabled, until app requests mouse grab */
- CGEventTapEnable(tapdata->tap, false);
- tapdata->thread = SDL_CreateThreadInternal(&Cocoa_MouseTapThread, "Event Tap Loop", 512 * 1024, tapdata);
- if (tapdata->thread) {
- /* Success - early out. Ownership transferred to thread. */
- return;
- }
- CFRelease(tapdata->tap);
- }
- SDL_DestroySemaphore(tapdata->runloopStartedSemaphore);
- }
- SDL_free(driverdata->tapdata);
- driverdata->tapdata = NULL;
-}
-
-void
-Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled)
-{
- SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
- if (tapdata && tapdata->tap)
- {
- CGEventTapEnable(tapdata->tap, !!enabled);
- }
-}
-
-void
-Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
-{
- SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
- int status;
-
- if (tapdata == NULL) {
- /* event tap was already cleaned up (possibly due to CGEventTapCreate
- * returning null.)
- */
- return;
- }
-
- /* 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_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled)
-{
-}
-
-void
-Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
-{
-}
-
-#endif /* !SDL_MAC_NO_SANDBOX */
-
-#endif /* SDL_VIDEO_DRIVER_COCOA */
-
-/* vi: set ts=4 sw=4 expandtab: */