Implemented OSX/InputImpl::IsKeyPressed

This commit is contained in:
Marco Antognini 2011-07-09 16:35:13 +02:00
parent 2f443ea08a
commit d80808b61d
5 changed files with 1090 additions and 290 deletions

View File

@ -68,7 +68,9 @@ else() # MACOSX
${SRCROOT}/OSX/cg_sf_conversion.hpp
${SRCROOT}/OSX/cg_sf_conversion.cpp
${SRCROOT}/OSX/InputImpl.mm
${SRCROOT}/OSX/InputImpl.hpp
${SRCROOT}/OSX/InputImpl.hpp
${SRCROOT}/OSX/HIDInputManager.hpp
${SRCROOT}/OSX/HIDInputManager.mm
${SRCROOT}/OSX/JoystickImpl.cpp
${SRCROOT}/OSX/JoystickImpl.hpp
${SRCROOT}/OSX/SFApplication.h
@ -105,7 +107,7 @@ if(WINDOWS)
elseif(LINUX)
set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} ${X11_X11_LIB} ${X11_Xrandr_LIB})
elseif(MACOSX)
set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} "-framework Foundation -framework AppKit -framework IOKit")
set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
endif()
# define the sfml-window target

View File

@ -0,0 +1,178 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent.gom@gmail.com),
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_HIDINPUTMANAGER_HPP
#define SFML_HIDINPUTMANAGER_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <SFML/Window/JoystickImpl.hpp>
#include <SFML/Window/Keyboard.hpp>
#include <SFML/Window/Mouse.hpp>
#include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/hid/IOHIDDevice.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief This class manage as a singleton instance the
/// keyboard and mouse states. It's only purpose is
/// to help sf::priv::InputImpl class.
///
/// sf::priv::JoystickImpl is not concerned by this class.
///
////////////////////////////////////////////////////////////
class HIDInputManager : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Get the unique instance of the class
///
/// \note Private use only
///
/// \return Reference to the HIDInputManager instance
///
////////////////////////////////////////////////////////////
static HIDInputManager& GetInstance();
////////////////////////////////////////////////////////////
/// \brief Check if a key is pressed
///
/// \param key Key to check
///
/// \return True if the key is pressed, false otherwise
///
////////////////////////////////////////////////////////////
bool IsKeyPressed(Keyboard::Key key);
////////////////////////////////////////////////////////////
/// \brief Check if a mouse button is pressed
///
/// \param button Button to check
///
/// \return True if the button is pressed, false otherwise
///
////////////////////////////////////////////////////////////
bool IsMouseButtonPressed(Mouse::Button button);
////////////////////////////////////////////////////////////
/// Try to convert a character into a SFML key code.
///
/// Return sf::Keyboard::KeyCount if it doesn't match any 'localized' keys.
///
/// By 'localized' I mean keys that depend on the keyboard layout
/// and might not be the same as the US keycode in some country
/// (e.g. the keys 'Y' and 'Z' are switched on QWERTZ keyboard and
/// US keyboard layouts.)
///
////////////////////////////////////////////////////////////
static Keyboard::Key LocalizedKeys(UniChar ch);
////////////////////////////////////////////////////////////
/// Try to convert a virtual keycode into a SFML key code.
///
/// Return sf::Keyboard::KeyCount if the keycode is unknown.
///
////////////////////////////////////////////////////////////
static Keyboard::Key NonLocalizedKeys(UniChar virtualKeycode);
private :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
HIDInputManager();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~HIDInputManager();
////////////////////////////////////////////////////////////
/// \brief Initialize the keyboard part of this class
///
/// If something went wrong FreeUp is called
///
////////////////////////////////////////////////////////////
void InitializeKeyboard();
////////////////////////////////////////////////////////////
/// \brief Release all resources
///
/// Close all connections to any devices, if required
/// Set amIValid to false
///
////////////////////////////////////////////////////////////
void FreeUp();
////////////////////////////////////////////////////////////
/// \brief Create a mask (dictionary) for an IOHIDManager
///
/// \param page HID page
/// \param usage HID usage page
/// \return a retained CFDictionaryRef
///
////////////////////////////////////////////////////////////
static CFDictionaryRef CopyDevicesMaskForManager(UInt32 page, UInt32 usage);
////////////////////////////////////////////////////////////
/// \brief Converte a HID key usage to it's conrresponding virtual code
///
/// See IOHIDUsageTables.h
///
/// \param usage Any kHIDUsage_Keyboard* usage
/// \return the virtual code associate to the given HID key usage
/// or 0xff if it is associate to no virtual code
///
////////////////////////////////////////////////////////////
static UInt8 UsageToVirtualCode(UInt32 usage);
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
bool amIValid; ///< If any error occurs this variable is false
CFDataRef myLayoutData; ///< CFData containing the layout
UCKeyboardLayout* myLayout; ///< Current Keyboard Layout
IOHIDManagerRef myManager; ///< HID Manager
IOHIDElementRef myKeys[Keyboard::KeyCount]; ///< All the keys on the current keyboard
/* myKeys index correspond to sf::Keyboard::Key enum */
/* if no key is assigned to a key XYZ then myKeys[XYZ] = 0 */
};
} // namespace priv
} // namespace sf
#endif

View File

