00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
00048 return;
00049
00050
00051
00052 pool = [[NSAutoreleasePool alloc] init];
00053 cgBundle = [NSBundle bundleWithPath: @"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework"];
00054 if (!cgBundle) {
00055
00056
00057 goto done;
00058 }
00059
00060 version = [[cgBundle infoDictionary] objectForKey: @"CFBundleShortVersionString"];
00061 components = [version componentsSeparatedByString: @"."];
00062
00063
00064
00065
00066 if ([components count] < 2)
00067
00068 goto done;
00069
00070 if (![[components objectAtIndex: 0] isEqualToString: @"1"] || [[components objectAtIndex: 1] intValue] > 93)
00071
00072 goto done;
00073
00074
00075 if (!NSIsSymbolNameDefined("_CGSRegisterNotifyProc")) {
00076
00077 goto done;
00078 }
00079
00080 registerNotifyProc = NSAddressOfSymbol(NSLookupAndBindSymbol("_CGSRegisterNotifyProc"));
00081
00082
00083
00084 originalVersionShouldWork = NO;
00085
00086
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
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
00131 }