• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 using namespace OIS;
39 
40 //Events we subscribe to and remove from queue
41 const EventTypeSpec mouseEvents[] = {
42 	{ kEventClassMouse, kEventMouseDown },
43 	{ kEventClassMouse, kEventMouseUp },
44 	{ kEventClassMouse, kEventMouseMoved },
45 	{ kEventClassMouse, kEventMouseDragged },
46 	{ kEventClassMouse, kEventMouseWheelMoved }
47 };
48 
49 const EventTypeSpec WinFocusAcquired [] = {{kEventClassApplication, kEventAppDeactivated}};
50 
51 //-------------------------------------------------------------------//
MacMouse(InputManager * creator,bool buffered)52 MacMouse::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 
~MacMouse()65 MacMouse::~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 
_initialize()83 void 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.0f, 0.0f, 0.0f, 0.0f};
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 
WindowFocusChanged(EventHandlerCallRef nextHandler,EventRef event,void * macMouse)130 OSStatus 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 
setBuffered(bool buffered)147 void MacMouse::setBuffered( bool buffered )
148 {
149 	mBuffered = buffered;
150 }
151 
capture()152 void 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 
_mouseCallback(EventRef theEvent)191 void 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.0f, 0.0f, 0.0f, 0.0f};
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
372