--- src/mac/CocoaMouse.mm (revision 0) +++ src/mac/CocoaMouse.mm (revision 0) @@ -0,0 +1,384 @@ +/* + The zlib/libpng License + + Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com) + + This software is provided 'as-is', without any express or implied warranty. In no event will + the authors be held liable for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, including commercial + applications, and to alter it and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that + you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + */ +#include "mac/CocoaMouse.h" +#include "mac/CocoaInputManager.h" +#include "mac/CocoaHelpers.h" +#include "OISException.h" +#include "OISEvents.h" + +using namespace OIS; + +//-------------------------------------------------------------------// +CocoaMouse::CocoaMouse( InputManager* creator, bool buffered ) + : Mouse(creator->inputSystemName(), buffered, 0, creator) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + CocoaInputManager *man = static_cast(mCreator); + mResponder = [[CocoaMouseView alloc] initWithFrame:[[man->_getWindow() contentView] frame]]; + if(!mResponder) + OIS_EXCEPT( E_General, "CocoaMouseView::CocoaMouseView >> Error creating event responder" ); + + [[man->_getWindow() contentView] addSubview:mResponder]; + [mResponder setOISMouseObj:this]; + + static_cast(mCreator)->_setMouseUsed(true); + + [pool drain]; +} + +CocoaMouse::~CocoaMouse() +{ + // Restore Mouse +// CGAssociateMouseAndMouseCursorPosition(true); + CGDisplayShowCursor(kCGDirectMainDisplay); + + if (mResponder) + { + [mResponder release]; + mResponder = nil; + } + + static_cast(mCreator)->_setMouseUsed(false); +} + +void CocoaMouse::_initialize() +{ + mState.clear(); + CGAssociateMouseAndMouseCursorPosition(false); +} + +void CocoaMouse::setBuffered( bool buffered ) +{ + mBuffered = buffered; +} + +void CocoaMouse::capture() +{ + [mResponder capture]; +} + +@implementation CocoaMouseView + +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + mTempState.clear(); + mMouseWarped = false; + mNeedsToRegainFocus = false; + + // Hide OS Mouse + CGDisplayHideCursor(kCGDirectMainDisplay); + + NSRect clipRect = NSMakeRect(0.0f, 0.0f, 0.0f, 0.0f); + clipRect = [[[self window] contentView] frame]; + + CGPoint warpPoint; + warpPoint.x = (((frame.origin.x + frame.size.width) - frame.origin.x) / 2) + frame.origin.x; + warpPoint.y = (((frame.origin.y + frame.size.height) - frame.origin.y) / 2) - frame.origin.y; +// warpPoint = CGPointMake(clipRect.size.height, clipRect.size.width); + CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint); + + // Use NSTrackingArea to track mouse move events + NSTrackingAreaOptions trackingOptions = + NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag | + NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp; + + NSDictionary *trackerData = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:0], @"OISMouseTrackingKey", nil]; + NSTrackingArea *trackingArea = [[NSTrackingArea alloc] + initWithRect:[self frame]// in our case track the entire view + options:trackingOptions + owner:self + userInfo:trackerData]; + [self addTrackingArea:trackingArea]; + [[self window] setAcceptsMouseMovedEvents:YES]; + [trackingArea release]; + } + return self; +} + +- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent +{ + return YES; +} + +- (void)setOISMouseObj:(CocoaMouse *)obj +{ + oisMouseObj = obj; +} + +- (void)capture +{ + MouseState *state = oisMouseObj->getMouseStatePtr(); + state->X.rel = 0; + state->Y.rel = 0; + state->Z.rel = 0; + + if(mTempState.X.rel || mTempState.Y.rel || mTempState.Z.rel) + { +// NSLog(@"%i %i %i", mTempState.X.rel, mTempState.Y.rel, mTempState.Z.rel); + + // Set new relative motion values + state->X.rel = mTempState.X.rel; + state->Y.rel = mTempState.Y.rel; + state->Z.rel = mTempState.Z.rel; + + // Update absolute position + state->X.abs += mTempState.X.rel; + state->Y.abs += mTempState.Y.rel; + + if(state->X.abs > state->width) + state->X.abs = state->width; + else if(state->X.abs < 0) + state->X.abs = 0; + + if(state->Y.abs > state->height) + state->Y.abs = state->height; + else if(state->Y.abs < 0) + state->Y.abs = 0; + + state->Z.abs += mTempState.Z.rel; + + //Fire off event + if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() ) + oisMouseObj->getEventCallback()->mouseMoved(MouseEvent(oisMouseObj, *state)); + } + + mTempState.clear(); +} + +#pragma mark Left Mouse Event overrides +- (void)mouseDown:(NSEvent *)theEvent +{ + int mouseButton = MB_Left; + NSEventType type = [theEvent type]; + MouseState *state = oisMouseObj->getMouseStatePtr(); + + if(mNeedsToRegainFocus) + return; + + if((type == NSLeftMouseDown) && ([theEvent modifierFlags] & NSAlternateKeyMask)) + { + mouseButton = MB_Middle; + } + else if((type == NSLeftMouseDown) && ([theEvent modifierFlags] & NSControlKeyMask)) + { + mouseButton = MB_Right; + } + else if(type == NSLeftMouseDown) + { + mouseButton = MB_Left; + } + state->buttons |= 1 << mouseButton; + if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() ) + oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton ); +} + +- (void)mouseUp:(NSEvent *)theEvent { + int mouseButton = MB_Left; + NSEventType type = [theEvent type]; + MouseState *state = oisMouseObj->getMouseStatePtr(); + + if((type == NSLeftMouseUp) && ([theEvent modifierFlags] & NSAlternateKeyMask)) + { + mouseButton = MB_Middle; + } + else if((type == NSLeftMouseUp) && ([theEvent modifierFlags] & NSControlKeyMask)) + { + mouseButton = MB_Right; + } + else if(type == NSLeftMouseUp) + { + mouseButton = MB_Left; + } + state->buttons &= ~(1 << mouseButton); + + if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() ) + oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton ); +} + + +- (void)mouseDragged:(NSEvent *)theEvent +{ + CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]); + if(mNeedsToRegainFocus) + return; + + // Relative positioning + if(!mMouseWarped) + { + mTempState.X.rel += delta.x; + mTempState.Y.rel += delta.y; + } + + mMouseWarped = false; +} + +#pragma mark Right Mouse Event overrides +- (void)rightMouseDown:(NSEvent *)theEvent +{ + int mouseButton = MB_Right; + NSEventType type = [theEvent type]; + MouseState *state = oisMouseObj->getMouseStatePtr(); + + if(mNeedsToRegainFocus) + return; + + if(type == NSRightMouseDown) + { + state->buttons |= 1 << mouseButton; + } + + if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() ) + oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton ); +} + +- (void)rightMouseUp:(NSEvent *)theEvent { + int mouseButton = MB_Right; + NSEventType type = [theEvent type]; + MouseState *state = oisMouseObj->getMouseStatePtr(); + + if(type == NSRightMouseUp) + { + state->buttons &= ~(1 << mouseButton); + } + + if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() ) + oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton ); +} + +- (void)rightMouseDragged:(NSEvent *)theEvent +{ + CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]); + if(mNeedsToRegainFocus) + return; + + // Relative positioning + if(!mMouseWarped) + { + mTempState.X.rel += delta.x; + mTempState.Y.rel += delta.y; + } + + mMouseWarped = false; +} + +#pragma mark Other Mouse Event overrides +- (void)otherMouseDown:(NSEvent *)theEvent +{ + int mouseButton = MB_Middle; + NSEventType type = [theEvent type]; + MouseState *state = oisMouseObj->getMouseStatePtr(); + + if(mNeedsToRegainFocus) + return; + + if(type == NSOtherMouseDown) + { + state->buttons |= 1 << mouseButton; + } + + if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() ) + oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton ); +} + +- (void)otherMouseUp:(NSEvent *)theEvent { + int mouseButton = MB_Middle; + NSEventType type = [theEvent type]; + MouseState *state = oisMouseObj->getMouseStatePtr(); + + if(type == NSOtherMouseUp) + { + state->buttons &= ~(1 << mouseButton); + } + + if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() ) + oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton ); +} + +- (void)otherMouseDragged:(NSEvent *)theEvent +{ + CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]); + if(mNeedsToRegainFocus) + return; + + // Relative positioning + if(!mMouseWarped) + { + mTempState.X.rel += delta.x; + mTempState.Y.rel += delta.y; + } + + mMouseWarped = false; +} + +- (void)scrollWheel:(NSEvent *)theEvent +{ + if([theEvent deltaY] != 0.0) + mTempState.Z.rel += ([theEvent deltaY] * 60); +} + +- (void)mouseMoved:(NSEvent *)theEvent +{ + CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]); + if(mNeedsToRegainFocus) + return; + + // Relative positioning + if(!mMouseWarped) + { + mTempState.X.rel += delta.x; + mTempState.Y.rel += delta.y; + } + + mMouseWarped = false; +} + +- (void)mouseEntered:(NSEvent *)theEvent +{ + CGDisplayHideCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(false); + if(!mMouseWarped) + { + NSPoint pos = [[self window] mouseLocationOutsideOfEventStream]; + NSRect frame = [[[self window] contentView] frame]; + + // Clear the previous mouse state + MouseState *state = oisMouseObj->getMouseStatePtr(); + state->clear(); + + // Cocoa's coordinate system has the origin in the bottom left so we need to transform the height + mTempState.X.rel = pos.x; + mTempState.Y.rel = frame.size.height - pos.y; + } +} + +- (void)mouseExited:(NSEvent *)theEvent +{ + CGDisplayShowCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(true); +} + +@end