diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 9d685da..2f3a71b 100755 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -406,6 +406,9 @@ 56A6702A185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; }; 56A6702B185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; }; 56A6702C185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; }; + 66B6DFA21CF2B86900944673 /* SDL_cocoamouseraw.m in Sources */ = {isa = PBXBuildFile; fileRef = 66B6DFA11CF2B86900944673 /* SDL_cocoamouseraw.m */; }; + 66B6DFA31CF2B86900944673 /* SDL_cocoamouseraw.m in Sources */ = {isa = PBXBuildFile; fileRef = 66B6DFA11CF2B86900944673 /* SDL_cocoamouseraw.m */; }; + 66B6DFA41CF2B86900944673 /* SDL_cocoamouseraw.m in Sources */ = {isa = PBXBuildFile; fileRef = 66B6DFA11CF2B86900944673 /* SDL_cocoamouseraw.m */; }; A77E6EB4167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; }; A77E6EB5167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; }; @@ -1027,6 +1030,8 @@ 56A6701E185654B40007D20F /* SDL_dynapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_dynapi.c; path = ../../src/dynapi/SDL_dynapi.c; sourceTree = ""; }; 56A6701F185654B40007D20F /* SDL_dynapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dynapi.h; path = ../../src/dynapi/SDL_dynapi.h; sourceTree = ""; }; 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dynapi_overrides.h; path = ../../src/dynapi/SDL_dynapi_overrides.h; sourceTree = ""; }; + 66B6DFA11CF2B86900944673 /* SDL_cocoamouseraw.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoamouseraw.m; sourceTree = ""; }; + 66B6DFA51CF2B87B00944673 /* SDL_cocoamouseraw.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_cocoamouseraw.h; sourceTree = ""; }; A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = ""; }; AA0F8490178D5ECC00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = ""; }; AA628AC8159367B7005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = ""; }; @@ -1595,6 +1600,8 @@ 04BDFECB12E6671800899322 /* SDL_cocoamouse.m */, D55A1B7F179F262300625D7C /* SDL_cocoamousetap.h */, D55A1B80179F262300625D7C /* SDL_cocoamousetap.m */, + 66B6DFA51CF2B87B00944673 /* SDL_cocoamouseraw.h */, + 66B6DFA11CF2B86900944673 /* SDL_cocoamouseraw.m */, 04BDFECC12E6671800899322 /* SDL_cocoaopengl.h */, 04BDFECD12E6671800899322 /* SDL_cocoaopengl.m */, 04BDFECE12E6671800899322 /* SDL_cocoashape.h */, @@ -2483,6 +2490,7 @@ 04BD01E912E6671800899322 /* SDL_x11mouse.c in Sources */, 04BD01EB12E6671800899322 /* SDL_x11opengl.c in Sources */, 04BD01ED12E6671800899322 /* SDL_x11opengles.c in Sources */, + 66B6DFA21CF2B86900944673 /* SDL_cocoamouseraw.m in Sources */, 04BD01F112E6671800899322 /* SDL_x11shape.c in Sources */, 04BD01F412E6671800899322 /* SDL_x11touch.c in Sources */, 04BD01F612E6671800899322 /* SDL_x11video.c in Sources */, @@ -2602,6 +2610,7 @@ 04BD03FD12E6671800899322 /* SDL_x11keyboard.c in Sources */, 04BD03FF12E6671800899322 /* SDL_x11modes.c in Sources */, 04BD040112E6671800899322 /* SDL_x11mouse.c in Sources */, + 66B6DFA31CF2B86900944673 /* SDL_cocoamouseraw.m in Sources */, 04BD040312E6671800899322 /* SDL_x11opengl.c in Sources */, 04BD040512E6671800899322 /* SDL_x11opengles.c in Sources */, 04BD040912E6671800899322 /* SDL_x11shape.c in Sources */, @@ -2721,6 +2730,7 @@ DB31404F17554B71006C0E22 /* SDL_x11keyboard.c in Sources */, DB31405017554B71006C0E22 /* SDL_x11modes.c in Sources */, DB31405117554B71006C0E22 /* SDL_x11mouse.c in Sources */, + 66B6DFA41CF2B86900944673 /* SDL_cocoamouseraw.m in Sources */, DB31405217554B71006C0E22 /* SDL_x11opengl.c in Sources */, DB31405317554B71006C0E22 /* SDL_x11opengles.c in Sources */, DB31405417554B71006C0E22 /* SDL_x11shape.c in Sources */, diff --git a/src/video/cocoa/SDL_cocoamouse.h b/src/video/cocoa/SDL_cocoamouse.h index 4f60c83..55169c4 100644 --- a/src/video/cocoa/SDL_cocoamouse.h +++ b/src/video/cocoa/SDL_cocoamouse.h @@ -30,6 +30,7 @@ extern void Cocoa_HandleMouseEvent(_THIS, NSEvent * event); extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent * event); extern void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y); extern void Cocoa_QuitMouse(_THIS); +extern void Cocoa_HandleRawMouseEvent(int deltaX, int deltaY); typedef struct { /* Wether we've seen a cursor warp since the last move event. */ @@ -41,6 +42,8 @@ typedef struct { CGFloat lastMoveX; CGFloat lastMoveY; void *tapdata; + /* For raw motion */ + void *rawMouseListener; } SDL_MouseData; @interface NSCursor (InvisibleCursor) diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m index aa753fc..dc40f90 100644 --- a/src/video/cocoa/SDL_cocoamouse.m +++ b/src/video/cocoa/SDL_cocoamouse.m @@ -26,6 +26,7 @@ #include "SDL_events.h" #include "SDL_cocoamouse.h" #include "SDL_cocoamousetap.h" +#include "SDL_cocoamouseraw.h" #include "../../events/SDL_mouse_c.h" @@ -296,6 +297,19 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled) } else { [NSCursor unhide]; } + + SDL_Mouse *mouse = SDL_GetMouse(); + if (!mouse) { + return SDL_FALSE; + } + + SDL_MouseData *driverdata = (SDL_MouseData *)mouse->driverdata; + if (!mouse->driverdata) { + return SDL_FALSE; + } + + Cocoa_SetRawMouseCallbackEnabled(driverdata, enabled); + return 0; } @@ -390,6 +404,8 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event) driverdata->lastMoveY = location.y; DLog("Last seen mouse: (%g, %g)", location.x, location.y); + /* The following is now handled by SDL_cocoamouseraw.m */ +#if 0 /* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */ if (!mouse->relative_mode) { return; @@ -414,6 +430,24 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event) } SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)deltaX, (int)deltaY); +#endif +} + +void +Cocoa_HandleRawMouseEvent(int deltaX, int deltaY) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata; + if (!driverdata) { + return; /* can happen when returning from fullscreen Space on shutdown */ + } + + /* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */ + if (!mouse->relative_mode) { + return; + } + + SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, deltaX, deltaY); } void @@ -463,8 +497,10 @@ Cocoa_QuitMouse(_THIS) { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse) { - if (mouse->driverdata) { - Cocoa_QuitMouseEventTap(((SDL_MouseData*)mouse->driverdata)); + SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata; + if (driverdata) { + Cocoa_QuitRawMouseCallback(driverdata); + Cocoa_QuitMouseEventTap(driverdata); } SDL_free(mouse->driverdata); diff --git a/src/video/cocoa/SDL_cocoamouseraw.h b/src/video/cocoa/SDL_cocoamouseraw.h new file mode 100644 index 0000000..6137231 --- /dev/null +++ b/src/video/cocoa/SDL_cocoamouseraw.h @@ -0,0 +1,33 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + 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" + +#ifndef _SDL_cocoamouseraw_h +#define _SDL_cocoamouseraw_h + +#include "SDL_cocoamouse.h" + +extern void Cocoa_SetRawMouseCallbackEnabled(SDL_MouseData *driverdata, SDL_bool enable); +extern void Cocoa_QuitRawMouseCallback(SDL_MouseData *driverdata); + +#endif /* _SDL_cocoamouseraw_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/cocoa/SDL_cocoamouseraw.m b/src/video/cocoa/SDL_cocoamouseraw.m new file mode 100644 index 0000000..85a07f1 --- /dev/null +++ b/src/video/cocoa/SDL_cocoamouseraw.m @@ -0,0 +1,306 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + 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 + +#include "SDL_cocoamouseraw.h" + +#include "../../events/SDL_mouse_c.h" + +#define DEBUG_COCOAMOUSERAW + +#ifdef DEBUG_COCOAMOUSERAW +#define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__) +#else +#define DLog(...) do { } while (0) +#endif + +#define COCOAMOUSERAW_QUEUE_SIZE 2000 + +typedef struct { + IOHIDManagerRef hidman; + CFMutableArrayRef queues; + SDL_bool started; +} SDL_RawMouseData; + +static void +Cocoa_RawMouseQueueCallback(void *context, IOReturn result, void *sender) +{ + + IOHIDQueueRef queue = SDL_static_cast(IOHIDQueueRef, sender); + IOHIDValueRef val; + int x = 0, y = 0; + + // empty the IOHIDQueue, adding up the X and Y deltas + while ((val = IOHIDQueueCopyNextValueWithTimeout(queue, 0.0)) != NULL) { + IOHIDElementRef elem = IOHIDValueGetElement(val); + + const CFIndex intval = IOHIDValueGetIntegerValue(val); + const uint32_t page = IOHIDElementGetUsagePage(elem); + const uint32_t usage = IOHIDElementGetUsage(elem); + + if (page == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_X) { + x += intval; + } else if (page == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Y) { + y += intval; + } else { + DLog("unexpected page 0x%x usage 0x%x\n", (int)page, (int)usage); + } + + // release the copy returned by IOHIDQueueCopyNextValueWithTimeout + CFRelease(val); + } + + // dispatch an SDL event if there was some motion + if (x != 0 || y != 0) { + Cocoa_HandleRawMouseEvent(x, y); + } +} + +static void +Cocoa_EnableQueue(IOHIDQueueRef q) +{ + DLog("Enabling queue: %p", q); + + IOHIDQueueStart(q); + IOHIDQueueRegisterValueAvailableCallback(q, Cocoa_RawMouseQueueCallback, NULL); + IOHIDQueueScheduleWithRunLoop(q, CFRunLoopGetMain(), kCFRunLoopDefaultMode); +} + +static void +Cocoa_DisableQueue(IOHIDQueueRef q) +{ + DLog("Disabling queue: %p", q); + + IOHIDQueueStop(q); + IOHIDQueueRegisterValueAvailableCallback(q, NULL, NULL); + IOHIDQueueUnscheduleFromRunLoop(q, CFRunLoopGetMain(), kCFRunLoopDefaultMode); +} + +static void +Cocoa_EnableQueue_Func( const void *value, void *context ) +{ + Cocoa_EnableQueue(SDL_static_cast(IOHIDQueueRef, value)); +} + +static void +Cocoa_DisableQueue_Func( const void *value, void *context ) +{ + Cocoa_DisableQueue(SDL_static_cast(IOHIDQueueRef, value)); +} + +static NSArray * +ElementMatchingDictionaries() +{ + NSDictionary *matchingDictX = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt: kHIDPage_GenericDesktop], CFSTR(kIOHIDElementUsagePageKey), + [NSNumber numberWithInt: kHIDUsage_GD_X], CFSTR(kIOHIDElementUsageKey), + nil]; + + NSDictionary *matchingDictY = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt: kHIDPage_GenericDesktop], CFSTR(kIOHIDElementUsagePageKey), + [NSNumber numberWithInt: kHIDUsage_GD_Y], CFSTR(kIOHIDElementUsageKey), + nil]; + + NSArray *matchingDicts = [NSArray arrayWithObjects: matchingDictX, matchingDictY, nil]; + return matchingDicts; +} + +static void +Cocoa_RawMouseAddedCallback(void *context, IOReturn res, void *sender, IOHIDDeviceRef device) +{ @autoreleasepool +{ + SDL_RawMouseData *rawdata = SDL_static_cast(SDL_RawMouseData *, context); + + if (NULL == rawdata) { + return; + } + + NSArray *matchingDicts = ElementMatchingDictionaries(); + + DLog("Mouse added: %s", [(NSString *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)) UTF8String]); + + // create the queue + IOHIDQueueRef queue = IOHIDQueueCreate(kCFAllocatorDefault, device, COCOAMOUSERAW_QUEUE_SIZE, kIOHIDOptionsTypeNone); + CFArrayAppendValue(rawdata->queues, queue); + CFRelease(queue); + + // make the queue subscribe to updates for X and Y changes + for (NSDictionary *matchingDict in matchingDicts) { + CFArrayRef elems = IOHIDDeviceCopyMatchingElements(device, SDL_static_cast(CFDictionaryRef, matchingDict), kIOHIDOptionsTypeNone); + for (id elem in SDL_static_cast(NSArray *, elems)) { + IOHIDQueueAddElement(queue, SDL_static_cast(IOHIDElementRef, elem)); + } + CFRelease(elems); + } + + // start it now if we are in relative mouse mode. + // otherwise, it gets started in Cocoa_StartRawMouseCallback + if (rawdata->started) { + Cocoa_EnableQueue(queue); + } +}} + +static void +Cocoa_RawMouseRemovedCallback(void *context, IOReturn res, void *sender, IOHIDDeviceRef device) +{ @autoreleasepool +{ + CFIndex i; + SDL_RawMouseData *rawdata = SDL_static_cast(SDL_RawMouseData *, context); + + if (NULL == rawdata) { + return; + } + + DLog("Mouse removed: %s", [(NSString *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)) UTF8String]); + + // remove any queues from the rawdata->queues CFArray that belonged to `device` + for (i = 0; i < CFArrayGetCount(rawdata->queues); ) { + IOHIDQueueRef queue = SDL_static_cast(IOHIDQueueRef, CFArrayGetValueAtIndex(rawdata->queues, i)); + if (IOHIDQueueGetDevice(queue) == device) { + // remove it, don't increment i + CFArrayRemoveValueAtIndex(rawdata->queues, i); + } else { + i++; + } + } +}} + +static NSDictionary * +DeviceMatchDictionary() +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt: kHIDPage_GenericDesktop], CFSTR(kIOHIDDeviceUsagePageKey), + [NSNumber numberWithInt: kHIDUsage_GD_Mouse], CFSTR(kIOHIDDeviceUsageKey), + nil]; +} + +static IOHIDManagerRef +CreateHIDManager(SDL_RawMouseData *rawdata) +{ @autoreleasepool +{ + IOHIDManagerRef hidman = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + + NSDictionary *matchingDict = DeviceMatchDictionary(); + if (!matchingDict) { + SDL_OutOfMemory(); + return NULL; + } + + IOHIDManagerSetDeviceMatching(hidman, SDL_static_cast(CFDictionaryRef, matchingDict)); + + if (IOHIDManagerOpen(hidman, kIOHIDOptionsTypeNone) != kIOReturnSuccess) { + return NULL; + } + + // it would be simpler to use IOHIDManagerRegisterInputValueCallback, but + // it's broken on OS X 10.6, an internal buffer seems to be filling up + // and events are dropped. so, instead, use the IOHIDQueue* API. + + IOHIDManagerRegisterDeviceMatchingCallback(hidman, Cocoa_RawMouseAddedCallback, rawdata); + IOHIDManagerRegisterDeviceRemovalCallback(hidman, Cocoa_RawMouseRemovedCallback, rawdata); + IOHIDManagerScheduleWithRunLoop(hidman, CFRunLoopGetMain(), kCFRunLoopDefaultMode); + return hidman; +}} + +static void +Cocoa_InitRawMouseCallback(SDL_MouseData *driverdata) +{ @autoreleasepool +{ + SDL_RawMouseData *rawdata; + + if (driverdata->rawMouseListener != NULL) { + // already initialized + return; + } + + DLog("init"); + + rawdata = SDL_calloc(1, sizeof(SDL_RawMouseData)); + if (NULL == rawdata) { + SDL_OutOfMemory(); + return; + } + + rawdata->queues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + rawdata->hidman = CreateHIDManager(rawdata); + + driverdata->rawMouseListener = rawdata; +}} + +void +Cocoa_SetRawMouseCallbackEnabled(SDL_MouseData *driverdata, SDL_bool enable) +{ @autoreleasepool +{ + SDL_RawMouseData *rawdata; + + // init if needed. + if (NULL == driverdata->rawMouseListener) { + Cocoa_InitRawMouseCallback(driverdata); + } + + rawdata = SDL_static_cast(SDL_RawMouseData *, driverdata->rawMouseListener); + if (rawdata) { + if (enable) { + DLog("starting"); + rawdata->started = SDL_TRUE; + + CFArrayApplyFunction(rawdata->queues, CFRangeMake(0, CFArrayGetCount(rawdata->queues)), Cocoa_EnableQueue_Func, NULL); + } else { + DLog("stopping"); + rawdata->started = SDL_FALSE; + + CFArrayApplyFunction(rawdata->queues, CFRangeMake(0, CFArrayGetCount(rawdata->queues)), Cocoa_DisableQueue_Func, NULL); + } + } else { + // failed + } +}} + +void +Cocoa_QuitRawMouseCallback(SDL_MouseData *driverdata) +{ @autoreleasepool +{ + DLog("quitting"); + + SDL_RawMouseData *rawdata = SDL_static_cast(SDL_RawMouseData *, driverdata->rawMouseListener); + if (rawdata != NULL) { + Cocoa_SetRawMouseCallbackEnabled(driverdata, SDL_FALSE); + + // release rawdata->queues + CFRelease(rawdata->queues); + + // release rawdata->hidman + IOHIDManagerUnscheduleFromRunLoop(rawdata->hidman, CFRunLoopGetMain(), kCFRunLoopDefaultMode); + IOHIDManagerClose(rawdata->hidman, kIOHIDOptionsTypeNone); + CFRelease(rawdata->hidman); + + SDL_free(rawdata); + driverdata->rawMouseListener = NULL; + } +}} + +#endif /* SDL_VIDEO_DRIVER_COCOA */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/test/testrelative.c b/test/testrelative.c index 59d23f6..d49dde8 100644 --- a/test/testrelative.c +++ b/test/testrelative.c @@ -27,6 +27,10 @@ int i, done; SDL_Rect rect; SDL_Event event; +int motioncount; +Uint32 motion_last_log_time; +#define RATE_LOG_INTERVAL 1000 + static void DrawRects(SDL_Renderer * renderer, SDL_Rect * rect) { @@ -44,10 +48,24 @@ loop(){ { rect.x += event.motion.xrel; rect.y += event.motion.yrel; + motioncount++; } break; } } + /* Log SDL_MOUSEMOTION event rate every RATE_LOG_INTERVAL milliseconds */ + { + const Uint32 currtime = SDL_GetTicks(); + if (currtime >= (motion_last_log_time + RATE_LOG_INTERVAL)) { + float seconds_elapsed = (float)(currtime - motion_last_log_time) / 1000.0f; + float rate = motioncount / seconds_elapsed; + + SDL_Log("SDL_MOUSEMOTION rate: %f Hz\n", rate); + + motioncount = 0; + motion_last_log_time = currtime; + } + } for (i = 0; i < state->num_windows; ++i) { SDL_Rect viewport; SDL_Renderer *renderer = state->renderers[i];