/extlibs/SFML/src/SFML/Window/Cocoa/WindowImplCocoa.mm

https://bitbucket.org/hugoruscitti/pilascpp · Objective C++ · 844 lines · 522 code · 143 blank · 179 comment · 78 complexity · 7d20b140e7781d1bc23126ca33398cdd MD5 · raw file

  1. ////////////////////////////////////////////////////////////
  2. //
  3. // SFML - Simple and Fast Multimedia Library
  4. // Copyright (C) 2007-2009 Lucas Soltic (ceylow@gmail.com) and Laurent Gomila (laurent.gom@gmail.com)
  5. //
  6. // This software is provided 'as-is', without any express or implied warranty.
  7. // In no event will 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,
  10. // including commercial applications, and to alter it and redistribute it freely,
  11. // subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented;
  14. // you must not claim that you wrote the original software.
  15. // If you use this software in a product, an acknowledgment
  16. // in the product documentation would be appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such,
  19. // and must not be misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source distribution.
  22. //
  23. ////////////////////////////////////////////////////////////
  24. ////////////////////////////////////////////////////////////
  25. // Headers
  26. ////////////////////////////////////////////////////////////
  27. #import <SFML/Window/Cocoa/WindowImplCocoa.hpp>
  28. #import <SFML/Window/Cocoa/AppController.h>
  29. #import <SFML/Window/Cocoa/GLKit.h>
  30. #import <SFML/Window/WindowStyle.hpp>
  31. #import <SFML/System.hpp>
  32. #import <iostream>
  33. namespace sf
  34. {
  35. namespace priv
  36. {
  37. // Do something only once (useful in loops)
  38. #define ONCE(make) \
  39. { static int __done = 0;\
  40. if (!__done) {\
  41. make;\
  42. __done = 1;\
  43. } }
  44. ////////////////////////////////////////////////////////////
  45. /// Private function declarations
  46. ////////////////////////////////////////////////////////////
  47. namespace {
  48. Key::Code KeyForVirtualCode(unsigned short vCode);
  49. Key::Code KeyForUnicode(unsigned short uniCode);
  50. } // anonymous namespace
  51. ////////////////////////////////////////////////////////////
  52. /// Default constructor
  53. /// (creates a dummy window to provide a valid OpenGL context)
  54. ////////////////////////////////////////////////////////////
  55. WindowImplCocoa::WindowImplCocoa() :
  56. myWrapper(nil),
  57. myUseKeyRepeat(false),
  58. myMouseIn(false),
  59. myWheelStatus(0.0f)
  60. {
  61. [sfPrivAppController sharedController];
  62. // Create the shared OpenGL context
  63. if ([sfPrivGLContext sharedContext]) {
  64. // Then we make it the current active OpenGL context
  65. SetActive();
  66. } else {
  67. std::cerr << "Unable to make the main shared OpenGL context" << std::endl;
  68. }
  69. }
  70. ////////////////////////////////////////////////////////////
  71. /// Create the window implementation from an existing control
  72. ////////////////////////////////////////////////////////////
  73. WindowImplCocoa::WindowImplCocoa(WindowHandle Handle, WindowSettings& params) :
  74. myWrapper(NULL),
  75. myUseKeyRepeat(false),
  76. myMouseIn(false),
  77. myWheelStatus(0.0f)
  78. {
  79. if (Handle) {
  80. // Classical window import
  81. if ([(id)Handle isKindOfClass:[NSWindow class]]) {
  82. myWrapper = [[sfPrivImportedWindow alloc]
  83. initWithWindow:(NSWindow *)Handle
  84. settings:params];
  85. }
  86. // Qt "window" import
  87. else if ([(id)Handle isKindOfClass:[NSView class]]) {
  88. myWrapper = [[sfPrivImportedView alloc]
  89. initWithView:(NSView *)Handle
  90. settings:params];
  91. } else {
  92. std::cerr
  93. << "Cannot import this Window Handle because it is neither"
  94. << "a <NSWindow *> nor <NSView *> object"
  95. << "(or any of its subclasses). You gave a <"
  96. << [[(id)Handle className] UTF8String]
  97. << "> object."
  98. << std::endl;
  99. }
  100. if (myWrapper) {
  101. [myWrapper setDelegate:this];
  102. // initial mouse state
  103. myMouseIn = [myWrapper mouseInside];
  104. // We set the myWidth and myHeight members to the correct values
  105. myWidth = (int) [[myWrapper view] frame].size.width;
  106. myHeight = (int) [[myWrapper view] frame].size.height;
  107. } else {
  108. std::cerr << "Failed to make the public window" << std::endl;
  109. }
  110. } else {
  111. std::cerr
  112. << "Invalid null handle given to "
  113. << "Window::Window(WindowHandle Handle, const WindowSettings& Params)"
  114. << std::endl;
  115. }
  116. }
  117. ////////////////////////////////////////////////////////////
  118. /// Create the window implementation
  119. ////////////////////////////////////////////////////////////
  120. WindowImplCocoa::WindowImplCocoa(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& params) :
  121. myWrapper(NULL),
  122. myUseKeyRepeat(false),
  123. myMouseIn(false),
  124. myWheelStatus(0.0f)
  125. {
  126. // Create a new window with given size, title and style
  127. // First we define some objects used for our window
  128. NSString *title = [NSString stringWithCString:(Title.c_str()) ? (Title.c_str()) : ""
  129. encoding:NSASCIIStringEncoding];
  130. // We create the window
  131. myWrapper = [[sfPrivOwnedWindow alloc]
  132. initWithVideoMode:Mode
  133. settings:params
  134. style:WindowStyle
  135. title:title];
  136. if (myWrapper)
  137. {
  138. [myWrapper setDelegate:this];
  139. // initial mouse state
  140. myMouseIn = [myWrapper mouseInside];
  141. // We set the myWidth and myHeight members to the correct values
  142. myWidth = Mode.Width;
  143. myHeight = Mode.Height;
  144. } else {
  145. std::cerr << "Failed to make the public window" << std::endl;
  146. }
  147. }
  148. ////////////////////////////////////////////////////////////
  149. /// Destructor
  150. ////////////////////////////////////////////////////////////
  151. WindowImplCocoa::~WindowImplCocoa()
  152. {
  153. // Release the window wrapper
  154. [myWrapper release];
  155. }
  156. ////////////////////////////////////////////////////////////
  157. /// Check if there's an active context on the current thread
  158. ////////////////////////////////////////////////////////////
  159. bool WindowImplCocoa::IsContextActive()
  160. {
  161. return ([NSOpenGLContext currentContext] != NULL);
  162. }
  163. ////////////////////////////////////////////////////////////
  164. /// Handle event sent by the default NSNotificationCenter
  165. ////////////////////////////////////////////////////////////
  166. void WindowImplCocoa::HandleNotifiedEvent(Event& event)
  167. {
  168. // Set myWidth and myHeight to correct value if
  169. // window size changed
  170. switch (event.Type) {
  171. case Event::Resized:
  172. myWidth = event.Size.Width;
  173. myHeight = event.Size.Height;
  174. break;
  175. default:
  176. break;
  177. }
  178. // And send the event
  179. SendEvent(event);
  180. }
  181. ////////////////////////////////////////////////////////////
  182. /// Handle a key down event (NSEvent)
  183. ////////////////////////////////////////////////////////////
  184. void WindowImplCocoa::HandleKeyDown(void *eventRef)
  185. {
  186. NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
  187. Event sfEvent;
  188. unichar chr = 0, rawchr = 0;
  189. unsigned long length = [[event characters] length];
  190. unsigned mods = [event modifierFlags];
  191. if (length) {
  192. chr = [[event characters] characterAtIndex:0];
  193. // Note : I got a crash (out of bounds exception) while typing so now I test...
  194. if ([[event charactersIgnoringModifiers] length])
  195. rawchr = [[event charactersIgnoringModifiers] characterAtIndex:0];
  196. // Don't handle repeated events if we chose not to send them
  197. if (!myUseKeyRepeat && [event isARepeat])
  198. return;
  199. // Is it also a text event ?
  200. if (IsTextEvent(event)) {
  201. // buffer for the UTF-32 characters
  202. Uint32 utf32Characters[2] = {0};
  203. // convert the characters
  204. // note: using CFString in order to keep compatibility with Mac OS X 10.4
  205. // (as NSUTF32StringEncoding is only being defined in Mac OS X 10.5 and later)
  206. if (!CFStringGetCString ((CFStringRef)[event characters],
  207. (char *)utf32Characters,
  208. sizeof(utf32Characters),
  209. kCFStringEncodingUTF32))
  210. {
  211. char asciiChar[3] = {0};
  212. if ([[event characters] lengthOfBytesUsingEncoding:NSASCIIStringEncoding])
  213. [[event characters] getCString:asciiChar
  214. maxLength:3
  215. encoding:NSASCIIStringEncoding];
  216. std::cerr << "Error while converting character to UTF32 : \""
  217. << asciiChar << "\"" << std::endl;
  218. }
  219. else
  220. {
  221. sfEvent.Type = Event::TextEntered;
  222. sfEvent.Text.Unicode = utf32Characters[0];
  223. SendEvent(sfEvent);
  224. }
  225. }
  226. // Anyway it's also a KeyPressed event
  227. sfEvent.Type = Event::KeyPressed;
  228. // Get the keys
  229. if (Key::Code(0) == (sfEvent.Key.Code = KeyForUnicode(rawchr))) {
  230. sfEvent.Key.Code = KeyForVirtualCode([event keyCode]);
  231. }
  232. // Get the modifiers
  233. sfEvent.Key.Alt = mods & NSAlternateKeyMask;
  234. sfEvent.Key.Control = mods & NSControlKeyMask;
  235. sfEvent.Key.Shift = mods & NSShiftKeyMask;
  236. // Send the event
  237. SendEvent(sfEvent);
  238. }
  239. }
  240. ////////////////////////////////////////////////////////////
  241. /// Handle a key up event (NSEvent)
  242. ////////////////////////////////////////////////////////////
  243. void WindowImplCocoa::HandleKeyUp(void *eventRef)
  244. {
  245. NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
  246. Event sfEvent;
  247. unsigned mods = [event modifierFlags];
  248. unichar chr = 0, rawchr = 0;
  249. if ([[event characters] length]) {
  250. chr = [[event characters] characterAtIndex:0];
  251. if ([[event charactersIgnoringModifiers] length])
  252. rawchr = [[event charactersIgnoringModifiers] characterAtIndex:0];
  253. sfEvent.Type = Event::KeyReleased;
  254. // Get the code
  255. if (Key::Code(0) == (sfEvent.Key.Code = KeyForUnicode(rawchr))) {
  256. sfEvent.Key.Code = KeyForVirtualCode([event keyCode]);
  257. }
  258. // Get the modifiers
  259. sfEvent.Key.Alt = mods & NSAlternateKeyMask;
  260. sfEvent.Key.Control = mods & NSControlKeyMask;
  261. sfEvent.Key.Shift = mods & NSShiftKeyMask;
  262. // Send the event
  263. SendEvent(sfEvent);
  264. }
  265. }
  266. ////////////////////////////////////////////////////////////
  267. /// Handle a key modifier event [Command, Option, Control, Shift]
  268. ////////////////////////////////////////////////////////////
  269. void WindowImplCocoa::HandleModifierKey(void *eventRef)
  270. {
  271. NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
  272. Event sfEvent;
  273. unsigned mods = [event modifierFlags];
  274. sfEvent.Type = Event::KeyPressed;
  275. // Get the code
  276. sfEvent.Key.Code = KeyForVirtualCode([event keyCode]);
  277. // Get the modifiers
  278. sfEvent.Key.Alt = mods & NSAlternateKeyMask;
  279. sfEvent.Key.Control = mods & NSControlKeyMask;
  280. sfEvent.Key.Shift = mods & NSShiftKeyMask;
  281. // Guess whether it's a pressed or released event
  282. // Note: this does not work fine is both left and right modifiers are pressed
  283. // I did not find any way to fix this.
  284. // TODO: fix handling of modifier flags for use of left and right key at the same time
  285. if (!(mods & NSAlternateKeyMask) &&
  286. (sfEvent.Key.Code == Key::LAlt || sfEvent.Key.Code == Key::RAlt)) {
  287. sfEvent.Type = Event::KeyReleased;
  288. }
  289. if (!(mods & NSControlKeyMask) &&
  290. (sfEvent.Key.Code == Key::LControl || sfEvent.Key.Code == Key::RControl)) {
  291. sfEvent.Type = Event::KeyReleased;
  292. }
  293. if (!(mods & NSShiftKeyMask) &&
  294. (sfEvent.Key.Code == Key::LShift || sfEvent.Key.Code == Key::RShift)) {
  295. sfEvent.Type = Event::KeyReleased;
  296. }
  297. if (!(mods & NSCommandKeyMask) &&
  298. (sfEvent.Key.Code == Key::LSystem || sfEvent.Key.Code == Key::RSystem)) {
  299. sfEvent.Type = Event::KeyReleased;
  300. }
  301. // Send the event
  302. SendEvent(sfEvent);
  303. }
  304. ////////////////////////////////////////////////////////////
  305. /// Handle a mouse down event (NSEvent)
  306. ////////////////////////////////////////////////////////////
  307. void WindowImplCocoa::HandleMouseDown(void *eventRef)
  308. {
  309. NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
  310. Event sfEvent;
  311. // Get mouse position relative to the window
  312. NSPoint loc = [myWrapper mouseLocation];
  313. unsigned mods = [event modifierFlags];
  314. switch ([event type]) {
  315. case NSLeftMouseDown:
  316. sfEvent.Type = Event::MouseButtonPressed;
  317. // Guess whether it's a mouse left or mouse right event
  318. if (mods & NSControlKeyMask) {
  319. sfEvent.MouseButton.Button = Mouse::Right;
  320. } else {
  321. sfEvent.MouseButton.Button = Mouse::Left;
  322. }
  323. sfEvent.MouseButton.X = (int) loc.x;
  324. sfEvent.MouseButton.Y = (int) loc.y;
  325. // Send the event
  326. SendEvent(sfEvent);
  327. break;
  328. case NSRightMouseDown:
  329. sfEvent.Type = Event::MouseButtonPressed;
  330. sfEvent.MouseButton.Button = Mouse::Right;
  331. sfEvent.MouseButton.X = (int) loc.x;
  332. sfEvent.MouseButton.Y = (int) loc.y;
  333. // Send the event
  334. SendEvent(sfEvent);
  335. break;
  336. default:
  337. break;
  338. }
  339. }
  340. ////////////////////////////////////////////////////////////
  341. /// Handle a mouse up event (NSEvent)
  342. ////////////////////////////////////////////////////////////
  343. void WindowImplCocoa::HandleMouseUp(void *eventRef)
  344. {
  345. NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
  346. Event sfEvent;
  347. // Get mouse position relative to the window
  348. NSPoint loc = [myWrapper mouseLocation];
  349. unsigned mods = [event modifierFlags];
  350. switch ([event type]) {
  351. case NSLeftMouseUp:
  352. sfEvent.Type = Event::MouseButtonReleased;
  353. // Guess whether it's a mouse left or mouse right event
  354. if (mods & NSControlKeyMask) {
  355. sfEvent.MouseButton.Button = Mouse::Right;
  356. } else {
  357. sfEvent.MouseButton.Button = Mouse::Left;
  358. }
  359. sfEvent.MouseButton.X = (int) loc.x;
  360. sfEvent.MouseButton.Y = (int) loc.y;
  361. // Send the event
  362. SendEvent(sfEvent);
  363. break;
  364. case NSRightMouseUp:
  365. sfEvent.Type = Event::MouseButtonReleased;
  366. sfEvent.MouseButton.Button = Mouse::Right;
  367. sfEvent.MouseButton.X = (int) loc.x;
  368. sfEvent.MouseButton.Y = (int) loc.y;
  369. // Send the event
  370. SendEvent(sfEvent);
  371. break;
  372. default:
  373. break;
  374. }
  375. }
  376. ////////////////////////////////////////////////////////////
  377. /// Handle a mouse move event (NSEvent)
  378. ////////////////////////////////////////////////////////////
  379. void WindowImplCocoa::HandleMouseMove(void *eventRef)
  380. {
  381. Event sfEvent;
  382. NSPoint loc = [myWrapper mouseLocation];
  383. sfEvent.Type = Event::MouseMoved;
  384. sfEvent.MouseMove.X = (int) loc.x;
  385. sfEvent.MouseMove.Y = (int) loc.y;
  386. SendEvent(sfEvent);
  387. if ([myWrapper mouseInside] && !myMouseIn) {
  388. // If mouse IS inside but WAS not inside last time
  389. sfEvent.Type = Event::MouseEntered;
  390. myMouseIn = true;
  391. SendEvent(sfEvent);
  392. } else if (![myWrapper mouseInside] && myMouseIn) {
  393. // Is mouse WAS not inside but IS now inside
  394. sfEvent.Type = Event::MouseLeft;
  395. myMouseIn = false;
  396. SendEvent(sfEvent);
  397. }
  398. }
  399. ////////////////////////////////////////////////////////////
  400. /// Handle a mouse wheel event (NSEvent)
  401. ////////////////////////////////////////////////////////////
  402. void WindowImplCocoa::HandleMouseWheel(void *eventRef)
  403. {
  404. NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
  405. // SFML uses integer values for delta but Cocoa uses float and it is mostly fewer than 1.0
  406. // Therefore I chose to add the float value to a 'wheel status' and
  407. // send a sf event only when it's greater than 1.0
  408. myWheelStatus += [event deltaY];
  409. if (fabs(myWheelStatus) > 1.0f) {
  410. // Make the event and send it
  411. Event sfEvent;
  412. sfEvent.Type = Event::MouseWheelMoved;
  413. sfEvent.MouseWheel.Delta = (int) myWheelStatus;
  414. SendEvent(sfEvent);
  415. // Remove as much integer units as the one that have been put in the event
  416. // (was a mistake to set this to 0)
  417. myWheelStatus -= (int) myWheelStatus;
  418. }
  419. }
  420. ////////////////////////////////////////////////////////////
  421. /// Return whether 'ev' must be considered as a TextEntered event
  422. ////////////////////////////////////////////////////////////
  423. bool WindowImplCocoa::IsTextEvent(void *eventRef)
  424. {
  425. NSEvent *event = (NSEvent *)eventRef;
  426. bool res = false;
  427. if (event && [event type] == NSKeyDown && [[event characters] length]) {
  428. unichar code = [[event characters] characterAtIndex:0];
  429. // Codes from 0xF700 to 0xF8FF are non text keys (see NSEvent.h)
  430. // 0x35 is the Escape key
  431. if ([event keyCode] != 0x35 && (code < 0xF700 || code > 0xF8FF))
  432. res = true;
  433. }
  434. return res;
  435. }
  436. ////////////////////////////////////////////////////////////
  437. /// /see sfWindowImpl::Display
  438. ////////////////////////////////////////////////////////////
  439. void WindowImplCocoa::Display()
  440. {
  441. // Forward flush call to the window
  442. [myWrapper flushBuffer];
  443. }
  444. ////////////////////////////////////////////////////////////
  445. /// /see sfWindowImpl::ProcessEvents
  446. ////////////////////////////////////////////////////////////
  447. void WindowImplCocoa::ProcessEvents()
  448. {
  449. // Forward event handling call to the application controller
  450. [[sfPrivAppController sharedController] processEvents];
  451. }
  452. ////////////////////////////////////////////////////////////
  453. /// /see sfWindowImpl::MakeActive
  454. ////////////////////////////////////////////////////////////
  455. void WindowImplCocoa::SetActive(bool Active) const
  456. {
  457. // Forward the call to the window
  458. if (myWrapper)
  459. [myWrapper setActive:Active];
  460. else {
  461. // Or directly activate the shared OpenGL context if we're not using a window
  462. if (Active) {
  463. if ([NSOpenGLContext currentContext] != [sfPrivGLContext sharedContext])
  464. [[sfPrivGLContext sharedContext] makeCurrentContext];
  465. } else {
  466. if ([NSOpenGLContext currentContext] == [sfPrivGLContext sharedContext])
  467. [NSOpenGLContext clearCurrentContext];
  468. }
  469. }
  470. }
  471. ////////////////////////////////////////////////////////////
  472. /// /see sfWindowImpl::UseVerticalSync
  473. ////////////////////////////////////////////////////////////
  474. void WindowImplCocoa::UseVerticalSync(bool Enabled)
  475. {
  476. // Forward the call to the window
  477. [myWrapper enableVerticalSync:Enabled];
  478. }
  479. ////////////////////////////////////////////////////////////
  480. /// /see sfWindowImpl::ShowMouseCursor
  481. ////////////////////////////////////////////////////////////
  482. void WindowImplCocoa::ShowMouseCursor(bool flag)
  483. {
  484. if (flag) {
  485. [NSCursor unhide];
  486. } else {
  487. [NSCursor hide];
  488. }
  489. }
  490. ////////////////////////////////////////////////////////////
  491. /// /see sfWindowImpl::SetCursorPosition
  492. ////////////////////////////////////////////////////////////
  493. void WindowImplCocoa::SetCursorPosition(unsigned int Left, unsigned int Top)
  494. {
  495. NSPoint pos = NSMakePoint ((float) Left, (float) Top);
  496. if (myWrapper) {
  497. // Flip for SFML window coordinate system
  498. pos.y = [[myWrapper window] frame].size.height - pos.y;
  499. // Adjust for view reference instead of window
  500. pos.y -= [[myWrapper window] frame].size.height - [[myWrapper view] frame].size.height;
  501. // Convert to screen coordinates
  502. NSPoint absolute = [[myWrapper window] convertBaseToScreen:pos];
  503. // Flip screen coodinates
  504. absolute.y = [[NSScreen mainScreen] frame].size.height - absolute.y;
  505. // Move cursor
  506. CGDisplayMoveCursorToPoint([sfPrivAppController primaryScreen],
  507. CGPointMake(absolute.x, absolute.y));
  508. }
  509. }
  510. ////////////////////////////////////////////////////////////
  511. /// /see sfWindowImpl::SetPosition
  512. ////////////////////////////////////////////////////////////
  513. void WindowImplCocoa::SetPosition(int Left, int Top)
  514. {
  515. [myWrapper setPosition:NSMakePoint(Left, Top)];
  516. }
  517. ////////////////////////////////////////////////////////////
  518. /// /see WindowImpl::SetSize
  519. ///
  520. ////////////////////////////////////////////////////////////
  521. void WindowImplCocoa::SetSize(unsigned int Width, unsigned int Height)
  522. {
  523. [myWrapper setSize:NSMakeSize(Width, Height)];
  524. }
  525. ////////////////////////////////////////////////////////////
  526. /// /see sfWindowImpl::Show
  527. ////////////////////////////////////////////////////////////
  528. void WindowImplCocoa::Show(bool State)
  529. {
  530. [myWrapper show:State];
  531. }
  532. ////////////////////////////////////////////////////////////
  533. /// /see sfWindowImpl::EnableKeyRepeat
  534. ////////////////////////////////////////////////////////////
  535. void WindowImplCocoa::EnableKeyRepeat(bool Enabled)
  536. {
  537. myUseKeyRepeat = Enabled;
  538. }
  539. ////////////////////////////////////////////////////////////
  540. /// see WindowImpl::SetIcon
  541. ////////////////////////////////////////////////////////////
  542. void WindowImplCocoa::SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels)
  543. {
  544. // Nothing to do
  545. }
  546. namespace {
  547. ////////////////////////////////////////////////////////////
  548. /// Return the SFML key corresponding to a key code
  549. ////////////////////////////////////////////////////////////
  550. Key::Code KeyForVirtualCode(unsigned short vCode)
  551. {
  552. static struct {
  553. unsigned short code;
  554. Key::Code sfKey;
  555. } virtualTable[] =
  556. {
  557. {0x35, Key::Escape},
  558. {0x31, Key::Space},
  559. {0x24, Key::Return}, // main Return key
  560. {0x4C, Key::Return}, // pav Return key
  561. {0x33, Key::Back},
  562. {0x30, Key::Tab},
  563. {0x74, Key::PageUp},
  564. {0x79, Key::PageDown},
  565. {0x77, Key::End},
  566. {0x73, Key::Home},
  567. {0x72, Key::Insert},
  568. {0x75, Key::Delete},
  569. {0x45, Key::Add},
  570. {0x4E, Key::Subtract},
  571. {0x43, Key::Multiply},
  572. {0x4B, Key::Divide},
  573. {0x7A, Key::F1}, {0x78, Key::F2}, {0x63, Key::F3},
  574. {0x76, Key::F4}, {0x60, Key::F5}, {0x61, Key::F6},
  575. {0x62, Key::F7}, {0x64, Key::F8}, {0x65, Key::F9},
  576. {0x6D, Key::F10}, {0x67, Key::F11}, {0x6F, Key::F12},
  577. {0x69, Key::F13}, {0x6B, Key::F14}, {0x71, Key::F15},
  578. {0x7B, Key::Left},
  579. {0x7C, Key::Right},
  580. {0x7E, Key::Up},
  581. {0x7D, Key::Down},
  582. {0x52, Key::Numpad0}, {0x53, Key::Numpad1}, {0x54, Key::Numpad2},
  583. {0x55, Key::Numpad3}, {0x56, Key::Numpad4}, {0x57, Key::Numpad5},
  584. {0x58, Key::Numpad6}, {0x59, Key::Numpad7}, {0x5B, Key::Numpad8},
  585. {0x5C, Key::Numpad9},
  586. {0x1D, Key::Num0}, {0x12, Key::Num1}, {0x13, Key::Num2},
  587. {0x14, Key::Num3}, {0x15, Key::Num4}, {0x17, Key::Num5},
  588. {0x16, Key::Num6}, {0x1A, Key::Num7}, {0x1C, Key::Num8},
  589. {0x19, Key::Num9},
  590. {0x3B, Key::LControl}, //< Left Ctrl
  591. {0x3A, Key::LAlt}, //< Left Option/Alt
  592. {0x37, Key::LSystem}, //< Left Command
  593. {0x38, Key::LShift}, //< Left Shift
  594. {0x3E, Key::RControl}, //< Right Ctrl
  595. {0x3D, Key::RAlt}, //< Right Option/Alt
  596. {0x36, Key::RSystem}, //< Right Command
  597. {0x3C, Key::RShift}, //< Right Shift
  598. {0x39, Key::Code(0)} //< Caps Lock (not handled by SFML for now)
  599. };
  600. Key::Code result = Key::Code(0);
  601. for (unsigned i = 0;virtualTable[i].code;i++) {
  602. if (virtualTable[i].code == vCode) {
  603. result = virtualTable[i].sfKey;
  604. break;
  605. }
  606. }
  607. return result;
  608. }
  609. ////////////////////////////////////////////////////////////
  610. /// Return the SFML key corresponding to a unicode code
  611. ////////////////////////////////////////////////////////////
  612. Key::Code KeyForUnicode(unsigned short uniCode)
  613. {
  614. // TODO: find a better way to get the language independant key
  615. static struct {
  616. unsigned short character;
  617. Key::Code sfKey;
  618. } unicodeTable[] =
  619. {
  620. {'!', Key::Code(0)}, //< No Key for this code
  621. {'"', Key::Code(0)}, //< No Key for this code
  622. {'#', Key::Code(0)}, //< No Key for this code
  623. {'$', Key::Code(0)}, //< No Key for this code
  624. {'%', Key::Code(0)}, //< No Key for this code
  625. {'&', Key::Code(0)}, //< No Key for this code
  626. {'\'', Key::Quote},
  627. {'(', Key::Code(0)}, //< No Key for this code
  628. {')', Key::Code(0)}, //< No Key for this code
  629. {'*', Key::Multiply},
  630. {'+', Key::Add},
  631. {',', Key::Comma},
  632. {'-', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  633. {'.', Key::Period},
  634. {'/', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  635. {'0', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  636. {'1', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  637. {'2', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  638. {'3', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  639. {'4', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  640. {'5', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  641. {'6', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  642. {'7', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  643. {'8', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  644. {'9', Key::Code(0)}, //< Handled by KeyForVirtualCode()
  645. {':', Key::Code(0)}, //< No Key for this code
  646. {';', Key::SemiColon},
  647. {'<', Key::Code(0)}, //< No Key for this code
  648. {'=', Key::Equal},
  649. {'>', Key::Code(0)}, //< No Key for this code
  650. {'?', Key::Code(0)}, //< No Key for this code
  651. {'@', Key::Code(0)}, //< No Key for this code
  652. {'A', Key::A}, {'B', Key::B}, {'C', Key::C},
  653. {'D', Key::D}, {'E', Key::E}, {'F', Key::F},
  654. {'G', Key::G}, {'H', Key::H}, {'I', Key::I},
  655. {'J', Key::J}, {'K', Key::K}, {'L', Key::L},
  656. {'M', Key::M}, {'N', Key::N}, {'O', Key::O},
  657. {'P', Key::P}, {'Q', Key::Q}, {'R', Key::R},
  658. {'S', Key::S}, {'T', Key::T}, {'U', Key::U},
  659. {'V', Key::V}, {'W', Key::W}, {'X', Key::X},
  660. {'Y', Key::Y}, {'Z', Key::Z},
  661. {'[', Key::LBracket},
  662. {'\\', Key::BackSlash},
  663. {']', Key::RBracket},
  664. {'^', Key::Code(0)}, //< No Key for this code
  665. {'_', Key::Code(0)}, //< No Key for this code
  666. {'`', Key::Code(0)}, //< No Key for this code
  667. {'a', Key::A}, {'b', Key::B}, {'c', Key::C},
  668. {'d', Key::D}, {'e', Key::E}, {'f', Key::F},
  669. {'g', Key::G}, {'h', Key::H}, {'i', Key::I},
  670. {'j', Key::J}, {'k', Key::K}, {'l', Key::L},
  671. {'m', Key::M}, {'n', Key::N}, {'o', Key::O},
  672. {'p', Key::P}, {'q', Key::Q}, {'r', Key::R},
  673. {'s', Key::S}, {'t', Key::T}, {'u', Key::U},
  674. {'v', Key::V}, {'w', Key::W}, {'x', Key::X},
  675. {'y', Key::Y}, {'z', Key::Z},
  676. {'{', Key::Code(0)}, //< No Key for this code
  677. {'|', Key::Code(0)}, //< No Key for this code
  678. {'}', Key::Code(0)}, //< No Key for this code
  679. {'~', Key::Tilde},
  680. {0, Key::Code(0)}
  681. };
  682. Key::Code result = Key::Code(0);
  683. for (unsigned i = 0;unicodeTable[i].character;i++) {
  684. if (unicodeTable[i].character == uniCode) {
  685. result = unicodeTable[i].sfKey;
  686. break;
  687. }
  688. }
  689. return result;
  690. }
  691. } // anonymous namespace
  692. } // namespace priv
  693. } // namespace sf