@ -0,0 +1,877 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent.gom@gmail.com),
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/HIDInputManager.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
#include <AppKit/AppKit.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
HIDInputManager& HIDInputManager::GetInstance()
{
static HIDInputManager instance;
return instance;
}
////////////////////////////////////////////////////////////
bool HIDInputManager::IsKeyPressed(Keyboard::Key key)
{
if (!amIValid) {
sf::Err() << "HIDInputManager is invalid." << std::endl;
return false;
}
// Have we an associate IOHIDElementRef to that key ?
if (myKeys[key] == 0) { // No
sf::Err() << key
<< " is not associate to any IOHIDElementRef."
<< std::endl;
return false;
} else { // Yes
IOHIDValueRef value = 0;
IOHIDDeviceRef device = IOHIDElementGetDevice(myKeys[key]);
IOHIDDeviceGetValue(device, myKeys[key], &value);
if (!value) {
// This means some kind of error / deconnection so we remove this
// element from our keys
CFRelease(myKeys[key]);
myKeys[key] = 0;
sf::Err() << key
<< " is dead (cannot access its value)."
<< std::endl;
return false;
} else if (IOHIDValueGetIntegerValue(value) == 1) {
// This means the key is pressed
return true;
} else {
// This means the key is released
return false;
}
}
}
////////////////////////////////////////////////////////////
bool HIDInputManager::IsMouseButtonPressed(Mouse::Button button)
{
if (!amIValid) {
sf::Err() << "HIDInputManager is invalid." << std::endl;
return false;
}
// @to be implemented
return false;
}
////////////////////////////////////////////////////////////
HIDInputManager::HIDInputManager()
: amIValid(true)
, myLayoutData(0)
, myLayout(0)
, myManager(0)
{
// And initialize myKeys with 0s.
std::fill(myKeys, myKeys + Keyboard::KeyCount, (IOHIDElementRef)0);
// Get the current keyboard layout
TISInputSourceRef tis = TISCopyCurrentKeyboardLayoutInputSource();
myLayoutData = (CFDataRef)TISGetInputSourceProperty(tis,
kTISPropertyUnicodeKeyLayoutData);
if (myLayoutData == 0) {
sf::Err() << "Cannot get the keyboard layout" << std::endl;
FreeUp();
return;
}
// Keep a reference for ourself
CFRetain(myLayoutData);
myLayout = (UCKeyboardLayout *)CFDataGetBytePtr(myLayoutData);
// The TIS is no more needed
CFRelease(tis);
// Create an HID Manager reference
myManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
// Open the HID Manager reference
IOReturn openStatus = IOHIDManagerOpen(myManager, kIOHIDOptionsTypeNone);
if (openStatus != kIOReturnSuccess) {
sf::Err() << "Error when opening the HID manager" << std::endl;
FreeUp();
return;
}
// Initialize the keyboard
InitializeKeyboard();
if (!amIValid) {
return; // Something went wrong
}
// TODO init mouse
}
////////////////////////////////////////////////////////////
HIDInputManager::~HIDInputManager()
{
FreeUp();
}
void HIDInputManager::InitializeKeyboard()
{
////////////////////////////////////////////////////////////
// The purpose of this function is to initalize myKeys so we can get
// the associate IOHIDElementRef of a sf::Keyboard::Key in constant time.
// Filter and keep only the keyboards
CFDictionaryRef mask = CopyDevicesMaskForManager(kHIDPage_GenericDesktop,
kHIDUsage_GD_Keyboard);
IOHIDManagerSetDeviceMatching(myManager, mask);
CFRelease(mask);
mask = 0;
CFSetRef keyboards = IOHIDManagerCopyDevices(myManager);
if (keyboards == NULL) {
sf::Err() << "Cannot find any keyboard (1)" << std::endl;
FreeUp();
return;
}
// Is there at least one keyboard ?
CFIndex keyboardCount = CFSetGetCount(keyboards);
if (keyboardCount < 1) {
sf::Err() << "Cannot find any keyboard (2)" << std::endl;
CFRelease(keyboards);
FreeUp();
return;
}
// Get the first keyboard
CFTypeRef devicesArray[keyboardCount];
CFSetGetValues(keyboards, devicesArray);
IOHIDDeviceRef keyboard = (IOHIDDeviceRef)devicesArray[0];
CFArrayRef keys = IOHIDDeviceCopyMatchingElements(keyboard,
NULL,
kIOHIDOptionsTypeNone);
// Release unused stuff
CFRelease(keyboards);
if (keys == NULL) {
sf::Err() << "We got a keyboard without any keys (1)" << std::endl;
FreeUp();
return;
}
// How many elements are there ?
CFIndex keysCount = CFArrayGetCount(keys);
if (keysCount == 0) {
sf::Err() << "We got a keyboard without any keys (2)" << std::endl;
CFRelease(keys);
FreeUp();
return;
}
// Go through all connected elements.
for (int i = 0; i < keysCount; ++i) {
IOHIDElementRef aKey = (IOHIDElementRef) CFArrayGetValueAtIndex(keys, i);
// Skip non-matching keys elements
if (IOHIDElementGetUsagePage(aKey) != kHIDPage_KeyboardOrKeypad) {
continue;
}
// Get its virtual code
UInt32 usageCode = IOHIDElementGetUsage(aKey);
UInt8 virtualCode = UsageToVirtualCode(usageCode);
if (virtualCode == 0xff) {
continue; // no corresponding virtual code -> skip
}
// Now translate the virtual code to unicode according to
// the current keyboard layout
UInt32 deadKeyState = 0;
// unicode string length is usually less or equal to 4
UniCharCount maxStringLength = 4;
UniCharCount actualStringLength = 0;
UniChar unicodeString[maxStringLength];
OSStatus error;
error = UCKeyTranslate(myLayout, // current layout
virtualCode, // our key
kUCKeyActionDown, // or kUCKeyActionUp ?
0x100, // no modifiers
LMGetKbdType(), // keyboard's type
kUCKeyTranslateNoDeadKeysBit,// some sort of option
&deadKeyState, // unused stuff
maxStringLength, // our memory limit
&actualStringLength, // length of what we get
unicodeString); // what we get
if (error == noErr) {
// Translation went fine
// The corresponding SFML key code
Keyboard::Key code = Keyboard::KeyCount;
// First we look if the key down is from a list of caracter
// that depend on keyboard localization.
if (actualStringLength > 0) {
code = LocalizedKeys(unicodeString[0]);
}
// The key is not a localized one, so we try to find a corresponding
// code through virtual key code.
if (code == Keyboard::KeyCount) {
code = NonLocalizedKeys(virtualCode);
}
// A code was found, wonderful!
if (code != Keyboard::KeyCount) {
// Last step : verify that the key was not found twice or more
// Some keys (modifiers) appears to be twice on my keyboard
// I've no idea why
// if (myKeys[code] != 0) {
// UInt32 firstUsageCode = IOHIDElementGetUsage(myKeys[code]);
// sf::Err() << "The current keyboard has several times the "
// << "same keys. Only the first one is considered "
// << "as valid. sf::Keyboard::Key is "
// << code
// << ", virtual key code is 0x"
// << std::hex
// << (UInt32)virtualCode
// << " and HID usage code is 0x"
// << usageCode
// << ". First HID usage code is 0x"
// << firstUsageCode
// << std::dec
// << "."
// << std::endl;
// }
if (myKeys[code] == 0) {
// Ok, everything went fine. Now we have a unique
// corresponding sf::Keyboard::Key to one IOHIDElementRef.
myKeys[code] = aKey;
// And don't forget to keep the reference alive for our usage
CFRetain(myKeys[code]);
}
}
////////////////////////////////////////////////////////////
// These are known to be unbound :
// Supposed Virtual | HID | Supposed Key
// ===============================================
// 0x1b | 0x2d | Hyphen
// 0x39 | 0x39 | CapsLock
// 0x47 | 0x53 | NumLock
// 0x4c | 0x58 | Keypad Enter
// 0x41 | 0x63 | Keypad Period
// 0x6e | 0x65 | Application
// 0x51 | 0x67 | Keypad Equal
// 0x4c | 0x77 | Select
// else { // The key is unknown.
// sf::Err() << "This is an unknow key. Virtual key code is 0x"
// << std::hex
// << (UInt32)virtualCode
// << " and HID usage code is 0x"
// << usageCode
// << std::dec
// << "."
// << std::endl;
// }
} /* if (error == noErr) */
else {
sf::Err() << "Cannot translate the virtual key code, error : "
<< error
<< std::endl;
}
} /* for (int i = 0; i < keysCount; ++i) */
CFRelease(keys);
////////////////////////////////////////////////////////////
// At this point myKeys is filled with as many IOHIDElementRef as possible
}
////////////////////////////////////////////////////////////
void HIDInputManager::FreeUp()
{
amIValid = false;
if (myLayoutData != 0) CFRelease(myLayoutData);
// Do not release myLayout ! It is owned by myLayoutData.
if (myManager != 0) CFRelease(myManager);
for (unsigned int i = 0; i < Keyboard::KeyCount; ++i) {
if (myKeys[i] != 0) {
CFRelease(myKeys[i]);
}
}
}
////////////////////////////////////////////////////////////
CFDictionaryRef HIDInputManager::CopyDevicesMaskForManager(UInt32 page, UInt32 usage)
{
// Create the dictionary.
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// Add the page value.
CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page);
CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), value);
CFRelease(value);
// Add the usage value (which is only valid if page value exists).
value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), value);
CFRelease(value);
return dict;
}
////////////////////////////////////////////////////////////
UInt8 HIDInputManager::UsageToVirtualCode(UInt32 usage)
{
// Some usage key doesn't have any corresponding virtual code or it was not
// found.
switch (usage) {
case kHIDUsage_KeyboardErrorRollOver: return 0xff;
case kHIDUsage_KeyboardPOSTFail: return 0xff;
case kHIDUsage_KeyboardErrorUndefined: return 0xff;
case kHIDUsage_KeyboardA: return 0x00;
case kHIDUsage_KeyboardB: return 0x0b;
case kHIDUsage_KeyboardC: return 0x08;
case kHIDUsage_KeyboardD: return 0x02;
case kHIDUsage_KeyboardE: return 0x0e;
case kHIDUsage_KeyboardF: return 0x03;
case kHIDUsage_KeyboardG: return 0x05;
case kHIDUsage_KeyboardH: return 0x04;
case kHIDUsage_KeyboardI: return 0x22;
case kHIDUsage_KeyboardJ: return 0x26;
case kHIDUsage_KeyboardK: return 0x28;
case kHIDUsage_KeyboardL: return 0x25;
case kHIDUsage_KeyboardM: return 0x2e;
case kHIDUsage_KeyboardN: return 0x2d;
case kHIDUsage_KeyboardO: return 0x1f;
case kHIDUsage_KeyboardP: return 0x23;
case kHIDUsage_KeyboardQ: return 0x0c;
case kHIDUsage_KeyboardR: return 0x0f;
case kHIDUsage_KeyboardS: return 0x01;
case kHIDUsage_KeyboardT: return 0x11;
case kHIDUsage_KeyboardU: return 0x20;
case kHIDUsage_KeyboardV: return 0x09;
case kHIDUsage_KeyboardW: return 0x0d;
case kHIDUsage_KeyboardX: return 0x07;
case kHIDUsage_KeyboardY: return 0x10;
case kHIDUsage_KeyboardZ: return 0x06;
case kHIDUsage_Keyboard1: return 0x12;
case kHIDUsage_Keyboard2: return 0x13;
case kHIDUsage_Keyboard3: return 0x14;
case kHIDUsage_Keyboard4: return 0x15;
case kHIDUsage_Keyboard5: return 0x17;
case kHIDUsage_Keyboard6: return 0x16;
case kHIDUsage_Keyboard7: return 0x1a;
case kHIDUsage_Keyboard8: return 0x1c;
case kHIDUsage_Keyboard9: return 0x19;
case kHIDUsage_Keyboard0: return 0x1d;
case kHIDUsage_KeyboardReturnOrEnter: return 0x24;
case kHIDUsage_KeyboardEscape: return 0x35;
case kHIDUsage_KeyboardDeleteOrBackspace: return 0x33;
case kHIDUsage_KeyboardTab: return 0x30;
case kHIDUsage_KeyboardSpacebar: return 0x31;
case kHIDUsage_KeyboardHyphen: return 0x1b;
case kHIDUsage_KeyboardEqualSign: return 0x18;
case kHIDUsage_KeyboardOpenBracket: return 0x21;
case kHIDUsage_KeyboardCloseBracket: return 0x1e;
case kHIDUsage_KeyboardBackslash: return 0x2a;
case kHIDUsage_KeyboardNonUSPound: return 0xff;
case kHIDUsage_KeyboardSemicolon: return 0x29;
case kHIDUsage_KeyboardQuote: return 0x27;
case kHIDUsage_KeyboardGraveAccentAndTilde: return 0x32;
case kHIDUsage_KeyboardComma: return 0x2b;
case kHIDUsage_KeyboardPeriod: return 0x2F;
case kHIDUsage_KeyboardSlash: return 0x2c;
case kHIDUsage_KeyboardCapsLock: return 0x39;
case kHIDUsage_KeyboardF1: return 0x7a;
case kHIDUsage_KeyboardF2: return 0x78;
case kHIDUsage_KeyboardF3: return 0x63;
case kHIDUsage_KeyboardF4: return 0x76;
case kHIDUsage_KeyboardF5: return 0x60;
case kHIDUsage_KeyboardF6: return 0x61;
case kHIDUsage_KeyboardF7: return 0x62;
case kHIDUsage_KeyboardF8: return 0x64;
case kHIDUsage_KeyboardF9: return 0x65;
case kHIDUsage_KeyboardF10: return 0x6d;
case kHIDUsage_KeyboardF11: return 0x67;
case kHIDUsage_KeyboardF12: return 0x6f;
case kHIDUsage_KeyboardPrintScreen: return 0xff;
case kHIDUsage_KeyboardScrollLock: return 0xff;
case kHIDUsage_KeyboardPause: return 0xff;
case kHIDUsage_KeyboardInsert: return 0x72;
case kHIDUsage_KeyboardHome: return 0x73;
case kHIDUsage_KeyboardPageUp: return 0x74;
case kHIDUsage_KeyboardDeleteForward: return 0x75;
case kHIDUsage_KeyboardEnd: return 0x77;
case kHIDUsage_KeyboardPageDown: return 0x79;
case kHIDUsage_KeyboardRightArrow: return 0x7c;
case kHIDUsage_KeyboardLeftArrow: return 0x7b;
case kHIDUsage_KeyboardDownArrow: return 0x7d;
case kHIDUsage_KeyboardUpArrow: return 0x7e;
case kHIDUsage_KeypadNumLock: return 0x47;
case kHIDUsage_KeypadSlash: return 0x4b;
case kHIDUsage_KeypadAsterisk: return 0x43;
case kHIDUsage_KeypadHyphen: return 0x4e;
case kHIDUsage_KeypadPlus: return 0x45;
case kHIDUsage_KeypadEnter: return 0x4c;
case kHIDUsage_Keypad1: return 0x53;
case kHIDUsage_Keypad2: return 0x54;
case kHIDUsage_Keypad3: return 0x55;
case kHIDUsage_Keypad4: return 0x56;
case kHIDUsage_Keypad5: return 0x57;
case kHIDUsage_Keypad6: return 0x58;
case kHIDUsage_Keypad7: return 0x59;
case kHIDUsage_Keypad8: return 0x5b;
case kHIDUsage_Keypad9: return 0x5c;
case kHIDUsage_Keypad0: return 0x52;
case kHIDUsage_KeypadPeriod: return 0x41;
case kHIDUsage_KeyboardNonUSBackslash: return 0xff;
case kHIDUsage_KeyboardApplication: return 0x6e;
case kHIDUsage_KeyboardPower: return 0xff;
case kHIDUsage_KeypadEqualSign: return 0x51;
case kHIDUsage_KeyboardF13: return 0x69;
case kHIDUsage_KeyboardF14: return 0x6b;
case kHIDUsage_KeyboardF15: return 0x71;
case kHIDUsage_KeyboardF16: return 0xff;
case kHIDUsage_KeyboardF17: return 0xff;
case kHIDUsage_KeyboardF18: return 0xff;
case kHIDUsage_KeyboardF19: return 0xff;
case kHIDUsage_KeyboardF20: return 0xff;
case kHIDUsage_KeyboardF21: return 0xff;
case kHIDUsage_KeyboardF22: return 0xff;
case kHIDUsage_KeyboardF23: return 0xff;
case kHIDUsage_KeyboardF24: return 0xff;
case kHIDUsage_KeyboardExecute: return 0xff;
case kHIDUsage_KeyboardHelp: return 0xff;
case kHIDUsage_KeyboardMenu: return 0x7F;
case kHIDUsage_KeyboardSelect: return 0x4c;
case kHIDUsage_KeyboardStop: return 0xff;
case kHIDUsage_KeyboardAgain: return 0xff;
case kHIDUsage_KeyboardUndo: return 0xff;
case kHIDUsage_KeyboardCut: return 0xff;
case kHIDUsage_KeyboardCopy: return 0xff;
case kHIDUsage_KeyboardPaste: return 0xff;
case kHIDUsage_KeyboardFind: return 0xff;
case kHIDUsage_KeyboardMute: return 0xff;
case kHIDUsage_KeyboardVolumeUp: return 0xff;
case kHIDUsage_KeyboardVolumeDown: return 0xff;
case kHIDUsage_KeyboardLockingCapsLock: return 0xff;
case kHIDUsage_KeyboardLockingNumLock: return 0xff;
case kHIDUsage_KeyboardLockingScrollLock: return 0xff;
case kHIDUsage_KeypadComma: return 0xff;
case kHIDUsage_KeypadEqualSignAS400: return 0xff;
case kHIDUsage_KeyboardInternational1: return 0xff;
case kHIDUsage_KeyboardInternational2: return 0xff;
case kHIDUsage_KeyboardInternational3: return 0xff;
case kHIDUsage_KeyboardInternational4: return 0xff;
case kHIDUsage_KeyboardInternational5: return 0xff;
case kHIDUsage_KeyboardInternational6: return 0xff;
case kHIDUsage_KeyboardInternational7: return 0xff;
case kHIDUsage_KeyboardInternational8: return 0xff;
case kHIDUsage_KeyboardInternational9: return 0xff;
case kHIDUsage_KeyboardLANG1: return 0xff;
case kHIDUsage_KeyboardLANG2: return 0xff;
case kHIDUsage_KeyboardLANG3: return 0xff;
case kHIDUsage_KeyboardLANG4: return 0xff;
case kHIDUsage_KeyboardLANG5: return 0xff;
case kHIDUsage_KeyboardLANG6: return 0xff;
case kHIDUsage_KeyboardLANG7: return 0xff;
case kHIDUsage_KeyboardLANG8: return 0xff;
case kHIDUsage_KeyboardLANG9: return 0xff;
case kHIDUsage_KeyboardAlternateErase: return 0xff;
case kHIDUsage_KeyboardSysReqOrAttention: return 0xff;
case kHIDUsage_KeyboardCancel: return 0xff;
case kHIDUsage_KeyboardClear: return 0xff;
case kHIDUsage_KeyboardPrior: return 0xff;
case kHIDUsage_KeyboardReturn: return 0xff;
case kHIDUsage_KeyboardSeparator: return 0xff;
case kHIDUsage_KeyboardOut: return 0xff;
case kHIDUsage_KeyboardOper: return 0xff;
case kHIDUsage_KeyboardClearOrAgain: return 0xff;
case kHIDUsage_KeyboardCrSelOrProps: return 0xff;
case kHIDUsage_KeyboardExSel: return 0xff;
/* 0xa5-0xdf Reserved */
case kHIDUsage_KeyboardLeftControl: return 0x3b;
case kHIDUsage_KeyboardLeftShift: return 0x38;
case kHIDUsage_KeyboardLeftAlt: return 0x3a;
case kHIDUsage_KeyboardLeftGUI: return 0x37;
case kHIDUsage_KeyboardRightControl: return 0x3e;
case kHIDUsage_KeyboardRightShift: return 0x3c;
case kHIDUsage_KeyboardRightAlt: return 0x3d;
case kHIDUsage_KeyboardRightGUI: return 0x36;
/* 0xe8-0xffff Reserved */
case kHIDUsage_Keyboard_Reserved: return 0xff;
default: return 0xff;
}
}
////////////////////////////////////////////////////////
Keyboard::Key HIDInputManager::LocalizedKeys(UniChar ch)
{
switch (ch) {
case 'a':
case 'A': return sf::Keyboard::A;
case 'b':
case 'B': return sf::Keyboard::B;
case 'c':
case 'C': return sf::Keyboard::C;
case 'd':
case 'D': return sf::Keyboard::D;
case 'e':
case 'E': return sf::Keyboard::E;
case 'f':
case 'F': return sf::Keyboard::F;
case 'g':
case 'G': return sf::Keyboard::G;
case 'h':
case 'H': return sf::Keyboard::H;
case 'i':
case 'I': return sf::Keyboard::I;
case 'j':
case 'J': return sf::Keyboard::J;
case 'k':
case 'K': return sf::Keyboard::K;
case 'l':
case 'L': return sf::Keyboard::L;
case 'm':
case 'M': return sf::Keyboard::M;
case 'n':
case 'N': return sf::Keyboard::N;
case 'o':
case 'O': return sf::Keyboard::O;
case 'p':
case 'P': return sf::Keyboard::P;
case 'q':
case 'Q': return sf::Keyboard::Q;
case 'r':
case 'R': return sf::Keyboard::R;
case 's':
case 'S': return sf::Keyboard::S;
case 't':
case 'T': return sf::Keyboard::T;
case 'u':
case 'U': return sf::Keyboard::U;
case 'v':
case 'V': return sf::Keyboard::V;
case 'w':
case 'W': return sf::Keyboard::W;
case 'x':
case 'X': return sf::Keyboard::X;
case 'y':
case 'Y': return sf::Keyboard::Y;
case 'z':
case 'Z': return sf::Keyboard::Z;
// The key is not 'localized'.
default: return sf::Keyboard::KeyCount;
}
}
////////////////////////////////////////////////////////
Keyboard::Key HIDInputManager::NonLocalizedKeys(UniChar virtualKeycode)
{
// (Some) 0x code based on http://forums.macrumors.com/showthread.php?t=780577
// Some sf::Keyboard::Key are present twice.
switch (virtualKeycode) {
// These cases should not be used but anyway...
case 0x00: return sf::Keyboard::A;
case 0x0b: return sf::Keyboard::B;
case 0x08: return sf::Keyboard::C;
case 0x02: return sf::Keyboard::D;
case 0x0e: return sf::Keyboard::E;
case 0x03: return sf::Keyboard::F;
case 0x05: return sf::Keyboard::G;
case 0x04: return sf::Keyboard::H;
case 0x22: return sf::Keyboard::I;
case 0x26: return sf::Keyboard::J;
case 0x28: return sf::Keyboard::K;
case 0x25: return sf::Keyboard::L;
case 0x2e: return sf::Keyboard::M;
case 0x2d: return sf::Keyboard::N;
case 0x1f: return sf::Keyboard::O;
case 0x23: return sf::Keyboard::P;
case 0x0c: return sf::Keyboard::Q;
case 0x0f: return sf::Keyboard::R;
case 0x01: return sf::Keyboard::S;
case 0x11: return sf::Keyboard::T;
case 0x20: return sf::Keyboard::U;
case 0x09: return sf::Keyboard::V;
case 0x0d: return sf::Keyboard::W;
case 0x07: return sf::Keyboard::X;
case 0x10: return sf::Keyboard::Y;
case 0x06: return sf::Keyboard::Z;
// These cases should not be used but anyway...
case 0x1d: return sf::Keyboard::Num0;
case 0x12: return sf::Keyboard::Num1;
case 0x13: return sf::Keyboard::Num2;
case 0x14: return sf::Keyboard::Num3;
case 0x15: return sf::Keyboard::Num4;
case 0x17: return sf::Keyboard::Num5;
case 0x16: return sf::Keyboard::Num6;
case 0x1a: return sf::Keyboard::Num7;
case 0x1c: return sf::Keyboard::Num8;
case 0x19: return sf::Keyboard::Num9;
case 0x35: return sf::Keyboard::Escape;
// Modifier keys : never happen with keyDown/keyUp methods (?)
case 0x3b: return sf::Keyboard::LControl;
case 0x38: return sf::Keyboard::LShift;
case 0x3a: return sf::Keyboard::LAlt;
case 0x37: return sf::Keyboard::LSystem;
case 0x3e: return sf::Keyboard::RControl;
case 0x3c: return sf::Keyboard::RShift;
case 0x3d: return sf::Keyboard::RAlt;
case 0x36: return sf::Keyboard::RSystem;
case 0x7f: return sf::Keyboard::Menu;
case NSMenuFunctionKey: return sf::Keyboard::Menu;
case 0x21: return sf::Keyboard::LBracket;
case 0x1e: return sf::Keyboard::RBracket;
case 0x29: return sf::Keyboard::SemiColon;
case 0x2b: return sf::Keyboard::Comma;
// case 0x41: /* keypad */ return sf::Keyboard::Period;
case 0x2f: /* keyboard */ return sf::Keyboard::Period;
case 0x27: return sf::Keyboard::Quote;
case 0x2c: return sf::Keyboard::Slash;
case 0x2a: return sf::Keyboard::BackSlash;
#warning sf::Keyboard::Tilde might be in conflict with some other key.
// 0x0a is for "Non-US Backslash" according to HID Calibrator,
// a sample provided by Apple.
case 0x0a: return sf::Keyboard::Tilde;
// case 0x51: /* keypad */ return sf::Keyboard::Equal;
case 0x18: /* keyboard */ return sf::Keyboard::Equal;
case 0x32: return sf::Keyboard::Dash;
case 0x31: return sf::Keyboard::Space;
// case 0x4c: /* keypad */ return sf::Keyboard::Return;
case 0x24: /* keyboard */ return sf::Keyboard::Return;
case 0x33: return sf::Keyboard::Back;
case 0x30: return sf::Keyboard::Tab;
// Duplicates (see next §).
case 0x74: return sf::Keyboard::PageUp;
case 0x79: return sf::Keyboard::PageDown;
case 0x77: return sf::Keyboard::End;
case 0x73: return sf::Keyboard::Home;
case NSPageUpFunctionKey: return sf::Keyboard::PageUp;
case NSPageDownFunctionKey: return sf::Keyboard::PageDown;
case NSEndFunctionKey: return sf::Keyboard::End;
case NSHomeFunctionKey: return sf::Keyboard::Home;
case 0x72: return sf::Keyboard::Insert;
case NSInsertFunctionKey: return sf::Keyboard::Insert;
case 0x75: return sf::Keyboard::Delete;
case NSDeleteFunctionKey: return sf::Keyboard::Delete;
case 0x45: return sf::Keyboard::Add;
case 0x4e: return sf::Keyboard::Subtract;
case 0x43: return sf::Keyboard::Multiply;
case 0x4b: return sf::Keyboard::Divide;
// Duplicates (see next §).
case 0x7b: return sf::Keyboard::Left;
case 0x7c: return sf::Keyboard::Right;
case 0x7e: return sf::Keyboard::Up;
case 0x7d: return sf::Keyboard::Down;
case NSLeftArrowFunctionKey: return sf::Keyboard::Left;
case NSRightArrowFunctionKey: return sf::Keyboard::Right;
case NSUpArrowFunctionKey: return sf::Keyboard::Up;
case NSDownArrowFunctionKey: return sf::Keyboard::Down;
case 0x52: return sf::Keyboard::Numpad0;
case 0x53: return sf::Keyboard::Numpad1;
case 0x54: return sf::Keyboard::Numpad2;
case 0x55: return sf::Keyboard::Numpad3;
case 0x56: return sf::Keyboard::Numpad4;
case 0x57: return sf::Keyboard::Numpad5;
case 0x58: return sf::Keyboard::Numpad6;
case 0x59: return sf::Keyboard::Numpad7;
case 0x5b: return sf::Keyboard::Numpad8;
case 0x5c: return sf::Keyboard::Numpad9;
// Duplicates (see next §).
case 0x7a: return sf::Keyboard::F1;
case 0x78: return sf::Keyboard::F2;
case 0x63: return sf::Keyboard::F3;
case 0x76: return sf::Keyboard::F4;
case 0x60: return sf::Keyboard::F5;
case 0x61: return sf::Keyboard::F6;
case 0x62: return sf::Keyboard::F7;
case 0x64: return sf::Keyboard::F8;
case 0x65: return sf::Keyboard::F9;
case 0x6d: return sf::Keyboard::F10;
case 0x67: return sf::Keyboard::F11;
case 0x6f: return sf::Keyboard::F12;
case 0x69: return sf::Keyboard::F13;
case 0x6b: return sf::Keyboard::F14;
case 0x71: return sf::Keyboard::F15;
case NSF1FunctionKey: return sf::Keyboard::F1;
case NSF2FunctionKey: return sf::Keyboard::F2;
case NSF3FunctionKey: return sf::Keyboard::F3;
case NSF4FunctionKey: return sf::Keyboard::F4;
case NSF5FunctionKey: return sf::Keyboard::F5;
case NSF6FunctionKey: return sf::Keyboard::F6;
case NSF7FunctionKey: return sf::Keyboard::F7;
case NSF8FunctionKey: return sf::Keyboard::F8;
case NSF9FunctionKey: return sf::Keyboard::F9;
case NSF10FunctionKey: return sf::Keyboard::F10;
case NSF11FunctionKey: return sf::Keyboard::F11;
case NSF12FunctionKey: return sf::Keyboard::F12;
case NSF13FunctionKey: return sf::Keyboard::F13;
case NSF14FunctionKey: return sf::Keyboard::F14;
case NSF15FunctionKey: return sf::Keyboard::F15;
case NSPauseFunctionKey: return sf::Keyboard::Pause;
#warning keycode 0x1b is not bound to any key.
// This key is ' on CH-FR, ) on FR and - on US layouts.
// An unknown key.
default: return sf::Keyboard::KeyCount;
}
}
} // namespace priv
} // namespace sf

