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