Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

CGMouseDeltaFix.m

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 #import "CGMouseDeltaFix.h"
00023 #import "CGPrivateAPI.h"
00024 
00025 #import <Foundation/Foundation.h>
00026 #import <mach-o/dyld.h>
00027 
00028 
00029 // 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.
00030 
00031 
00032 static BOOL originalVersionShouldWork = YES;
00033 static CGMouseDelta CGFix_Mouse_DeltaX, CGFix_Mouse_DeltaY;
00034 
00035 static void CGFix_NotificationCallback(CGSNotificationType note, CGSNotificationData data, CGSByteCount dataLength, CGSNotificationArg arg);
00036 
00037 static CGSRegisterNotifyProcType registerNotifyProc = NULL;
00038 
00039 void CGFix_Initialize()
00040 {
00041     NSAutoreleasePool *pool;
00042     NSBundle *cgBundle;
00043     NSString *version;
00044     NSArray *components;
00045     
00046     if (registerNotifyProc)
00047         // 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).
00048         return;
00049 
00050     //NSLog(@"CGFix_Initialize\n");
00051         
00052     pool = [[NSAutoreleasePool alloc] init];
00053     cgBundle = [NSBundle bundleWithPath: @"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework"];
00054     if (!cgBundle) {
00055         // If it's moved, it must be newer than what we know about and should work
00056         //NSLog(@"No /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework\n");
00057         goto done;
00058     }
00059     
00060     version = [[cgBundle infoDictionary] objectForKey: @"CFBundleShortVersionString"];
00061     components = [version componentsSeparatedByString: @"."];
00062     //NSLog(@"version = %@\n", version);
00063     //NSLog(@"components = %@\n", components);
00064 
00065 
00066     if ([components count] < 2)
00067         // We don't understand this versioning scheme.  Must have changed.
00068         goto done;
00069     
00070     if (![[components objectAtIndex: 0] isEqualToString: @"1"] || [[components objectAtIndex: 1] intValue] > 93)
00071         // This version should be new enough to work
00072         goto done;
00073     
00074     // Look up the function pointer we need to register our callback.
00075     if (!NSIsSymbolNameDefined("_CGSRegisterNotifyProc")) {
00076         //NSLog(@"No _CGSRegisterNotifyProc\n");
00077         goto done;
00078     }
00079     
00080     registerNotifyProc = NSAddressOfSymbol(NSLookupAndBindSymbol("_CGSRegisterNotifyProc"));
00081     //NSLog(@"registerNotifyProc = 0x%08x", registerNotifyProc);
00082 
00083     // Must not work if we got here
00084     originalVersionShouldWork = NO;
00085     
00086     // We want to catch all the events that could possible indicate mouse movement and sum them up
00087     registerNotifyProc( CGFix_NotificationCallback, kCGSEventNotificationMouseMoved, NULL);
00088     registerNotifyProc( CGFix_NotificationCallback, kCGSEventNotificationLeftMouseDragged, NULL);
00089     registerNotifyProc( CGFix_NotificationCallback, kCGSEventNotificationRightMouseDragged, NULL);
00090     registerNotifyProc( CGFix_NotificationCallback, kCGSEventNotificationNotificationOtherMouseDragged, NULL);
00091     
00092 done:
00093     [pool release];
00094 }
00095 
00096 void CGFix_GetLastMouseDelta(CGMouseDelta *dx, CGMouseDelta *dy)
00097 {
00098     if (originalVersionShouldWork) {
00099         CGGetLastMouseDelta(dx, dy);
00100         return;
00101     }
00102     
00103     *dx = CGFix_Mouse_DeltaX;
00104     *dy = CGFix_Mouse_DeltaY;
00105     
00106     CGFix_Mouse_DeltaX = CGFix_Mouse_DeltaY = 0;
00107 }
00108 
00109 static void CGFix_NotificationCallback(CGSNotificationType note, CGSNotificationData data, CGSByteCount dataLength, CGSNotificationArg arg)
00110 {
00111     CGSEventRecordPtr event;
00112 
00113     //fprintf(stderr, "CGFix_NotificationCallback(note=%d, date=0x%08x, dataLength=%d, arg=0x%08x)\n", note, data, dataLength, arg);
00114     
00115 #ifdef DEBUG
00116     if ((note != kCGSEventNotificationMouseMoved && 
00117          note != kCGSEventNotificationLeftMouseDragged &&
00118          note != kCGSEventNotificationRightMouseDragged &&
00119          note != kCGSEventNotificationNotificationOtherMouseDragged) ||
00120          dataLength != sizeof (CGSEventRecord))
00121          fprintf(stderr, "Unexpected arguments to callback function CGFix_NotificationCallback(note=%d, date=0x%08x, dataLength=%d, arg=0x%08x)\n", note, data, dataLength, arg);
00122          abort();
00123     }
00124 #endif
00125 
00126     event = (CGSEventRecordPtr)data;
00127 
00128     CGFix_Mouse_DeltaX += event->data.move.deltaX;
00129     CGFix_Mouse_DeltaY += event->data.move.deltaY;
00130     //fprintf(stderr, "  dx += %d, dy += %d\n", event->data.move.deltaX, event->data.move.deltaY);
00131 }

Generated on Thu Aug 25 12:37:37 2005 for Quake III Arena by  doxygen 1.3.9.1