View File

@ -30,10 +30,20 @@
#include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/Window.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/Window/OSX/HIDInputManager.hpp>
#import <AppKit/AppKit.h>
#import <SFML/Window/OSX/SFOpenGLView.h>
////////////////////////////////////////////////////////////
/// In order to keep track of the keyboard's state and mouse buttons' state
/// we use the HID manager. Mouse position is handled differently.
///
/// NB : we probably could use
/// NSEvent +addGlobalMonitorForEventsMatchingMask:handler: for mouse only.
///
////////////////////////////////////////////////////////////
namespace sf
{
namespace priv
@ -92,16 +102,14 @@ SFOpenGLView* GetSFOpenGLViewFromSFMLWindow(const Window& window)
////////////////////////////////////////////////////////////
bool InputImpl::IsKeyPressed(Keyboard::Key key)
{
// @to be implemented
return false;
return HIDInputManager::GetInstance().IsKeyPressed(key);
}
////////////////////////////////////////////////////////////
bool InputImpl::IsMouseButtonPressed(Mouse::Button button)
{
// @to be implemented
return false;
return HIDInputManager::GetInstance().IsMouseButtonPressed(button);
}

View File

@ -27,6 +27,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/WindowImplCocoa.hpp>
#include <SFML/Window/OSX/HIDInputManager.hpp> // For LocalizedKeys and NonLocalizedKeys
#include <SFML/System/Err.hpp>
#import <SFML/Window/OSX/SFOpenGLView.h>
@ -60,25 +61,6 @@ NSUInteger EraseMaskFromData(NSUInteger data, NSUInteger mask);
////////////////////////////////////////////////////////////
NSUInteger KeepOnlyMaskFromData(NSUInteger data, NSUInteger mask);
////////////////////////////////////////////////////////////
/// Try to convert a character into a SFML key code.
/// Return sf::Keyboard::KeyCount if it doesn't match any 'localized' keys.
///
/// By 'localized' I mean keys that depend on the keyboard layout
/// and might not be the same as the US keycode in some country
/// (e.g. the keys 'Y' and 'Z' are switched on QWERTZ keyboard and
/// US keyboard layouts.)
///
////////////////////////////////////////////////////////////
sf::Keyboard::Key LocalizedKeys(unichar ch);
////////////////////////////////////////////////////////////
/// Try to convert a keycode into a SFML key code.
/// Return sf::Keyboard::KeyCount if the keycode is unknown.
///
////////////////////////////////////////////////////////////
sf::Keyboard::Key NonLocalizedKeys(unsigned short keycode);
////////////////////////////////////////////////////////////
/// SFOpenGLView class : Privates Methods Declaration
///
@ -105,6 +87,8 @@ sf::Keyboard::Key NonLocalizedKeys(unsigned short keycode);
////////////////////////////////////////////////////////////
/// Converte the NSEvent mouse button type to SFML type.
///
/// Returns ButtonCount if the button is unknown
///
////////////////////////////////////////////////////////////
-(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent *)event;
@ -197,7 +181,7 @@ sf::Keyboard::Key NonLocalizedKeys(unsigned short keycode);
/*we don't care about this : */0);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
// This is a workaround to deprecated CGSetLocalEventsSuppressionInterval.
// This is a workaround to deprecated CGSetLocalEventsSuppressionInterval function
}
@ -489,6 +473,7 @@ sf::Keyboard::Key NonLocalizedKeys(unsigned short keycode);
{
if (myRequester == 0) return;
// Handle key down event
if (myUseKeyRepeat || ![theEvent isARepeat]) {
sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent];
@ -497,6 +482,7 @@ sf::Keyboard::Key NonLocalizedKeys(unsigned short keycode);
}
}
// Handle text entred event
if ((myUseKeyRepeat || ![theEvent isARepeat]) && [[theEvent characters] length] > 0) {
// Ignore escape key and non text keycode. (See NSEvent.h)
@ -966,25 +952,27 @@ sf::Keyboard::Key NonLocalizedKeys(unsigned short keycode);
// Key code.
key.Code = sf::Keyboard::KeyCount;
// First we look if the key down is from a list of caracter that depend on keyboard localization.
// First we look if the key down is from a list of caracter
// that depend on keyboard localization.
NSString* string = [anEvent charactersIgnoringModifiers];
if ([string length] > 0) {
key.Code = LocalizedKeys([string characterAtIndex:0]);
key.Code = sf::priv::HIDInputManager::LocalizedKeys([string characterAtIndex:0]);
}
// The key is not a localized one, the other keys.
// The key is not a localized one, so we try to find a corresponding code
// through virtual key code.
if (key.Code == sf::Keyboard::KeyCount) {
key.Code = NonLocalizedKeys([anEvent keyCode]);
key.Code = sf::priv::HIDInputManager::NonLocalizedKeys([anEvent keyCode]);
}
#ifdef SFML_DEBUG // We don't want to bother the final customer with annoying messages.
#ifdef SFML_DEBUG // Don't bother the final customers with annoying messages.
if (key.Code == sf::Keyboard::KeyCount) { // The key is unknown.
sf::Err()
<< "This is an unknow key. Should not happen (?). Keycode is 0x"
<< std::hex
<< [anEvent keyCode]
<< "."
<< std::endl;
sf::Err() << "This is an unknow key. Virtual key code is 0x"
<< std::hex
<< [anEvent keyCode]
<< "."
<< std::endl;
}
#endif
@ -1012,256 +1000,3 @@ NSUInteger KeepOnlyMaskFromData(NSUInteger data, NSUInteger mask)
}
////////////////////////////////////////////////////////
sf::Keyboard::Key LocalizedKeys(unichar ch)
{
switch (ch) {
case 'a':
case 'A': return sf::Keyboard::A;
case 'b':
case 'B': return sf::Keyboard::B;
case 'c':
case 'C': return sf::Keyboard::C;
case 'd':
case 'D': return sf::Keyboard::D;
case 'e':
case 'E': return sf::Keyboard::E;
case 'f':
case 'F': return sf::Keyboard::F;
case 'g':
case 'G': return sf::Keyboard::G;
case 'h':
case 'H': return sf::Keyboard::H;
case 'i':
case 'I': return sf::Keyboard::I;
case 'j':
case 'J': return sf::Keyboard::J;
case 'k':
case 'K': return sf::Keyboard::K;
case 'l':
case 'L': return sf::Keyboard::L;
case 'm':
case 'M': return sf::Keyboard::M;
case 'n':
case 'N': return sf::Keyboard::N;
case 'o':
case 'O': return sf::Keyboard::O;
case 'p':
case 'P': return sf::Keyboard::P;
case 'q':
case 'Q': return sf::Keyboard::Q;
case 'r':
case 'R': return sf::Keyboard::R;
case 's':
case 'S': return sf::Keyboard::S;
case 't':
case 'T': return sf::Keyboard::T;
case 'u':
case 'U': return sf::Keyboard::U;
case 'v':
case 'V': return sf::Keyboard::V;
case 'w':
case 'W': return sf::Keyboard::W;
case 'x':
case 'X': return sf::Keyboard::X;
case 'y':
case 'Y': return sf::Keyboard::Y;
case 'z':
case 'Z': return sf::Keyboard::Z;
// The kew is not 'localized'.
default: return sf::Keyboard::KeyCount;
}
}
////////////////////////////////////////////////////////
sf::Keyboard::Key NonLocalizedKeys(unsigned short keycode)
{
// (Some) 0x code based on http://forums.macrumors.com/showthread.php?t=780577
// Some sf::Keyboard::Key are present twice.
switch (keycode) {
// These cases should not be used but anyway...
case 0x00: return sf::Keyboard::A;
case 0x0b: return sf::Keyboard::B;
case 0x08: return sf::Keyboard::C;
case 0x02: return sf::Keyboard::D;
case 0x0e: return sf::Keyboard::E;
case 0x03: return sf::Keyboard::F;
case 0x05: return sf::Keyboard::G;
case 0x04: return sf::Keyboard::H;
case 0x22: return sf::Keyboard::I;
case 0x26: return sf::Keyboard::J;
case 0x28: return sf::Keyboard::K;
case 0x25: return sf::Keyboard::L;
case 0x2e: return sf::Keyboard::M;
case 0x2d: return sf::Keyboard::N;
case 0x1f: return sf::Keyboard::O;
case 0x23: return sf::Keyboard::P;
case 0x0c: return sf::Keyboard::Q;
case 0x0f: return sf::Keyboard::R;
case 0x01: return sf::Keyboard::S;
case 0x11: return sf::Keyboard::T;
case 0x20: return sf::Keyboard::U;
case 0x09: return sf::Keyboard::V;
case 0x0d: return sf::Keyboard::W;
case 0x07: return sf::Keyboard::X;
case 0x10: return sf::Keyboard::Y;
case 0x06: return sf::Keyboard::Z;
// These cases should not be used but anyway...
case 0x1d: return sf::Keyboard::Num0;
case 0x12: return sf::Keyboard::Num1;
case 0x13: return sf::Keyboard::Num2;
case 0x14: return sf::Keyboard::Num3;
case 0x15: return sf::Keyboard::Num4;
case 0x17: return sf::Keyboard::Num5;
case 0x16: return sf::Keyboard::Num6;
case 0x1a: return sf::Keyboard::Num7;
case 0x1c: return sf::Keyboard::Num8;
case 0x19: return sf::Keyboard::Num9;
case 0x35: return sf::Keyboard::Escape;
// Modifier keys : never happen with keyDown/keyUp methods (?)
case 0x3b: return sf::Keyboard::LControl;
case 0x38: return sf::Keyboard::LShift;
case 0x3a: return sf::Keyboard::LAlt;
case 0x37: return sf::Keyboard::LSystem;
case 0x3e: return sf::Keyboard::RControl;
case 0x3c: return sf::Keyboard::RShift;
case 0x3d: return sf::Keyboard::RAlt;
case 0x36: return sf::Keyboard::RSystem;
case NSMenuFunctionKey: return sf::Keyboard::Menu;
case 0x21: return sf::Keyboard::LBracket;
case 0x1e: return sf::Keyboard::RBracket;
case 0x29: return sf::Keyboard::SemiColon;
case 0x2b: return sf::Keyboard::Comma;
case 0x2f: return sf::Keyboard::Period;
case 0x27: return sf::Keyboard::Quote;
case 0x2c: return sf::Keyboard::Slash;
case 0x2a: return sf::Keyboard::BackSlash;
#warning sf::Keyboard::Tilde might be in conflict with some other key.
// 0x0a is for "Non-US Backslash" according to HID Calibrator,
// a sample provided by Apple.
case 0x0a: return sf::Keyboard::Tilde;
case 0x18: return sf::Keyboard::Equal;
case 0x32: return sf::Keyboard::Dash;
case 0x31: return sf::Keyboard::Space;
case 0x24: return sf::Keyboard::Return;
case 0x33: return sf::Keyboard::Back;
case 0x30: return sf::Keyboard::Tab;
// Duplicates (see next §).
case 0x74: return sf::Keyboard::PageUp;
case 0x79: return sf::Keyboard::PageDown;
case 0x77: return sf::Keyboard::End;
case 0x73: return sf::Keyboard::Home;
case NSPageUpFunctionKey: return sf::Keyboard::PageUp;
case NSPageDownFunctionKey: return sf::Keyboard::PageDown;
case NSEndFunctionKey: return sf::Keyboard::End;
case NSHomeFunctionKey: return sf::Keyboard::Home;
case NSInsertFunctionKey: return sf::Keyboard::Insert;
case NSDeleteFunctionKey: return sf::Keyboard::Delete;
case 0x45: return sf::Keyboard::Add;
case 0x4e: return sf::Keyboard::Subtract;
case 0x43: return sf::Keyboard::Multiply;
case 0x4b: return sf::Keyboard::Divide;
// Duplicates (see next §).
case 0x7b: return sf::Keyboard::Left;
case 0x7c: return sf::Keyboard::Right;
case 0x7e: return sf::Keyboard::Up;
case 0x7d: return sf::Keyboard::Down;
case NSLeftArrowFunctionKey: return sf::Keyboard::Left;
case NSRightArrowFunctionKey: return sf::Keyboard::Right;
case NSUpArrowFunctionKey: return sf::Keyboard::Up;
case NSDownArrowFunctionKey: return sf::Keyboard::Down;
case 0x52: return sf::Keyboard::Numpad0;
case 0x53: return sf::Keyboard::Numpad1;
case 0x54: return sf::Keyboard::Numpad2;
case 0x55: return sf::Keyboard::Numpad3;
case 0x56: return sf::Keyboard::Numpad4;
case 0x57: return sf::Keyboard::Numpad5;
case 0x58: return sf::Keyboard::Numpad6;
case 0x59: return sf::Keyboard::Numpad7;
case 0x5b: return sf::Keyboard::Numpad8;
case 0x5c: return sf::Keyboard::Numpad9;
// Duplicates (see next §).
case 0x7a: return sf::Keyboard::F1;
case 0x78: return sf::Keyboard::F2;
case 0x63: return sf::Keyboard::F3;
case 0x76: return sf::Keyboard::F4;
case 0x60: return sf::Keyboard::F5;
case 0x61: return sf::Keyboard::F6;
case 0x62: return sf::Keyboard::F7;
case 0x64: return sf::Keyboard::F8;
case 0x65: return sf::Keyboard::F9;
case 0x6d: return sf::Keyboard::F10;
case 0x67: return sf::Keyboard::F11;
case 0x6f: return sf::Keyboard::F12;
case 0x69: return sf::Keyboard::F13;
case 0x6b: return sf::Keyboard::F14;
case 0x71: return sf::Keyboard::F15;
case NSF1FunctionKey: return sf::Keyboard::F1;
case NSF2FunctionKey: return sf::Keyboard::F2;
case NSF3FunctionKey: return sf::Keyboard::F3;
case NSF4FunctionKey: return sf::Keyboard::F4;
case NSF5FunctionKey: return sf::Keyboard::F5;
case NSF6FunctionKey: return sf::Keyboard::F6;
case NSF7FunctionKey: return sf::Keyboard::F7;
case NSF8FunctionKey: return sf::Keyboard::F8;
case NSF9FunctionKey: return sf::Keyboard::F9;
case NSF10FunctionKey: return sf::Keyboard::F10;
case NSF11FunctionKey: return sf::Keyboard::F11;
case NSF12FunctionKey: return sf::Keyboard::F12;
case NSF13FunctionKey: return sf::Keyboard::F13;
case NSF14FunctionKey: return sf::Keyboard::F14;
case NSF15FunctionKey: return sf::Keyboard::F15;
case NSPauseFunctionKey: return sf::Keyboard::Pause;
#warning keycode 0x1b is not bound to any key.
// This key is ' on CH-FR, ) on FR and - on US layouts.
// An unknown key.
default: return sf::Keyboard::KeyCount;
}
}