Back to index

libsfml  1.6+dfsg2
WindowImplCocoa.mm
Go to the documentation of this file.
00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007-2009 Lucas Soltic (ceylow@gmail.com) and Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00025 
00027 // Headers
00029 #import <SFML/Window/Cocoa/WindowImplCocoa.hpp>
00030 #import <SFML/Window/Cocoa/AppController.h>
00031 #import <SFML/Window/Cocoa/GLKit.h>
00032 #import <SFML/Window/WindowStyle.hpp>
00033 #import <SFML/System.hpp>
00034 #import <iostream>
00035 
00036 
00037 namespace sf
00038 {
00039 namespace priv
00040 {
00041 
00042 // Do something only once (useful in loops)
00043 #define ONCE(make) \
00044 { static int __done = 0;\
00045 if (!__done) {\
00046 make;\
00047 __done = 1;\
00048 } }
00049 
00050 
00054 namespace {
00055        Key::Code            KeyForVirtualCode(unsigned short vCode);
00056        Key::Code            KeyForUnicode(unsigned short uniCode);
00057 } // anonymous namespace
00058 
00059 
00064 WindowImplCocoa::WindowImplCocoa() :
00065 myWrapper(nil),
00066 myUseKeyRepeat(false),
00067 myMouseIn(false),
00068 myWheelStatus(0.0f)
00069 {
00070        [sfPrivAppController sharedController];
00071        
00072     // Create the shared OpenGL context
00073        if ([sfPrivGLContext sharedContext]) {
00074               // Then we make it the current active OpenGL context
00075               SetActive();
00076        } else {
00077               std::cerr << "Unable to make the main shared OpenGL context" << std::endl;
00078        }
00079 }
00080 
00081 
00085 WindowImplCocoa::WindowImplCocoa(WindowHandle Handle, WindowSettings& params) :
00086 myWrapper(NULL),
00087 myUseKeyRepeat(false),
00088 myMouseIn(false),
00089 myWheelStatus(0.0f)
00090 {
00091        if (Handle) {
00092               // Classical window import
00093               if ([(id)Handle isKindOfClass:[NSWindow class]]) {
00094                      myWrapper = [[sfPrivImportedWindow alloc]
00095                                            initWithWindow:(NSWindow *)Handle
00096                                            settings:params];
00097               }
00098               // Qt "window" import
00099               else if ([(id)Handle isKindOfClass:[NSView class]]) {
00100                      myWrapper = [[sfPrivImportedView alloc]
00101                                            initWithView:(NSView *)Handle
00102                                            settings:params];
00103               } else {
00104                      std::cerr 
00105                      << "Cannot import this Window Handle because it is neither"
00106                      << "a <NSWindow *> nor <NSView *> object"
00107                      << "(or any of its subclasses). You gave a <" 
00108                      << [[(id)Handle className] UTF8String]
00109                      << "> object."
00110                      << std::endl;
00111                      
00112               }
00113 
00114               if (myWrapper) {
00115                      [myWrapper setDelegate:this];
00116                      
00117                      // initial mouse state
00118                      myMouseIn = [myWrapper mouseInside];
00119                      
00120                      // We set the myWidth and myHeight members to the correct values
00121                      myWidth = (int) [[myWrapper view] frame].size.width;
00122                      myHeight = (int) [[myWrapper view] frame].size.height;
00123               } else {
00124                      std::cerr << "Failed to make the public window" << std::endl;
00125               }
00126        } else {
00127               std::cerr
00128               << "Invalid null handle given to "
00129               << "Window::Window(WindowHandle Handle, const WindowSettings& Params)"
00130               << std::endl;
00131        }
00132 }
00133 
00134 
00138 WindowImplCocoa::WindowImplCocoa(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& params) :
00139 myWrapper(NULL),
00140 myUseKeyRepeat(false),
00141 myMouseIn(false),
00142 myWheelStatus(0.0f)
00143 {
00144     // Create a new window with given size, title and style
00145        // First we define some objects used for our window
00146        NSString *title = [NSString stringWithCString:(Title.c_str()) ? (Title.c_str()) : ""
00147                                                                        encoding:NSASCIIStringEncoding];
00148        
00149        // We create the window
00150        myWrapper = [[sfPrivOwnedWindow alloc]
00151                              initWithVideoMode:Mode
00152                              settings:params
00153                              style:WindowStyle
00154                              title:title];
00155        
00156        
00157        
00158        if (myWrapper)
00159        {
00160               [myWrapper setDelegate:this];
00161               
00162               // initial mouse state
00163               myMouseIn = [myWrapper mouseInside];
00164               
00165               // We set the myWidth and myHeight members to the correct values
00166               myWidth = Mode.Width;
00167               myHeight = Mode.Height;
00168        } else {
00169               std::cerr << "Failed to make the public window" << std::endl;
00170        }
00171 }
00172 
00173 
00177 WindowImplCocoa::~WindowImplCocoa()
00178 {
00179        // Release the window wrapper
00180        [myWrapper release];
00181 }
00182 
00183 
00187 bool WindowImplCocoa::IsContextActive()
00188 {
00189        return ([NSOpenGLContext currentContext] != NULL);
00190 }
00191 
00192 
00196 void WindowImplCocoa::HandleNotifiedEvent(Event& event)
00197 {
00198        // Set myWidth and myHeight to correct value if
00199        // window size changed
00200        switch (event.Type) {
00201               case Event::Resized:
00202                      myWidth = event.Size.Width;
00203                      myHeight = event.Size.Height;
00204                      break;
00205                      
00206               default:
00207                      break;
00208        }
00209        
00210        // And send the event
00211        SendEvent(event);
00212 }
00213 
00214 
00218 void WindowImplCocoa::HandleKeyDown(void *eventRef)
00219 {
00220        NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
00221        
00222        Event sfEvent;
00223        unichar chr = 0, rawchr = 0;
00224        unsigned long length = [[event characters] length];
00225        unsigned mods = [event modifierFlags];
00226        
00227        if (length) {
00228               chr = [[event characters] characterAtIndex:0];
00229               
00230               // Note : I got a crash (out of bounds exception) while typing so now I test...
00231               if ([[event charactersIgnoringModifiers] length])
00232                      rawchr = [[event charactersIgnoringModifiers] characterAtIndex:0];
00233               
00234               
00235               // Don't handle repeated events if we chose not to send them
00236               if (!myUseKeyRepeat && [event isARepeat])
00237                      return;
00238               
00239               // Is it also a text event ?
00240               if (IsTextEvent(event)) {
00241                      // buffer for the UTF-32 characters
00242                      Uint32 utf32Characters[2] = {0};
00243                      
00244                      // convert the characters
00245                      // note: using CFString in order to keep compatibility with Mac OS X 10.4
00246                      // (as NSUTF32StringEncoding is only being defined in Mac OS X 10.5 and later)
00247                      if (!CFStringGetCString ((CFStringRef)[event characters],
00248                                                                 (char *)utf32Characters,
00249                                                                 sizeof(utf32Characters),
00250                                                                 kCFStringEncodingUTF32))
00251                      {
00252                             char asciiChar[3] = {0};
00253                             if ([[event characters] lengthOfBytesUsingEncoding:NSASCIIStringEncoding])
00254                                    [[event characters] getCString:asciiChar
00255                                                                        maxLength:3
00256                                                                         encoding:NSASCIIStringEncoding];
00257                             
00258                             std::cerr << "Error while converting character to UTF32 : \""
00259                             << asciiChar << "\"" << std::endl;
00260                      }
00261                      else
00262                      {
00263                             sfEvent.Type = Event::TextEntered;
00264                             sfEvent.Text.Unicode = utf32Characters[0];
00265                             
00266                             SendEvent(sfEvent);
00267                      }
00268               }
00269               
00270               // Anyway it's also a KeyPressed event
00271               sfEvent.Type = Event::KeyPressed;
00272               
00273               // Get the keys
00274               if (Key::Code(0) == (sfEvent.Key.Code = KeyForUnicode(rawchr))) {
00275                      sfEvent.Key.Code = KeyForVirtualCode([event keyCode]);
00276               }
00277               
00278               // Get the modifiers
00279               sfEvent.Key.Alt = mods & NSAlternateKeyMask;
00280               sfEvent.Key.Control = mods & NSControlKeyMask;
00281               sfEvent.Key.Shift = mods & NSShiftKeyMask;
00282               
00283               // Send the event
00284               SendEvent(sfEvent);
00285        }
00286 }
00287 
00288 
00292 void WindowImplCocoa::HandleKeyUp(void *eventRef)
00293 {
00294        NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
00295        
00296        Event sfEvent;
00297        unsigned mods = [event modifierFlags];
00298        unichar chr = 0, rawchr = 0;
00299        
00300        if ([[event characters] length]) {
00301               chr = [[event characters] characterAtIndex:0];
00302               
00303               if ([[event charactersIgnoringModifiers] length])
00304                      rawchr = [[event charactersIgnoringModifiers] characterAtIndex:0];
00305               
00306               sfEvent.Type = Event::KeyReleased;
00307               
00308               // Get the code
00309               if (Key::Code(0) == (sfEvent.Key.Code = KeyForUnicode(rawchr))) {
00310                      sfEvent.Key.Code = KeyForVirtualCode([event keyCode]);
00311               }
00312               
00313               // Get the modifiers
00314               sfEvent.Key.Alt = mods & NSAlternateKeyMask;
00315               sfEvent.Key.Control = mods & NSControlKeyMask;
00316               sfEvent.Key.Shift = mods & NSShiftKeyMask;
00317               
00318               // Send the event
00319               SendEvent(sfEvent);
00320        }
00321 }
00322 
00323 
00327 void WindowImplCocoa::HandleModifierKey(void *eventRef)
00328 {
00329        NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
00330        Event sfEvent;
00331        unsigned mods = [event modifierFlags];
00332        
00333        sfEvent.Type = Event::KeyPressed;
00334        
00335        // Get the code
00336        sfEvent.Key.Code = KeyForVirtualCode([event keyCode]);
00337        
00338        // Get the modifiers
00339        sfEvent.Key.Alt = mods & NSAlternateKeyMask;
00340        sfEvent.Key.Control = mods & NSControlKeyMask;
00341        sfEvent.Key.Shift = mods & NSShiftKeyMask;
00342        
00343        // Guess whether it's a pressed or released event
00344        // Note: this does not work fine is both left and right modifiers are pressed
00345        // I did not find any way to fix this.
00346        // TODO: fix handling of modifier flags for use of left and right key at the same time
00347        if (!(mods & NSAlternateKeyMask) &&
00348               (sfEvent.Key.Code == Key::LAlt || sfEvent.Key.Code == Key::RAlt)) {
00349               sfEvent.Type = Event::KeyReleased;
00350        }
00351        
00352        if (!(mods & NSControlKeyMask) &&
00353               (sfEvent.Key.Code == Key::LControl || sfEvent.Key.Code == Key::RControl)) {
00354               sfEvent.Type = Event::KeyReleased;
00355        }
00356        
00357        if (!(mods & NSShiftKeyMask) &&
00358               (sfEvent.Key.Code == Key::LShift || sfEvent.Key.Code == Key::RShift)) {
00359               sfEvent.Type = Event::KeyReleased;
00360        }
00361        
00362        if (!(mods & NSCommandKeyMask) &&
00363               (sfEvent.Key.Code == Key::LSystem || sfEvent.Key.Code == Key::RSystem)) {
00364               sfEvent.Type = Event::KeyReleased;
00365        }
00366        
00367        // Send the event
00368        SendEvent(sfEvent);
00369 }
00370 
00371 
00375 void WindowImplCocoa::HandleMouseDown(void *eventRef)
00376 {
00377        NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
00378        Event sfEvent;
00379        
00380        // Get mouse position relative to the window
00381        NSPoint loc = [myWrapper mouseLocation];
00382        unsigned mods = [event modifierFlags];
00383        
00384        switch ([event type]) {
00385               case NSLeftMouseDown:
00386                      sfEvent.Type = Event::MouseButtonPressed;
00387                      
00388                      // Guess whether it's a mouse left or mouse right event
00389                      if (mods & NSControlKeyMask) {
00390                             sfEvent.MouseButton.Button = Mouse::Right;
00391                      } else {
00392                             sfEvent.MouseButton.Button = Mouse::Left;
00393                      }
00394                      
00395                      sfEvent.MouseButton.X = (int) loc.x;
00396                      sfEvent.MouseButton.Y = (int) loc.y;
00397                      
00398                      // Send the event
00399                      SendEvent(sfEvent);
00400                      break;
00401                      
00402               case NSRightMouseDown:
00403                      sfEvent.Type = Event::MouseButtonPressed;
00404                      sfEvent.MouseButton.Button = Mouse::Right;
00405                      
00406                      sfEvent.MouseButton.X = (int) loc.x;
00407                      sfEvent.MouseButton.Y = (int) loc.y;
00408                      
00409                      // Send the event
00410                      SendEvent(sfEvent);
00411                      break;
00412                      
00413               default:
00414                      break;
00415        }
00416 }
00417 
00418 
00422 void WindowImplCocoa::HandleMouseUp(void *eventRef)
00423 {
00424        NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
00425        Event sfEvent;
00426        
00427        // Get mouse position relative to the window
00428        NSPoint loc = [myWrapper mouseLocation];
00429        unsigned mods = [event modifierFlags];
00430        
00431        switch ([event type]) {
00432               case NSLeftMouseUp:
00433                      sfEvent.Type = Event::MouseButtonReleased;
00434                      
00435                      // Guess whether it's a mouse left or mouse right event
00436                      if (mods & NSControlKeyMask) {
00437                             sfEvent.MouseButton.Button = Mouse::Right;
00438                      } else {
00439                             sfEvent.MouseButton.Button = Mouse::Left;
00440                      }
00441                      
00442                      sfEvent.MouseButton.X = (int) loc.x;
00443                      sfEvent.MouseButton.Y = (int) loc.y;
00444                      
00445                      // Send the event
00446                      SendEvent(sfEvent);
00447                      break;
00448                      
00449               case NSRightMouseUp:
00450                      sfEvent.Type = Event::MouseButtonReleased;
00451                      sfEvent.MouseButton.Button = Mouse::Right;
00452                      
00453                      sfEvent.MouseButton.X = (int) loc.x;
00454                      sfEvent.MouseButton.Y = (int) loc.y;
00455                      
00456                      // Send the event
00457                      SendEvent(sfEvent);
00458                      break;
00459                      
00460               default:
00461                      break;
00462        }
00463 }
00464 
00465 
00469 void WindowImplCocoa::HandleMouseMove(void *eventRef)
00470 {
00471        Event sfEvent;
00472        NSPoint loc = [myWrapper mouseLocation];
00473        sfEvent.Type = Event::MouseMoved;
00474        
00475        sfEvent.MouseMove.X = (int) loc.x;
00476        sfEvent.MouseMove.Y = (int) loc.y;
00477        
00478        SendEvent(sfEvent);
00479        
00480        if ([myWrapper mouseInside] && !myMouseIn) {
00481               // If mouse IS inside but WAS not inside last time
00482               sfEvent.Type = Event::MouseEntered;
00483               myMouseIn = true;
00484               
00485               SendEvent(sfEvent);
00486        } else if (![myWrapper mouseInside] && myMouseIn) {
00487               // Is mouse WAS not inside but IS now inside
00488               sfEvent.Type = Event::MouseLeft;
00489               myMouseIn     = false;
00490               
00491               SendEvent(sfEvent);
00492        }
00493 }
00494 
00495 
00499 void WindowImplCocoa::HandleMouseWheel(void *eventRef)
00500 {
00501        NSEvent *event = reinterpret_cast <NSEvent *> (eventRef);
00502        
00503        // SFML uses integer values for delta but Cocoa uses float and it is mostly fewer than 1.0
00504        // Therefore I chose to add the float value to a 'wheel status' and
00505        // send a sf event only when it's greater than 1.0
00506        myWheelStatus += [event deltaY];
00507        
00508        if (fabs(myWheelStatus) > 1.0f) {
00509               // Make the event and send it
00510               Event sfEvent;
00511               sfEvent.Type = Event::MouseWheelMoved;
00512               sfEvent.MouseWheel.Delta = (int) myWheelStatus;
00513               SendEvent(sfEvent);
00514               
00515               // Remove as much integer units as the one that have been put in the event
00516               // (was a mistake to set this to 0)
00517               myWheelStatus -= (int) myWheelStatus;
00518        }
00519 }
00520        
00524 bool WindowImplCocoa::IsTextEvent(void *eventRef)
00525 {
00526        NSEvent *event = (NSEvent *)eventRef;
00527        bool res = false;
00528        
00529        if (event && [event type] == NSKeyDown && [[event characters] length]) {
00530               unichar code = [[event characters] characterAtIndex:0];
00531               
00532               // Codes from 0xF700 to 0xF8FF are non text keys (see NSEvent.h)
00533               // 0x35 is the Escape key
00534               if ([event keyCode] != 0x35 && (code < 0xF700 || code > 0xF8FF))
00535                      res = true;
00536        }
00537        
00538        return res;
00539 }
00540        
00544 void WindowImplCocoa::Display()
00545 {
00546        // Forward flush call to the window
00547        [myWrapper flushBuffer];
00548 }
00549 
00550 
00554 void WindowImplCocoa::ProcessEvents()
00555 {
00556        // Forward event handling call to the application controller
00557        [[sfPrivAppController sharedController] processEvents];
00558 }
00559 
00560 
00564 void WindowImplCocoa::SetActive(bool Active) const
00565 {
00566        // Forward the call to the window
00567        if (myWrapper)
00568               [myWrapper setActive:Active];
00569        else {
00570               // Or directly activate the shared OpenGL context if we're not using a window
00571               if (Active) {
00572                      if ([NSOpenGLContext currentContext] != [sfPrivGLContext sharedContext])
00573                             [[sfPrivGLContext sharedContext] makeCurrentContext];
00574               } else {
00575                      if ([NSOpenGLContext currentContext] == [sfPrivGLContext sharedContext])
00576                             [NSOpenGLContext clearCurrentContext];
00577               }
00578        }
00579 }
00580 
00581 
00585 void WindowImplCocoa::UseVerticalSync(bool Enabled)
00586 {
00587        // Forward the call to the window
00588        [myWrapper enableVerticalSync:Enabled];
00589 }
00590 
00591 
00595 void WindowImplCocoa::ShowMouseCursor(bool flag)
00596 {
00597        if (flag) {
00598               [NSCursor unhide];
00599        } else {
00600               [NSCursor hide];
00601        }
00602 }
00603 
00604 
00608 void WindowImplCocoa::SetCursorPosition(unsigned int Left, unsigned int Top)
00609 {
00610        NSPoint pos = NSMakePoint ((float) Left, (float) Top);
00611        
00612        if (myWrapper) {
00613               // Flip for SFML window coordinate system
00614               pos.y = [[myWrapper window] frame].size.height - pos.y;
00615               
00616               // Adjust for view reference instead of window
00617               pos.y -= [[myWrapper window] frame].size.height - [[myWrapper view] frame].size.height;
00618               
00619               // Convert to screen coordinates
00620               NSPoint absolute = [[myWrapper window] convertBaseToScreen:pos];
00621               
00622               // Flip screen coodinates
00623               absolute.y = [[NSScreen mainScreen] frame].size.height - absolute.y;
00624               
00625               // Move cursor
00626               CGDisplayMoveCursorToPoint([sfPrivAppController primaryScreen],
00627                                                            CGPointMake(absolute.x, absolute.y));
00628        }
00629 }
00630 
00631 
00635 void WindowImplCocoa::SetPosition(int Left, int Top)
00636 {
00637        [myWrapper setPosition:NSMakePoint(Left, Top)];
00638 }
00639 
00640 
00645 void WindowImplCocoa::SetSize(unsigned int Width, unsigned int Height)
00646 {
00647        [myWrapper setSize:NSMakeSize(Width, Height)];
00648 }
00649 
00650 
00654 void WindowImplCocoa::Show(bool State)
00655 {
00656        [myWrapper show:State];
00657 }
00658 
00659 
00663 void WindowImplCocoa::EnableKeyRepeat(bool Enabled)
00664 {
00665        myUseKeyRepeat = Enabled;
00666 }
00667 
00668 
00672 void WindowImplCocoa::SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels)
00673 {
00674        // Nothing to do
00675 }
00676 
00677 
00678 namespace {
00682        Key::Code KeyForVirtualCode(unsigned short vCode)
00683        {
00684               static struct {
00685                      unsigned short code;
00686                      Key::Code sfKey;
00687               } virtualTable[] =
00688               {
00689                      {0x35, Key::Escape},
00690                      {0x31, Key::Space},
00691                      {0x24, Key::Return}, // main Return key
00692                      {0x4C, Key::Return}, // pav Return key
00693                      {0x33, Key::Back},
00694                      {0x30, Key::Tab},
00695                      {0x74, Key::PageUp},
00696                      {0x79, Key::PageDown},
00697                      {0x77, Key::End},
00698                      {0x73, Key::Home},
00699                      {0x72, Key::Insert},
00700                      {0x75, Key::Delete},
00701                      {0x45, Key::Add},
00702                      {0x4E, Key::Subtract},
00703                      {0x43, Key::Multiply},
00704                      {0x4B, Key::Divide},
00705                      
00706                      {0x7A, Key::F1}, {0x78, Key::F2}, {0x63, Key::F3},
00707                      {0x76, Key::F4}, {0x60, Key::F5}, {0x61, Key::F6},
00708                      {0x62, Key::F7}, {0x64, Key::F8}, {0x65, Key::F9},
00709                      {0x6D, Key::F10}, {0x67, Key::F11}, {0x6F, Key::F12},
00710                      {0x69, Key::F13}, {0x6B, Key::F14}, {0x71, Key::F15},
00711                      
00712                      {0x7B, Key::Left},
00713                      {0x7C, Key::Right},
00714                      {0x7E, Key::Up},
00715                      {0x7D, Key::Down},
00716                      
00717                      {0x52, Key::Numpad0}, {0x53, Key::Numpad1}, {0x54, Key::Numpad2},
00718                      {0x55, Key::Numpad3}, {0x56, Key::Numpad4}, {0x57, Key::Numpad5},
00719                      {0x58, Key::Numpad6}, {0x59, Key::Numpad7}, {0x5B, Key::Numpad8},
00720                      {0x5C, Key::Numpad9},
00721                      
00722                      {0x1D, Key::Num0}, {0x12, Key::Num1}, {0x13, Key::Num2},
00723                      {0x14, Key::Num3}, {0x15, Key::Num4}, {0x17, Key::Num5},
00724                      {0x16, Key::Num6}, {0x1A, Key::Num7}, {0x1C, Key::Num8},
00725                      {0x19, Key::Num9},
00726                      
00727                      {0x3B, Key::LControl},      //< Left Ctrl
00728                      {0x3A, Key::LAlt},          //< Left Option/Alt
00729                      {0x37, Key::LSystem},       //< Left Command
00730                      {0x38, Key::LShift}, //< Left Shift
00731                      {0x3E, Key::RControl},      //< Right Ctrl
00732                      {0x3D, Key::RAlt},          //< Right Option/Alt
00733                      {0x36, Key::RSystem},       //< Right Command
00734                      {0x3C, Key::RShift}, //< Right Shift
00735                      
00736                      {0x39, Key::Code(0)} //< Caps Lock (not handled by SFML for now)
00737               };
00738               
00739               Key::Code result = Key::Code(0);
00740               
00741               for (unsigned i = 0;virtualTable[i].code;i++) {
00742                      if (virtualTable[i].code == vCode) {
00743                             result = virtualTable[i].sfKey;
00744                             break;
00745                      }
00746               }
00747               
00748               return result;
00749        }
00750        
00751        
00755        Key::Code KeyForUnicode(unsigned short uniCode)
00756        {
00757               // TODO: find a better way to get the language independant key
00758               static struct {
00759                      unsigned short character;
00760                      Key::Code sfKey;
00761               } unicodeTable[] =
00762               {
00763                      {'!', Key::Code(0)}, //< No Key for this code
00764                      {'"', Key::Code(0)}, //< No Key for this code
00765                      {'#', Key::Code(0)}, //< No Key for this code
00766                      {'$', Key::Code(0)}, //< No Key for this code
00767                      {'%', Key::Code(0)}, //< No Key for this code
00768                      {'&', Key::Code(0)}, //< No Key for this code
00769                      {'\'', Key::Quote},
00770                      {'(', Key::Code(0)}, //< No Key for this code
00771                      {')', Key::Code(0)}, //< No Key for this code
00772                      {'*', Key::Multiply},
00773                      {'+', Key::Add},
00774                      {',', Key::Comma},
00775                      {'-', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00776                      {'.', Key::Period},
00777                      {'/', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00778                      {'0', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00779                      {'1', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00780                      {'2', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00781                      {'3', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00782                      {'4', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00783                      {'5', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00784                      {'6', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00785                      {'7', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00786                      {'8', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00787                      {'9', Key::Code(0)}, //< Handled by KeyForVirtualCode()
00788                      {':', Key::Code(0)}, //< No Key for this code
00789                      {';', Key::SemiColon},
00790                      {'<', Key::Code(0)}, //< No Key for this code
00791                      {'=', Key::Equal},
00792                      {'>', Key::Code(0)}, //< No Key for this code
00793                      {'?', Key::Code(0)}, //< No Key for this code
00794                      {'@', Key::Code(0)}, //< No Key for this code
00795                      {'A', Key::A}, {'B', Key::B}, {'C', Key::C},
00796                      {'D', Key::D}, {'E', Key::E}, {'F', Key::F},
00797                      {'G', Key::G}, {'H', Key::H}, {'I', Key::I},
00798                      {'J', Key::J}, {'K', Key::K}, {'L', Key::L},
00799                      {'M', Key::M}, {'N', Key::N}, {'O', Key::O},
00800                      {'P', Key::P}, {'Q', Key::Q}, {'R', Key::R},
00801                      {'S', Key::S}, {'T', Key::T}, {'U', Key::U},
00802                      {'V', Key::V}, {'W', Key::W}, {'X', Key::X},
00803                      {'Y', Key::Y}, {'Z', Key::Z},
00804                      {'[', Key::LBracket},
00805                      {'\\', Key::BackSlash},
00806                      {']', Key::RBracket},
00807                      {'^', Key::Code(0)}, //< No Key for this code
00808                      {'_', Key::Code(0)}, //< No Key for this code
00809                      {'`', Key::Code(0)}, //< No Key for this code
00810                      {'a', Key::A}, {'b', Key::B}, {'c', Key::C},
00811                      {'d', Key::D}, {'e', Key::E}, {'f', Key::F},
00812                      {'g', Key::G}, {'h', Key::H}, {'i', Key::I},
00813                      {'j', Key::J}, {'k', Key::K}, {'l', Key::L},
00814                      {'m', Key::M}, {'n', Key::N}, {'o', Key::O},
00815                      {'p', Key::P}, {'q', Key::Q}, {'r', Key::R},
00816                      {'s', Key::S}, {'t', Key::T}, {'u', Key::U},
00817                      {'v', Key::V}, {'w', Key::W}, {'x', Key::X},
00818                      {'y', Key::Y}, {'z', Key::Z},
00819                      {'{', Key::Code(0)}, //< No Key for this code
00820                      {'|', Key::Code(0)}, //< No Key for this code
00821                      {'}', Key::Code(0)}, //< No Key for this code
00822                      {'~', Key::Tilde},
00823                      {0, Key::Code(0)}
00824               };
00825               
00826               Key::Code result = Key::Code(0);
00827               
00828               for (unsigned i = 0;unicodeTable[i].character;i++) {
00829                      if (unicodeTable[i].character == uniCode) {
00830                             result = unicodeTable[i].sfKey;
00831                             break;
00832                      }
00833               }
00834               
00835               return result;
00836        }
00837        
00838 } // anonymous namespace
00839 
00840 
00841 } // namespace priv
00842 
00843 } // namespace sf
00844