PageRenderTime 26ms CodeModel.GetById 19ms app.highlight 4ms RepoModel.GetById 0ms app.codeStats 0ms

/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
 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