tenebrae2/macosx/in_osx.m
2003-01-17 21:18:53 +00:00

405 lines
11 KiB
Objective-C

//___________________________________________________________________________________________________________nFO
// "in_osx.m" - MacOS X mouse driver
//
// Written by: Axel "awe" Wefers [mailto:awe@fruitz-of-dojo.de].
// (C)2001-2002 Fruitz Of Dojo [http://www.fruitz-of-dojo.de].
//
// Quakeª is copyrighted by id software [http://www.idsoftware.com].
//
// Version History:
//
// TenebraeQuake:
// v1.0.0: Initial release.
//
// Standard Quake branch [pre-TenebraeQuake]:
// v1.0.6: Mouse sensitivity works now as expected.
// v1.0.5: Reworked whole mouse handling code [required for windowed mouse].
// v1.0.0: Initial release.
//______________________________________________________________________________________________________iNCLUDES
#pragma mark =Includes=
#include "quakedef.h"
#include <AppKit/AppKit.h>
#import <IOKit/IOKitLib.h>
#import <IOKit/hidsystem/IOHIDLib.h>
#import <IOKit/hidsystem/IOHIDParameter.h>
#pragma mark -
//______________________________________________________________________________________________________tYPEDEFS
#pragma mark =TypeDefs=
typedef struct {
SInt X;
SInt Y;
SInt OldX;
SInt OldY;
} gMousePositionStruct;
#pragma mark -
//_______________________________________________________________________________________________________sTATICS
#pragma mark =Variables=
extern Boolean gIsMinimized,
gIsHidden,
gIsDeactivated;
extern qboolean gDisplayFullscreen;
extern cvar_t _windowed_mouse;
cvar_t aux_look = {"auxlook","1", true};
cvar_t m_filter = {"m_filter","1"};
qboolean gMouseEnabled;
static qboolean gMouseMoved;
static gMousePositionStruct gMousePosition, gMouseNewPosition, gMouseOldPosition;
#pragma mark -
//___________________________________________________________________________________________fUNCTION_pROTOTYPES
#pragma mark =Function Prototypes=
void IN_CenterCursor (void);
void IN_ShowCursor (Boolean);
void IN_InitMouse (void);
void IN_ReceiveMouseMove (CGMouseDelta, CGMouseDelta);
void IN_MouseMove (usercmd_t *);
static io_connect_t IN_GetIOHandle (void);
static void IN_SetMouseScalingEnabled (Boolean theState);
#pragma mark -
//____________________________________________________________________________________________Toggle_AuxLook_f()
void Toggle_AuxLook_f (void)
{
if (aux_look.value)
{
Cvar_Set ("auxlook","0");
}
else
{
Cvar_Set ("auxlook","1");
}
}
//__________________________________________________________________________________________Force_CenterView_f()
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
//______________________________________________________________________________________________IN_GetIOHandle()
io_connect_t IN_GetIOHandle (void)
{
io_connect_t myHandle = MACH_PORT_NULL;
kern_return_t myStatus;
io_service_t myService = MACH_PORT_NULL;
mach_port_t myMasterPort;
myStatus = IOMasterPort (MACH_PORT_NULL, &myMasterPort );
if (myStatus != KERN_SUCCESS)
{
return (NULL);
}
myService = IORegistryEntryFromPath (myMasterPort, kIOServicePlane ":/IOResources/IOHIDSystem");
if (myService == NULL)
{
return (NULL);
}
myStatus = IOServiceOpen (myService, mach_task_self (), kIOHIDParamConnectType, &myHandle);
IOObjectRelease (myService);
return (myHandle);
}
//___________________________________________________________________________________IN_SetMouseScalingEnabled()
void IN_SetMouseScalingEnabled (Boolean theState)
{
static BOOL myMouseScalingEnabled = YES;
static double myOldAcceleration = 0.0;
io_connect_t myIOHandle = NULL;
// Do we have a state change?
if (theState == myMouseScalingEnabled)
{
return;
}
// Get the IOKit handle:
myIOHandle = IN_GetIOHandle ();
if (myIOHandle == NULL)
{
return;
}
// Set the mouse acceleration according to the current state:
if (theState == YES)
{
IOHIDSetAccelerationWithKey (myIOHandle,
CFSTR (kIOHIDMouseAccelerationType),
myOldAcceleration);
}
else
{
kern_return_t myStatus;
myStatus = IOHIDGetAccelerationWithKey (myIOHandle,
CFSTR (kIOHIDMouseAccelerationType),
&myOldAcceleration);
// change only the settings, if we were successfull!
if (myStatus != kIOReturnSuccess || myOldAcceleration == 0.0)
{
theState = YES;
}
// finally change the acceleration:
if (theState == NO)
{
IOHIDSetAccelerationWithKey (myIOHandle, CFSTR (kIOHIDMouseAccelerationType), -1.0);
}
}
myMouseScalingEnabled = theState;
IOServiceClose (myIOHandle);
}
//_______________________________________________________________________________________________IN_ShowCursor()
void IN_ShowCursor (Boolean theState)
{
static Boolean myCursorIsVisible = YES;
// change only if we got a state change:
if (theState != myCursorIsVisible)
{
if (theState == YES)
{
CGAssociateMouseAndMouseCursorPosition (YES);
IN_SetMouseScalingEnabled (YES);
IN_CenterCursor ();
CGDisplayShowCursor (kCGDirectMainDisplay);
}
else
{
[NSApp activateIgnoringOtherApps: YES];
CGDisplayHideCursor (kCGDirectMainDisplay);
CGAssociateMouseAndMouseCursorPosition (NO);
IN_CenterCursor ();
IN_SetMouseScalingEnabled (NO);
}
myCursorIsVisible = theState;
}
}
//_____________________________________________________________________________________________IN_CenterCursor()
void IN_CenterCursor (void)
{
CGPoint myCenter;
if (gDisplayFullscreen == NO)
{
extern float gWindowPosX, gWindowPosY;
float myCenterX = gWindowPosX, myCenterY = -gWindowPosY;
// calculate the window center:
myCenterX += (float) (vid.width >> 1);
myCenterY += (float) CGDisplayPixelsHigh (kCGDirectMainDisplay) - (float) (vid.height >> 1);
myCenter = CGPointMake (myCenterX, myCenterY);
}
else
{
// just center at the middle of the screen:
myCenter = CGPointMake ((float) (vid.width >> 1), (float) (vid.height >> 1));
}
// and go:
CGDisplayMoveCursorToPoint (kCGDirectMainDisplay, myCenter);
}
//________________________________________________________________________________________________IN_InitMouse()
void IN_InitMouse (void)
{
// check for command line:
if (COM_CheckParm ("-nomouse"))
{
gMouseEnabled = NO;
return;
}
else
{
gMouseEnabled = YES;
}
gMouseMoved = NO;
}
//_____________________________________________________________________________________________________IN_Init()
void IN_Init (void)
{
// register variables:
Cvar_RegisterVariable (&m_filter);
Cvar_RegisterVariable (&aux_look);
// register console commands:
Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f);
Cmd_AddCommand ("force_centerview", Force_CenterView_f);
// init the mouse:
IN_InitMouse ();
IN_SetMouseScalingEnabled (NO);
}
//_________________________________________________________________________________________________IN_Shutdown()
void IN_Shutdown (void)
{
IN_SetMouseScalingEnabled (YES);
}
//_________________________________________________________________________________________________IN_Commands()
void IN_Commands (void)
{
// avoid popping of the app back to the front:
if (gIsHidden == YES)
{
return;
}
// set the cursor visibility by respecting the display mode:
if (gDisplayFullscreen == 1.0f)
{
IN_ShowCursor (NO);
}
else
{
// is the mouse in windowed mode?
if (gMouseEnabled == YES && gIsDeactivated == NO &&
gIsMinimized == NO && _windowed_mouse.value != 0.0f)
{
IN_ShowCursor (NO);
}
else
{
IN_ShowCursor (YES);
}
}
}
//_________________________________________________________________________________________IN_ReceiveMouseMove()
void IN_ReceiveMouseMove (CGMouseDelta theDeltaX, CGMouseDelta theDeltaY)
{
gMouseNewPosition.X = theDeltaX;
gMouseNewPosition.Y = theDeltaY;
}
//________________________________________________________________________________________________IN_MouseMove()
void IN_MouseMove (usercmd_t *cmd)
{
CGMouseDelta myMouseX = gMouseNewPosition.X,
myMouseY = gMouseNewPosition.Y;
if ((gDisplayFullscreen == NO && _windowed_mouse.value == 0.0f) ||
gMouseEnabled == NO || gIsMinimized == YES || gIsDeactivated == YES)
{
return;
}
gMouseNewPosition.X = 0;
gMouseNewPosition.Y = 0;
if (m_filter.value != 0.0f)
{
gMousePosition.X = (myMouseX + gMouseOldPosition.X) >> 1;
gMousePosition.Y = (myMouseY + gMouseOldPosition.Y) >> 1;
}
else
{
gMousePosition.X = myMouseX;
gMousePosition.Y = myMouseY;
}
gMouseOldPosition.X = myMouseX;
gMouseOldPosition.Y = myMouseY;
gMousePosition.X *= sensitivity.value;
gMousePosition.Y *= sensitivity.value;
// lookstrafe or view?
if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1)))
{
cmd->sidemove += m_side.value * gMousePosition.X;
}
else
{
cl.viewangles[YAW] -= m_yaw.value * gMousePosition.X;
}
if (in_mlook.state & 1)
{
V_StopPitchDrift ();
}
if ((in_mlook.state & 1) && !(in_strafe.state & 1))
{
cl.viewangles[PITCH] += m_pitch.value * gMousePosition.Y;
if (cl.viewangles[PITCH] > 80)
{
cl.viewangles[PITCH] = 80;
}
if (cl.viewangles[PITCH] < -70)
{
cl.viewangles[PITCH] = -70;
}
}
else
{
if ((in_strafe.state & 1) && noclip_anglehack)
{
cmd->upmove -= m_forward.value * gMousePosition.Y;
}
else
{
cmd->forwardmove -= m_forward.value * gMousePosition.Y;
}
}
// force the mouse to the center, so there's room to move:
if (myMouseX != 0 || myMouseY != 0)
{
IN_CenterCursor ();
}
}
//_____________________________________________________________________________________________________IN_Move()
void IN_Move (usercmd_t *cmd)
{
IN_MouseMove (cmd);
}
//___________________________________________________________________________________________________________eOF