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

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 371 lines · 221 code · 74 blank · 76 comment · 65 complexity · b98318143d714d101604782cf0e73f5d MD5 · raw file

  1. /*
  2. The zlib/libpng License
  3. Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
  4. This software is provided 'as-is', without any express or implied warranty. In no event will
  5. the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose, including commercial
  7. applications, and to alter it and redistribute it freely, subject to the following
  8. restrictions:
  9. 1. The origin of this software must not be misrepresented; you must not claim that
  10. you wrote the original software. If you use this software in a product,
  11. an acknowledgment in the product documentation would be appreciated but is
  12. not required.
  13. 2. Altered source versions must be plainly marked as such, and must not be
  14. misrepresented as being the original software.
  15. 3. This notice may not be removed or altered from any source distribution.
  16. */
  17. #ifndef __LP64__
  18. #include "mac/MacMouse.h"
  19. #include "mac/MacInputManager.h"
  20. #include "mac/MacHelpers.h"
  21. #include "OISException.h"
  22. #include "OISEvents.h"
  23. #include <Carbon/Carbon.h>
  24. #include <list>
  25. #include <iostream>
  26. using namespace OIS;
  27. //Events we subscribe to and remove from queue
  28. const EventTypeSpec mouseEvents[] = {
  29. { kEventClassMouse, kEventMouseDown },
  30. { kEventClassMouse, kEventMouseUp },
  31. { kEventClassMouse, kEventMouseMoved },
  32. { kEventClassMouse, kEventMouseDragged },
  33. { kEventClassMouse, kEventMouseWheelMoved }
  34. };
  35. const EventTypeSpec WinFocusAcquired [] = {{kEventClassApplication, kEventAppDeactivated}};
  36. //-------------------------------------------------------------------//
  37. MacMouse::MacMouse( InputManager* creator, bool buffered )
  38. : Mouse(creator->inputSystemName(), buffered, 0, creator), mNeedsToRegainFocus( false )
  39. {
  40. mouseEventRef = NULL;
  41. mWindowFocusHandler = NULL;
  42. // Get a "Univeral procedure pointer" for our callback
  43. mouseUPP = NewEventHandlerUPP(MouseWrapper);
  44. mWindowFocusListener = NewEventHandlerUPP(WindowFocusChanged);
  45. static_cast<MacInputManager*>(mCreator)->_setMouseUsed(true);
  46. }
  47. MacMouse::~MacMouse()
  48. {
  49. if(mouseEventRef != NULL)
  50. RemoveEventHandler(mouseEventRef);
  51. if(mWindowFocusHandler != NULL)
  52. RemoveEventHandler(mWindowFocusHandler);
  53. DisposeEventHandlerUPP(mouseUPP);
  54. DisposeEventHandlerUPP(mWindowFocusListener);
  55. // Restore Mouse
  56. CGAssociateMouseAndMouseCursorPosition(TRUE);
  57. CGDisplayShowCursor(kCGDirectMainDisplay);
  58. static_cast<MacInputManager*>(mCreator)->_setMouseUsed(false);
  59. }
  60. void MacMouse::_initialize()
  61. {
  62. mState.clear();
  63. mTempState.clear();
  64. mMouseWarped = false;
  65. // Hide OS Mouse
  66. CGDisplayHideCursor(kCGDirectMainDisplay);
  67. MacInputManager* im = static_cast<MacInputManager*>(mCreator);
  68. WindowRef win = im->_getWindow();
  69. if(win)
  70. {
  71. Rect clipRect = {0, 0, 0, 0};
  72. GetWindowBounds(win, kWindowContentRgn, &clipRect);
  73. CGPoint warpPoint;
  74. warpPoint.x = ((clipRect.right - clipRect.left) / 2) + clipRect.left;
  75. warpPoint.y = ((clipRect.bottom - clipRect.top) / 2) + clipRect.top;
  76. CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint); //Place at display origin
  77. mMouseWarped = true;
  78. }
  79. //Now that mouse is warped, start listening for events
  80. EventTargetRef event = ((MacInputManager*)mCreator)->_getEventTarget();
  81. if(mouseEventRef != NULL)
  82. RemoveEventHandler(mouseEventRef);
  83. if(mWindowFocusHandler != NULL)
  84. RemoveEventHandler(mWindowFocusHandler);
  85. mouseEventRef = mWindowFocusHandler = NULL;
  86. if(InstallEventHandler(event, mouseUPP, GetEventTypeCount(mouseEvents), mouseEvents, this, &mouseEventRef) != noErr)
  87. OIS_EXCEPT( E_General, "MacMouse::_initialize >> Error loading Mouse event handler" );
  88. if(InstallEventHandler(event, mWindowFocusListener, GetEventTypeCount(WinFocusAcquired), WinFocusAcquired, this, &mWindowFocusHandler) != noErr)
  89. OIS_EXCEPT( E_General, "MacMouse::_initialize >> Error loading Mouse event handler" );
  90. //Lock OS Mouse movement
  91. mNeedsToRegainFocus = false;
  92. CGAssociateMouseAndMouseCursorPosition(FALSE);
  93. }
  94. OSStatus MacMouse::WindowFocusChanged(EventHandlerCallRef nextHandler, EventRef event, void* macMouse)
  95. {
  96. //std::cout << "Window Focus Changed\n";
  97. MacMouse* _this = static_cast<MacMouse*>(macMouse);
  98. if (_this)
  99. {
  100. _this->mNeedsToRegainFocus = true;
  101. CGAssociateMouseAndMouseCursorPosition(TRUE);
  102. // propagate the event down the chain
  103. return CallNextEventHandler(nextHandler, event);
  104. }
  105. else
  106. OIS_EXCEPT(E_General, "MouseWrapper >> Being called by something other than our event handler!");
  107. }
  108. void MacMouse::setBuffered( bool buffered )
  109. {
  110. mBuffered = buffered;
  111. }
  112. void MacMouse::capture()
  113. {
  114. mState.X.rel = 0;
  115. mState.Y.rel = 0;
  116. mState.Z.rel = 0;
  117. if(mTempState.X.rel || mTempState.Y.rel || mTempState.Z.rel)
  118. {
  119. //printf("%i %i %i\n\n", mTempState.X.rel, mTempState.Y.rel, mTempState.Z.rel);
  120. //Set new relative motion values
  121. mState.X.rel = mTempState.X.rel;
  122. mState.Y.rel = mTempState.Y.rel;
  123. mState.Z.rel = mTempState.Z.rel;
  124. //Update absolute position
  125. mState.X.abs += mTempState.X.rel;
  126. mState.Y.abs += mTempState.Y.rel;
  127. if(mState.X.abs > mState.width)
  128. mState.X.abs = mState.width;
  129. else if(mState.X.abs < 0)
  130. mState.X.abs = 0;
  131. if(mState.Y.abs > mState.height)
  132. mState.Y.abs = mState.height;
  133. else if(mState.Y.abs < 0)
  134. mState.Y.abs = 0;
  135. mState.Z.abs += mTempState.Z.rel;
  136. //Fire off event
  137. if(mListener && mBuffered)
  138. mListener->mouseMoved(MouseEvent(this, mState));
  139. }
  140. mTempState.clear();
  141. }
  142. void MacMouse::_mouseCallback( EventRef theEvent )
  143. {
  144. UInt32 kind = GetEventKind (theEvent);
  145. switch(kind)
  146. {
  147. case kEventMouseDragged:
  148. case kEventMouseMoved:
  149. {
  150. //HIPoint location = {0.0f, 0.0f};
  151. HIPoint delta = {0.0f, 0.0f};
  152. //Rect clipRect = {0.0f, 0.0f, 0.0f, 0.0f};
  153. if(mNeedsToRegainFocus)
  154. break;
  155. // Capture the parameters
  156. // TODO: Look into HIViewNewTrackingArea
  157. //GetEventParameter(theEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(HIPoint), NULL, &location);
  158. GetEventParameter(theEvent, kEventParamMouseDelta, typeHIPoint, NULL, sizeof(HIPoint), NULL, &delta);
  159. // Mouse X and Y are the position on the screen,
  160. // startng from top-left at 0,0 caps at full monitor resolution
  161. // If we have a window we need to return adjusted coordinates
  162. // If not, just use raw coordinates - only do this if showing OS mouse
  163. //MacInputManager* im = static_cast<MacInputManager*>(mCreator);
  164. //WindowRef win = im->_getWindow();
  165. //if(win != NULL)
  166. //{
  167. // GetWindowBounds(win, kWindowContentRgn, &clipRect);
  168. //}
  169. //else
  170. //{
  171. // clipRect.right = mState.width;
  172. // clipRect.bottom = mState.height;
  173. //}
  174. // clip the mouse, absolute positioning
  175. //if (location.x <= clipRect.left)
  176. // mState.X.abs = 0;
  177. //else if(location.x >= clipRect.right)
  178. // mState.X.abs = clipRect.right - clipRect.left;
  179. //else
  180. // mState.X.abs = location.x - clipRect.left;
  181. //if (location.y <= clipRect.top)
  182. // mState.Y.abs = 0;
  183. //else if(location.y >= clipRect.bottom)
  184. // mState.Y.abs = clipRect.bottom - clipRect.top;
  185. //else
  186. // mState.Y.abs = location.y - clipRect.top;
  187. // relative positioning
  188. if(!mMouseWarped)
  189. {
  190. mTempState.X.rel += delta.x;
  191. mTempState.Y.rel += delta.y;
  192. }
  193. mMouseWarped = false;
  194. break;
  195. }
  196. case kEventMouseDown:
  197. {
  198. EventMouseButton button = 0;
  199. int mouseButton = 3;
  200. UInt32 modifiers = 0;
  201. if(mNeedsToRegainFocus)
  202. break;
  203. // Capture parameters
  204. GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &button);
  205. GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
  206. if((button == kEventMouseButtonTertiary) || ((button == kEventMouseButtonPrimary) && (modifiers & optionKey)))
  207. {
  208. mouseButton = 2;
  209. mState.buttons |= 1 << mouseButton;
  210. }
  211. else if((button == kEventMouseButtonSecondary) || ((button == kEventMouseButtonPrimary) && (modifiers & controlKey)))
  212. {
  213. mouseButton = 1;
  214. mState.buttons |= 1 << mouseButton;
  215. }
  216. else if(button == kEventMouseButtonPrimary)
  217. {
  218. mouseButton = 0;
  219. mState.buttons |= 1 << mouseButton;
  220. }
  221. if( mListener && mBuffered )
  222. mListener->mousePressed( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
  223. break;
  224. }
  225. case kEventMouseUp:
  226. {
  227. EventMouseButton button = 0;
  228. int mouseButton = 3;
  229. UInt32 modifiers = 0;
  230. if(mNeedsToRegainFocus)
  231. {
  232. mNeedsToRegainFocus = false;
  233. CGAssociateMouseAndMouseCursorPosition(false);
  234. MacInputManager* im = static_cast<MacInputManager*>(mCreator);
  235. WindowRef win = im->_getWindow();
  236. if(win)
  237. {
  238. Rect clipRect = {0, 0, 0, 0};
  239. GetWindowBounds(win, kWindowContentRgn, &clipRect);
  240. CGPoint warpPoint;
  241. warpPoint.x = ((clipRect.right - clipRect.left) / 2) + clipRect.left;
  242. warpPoint.y = ((clipRect.bottom - clipRect.top) / 2) + clipRect.top;
  243. CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint); //Place at display origin
  244. CGDisplayHideCursor(kCGDirectMainDisplay);
  245. mMouseWarped = true;
  246. }
  247. //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
  248. //compare against old status, and send off any needed events
  249. mState.buttons = 0;
  250. break;
  251. }
  252. // Capture parameters
  253. GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &button);
  254. GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
  255. if ((button == kEventMouseButtonTertiary) || ((button == kEventMouseButtonPrimary) && (modifiers & optionKey)))
  256. {
  257. mouseButton = 2;
  258. mState.buttons &= ~(1 << mouseButton);
  259. }
  260. else if ((button == kEventMouseButtonSecondary) || ((button == kEventMouseButtonPrimary) && (modifiers & controlKey)))
  261. {
  262. mouseButton = 1;
  263. mState.buttons &= ~(1 << mouseButton);
  264. }
  265. else if (button == kEventMouseButtonPrimary)
  266. {
  267. mouseButton = 0;
  268. mState.buttons &= ~(1 << mouseButton);
  269. }
  270. if( mListener && mBuffered )
  271. mListener->mouseReleased( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
  272. break;
  273. }
  274. case kEventMouseWheelMoved:
  275. {
  276. SInt32 wheelDelta = 0;
  277. EventMouseWheelAxis wheelAxis = 0;
  278. // Capture parameters
  279. GetEventParameter(theEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(EventMouseWheelAxis), NULL, &wheelAxis);
  280. GetEventParameter(theEvent, kEventParamMouseWheelDelta, typeSInt32, NULL, sizeof(SInt32), NULL, &wheelDelta);
  281. // If the Y axis of the wheel changed, then update the Z
  282. // Does OIS care about the X wheel axis?
  283. if(wheelAxis == kEventMouseWheelAxisY)
  284. mTempState.Z.rel += (wheelDelta * 60);
  285. break;
  286. }
  287. default:
  288. break;
  289. }
  290. }
  291. #endif