Home | History | Annotate | Download | only in mac
      1 /*
      2  The zlib/libpng License
      3 
      4  Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
      5 
      6  This software is provided 'as-is', without any express or implied warranty. In no event will
      7  the authors be held liable for any damages arising from the use of this software.
      8 
      9  Permission is granted to anyone to use this software for any purpose, including commercial
     10  applications, and to alter it and redistribute it freely, subject to the following
     11  restrictions:
     12 
     13  1. The origin of this software must not be misrepresented; you must not claim that
     14  you wrote the original software. If you use this software in a product,
     15  an acknowledgment in the product documentation would be appreciated but is
     16  not required.
     17 
     18  2. Altered source versions must be plainly marked as such, and must not be
     19  misrepresented as being the original software.
     20 
     21  3. This notice may not be removed or altered from any source distribution.
     22  */
     23 #include "mac/CocoaMouse.h"
     24 #include "mac/CocoaInputManager.h"
     25 #include "mac/CocoaHelpers.h"
     26 #include "OISException.h"
     27 #include "OISEvents.h"
     28 
     29 using namespace OIS;
     30 
     31 //-------------------------------------------------------------------//
     32 CocoaMouse::CocoaMouse( InputManager* creator, bool buffered )
     33 	: Mouse(creator->inputSystemName(), buffered, 0, creator)
     34 {
     35     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     36 
     37 	CocoaInputManager *man = static_cast<CocoaInputManager*>(mCreator);
     38     mResponder = [[CocoaMouseView alloc] initWithFrame:[[man->_getWindow() contentView] frame]];
     39     if(!mResponder)
     40         OIS_EXCEPT( E_General, "CocoaMouseView::CocoaMouseView >> Error creating event responder" );
     41 
     42     [[man->_getWindow() contentView] addSubview:mResponder];
     43     [mResponder setOISMouseObj:this];
     44 
     45 	static_cast<CocoaInputManager*>(mCreator)->_setMouseUsed(true);
     46 
     47     [pool drain];
     48 }
     49 
     50 CocoaMouse::~CocoaMouse()
     51 {
     52 	// Restore Mouse
     53 //	CGAssociateMouseAndMouseCursorPosition(true);
     54 	CGDisplayShowCursor(kCGDirectMainDisplay);
     55 
     56     if (mResponder)
     57     {
     58         [mResponder release];
     59         mResponder = nil;
     60     }
     61 
     62 	static_cast<CocoaInputManager*>(mCreator)->_setMouseUsed(false);
     63 }
     64 
     65 void CocoaMouse::_initialize()
     66 {
     67 	mState.clear();
     68 	CGAssociateMouseAndMouseCursorPosition(false);
     69 }
     70 
     71 void CocoaMouse::setBuffered( bool buffered )
     72 {
     73 	mBuffered = buffered;
     74 }
     75 
     76 void CocoaMouse::capture()
     77 {
     78     [mResponder capture];
     79 }
     80 
     81 @implementation CocoaMouseView
     82 
     83 - (id)initWithFrame:(NSRect)frame
     84 {
     85     self = [super initWithFrame:frame];
     86     if (self) {
     87         mTempState.clear();
     88         mMouseWarped = false;
     89         mNeedsToRegainFocus = false;
     90 
     91         // Hide OS Mouse
     92         CGDisplayHideCursor(kCGDirectMainDisplay);
     93 
     94         NSRect clipRect = NSMakeRect(0.0f, 0.0f, 0.0f, 0.0f);
     95         clipRect = [[[self window] contentView] frame];
     96 
     97         CGPoint warpPoint;
     98 		warpPoint.x = (((frame.origin.x + frame.size.width) - frame.origin.x) / 2) + frame.origin.x;
     99 		warpPoint.y = (((frame.origin.y + frame.size.height) - frame.origin.y) / 2) - frame.origin.y;
    100 //        warpPoint = CGPointMake(clipRect.size.height, clipRect.size.width);
    101         CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint);
    102 
    103         // Use NSTrackingArea to track mouse move events
    104         NSTrackingAreaOptions trackingOptions =
    105             NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag |
    106             NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp;
    107 
    108         NSDictionary *trackerData = [NSDictionary dictionaryWithObjectsAndKeys:
    109                                      [NSNumber numberWithInt:0], @"OISMouseTrackingKey", nil];
    110         NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
    111                                         initWithRect:[self frame]// in our case track the entire view
    112                                         options:trackingOptions
    113                                         owner:self
    114                                         userInfo:trackerData];
    115         [self addTrackingArea:trackingArea];
    116         [[self window] setAcceptsMouseMovedEvents:YES];
    117         [trackingArea release];
    118     }
    119     return self;
    120 }
    121 
    122 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
    123 {
    124     return YES;
    125 }
    126 
    127 - (void)setOISMouseObj:(CocoaMouse *)obj
    128 {
    129     oisMouseObj = obj;
    130 }
    131 
    132 - (void)capture
    133 {
    134 	MouseState *state = oisMouseObj->getMouseStatePtr();
    135     state->X.rel = 0;
    136     state->Y.rel = 0;
    137     state->Z.rel = 0;
    138 
    139 	if(mTempState.X.rel || mTempState.Y.rel || mTempState.Z.rel)
    140 	{
    141 //		NSLog(@"%i %i %i", mTempState.X.rel, mTempState.Y.rel, mTempState.Z.rel);
    142 
    143 		// Set new relative motion values
    144 		state->X.rel = mTempState.X.rel;
    145 		state->Y.rel = mTempState.Y.rel;
    146 		state->Z.rel = mTempState.Z.rel;
    147 
    148 		// Update absolute position
    149 		state->X.abs += mTempState.X.rel;
    150 		state->Y.abs += mTempState.Y.rel;
    151 
    152 		if(state->X.abs > state->width)
    153 			state->X.abs = state->width;
    154 		else if(state->X.abs < 0)
    155 			state->X.abs = 0;
    156 
    157 		if(state->Y.abs > state->height)
    158 			state->Y.abs = state->height;
    159 		else if(state->Y.abs < 0)
    160 			state->Y.abs = 0;
    161 
    162 		state->Z.abs += mTempState.Z.rel;
    163 
    164 		//Fire off event
    165         if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
    166 			oisMouseObj->getEventCallback()->mouseMoved(MouseEvent(oisMouseObj, *state));
    167 	}
    168 
    169 	mTempState.clear();
    170 }
    171 
    172 #pragma mark Left Mouse Event overrides
    173 - (void)mouseDown:(NSEvent *)theEvent
    174 {
    175     int mouseButton = MB_Left;
    176     NSEventType type = [theEvent type];
    177     MouseState *state = oisMouseObj->getMouseStatePtr();
    178 
    179     if(mNeedsToRegainFocus)
    180         return;
    181 
    182     if((type == NSLeftMouseDown) && ([theEvent modifierFlags] & NSAlternateKeyMask))
    183     {
    184         mouseButton = MB_Middle;
    185     }
    186     else if((type == NSLeftMouseDown) && ([theEvent modifierFlags] & NSControlKeyMask))
    187     {
    188         mouseButton = MB_Right;
    189     }
    190     else if(type == NSLeftMouseDown)
    191     {
    192         mouseButton = MB_Left;
    193     }
    194     state->buttons |= 1 << mouseButton;
    195     if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
    196         oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
    197 }
    198 
    199 - (void)mouseUp:(NSEvent *)theEvent {
    200     int mouseButton = MB_Left;
    201     NSEventType type = [theEvent type];
    202     MouseState *state = oisMouseObj->getMouseStatePtr();
    203 
    204     if((type == NSLeftMouseUp) && ([theEvent modifierFlags] & NSAlternateKeyMask))
    205     {
    206         mouseButton = MB_Middle;
    207     }
    208     else if((type == NSLeftMouseUp) && ([theEvent modifierFlags] & NSControlKeyMask))
    209     {
    210         mouseButton = MB_Right;
    211     }
    212     else if(type == NSLeftMouseUp)
    213     {
    214         mouseButton = MB_Left;
    215     }
    216     state->buttons &= ~(1 << mouseButton);
    217 
    218     if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
    219         oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
    220 }
    221 
    222 
    223 - (void)mouseDragged:(NSEvent *)theEvent
    224 {
    225     CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]);
    226     if(mNeedsToRegainFocus)
    227         return;
    228 
    229     // Relative positioning
    230     if(!mMouseWarped)
    231     {
    232         mTempState.X.rel += delta.x;
    233         mTempState.Y.rel += delta.y;
    234     }
    235 
    236     mMouseWarped = false;
    237 }
    238 
    239 #pragma mark Right Mouse Event overrides
    240 - (void)rightMouseDown:(NSEvent *)theEvent
    241 {
    242     int mouseButton = MB_Right;
    243     NSEventType type = [theEvent type];
    244     MouseState *state = oisMouseObj->getMouseStatePtr();
    245 
    246     if(mNeedsToRegainFocus)
    247         return;
    248 
    249     if(type == NSRightMouseDown)
    250     {
    251         state->buttons |= 1 << mouseButton;
    252     }
    253 
    254     if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
    255         oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
    256 }
    257 
    258 - (void)rightMouseUp:(NSEvent *)theEvent {
    259     int mouseButton = MB_Right;
    260     NSEventType type = [theEvent type];
    261     MouseState *state = oisMouseObj->getMouseStatePtr();
    262 
    263     if(type == NSRightMouseUp)
    264     {
    265         state->buttons &= ~(1 << mouseButton);
    266     }
    267 
    268     if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
    269         oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
    270 }
    271 
    272 - (void)rightMouseDragged:(NSEvent *)theEvent
    273 {
    274     CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]);
    275     if(mNeedsToRegainFocus)
    276         return;
    277 
    278     // Relative positioning
    279     if(!mMouseWarped)
    280     {
    281         mTempState.X.rel += delta.x;
    282         mTempState.Y.rel += delta.y;
    283     }
    284 
    285     mMouseWarped = false;
    286 }
    287 
    288 #pragma mark Other Mouse Event overrides
    289 - (void)otherMouseDown:(NSEvent *)theEvent
    290 {
    291     int mouseButton = MB_Middle;
    292     NSEventType type = [theEvent type];
    293     MouseState *state = oisMouseObj->getMouseStatePtr();
    294 
    295     if(mNeedsToRegainFocus)
    296         return;
    297 
    298     if(type == NSOtherMouseDown)
    299     {
    300         state->buttons |= 1 << mouseButton;
    301     }
    302 
    303     if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
    304         oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
    305 }
    306 
    307 - (void)otherMouseUp:(NSEvent *)theEvent {
    308     int mouseButton = MB_Middle;
    309     NSEventType type = [theEvent type];
    310     MouseState *state = oisMouseObj->getMouseStatePtr();
    311 
    312     if(type == NSOtherMouseUp)
    313     {
    314         state->buttons &= ~(1 << mouseButton);
    315     }
    316 
    317     if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
    318         oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
    319 }
    320 
    321 - (void)otherMouseDragged:(NSEvent *)theEvent
    322 {
    323     CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]);
    324     if(mNeedsToRegainFocus)
    325         return;
    326 
    327     // Relative positioning
    328     if(!mMouseWarped)
    329     {
    330         mTempState.X.rel += delta.x;
    331         mTempState.Y.rel += delta.y;
    332     }
    333 
    334     mMouseWarped = false;
    335 }
    336 
    337 - (void)scrollWheel:(NSEvent *)theEvent
    338 {
    339     if([theEvent deltaY] != 0.0)
    340         mTempState.Z.rel += ([theEvent deltaY] * 60);
    341 }
    342 
    343 - (void)mouseMoved:(NSEvent *)theEvent
    344 {
    345     CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]);
    346     if(mNeedsToRegainFocus)
    347         return;
    348 
    349     // Relative positioning
    350     if(!mMouseWarped)
    351     {
    352         mTempState.X.rel += delta.x;
    353         mTempState.Y.rel += delta.y;
    354     }
    355 
    356     mMouseWarped = false;
    357 }
    358 
    359 - (void)mouseEntered:(NSEvent *)theEvent
    360 {
    361 	CGDisplayHideCursor(kCGDirectMainDisplay);
    362 	CGAssociateMouseAndMouseCursorPosition(false);
    363     if(!mMouseWarped)
    364     {
    365         NSPoint pos = [[self window] mouseLocationOutsideOfEventStream];
    366         NSRect frame = [[[self window] contentView] frame];
    367 
    368         // Clear the previous mouse state
    369         MouseState *state = oisMouseObj->getMouseStatePtr();
    370         state->clear();
    371 
    372         // Cocoa's coordinate system has the origin in the bottom left so we need to transform the height
    373         mTempState.X.rel = pos.x;
    374         mTempState.Y.rel = frame.size.height - pos.y;
    375     }
    376 }
    377 
    378 - (void)mouseExited:(NSEvent *)theEvent
    379 {
    380 	CGDisplayShowCursor(kCGDirectMainDisplay);
    381 	CGAssociateMouseAndMouseCursorPosition(true);
    382 }
    383 
    384 @end
    385