405 lines
11 KiB
Objective-C
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
|