From 952c5c128f9efaea89d41d882c4ea3ade7df4591 Mon Sep 17 00:00:00 2001 From: zakk Date: Fri, 26 Aug 2005 04:48:05 +0000 Subject: Itsa me, quake3io! git-svn-id: svn://svn.icculus.org/quake3/trunk@2 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/macosx/CGMouseDeltaFix.m | 131 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100755 code/macosx/CGMouseDeltaFix.m (limited to 'code/macosx/CGMouseDeltaFix.m') diff --git a/code/macosx/CGMouseDeltaFix.m b/code/macosx/CGMouseDeltaFix.m new file mode 100755 index 0000000..ee83eeb --- /dev/null +++ b/code/macosx/CGMouseDeltaFix.m @@ -0,0 +1,131 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#import "CGMouseDeltaFix.h" +#import "CGPrivateAPI.h" + +#import +#import + + +// We will try to automatically fall back to using the original CGGetLastMouseDelta when we are on a system new enough to have the fix. Any version of CoreGraphics past 1.93.0 will have the fixed version. + + +static BOOL originalVersionShouldWork = YES; +static CGMouseDelta CGFix_Mouse_DeltaX, CGFix_Mouse_DeltaY; + +static void CGFix_NotificationCallback(CGSNotificationType note, CGSNotificationData data, CGSByteCount dataLength, CGSNotificationArg arg); + +static CGSRegisterNotifyProcType registerNotifyProc = NULL; + +void CGFix_Initialize() +{ + NSAutoreleasePool *pool; + NSBundle *cgBundle; + NSString *version; + NSArray *components; + + if (registerNotifyProc) + // We've already been called once and have registered our callbacks. If the original version works, this will be NULL, but we'll end up doing nothing (again, possibly). + return; + + //NSLog(@"CGFix_Initialize\n"); + + pool = [[NSAutoreleasePool alloc] init]; + cgBundle = [NSBundle bundleWithPath: @"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework"]; + if (!cgBundle) { + // If it's moved, it must be newer than what we know about and should work + //NSLog(@"No /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework\n"); + goto done; + } + + version = [[cgBundle infoDictionary] objectForKey: @"CFBundleShortVersionString"]; + components = [version componentsSeparatedByString: @"."]; + //NSLog(@"version = %@\n", version); + //NSLog(@"components = %@\n", components); + + + if ([components count] < 2) + // We don't understand this versioning scheme. Must have changed. + goto done; + + if (![[components objectAtIndex: 0] isEqualToString: @"1"] || [[components objectAtIndex: 1] intValue] > 93) + // This version should be new enough to work + goto done; + + // Look up the function pointer we need to register our callback. + if (!NSIsSymbolNameDefined("_CGSRegisterNotifyProc")) { + //NSLog(@"No _CGSRegisterNotifyProc\n"); + goto done; + } + + registerNotifyProc = NSAddressOfSymbol(NSLookupAndBindSymbol("_CGSRegisterNotifyProc")); + //NSLog(@"registerNotifyProc = 0x%08x", registerNotifyProc); + + // Must not work if we got here + originalVersionShouldWork = NO; + + // We want to catch all the events that could possible indicate mouse movement and sum them up + registerNotifyProc( CGFix_NotificationCallback, kCGSEventNotificationMouseMoved, NULL); + registerNotifyProc( CGFix_NotificationCallback, kCGSEventNotificationLeftMouseDragged, NULL); + registerNotifyProc( CGFix_NotificationCallback, kCGSEventNotificationRightMouseDragged, NULL); + registerNotifyProc( CGFix_NotificationCallback, kCGSEventNotificationNotificationOtherMouseDragged, NULL); + +done: + [pool release]; +} + +void CGFix_GetLastMouseDelta(CGMouseDelta *dx, CGMouseDelta *dy) +{ + if (originalVersionShouldWork) { + CGGetLastMouseDelta(dx, dy); + return; + } + + *dx = CGFix_Mouse_DeltaX; + *dy = CGFix_Mouse_DeltaY; + + CGFix_Mouse_DeltaX = CGFix_Mouse_DeltaY = 0; +} + +static void CGFix_NotificationCallback(CGSNotificationType note, CGSNotificationData data, CGSByteCount dataLength, CGSNotificationArg arg) +{ + CGSEventRecordPtr event; + + //fprintf(stderr, "CGFix_NotificationCallback(note=%d, date=0x%08x, dataLength=%d, arg=0x%08x)\n", note, data, dataLength, arg); + +#ifdef DEBUG + if ((note != kCGSEventNotificationMouseMoved && + note != kCGSEventNotificationLeftMouseDragged && + note != kCGSEventNotificationRightMouseDragged && + note != kCGSEventNotificationNotificationOtherMouseDragged) || + dataLength != sizeof (CGSEventRecord)) + fprintf(stderr, "Unexpected arguments to callback function CGFix_NotificationCallback(note=%d, date=0x%08x, dataLength=%d, arg=0x%08x)\n", note, data, dataLength, arg); + abort(); + } +#endif + + event = (CGSEventRecordPtr)data; + + CGFix_Mouse_DeltaX += event->data.move.deltaX; + CGFix_Mouse_DeltaY += event->data.move.deltaY; + //fprintf(stderr, " dx += %d, dy += %d\n", event->data.move.deltaX, event->data.move.deltaY); +} -- cgit v1.2.3