Просмотр исходного кода

Merge pull request #157 from emoon/master

Added inital mouse and keyboard support for OSX
Branimir Karadžić 11 лет назад
Родитель
Сommit
6c8a84f556
1 измененных файлов с 269 добавлено и 0 удалено
  1. 269 0
      examples/common/entry/entry_osx.mm

+ 269 - 0
examples/common/entry/entry_osx.mm

@@ -126,8 +126,18 @@
 }
 @end
 
+// Scan codes on Mac taken from http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes
+
+#define KEY_RETURN 36
+#define KEY_TAB 48
+#define KEY_DELETE 51
+#define KEY_ESCAPE 53
+
 namespace entry
 {
+	static WindowHandle s_defaultWindow = { 0 };	// TODO: Add support for more windows
+	static uint8_t s_translateKey[256];
+
 	struct MainThreadEntry
 	{
 		int m_argc;
@@ -145,6 +155,106 @@ namespace entry
 		Context()
 			: m_exit(false)
 		{
+			s_translateKey[KEY_ESCAPE]	 = Key::Esc;
+			s_translateKey[KEY_RETURN]	 = Key::Return;
+			s_translateKey[KEY_TAB]		 = Key::Tab;
+			s_translateKey[KEY_DELETE]	 = Key::Backspace;
+			//s_translateKey[VK_SPACE]	   = Key::Space;
+			//s_translateKey[VK_UP]		   = Key::Up;
+			//s_translateKey[VK_DOWN]	   = Key::Down;
+			//s_translateKey[VK_LEFT]	   = Key::Left;
+			//s_translateKey[VK_RIGHT]	   = Key::Right;
+			//s_translateKey[VK_PRIOR]	   = Key::PageUp;
+			//s_translateKey[VK_NEXT]	   = Key::PageUp;
+			//s_translateKey[VK_HOME]	   = Key::Home;
+			//s_translateKey[VK_END]	   = Key::End;
+			//s_translateKey[VK_SNAPSHOT]  = Key::Print;
+			//s_translateKey[VK_OEM_PLUS]  = Key::Plus;
+			//s_translateKey[VK_OEM_MINUS] = Key::Minus;
+			//s_translateKey[VK_F1]		   = Key::F1;
+			//s_translateKey[VK_F2]		   = Key::F2;
+			//s_translateKey[VK_F3]		   = Key::F3;
+			//s_translateKey[VK_F4]		   = Key::F4;
+			//s_translateKey[VK_F5]		   = Key::F5;
+			//s_translateKey[VK_F6]		   = Key::F6;
+			//s_translateKey[VK_F7]		   = Key::F7;
+			//s_translateKey[VK_F8]		   = Key::F8;
+			//s_translateKey[VK_F9]		   = Key::F9;
+			//s_translateKey[VK_F10]	   = Key::F10;
+			//s_translateKey[VK_F11]	   = Key::F11;
+			//s_translateKey[VK_F12]	   = Key::F12;
+			//s_translateKey[VK_NUMPAD0]   = Key::NumPad0;
+			//s_translateKey[VK_NUMPAD1]   = Key::NumPad1;
+			//s_translateKey[VK_NUMPAD2]   = Key::NumPad2;
+			//s_translateKey[VK_NUMPAD3]   = Key::NumPad3;
+			//s_translateKey[VK_NUMPAD4]   = Key::NumPad4;
+			//s_translateKey[VK_NUMPAD5]   = Key::NumPad5;
+			//s_translateKey[VK_NUMPAD6]   = Key::NumPad6;
+			//s_translateKey[VK_NUMPAD7]   = Key::NumPad7;
+			//s_translateKey[VK_NUMPAD8]   = Key::NumPad8;
+			//s_translateKey[VK_NUMPAD9]   = Key::NumPad9;
+			s_translateKey['0']			 = Key::Key0;
+			s_translateKey['1']			 = Key::Key1;
+			s_translateKey['2']			 = Key::Key2;
+			s_translateKey['3']			 = Key::Key3;
+			s_translateKey['4']			 = Key::Key4;
+			s_translateKey['5']			 = Key::Key5;
+			s_translateKey['6']			 = Key::Key6;
+			s_translateKey['7']			 = Key::Key7;
+			s_translateKey['8']			 = Key::Key8;
+			s_translateKey['9']			 = Key::Key9;
+			s_translateKey['A']			 = Key::KeyA;
+			s_translateKey['B']			 = Key::KeyB;
+			s_translateKey['C']			 = Key::KeyC;
+			s_translateKey['D']			 = Key::KeyD;
+			s_translateKey['E']			 = Key::KeyE;
+			s_translateKey['F']			 = Key::KeyF;
+			s_translateKey['G']			 = Key::KeyG;
+			s_translateKey['H']			 = Key::KeyH;
+			s_translateKey['I']			 = Key::KeyI;
+			s_translateKey['J']			 = Key::KeyJ;
+			s_translateKey['K']			 = Key::KeyK;
+			s_translateKey['L']			 = Key::KeyL;
+			s_translateKey['M']			 = Key::KeyM;
+			s_translateKey['N']			 = Key::KeyN;
+			s_translateKey['O']			 = Key::KeyO;
+			s_translateKey['P']			 = Key::KeyP;
+			s_translateKey['Q']			 = Key::KeyQ;
+			s_translateKey['R']			 = Key::KeyR;
+			s_translateKey['S']			 = Key::KeyS;
+			s_translateKey['T']			 = Key::KeyT;
+			s_translateKey['U']			 = Key::KeyU;
+			s_translateKey['V']			 = Key::KeyV;
+			s_translateKey['W']			 = Key::KeyW;
+			s_translateKey['X']			 = Key::KeyX;
+			s_translateKey['Y']			 = Key::KeyY;
+			s_translateKey['Z']			 = Key::KeyZ;
+			s_translateKey['a']			 = Key::KeyA;
+			s_translateKey['b']			 = Key::KeyB;
+			s_translateKey['c']			 = Key::KeyC;
+			s_translateKey['d']			 = Key::KeyD;
+			s_translateKey['e']			 = Key::KeyE;
+			s_translateKey['f']			 = Key::KeyF;
+			s_translateKey['g']			 = Key::KeyG;
+			s_translateKey['h']			 = Key::KeyH;
+			s_translateKey['i']			 = Key::KeyI;
+			s_translateKey['j']			 = Key::KeyJ;
+			s_translateKey['k']			 = Key::KeyK;
+			s_translateKey['l']			 = Key::KeyL;
+			s_translateKey['m']			 = Key::KeyM;
+			s_translateKey['n']			 = Key::KeyN;
+			s_translateKey['o']			 = Key::KeyO;
+			s_translateKey['p']			 = Key::KeyP;
+			s_translateKey['q']			 = Key::KeyQ;
+			s_translateKey['r']			 = Key::KeyR;
+			s_translateKey['s']			 = Key::KeyS;
+			s_translateKey['t']			 = Key::KeyT;
+			s_translateKey['u']			 = Key::KeyU;
+			s_translateKey['v']			 = Key::KeyV;
+			s_translateKey['w']			 = Key::KeyW;
+			s_translateKey['x']			 = Key::KeyX;
+			s_translateKey['y']			 = Key::KeyY;
+			s_translateKey['z']			 = Key::KeyZ;
 		}
 
 		NSEvent* waitEvent()
@@ -167,12 +277,167 @@ namespace entry
 				];
 		}
 
