2005-08-26 17:39:27 +00:00
/ *
=== === === === === === === === === === === === === === === === === === === === === === === === ===
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 < Foundation / Foundation . h >
# import < mach - o / dyld . h >
// 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 ) ;
}