PageRenderTime 56ms CodeModel.GetById 2ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ois/src/mac/MacMouse.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 371 lines | 221 code | 74 blank | 76 comment | 64 complexity | b98318143d714d101604782cf0e73f5d MD5 | raw file
  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
 24#ifndef __LP64__
 25
 26#include "mac/MacMouse.h"
 27#include "mac/MacInputManager.h"
 28#include "mac/MacHelpers.h"
 29#include "OISException.h"
 30#include "OISEvents.h"
 31
 32#include <Carbon/Carbon.h>
 33
 34#include <list>
 35
 36#include <iostream>
 37
 38using namespace OIS;
 39
 40//Events we subscribe to and remove from queue
 41const EventTypeSpec mouseEvents[] = {
 42	{ kEventClassMouse, kEventMouseDown },
 43	{ kEventClassMouse, kEventMouseUp },
 44	{ kEventClassMouse, kEventMouseMoved },
 45	{ kEventClassMouse, kEventMouseDragged },
 46	{ kEventClassMouse, kEventMouseWheelMoved }		
 47};
 48
 49const EventTypeSpec WinFocusAcquired [] = {{kEventClassApplication, kEventAppDeactivated}};
 50
 51//-------------------------------------------------------------------//
 52MacMouse::MacMouse( InputManager* creator, bool buffered )
 53	: Mouse(creator->inputSystemName(), buffered, 0, creator), mNeedsToRegainFocus( false )
 54{
 55    mouseEventRef = NULL;
 56	mWindowFocusHandler = NULL;
 57
 58    // Get a "Univeral procedure pointer" for our callback
 59    mouseUPP = NewEventHandlerUPP(MouseWrapper);
 60	mWindowFocusListener = NewEventHandlerUPP(WindowFocusChanged);
 61
 62	static_cast<MacInputManager*>(mCreator)->_setMouseUsed(true);
 63}
 64
 65MacMouse::~MacMouse()
 66{
 67    if(mouseEventRef != NULL)
 68		RemoveEventHandler(mouseEventRef);
 69
 70	if(mWindowFocusHandler != NULL)
 71		RemoveEventHandler(mWindowFocusHandler);
 72	
 73	DisposeEventHandlerUPP(mouseUPP);
 74	DisposeEventHandlerUPP(mWindowFocusListener);
 75	
 76	// Restore Mouse
 77	CGAssociateMouseAndMouseCursorPosition(TRUE);
 78	CGDisplayShowCursor(kCGDirectMainDisplay);
 79
 80	static_cast<MacInputManager*>(mCreator)->_setMouseUsed(false);
 81}
 82
 83void MacMouse::_initialize()
 84{
 85	mState.clear();
 86	mTempState.clear();
 87	mMouseWarped = false;
 88	
 89	// Hide OS Mouse
 90 	CGDisplayHideCursor(kCGDirectMainDisplay);
 91
 92	MacInputManager* im = static_cast<MacInputManager*>(mCreator);
 93	WindowRef win = im->_getWindow();
 94	
 95	if(win)
 96	{
 97		Rect clipRect = {0, 0, 0, 0};
 98		GetWindowBounds(win, kWindowContentRgn, &clipRect);
 99		
100		CGPoint warpPoint;
101		warpPoint.x = ((clipRect.right - clipRect.left) / 2) + clipRect.left;
102		warpPoint.y = ((clipRect.bottom - clipRect.top) / 2) + clipRect.top;
103		CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint); //Place at display origin
104		
105		mMouseWarped = true;
106	}
107
108	//Now that mouse is warped, start listening for events
109	EventTargetRef event = ((MacInputManager*)mCreator)->_getEventTarget();
110    
111	if(mouseEventRef != NULL)
112		RemoveEventHandler(mouseEventRef);
113		
114	if(mWindowFocusHandler != NULL)
115		RemoveEventHandler(mWindowFocusHandler);
116
117	mouseEventRef = mWindowFocusHandler = NULL;
118
119	if(InstallEventHandler(event, mouseUPP, GetEventTypeCount(mouseEvents), mouseEvents, this, &mouseEventRef) != noErr)
120		OIS_EXCEPT( E_General, "MacMouse::_initialize >> Error loading Mouse event handler" );
121
122	if(InstallEventHandler(event, mWindowFocusListener, GetEventTypeCount(WinFocusAcquired), WinFocusAcquired, this, &mWindowFocusHandler) != noErr)
123		OIS_EXCEPT( E_General, "MacMouse::_initialize >> Error loading Mouse event handler" );		
124
125	//Lock OS Mouse movement
126	mNeedsToRegainFocus = false;
127	CGAssociateMouseAndMouseCursorPosition(FALSE);
128}
129
130OSStatus MacMouse::WindowFocusChanged(EventHandlerCallRef nextHandler, EventRef event, void* macMouse)
131{
132	//std::cout << "Window Focus Changed\n";
133
134	MacMouse* _this = static_cast<MacMouse*>(macMouse);
135    if (_this)
136	{
137		_this->mNeedsToRegainFocus = true;
138		CGAssociateMouseAndMouseCursorPosition(TRUE);
139
140        // propagate the event down the chain
141        return CallNextEventHandler(nextHandler, event);
142    }
143    else
144        OIS_EXCEPT(E_General, "MouseWrapper >> Being called by something other than our event handler!");
145}
146
147void MacMouse::setBuffered( bool buffered )
148{
149	mBuffered = buffered;
150}
151
152void MacMouse::capture()
153{
154	mState.X.rel = 0;
155	mState.Y.rel = 0;
156	mState.Z.rel = 0;
157	    
158	if(mTempState.X.rel || mTempState.Y.rel || mTempState.Z.rel)
159	{
160		//printf("%i %i %i\n\n", mTempState.X.rel, mTempState.Y.rel, mTempState.Z.rel);
161
162		//Set new relative motion values
163		mState.X.rel = mTempState.X.rel;
164		mState.Y.rel = mTempState.Y.rel;
165		mState.Z.rel = mTempState.Z.rel;
166		
167		//Update absolute position
168		mState.X.abs += mTempState.X.rel;
169		mState.Y.abs += mTempState.Y.rel;
170		
171		if(mState.X.abs > mState.width)
172			mState.X.abs = mState.width;
173		else if(mState.X.abs < 0)
174			mState.X.abs = 0;
175
176		if(mState.Y.abs > mState.height)
177			mState.Y.abs = mState.height;
178		else if(mState.Y.abs < 0)
179			mState.Y.abs = 0;
180			
181		mState.Z.abs += mTempState.Z.rel;
182		
183		//Fire off event
184		if(mListener && mBuffered)
185			mListener->mouseMoved(MouseEvent(this, mState));
186	}
187
188	mTempState.clear();
189}
190
191void MacMouse::_mouseCallback( EventRef theEvent )
192{
193    UInt32 kind = GetEventKind (theEvent);
194
195	switch(kind)
196	{
197		case kEventMouseDragged:
198		case kEventMouseMoved:
199		{
200			//HIPoint location = {0.0f, 0.0f};
201			HIPoint delta = {0.0f, 0.0f};
202			//Rect clipRect = {0.0f, 0.0f, 0.0f, 0.0f};
203			
204			if(mNeedsToRegainFocus)
205				break;
206
207			// Capture the parameters
208			// TODO: Look into HIViewNewTrackingArea
209			//GetEventParameter(theEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(HIPoint), NULL, &location);
210			GetEventParameter(theEvent, kEventParamMouseDelta, typeHIPoint, NULL, sizeof(HIPoint), NULL, &delta);
211			
212			// Mouse X and Y are the position on the screen, 
213			// startng from top-left at 0,0 caps at full monitor resolution
214			
215			// If we have a window we need to return adjusted coordinates
216			// If not, just use raw coordinates - only do this if showing OS mouse
217			//MacInputManager* im = static_cast<MacInputManager*>(mCreator);
218			//WindowRef win = im->_getWindow();
219			
220			//if(win != NULL)
221			//{
222			//	GetWindowBounds(win, kWindowContentRgn, &clipRect);
223			//}
224            //else
225            //{
226            //    clipRect.right = mState.width;
227            //    clipRect.bottom = mState.height;
228            //}
229                
230            // clip the mouse, absolute positioning
231            //if (location.x <= clipRect.left)
232			//	mState.X.abs = 0;
233			//else if(location.x >= clipRect.right)
234			//	mState.X.abs = clipRect.right - clipRect.left;
235			//else
236			//	mState.X.abs = location.x - clipRect.left;
237			
238			//if (location.y <= clipRect.top)
239			//	mState.Y.abs = 0;
240			//else if(location.y >= clipRect.bottom)
241			//	mState.Y.abs = clipRect.bottom - clipRect.top;
242			//else
243			//	mState.Y.abs = location.y - clipRect.top;
244			
245			// relative positioning
246			if(!mMouseWarped)
247			{
248				mTempState.X.rel += delta.x;
249				mTempState.Y.rel += delta.y;
250			}
251			
252			mMouseWarped = false;
253
254			break;
255		}
256		case kEventMouseDown:
257		{
258			EventMouseButton button = 0;
259			int mouseButton = 3;
260			UInt32 modifiers = 0;
261			
262			if(mNeedsToRegainFocus)
263				break;
264
265			// Capture parameters
266			GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &button);
267			GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
268			
269			if((button == kEventMouseButtonTertiary) || ((button == kEventMouseButtonPrimary) && (modifiers & optionKey)))
270			{
271				mouseButton = 2;
272				mState.buttons |= 1 << mouseButton;
273			}
274            else if((button == kEventMouseButtonSecondary) || ((button == kEventMouseButtonPrimary) && (modifiers & controlKey)))
275            {	
276                mouseButton = 1;
277                mState.buttons |= 1 << mouseButton;
278            }
279            else if(button == kEventMouseButtonPrimary)
280            {
281                mouseButton = 0;
282                mState.buttons |= 1 << mouseButton;
283            }
284
285            if( mListener && mBuffered )
286                mListener->mousePressed( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
287
288            break;
289		}
290		case kEventMouseUp:
291		{
292			EventMouseButton button = 0;
293			int mouseButton = 3;
294			UInt32 modifiers = 0;
295			
296			if(mNeedsToRegainFocus)
297			{
298				mNeedsToRegainFocus = false;
299				CGAssociateMouseAndMouseCursorPosition(false);
300				
301				MacInputManager* im = static_cast<MacInputManager*>(mCreator);
302				WindowRef win = im->_getWindow();
303				
304				if(win)
305				{
306					Rect clipRect = {0, 0, 0, 0};
307					GetWindowBounds(win, kWindowContentRgn, &clipRect);
308					
309					CGPoint warpPoint;
310					warpPoint.x = ((clipRect.right - clipRect.left) / 2) + clipRect.left;
311					warpPoint.y = ((clipRect.bottom - clipRect.top) / 2) + clipRect.top;
312					CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint); //Place at display origin
313					
314					CGDisplayHideCursor(kCGDirectMainDisplay);
315					
316					mMouseWarped = true;
317				}
318				
319				//Once we regain focus, we do not really know what state all the buttons are in - for now, set to not pressed. todo, check current status
320				//compare against old status, and send off any needed events
321				mState.buttons = 0;
322				
323				break;
324			}
325			
326			// Capture parameters
327			GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &button);
328			GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
329			
330			if ((button == kEventMouseButtonTertiary) || ((button == kEventMouseButtonPrimary) && (modifiers & optionKey)))
331			{
332				mouseButton = 2;
333				mState.buttons &= ~(1 << mouseButton);
334			}
335            else if ((button == kEventMouseButtonSecondary) || ((button == kEventMouseButtonPrimary) && (modifiers & controlKey)))
336            {	
337                mouseButton = 1;
338                mState.buttons &= ~(1 << mouseButton);
339            }
340            else if (button == kEventMouseButtonPrimary)
341            {
342                mouseButton = 0;
343                mState.buttons &= ~(1 << mouseButton);
344            }
345
346            if( mListener && mBuffered )
347                mListener->mouseReleased( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
348
349            break;
350		}
351		case kEventMouseWheelMoved:
352		{
353			SInt32 wheelDelta = 0;
354			EventMouseWheelAxis	wheelAxis = 0; 
355
356			// Capture parameters
357			GetEventParameter(theEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(EventMouseWheelAxis), NULL, &wheelAxis);
358			GetEventParameter(theEvent, kEventParamMouseWheelDelta, typeSInt32, NULL, sizeof(SInt32), NULL, &wheelDelta);
359			
360			// If the Y axis of the wheel changed, then update the Z
361			// Does OIS care about the X wheel axis?
362			if(wheelAxis == kEventMouseWheelAxisY)
363				mTempState.Z.rel += (wheelDelta * 60);
364
365            break;
366		}
367		default:
368			break;
369	}    
370}
371#endif