+		void getMousePos(int* outX, int* outY)
+		{
+			NSRect originalFrame = [m_window frame];
+			NSPoint location = [m_window mouseLocationOutsideOfEventStream];
+			NSRect adjustFrame = [NSWindow contentRectForFrameRect: originalFrame styleMask: NSTitledWindowMask];
+
+			int x = location.x;
+			int y = (int)adjustFrame.size.height - (int)location.y;
+
+			// clamp within the range of the window
+
+			if (x < 0) x = 0;
+			if (y < 0) y = 0;
+			if (x > (int)adjustFrame.size.width) x = (int)adjustFrame.size.width;
+			if (y > (int)adjustFrame.size.height) y = (int)adjustFrame.size.height;
+
+			*outX = x;
+			*outY = y;
+		}
+
+		uint8_t translateModifiers(int flags)
+		{
+			uint8_t mask = 0;
+
+			if (flags & NSShiftKeyMask)
+				mask |= Modifier::LeftShift | Modifier::RightShift;
+
+			if (flags & NSAlternateKeyMask)
+				mask |= Modifier::LeftAlt | Modifier::RightAlt;
+
+			if (flags & NSControlKeyMask)
+				mask |= Modifier::LeftCtrl | Modifier::RightCtrl;
+
+			if (flags & NSCommandKeyMask)
+				mask |= Modifier::LeftMeta | Modifier::RightMeta;
+
+			return mask;
+		}
+
+		Key::Enum handleKeyEvent(NSEvent* event, uint8_t* specialKeys)
+		{
+			NSString* key = [event charactersIgnoringModifiers];
+			unichar keyChar = 0;
+			if ([key length] == 0)
+				return Key::None;
+
+			keyChar = [key characterAtIndex:0];
+
+			int keyCode = keyChar;
+			*specialKeys = translateModifiers([event modifierFlags]);
+
+			// if this is a unhandled key just return None
+
+			if (keyCode >= 256)
+				return Key::None;
+
+			return (Key::Enum)s_translateKey[keyCode];
+		}
+
 		bool dispatchEvent(NSEvent* event)
 		{
 			if (event)
 			{
+				NSEventType eventType = [event type];
+
+				switch (eventType)
+				{
+					case NSMouseMoved :
+					{
+						int x, y;
+
+						getMousePos(&x, &y);
+						
+						m_eventQueue.postMouseEvent(s_defaultWindow, x, y, 0);
+
+						break;
+					}
+
+					case NSLeftMouseDown:
+					{
+						int x, y;
+
+						getMousePos(&x, &y);
+
+						m_eventQueue.postMouseEvent(s_defaultWindow, x, y, 0, MouseButton::Left, true);
+
+						break;
+					}
+
+					case NSLeftMouseUp:
+					{
+						int x, y;
+
+						getMousePos(&x, &y);
+
+						m_eventQueue.postMouseEvent(s_defaultWindow, x, y, 0, MouseButton::Left, false);
+
+						break;
+					}
+
+					case NSRightMouseDown:
+					{
+						int x, y;
+
+						getMousePos(&x, &y);
+
+						m_eventQueue.postMouseEvent(s_defaultWindow, x, y, 0, MouseButton::Right, true);
+
+						break;
+					}
+
+					case NSRightMouseUp:
+					{
+						int x, y;
+
+						getMousePos(&x, &y);
+
+						m_eventQueue.postMouseEvent(s_defaultWindow, x, y, 0, MouseButton::Right, false);
+
+						break;
+					}
+
+					case NSKeyDown:
+					{
+						uint8_t modifiers = 0;
+						Key::Enum key = handleKeyEvent(event, &modifiers);
+
+						// If KeyCode is none we don't don't handle the key and special case for cmd+q (quit)
+						// Note that return false here means that we take care of the key (instead of the default behavior)
+
+						if (key != Key::None)
+						{
+							if (key != Key::KeyQ && !((modifiers & Modifier::RightMeta)))
+							{
+								m_eventQueue.postKeyEvent(s_defaultWindow, key, modifiers, true);
+								return false;
+							}
+						}
+
+						break;
+					}
+
+					case NSKeyUp:
+					{
+						uint8_t modifiers  = 0;
+						Key::Enum key = handleKeyEvent(event, &modifiers);
+
+						if (key != Key::None)
+						{
+							m_eventQueue.postKeyEvent(s_defaultWindow, key, modifiers, false);
+							return false;
+						}
+
+						break;
+					}
+				}
+				
+				
 				[NSApp sendEvent:event];
 				[NSApp updateWindows];
+
 				return true;
 			}
 
@@ -229,9 +494,12 @@ namespace entry
 			[window cascadeTopLeftFromPoint:NSMakePoint(20,20)];
 			[window makeKeyAndOrderFront:window];
 //			[window setContentView:nil];
+			[window setAcceptsMouseMovedEvents:YES];
 			[window setBackgroundColor:[NSColor blackColor]];
 			[[Window sharedDelegate] windowCreated:window];
 
+			m_window = window;
+
 			bgfx::osxSetNSWindow(window);
 
 			MainThreadEntry mte;
@@ -265,6 +533,7 @@ namespace entry
 		EventQueue m_eventQueue;
 
 		bool m_exit;
+		NSWindow* m_window;
 	};
 
 	static Context s_ctx;