From e806048904c562783d9a39282507a52c04f859a9 Mon Sep 17 00:00:00 2001 From: Marco Antognini Date: Tue, 28 Mar 2017 23:37:06 +0200 Subject: [PATCH] Add support of scancodes for macOS --- src/SFML/Window/OSX/HIDInputManager.hpp | 140 +- src/SFML/Window/OSX/HIDInputManager.mm | 1573 +++++++++++------ src/SFML/Window/OSX/InputImpl.mm | 32 +- .../Window/OSX/SFKeyboardModifiersHelper.h | 3 +- .../Window/OSX/SFKeyboardModifiersHelper.mm | 27 +- src/SFML/Window/OSX/SFOpenGLView+keyboard.mm | 22 +- 6 files changed, 1167 insertions(+), 630 deletions(-) diff --git a/src/SFML/Window/OSX/HIDInputManager.hpp b/src/SFML/Window/OSX/HIDInputManager.hpp index fd965270a..6bdb579bd 100644 --- a/src/SFML/Window/OSX/HIDInputManager.hpp +++ b/src/SFML/Window/OSX/HIDInputManager.hpp @@ -65,16 +65,6 @@ public: //////////////////////////////////////////////////////////// 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); - public: //////////////////////////////////////////////////////////// @@ -103,21 +93,64 @@ public: /// /// Return sf::Keyboard::Unknown 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 + /// By 'localized' we mean keys that depend on the keyboard layout + /// and might not be the same as the US keycode for some countries + /// (e.g. the keys 'Y' and 'Z' are swapped on QWERTZ keyboard and /// US keyboard layouts.) /// //////////////////////////////////////////////////////////// - static Keyboard::Key localizedKeys(UniChar ch); + static Keyboard::Key localizedKey(UniChar ch); //////////////////////////////////////////////////////////// - /// Try to convert a virtual keycode into a SFML key code. + /// Opposite transformation as localizedKeys /// - /// Return sf::Keyboard::Unknown if the keycode is unknown. + /// Return 0x00 (NULL) for non-convertible keys/numpad numbers. + /// For letters, uppercase codes are returned. + /// Some returned value are specific to macOS. /// //////////////////////////////////////////////////////////// - static Keyboard::Key nonLocalizedKeys(UniChar virtualKeycode); + static UniChar toUnicode(Keyboard::Key key); + + //////////////////////////////////////////////////////////// + /// Try to convert a virtual keycode (HID level) into a + /// SFML scancode. + /// + /// Return sf::Keyboard::sUnknown if the keycode is unknown. + /// + //////////////////////////////////////////////////////////// + static Keyboard::Scancode nonLocalizedKey(UniChar virtualKeycode); + +public: + + //////////////////////////////////////////////////////////// + /// \copydoc sf::Keyboard::isKeyPressed(Key) + /// + //////////////////////////////////////////////////////////// + bool isKeyPressed(Keyboard::Key key); + + //////////////////////////////////////////////////////////// + /// \copydoc sf::Keyboard::isKeyPressed(Scancode) + /// + //////////////////////////////////////////////////////////// + bool isKeyPressed(Keyboard::Scancode code); + + //////////////////////////////////////////////////////////// + /// \copydoc sf::Keyboard::localize + /// + //////////////////////////////////////////////////////////// + Keyboard::Key localize(Keyboard::Scancode code); + + //////////////////////////////////////////////////////////// + /// \copydoc sf::Keyboard::unlocalize + /// + //////////////////////////////////////////////////////////// + Keyboard::Scancode unlocalize(Keyboard::Key key); + + //////////////////////////////////////////////////////////// + /// \copydoc sf::Keyboard::localizedRepresentation + /// + //////////////////////////////////////////////////////////// + String localizedRepresentation(Keyboard::Scancode code); private: @@ -136,7 +169,13 @@ private: //////////////////////////////////////////////////////////// /// \brief Initialize the keyboard part of this class /// - /// If something went wrong freeUp is called + /// If something went wrong freeUp is called. + /// + /// In a nutshell, this function does this: + /// + /// for each connected keyboard kb: + /// for each key k of kb: + /// memorise k -> scancode mapping /// //////////////////////////////////////////////////////////// void initializeKeyboard(); @@ -145,28 +184,39 @@ private: /// \brief Load the given keyboard into m_keys /// /// If the given keyboard has no key this function simply - /// returns. freeUp is _not_ called because this is not fatal. + /// returns without calling freeUp because this is not fatal. /// /// \param keyboard Keyboard to load /// + /// \see initializeKeyboard + /// //////////////////////////////////////////////////////////// void loadKeyboard(IOHIDDeviceRef keyboard); //////////////////////////////////////////////////////////// /// \brief Load the given key into m_keys /// - /// freeUp is _not_ called by this function. + /// On error, freeUp is _not_ called by this function. /// /// \param key Key to load /// + /// \see initializeKeyboard + /// //////////////////////////////////////////////////////////// void loadKey(IOHIDElementRef key); + //////////////////////////////////////////////////////////// + /// Regenerate the mappings from/to Key and Scancode + /// + //////////////////////////////////////////////////////////// + void buildMappings(); + //////////////////////////////////////////////////////////// /// \brief Release all resources /// - /// Close all connections to any devices, if required - /// Set m_isValid to false + /// Close all connections to any devices. + /// + /// \see initializeKeyboard /// //////////////////////////////////////////////////////////// void freeUp(); @@ -174,11 +224,11 @@ private: //////////////////////////////////////////////////////////// /// \brief Filter the devices and return them /// - /// freeUp is _not_ called by this function. + /// On error, freeUp is _not_ called by this function. /// /// \param page HID page like kHIDPage_GenericDesktop /// \param usage HID usage page like kHIDUsage_GD_Keyboard or kHIDUsage_GD_Mouse - /// \return a retained CFSetRef of IOHIDDeviceRef or NULL + /// \return a retained, non-emtpy CFSetRef of IOHIDDeviceRef or NULL /// //////////////////////////////////////////////////////////// CFSetRef copyDevices(UInt32 page, UInt32 usage); @@ -196,36 +246,48 @@ private: bool isPressed(IOHIDElements& elements); //////////////////////////////////////////////////////////// - /// \brief Convert a HID key usage to its corresponding virtual code - /// - /// See IOHIDUsageTables.h + /// \brief Convert a HID key usage to its corresponding scancode /// /// \param usage Any kHIDUsage_Keyboard* usage - /// \return the virtual code associate with the given HID key usage - /// or 0xff if it is associate with no virtual code + /// \return the scancode associate with the given HID key usage + /// or sUnknown if it is associate with no scancode. /// //////////////////////////////////////////////////////////// - static UInt8 usageToVirtualCode(UInt32 usage); + static Keyboard::Scancode usageToScancode(UInt32 usage); + + //////////////////////////////////////////////////////////// + /// Convert the scancode to the expected virtual code. + /// + //////////////////////////////////////////////////////////// + static UInt8 scanToVirtualCode(Keyboard::Scancode code); + + //////////////////////////////////////////////////////////// + /// Fallback convertion for key that aren't expected to be impacted + /// by the layout. Can return Unknown. + /// + //////////////////////////////////////////////////////////// + static Keyboard::Key localizedKeyFallback(Keyboard::Scancode code); private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - bool m_isValid; ///< If any error occurs this variable is false - CFDataRef m_layoutData; ///< CFData containing the layout - UCKeyboardLayout* m_layout; ///< Current Keyboard Layout - IOHIDManagerRef m_manager; ///< HID Manager - - IOHIDElements m_keys[Keyboard::KeyCount]; ///< All the keys on any connected keyboard + IOHIDManagerRef m_manager; ///< Underlying HID Manager + IOHIDElements m_keys[Keyboard::sCodeCount]; ///< All the keys on any connected keyboard + Keyboard::Scancode m_mapping[Keyboard::KeyCount]; ///< Mapping from Key to Scancode + Keyboard::Key m_gnippam[Keyboard::sCodeCount]; ///< Mapping from Scancode to Key //////////////////////////////////////////////////////////// - /// m_keys' index corresponds to sf::Keyboard::Key enum. - /// if no key is assigned with key XYZ then m_keys[XYZ].size() == 0. - /// if there are several keyboards connected and several HID keys associate + /// m_keys' index corresponds to sf::Keyboard::Scancode enum. + /// If no key is assigned with key XYZ then m_keys[XYZ].size() == 0. + /// If there are several keyboards connected and several HID keys associated /// with the same sf::Keyboard::Key then m_keys[XYZ] contains all these /// HID keys. /// + /// The mappings (both directions) get invalidated when the + /// keyboard layout changes. They both default to (s)Unknown. + /// //////////////////////////////////////////////////////////// }; diff --git a/src/SFML/Window/OSX/HIDInputManager.mm b/src/SFML/Window/OSX/HIDInputManager.mm index 303a7bc41..0e833f74b 100644 --- a/src/SFML/Window/OSX/HIDInputManager.mm +++ b/src/SFML/Window/OSX/HIDInputManager.mm @@ -42,13 +42,6 @@ HIDInputManager& HIDInputManager::getInstance() } -//////////////////////////////////////////////////////////// -bool HIDInputManager::isKeyPressed(Keyboard::Key key) -{ - return isPressed(m_keys[key]); -} - - //////////////////////////////////////////////////////////// long HIDInputManager::getLocationID(IOHIDDeviceRef device) { @@ -91,35 +84,141 @@ CFDictionaryRef HIDInputManager::copyDevicesMask(UInt32 page, UInt32 usage) } +//////////////////////////////////////////////////////////// +bool HIDInputManager::isKeyPressed(Keyboard::Key key) +{ + return isKeyPressed(unlocalize(key)); +} + + +//////////////////////////////////////////////////////////// +bool HIDInputManager::isKeyPressed(Keyboard::Scancode code) +{ + return (code != Keyboard::sUnknown) && isPressed(m_keys[code]); +} + + +//////////////////////////////////////////////////////////// +Keyboard::Key HIDInputManager::localize(Keyboard::Scancode code) +{ + // TODO ensure mapping is still valid + return m_gnippam[code]; +} + + +//////////////////////////////////////////////////////////// +Keyboard::Scancode HIDInputManager::unlocalize(Keyboard::Key key) +{ + // TODO ensure mapping is still valid + return m_mapping[key]; +} + + +//////////////////////////////////////////////////////////// +String HIDInputManager::localizedRepresentation(Keyboard::Scancode code) +{ + UniChar unicode = toUnicode(localize(code)); + if (unicode != 0x00) + return sf::String(static_cast(unicode)); + + // Fallback to our best guess for the keys that are known to be independent of the layout. + switch (code) + { + case sf::Keyboard::sEnter: return "Enter"; + case sf::Keyboard::sEscape: return "Escape"; + case sf::Keyboard::sBackspace: return "Backspace"; + case sf::Keyboard::sTab: return "Tab"; + case sf::Keyboard::sSpace: return "Space"; + + case sf::Keyboard::sF1: return "F1"; + case sf::Keyboard::sF2: return "F2"; + case sf::Keyboard::sF3: return "F3"; + case sf::Keyboard::sF4: return "F4"; + case sf::Keyboard::sF5: return "F5"; + case sf::Keyboard::sF6: return "F6"; + case sf::Keyboard::sF7: return "F7"; + case sf::Keyboard::sF8: return "F8"; + case sf::Keyboard::sF9: return "F9"; + case sf::Keyboard::sF10: return "F10"; + case sf::Keyboard::sF11: return "F11"; + case sf::Keyboard::sF12: return "F12"; + case sf::Keyboard::sF13: return "F13"; + case sf::Keyboard::sF14: return "F14"; + case sf::Keyboard::sF15: return "F15"; + + case sf::Keyboard::sCapsLock: return "CapsLock"; + case sf::Keyboard::sPrintScreen: return "PrintScreen"; + case sf::Keyboard::sScrollLock: return "ScrollLock"; + + case sf::Keyboard::sPause: return "Pause"; + case sf::Keyboard::sInsert: return "Insert"; + case sf::Keyboard::sHome: return "Home"; + case sf::Keyboard::sPageUp: return "PageUp"; + case sf::Keyboard::sDelete: return "Delete"; + case sf::Keyboard::sEnd: return "End"; + case sf::Keyboard::sPageDown: return "PageDown"; + + case sf::Keyboard::sLeft: return "Left Arrow"; + case sf::Keyboard::sRight: return "Right Arrow"; + case sf::Keyboard::sDown: return "Down Arrow"; + case sf::Keyboard::sUp: return "Up Arrow"; + + case sf::Keyboard::sNumLock: return "NumLock"; + case sf::Keyboard::sDivide: return "Divide (Numpad)"; + case sf::Keyboard::sMultiply: return "Multiply (Numpad)"; + case sf::Keyboard::sMinus: return "Minux (Numpad)"; + case sf::Keyboard::sPlus: return "Plus (Numpad)"; + case sf::Keyboard::sPadEquals: return "Equals (Numpad)"; + case sf::Keyboard::sReturn: return "Return (Numpad)"; + case sf::Keyboard::sDecimal: return "Decimal (Numpad)"; + + case sf::Keyboard::sNumpad0: return "0 (Numpad)"; + case sf::Keyboard::sNumpad1: return "1 (Numpad)"; + case sf::Keyboard::sNumpad2: return "2 (Numpad)"; + case sf::Keyboard::sNumpad3: return "3 (Numpad)"; + case sf::Keyboard::sNumpad4: return "4 (Numpad)"; + case sf::Keyboard::sNumpad5: return "5 (Numpad)"; + case sf::Keyboard::sNumpad6: return "6 (Numpad)"; + case sf::Keyboard::sNumpad7: return "7 (Numpad)"; + case sf::Keyboard::sNumpad8: return "8 (Numpad)"; + case sf::Keyboard::sNumpad9: return "9 (Numpad)"; + + case sf::Keyboard::sApplication: return "Application"; + case sf::Keyboard::sExecute: return "Execute"; + case sf::Keyboard::sHelp: return "Help"; + case sf::Keyboard::sMenu: return "Menu"; + case sf::Keyboard::sSelect: return "Select"; + case sf::Keyboard::sStop: return "Stop"; + case sf::Keyboard::sAgain: return "Again"; + case sf::Keyboard::sUndo: return "Undo"; + case sf::Keyboard::sCut: return "Cut"; + case sf::Keyboard::sCopy: return "Copy"; + case sf::Keyboard::sPaste: return "Paste"; + case sf::Keyboard::sFind: return "Find"; + case sf::Keyboard::sMute: return "Mute"; + case sf::Keyboard::sVolumeUp: return "Volume Up"; + case sf::Keyboard::sVolumeDown: return "Volume Down"; + + case sf::Keyboard::sLControl: return "Control (Left)"; + case sf::Keyboard::sLShift: return "Shift (Left)"; + case sf::Keyboard::sLAlt: return "Alt (Left)"; + case sf::Keyboard::sLSystem: return "Command (Left)"; + case sf::Keyboard::sRControl: return "Control (Right)"; + case sf::Keyboard::sRShift: return "Shift (Right)"; + case sf::Keyboard::sRAlt: return "Alt (Right)"; + case sf::Keyboard::sRSystem: return "Command (Right)"; + + default: return "Unknown Scancode"; // no guess good enough possible. + } +} + + //////////////////////////////////////////////////////////// HIDInputManager::HIDInputManager() : -m_isValid(true), -m_layoutData(0), -m_layout(0), m_manager(0) { - // Get the current keyboard layout - TISInputSourceRef tis = TISCopyCurrentKeyboardLayoutInputSource(); - m_layoutData = static_cast(TISGetInputSourceProperty(tis, kTISPropertyUnicodeKeyLayoutData)); - - if (m_layoutData == 0) - { - sf::err() << "Cannot get the keyboard layout" << std::endl; - freeUp(); - return; - } - - // Keep a reference for ourself - CFRetain(m_layoutData); - m_layout = reinterpret_cast(const_cast(CFDataGetBytePtr(m_layoutData))); - - // The TIS is no more needed - CFRelease(tis); - // Create an HID Manager reference m_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - - // Open the HID Manager reference IOReturn openStatus = IOHIDManagerOpen(m_manager, kIOHIDOptionsTypeNone); if (openStatus != kIOReturnSuccess) @@ -129,8 +228,8 @@ m_manager(0) return; } - // Initialize the keyboard initializeKeyboard(); + buildMappings(); } @@ -145,31 +244,23 @@ void HIDInputManager::initializeKeyboard() { //////////////////////////////////////////////////////////// // The purpose of this function is to initialize m_keys so we can get - // the associate IOHIDElementRef with a sf::Keyboard::Key in ~constant~ time. + // the associate IOHIDElementRef with a sf::Keyboard::Scancode + // in approximately constant time. // Get only keyboards - CFSetRef keyboards = copyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard); - if (keyboards == NULL) + CFSetRef underlying = copyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard); + if (underlying == NULL) { sf::err() << "No keyboard detected by the HID manager!" << std::endl; freeUp(); return; } - CFIndex keyboardCount = CFSetGetCount(keyboards); // >= 1 (asserted by copyDevices) + NSSet* keyboards = static_cast(underlying); // Toll-Free Bridge + for (id keyboard in keyboards) + loadKeyboard(static_cast(keyboard)); - // Get an iterable array - std::vector devicesArray(static_cast(keyboardCount)); - CFSetGetValues(keyboards, &devicesArray[0]); - - for (CFIndex i = 0; i < keyboardCount; ++i) - { - IOHIDDeviceRef keyboard = static_cast(const_cast(devicesArray[static_cast(i)])); - loadKeyboard(keyboard); - } - - // Release unused stuff - CFRelease(keyboards); + CFRelease(underlying); //////////////////////////////////////////////////////////// // At this point m_keys is filled with as many IOHIDElementRef as possible @@ -179,142 +270,105 @@ void HIDInputManager::initializeKeyboard() //////////////////////////////////////////////////////////// void HIDInputManager::loadKeyboard(IOHIDDeviceRef keyboard) { - CFArrayRef keys = IOHIDDeviceCopyMatchingElements(keyboard, - NULL, - kIOHIDOptionsTypeNone); - if (keys == NULL) + CFArrayRef underlying = IOHIDDeviceCopyMatchingElements(keyboard, NULL, kIOHIDOptionsTypeNone); + if ((underlying == NULL) || (CFArrayGetCount(underlying) == 0)) { - sf::err() << "We got a keyboard without any keys (1)" << std::endl; + sf::err() << "We got a keyboard without any keys." << std::endl; return; } - // How many elements are there? - CFIndex keysCount = CFArrayGetCount(keys); - - if (keysCount == 0) + NSArray* keys = static_cast(underlying); // Toll-Free Bridge + for (id key in keys) { - sf::err() << "We got a keyboard without any keys (2)" << std::endl; - CFRelease(keys); - return; + IOHIDElementRef elem = static_cast(key); + if (IOHIDElementGetUsagePage(elem) == kHIDPage_KeyboardOrKeypad) + loadKey(elem); } - // Go through all connected elements. - for (CFIndex i = 0; i < keysCount; ++i) - { - IOHIDElementRef aKey = static_cast(const_cast(CFArrayGetValueAtIndex(keys, i))); - - // Skip non-matching keys elements - if (IOHIDElementGetUsagePage(aKey) != kHIDPage_KeyboardOrKeypad) - continue; - - loadKey(aKey); - } - - // Release unused stuff - CFRelease(keys); + CFRelease(underlying); } //////////////////////////////////////////////////////////// void HIDInputManager::loadKey(IOHIDElementRef key) { - // Get its virtual code - UInt32 usageCode = IOHIDElementGetUsage(key); - UInt8 virtualCode = usageToVirtualCode(usageCode); - - if (virtualCode == 0xff) - return; // 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; - std::vector unicodeString(maxStringLength); - - OSStatus error; - - error = UCKeyTranslate(m_layout, // 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.data()); // what we get - - if (error == noErr) + UInt32 usage = IOHIDElementGetUsage(key); + sf::Keyboard::Scancode code = usageToScancode(usage); + if (code != Keyboard::sUnknown) { - // Translation went fine + CFRetain(key); + m_keys[code].push_back(key); + } +} - // The corresponding SFML key code - Keyboard::Key code = Keyboard::Unknown; // KeyCound means 'none' - // First we look if the key down is from a list of characters - // that depend on keyboard localization - if (actualStringLength > 0) - code = localizedKeys(unicodeString[0]); +//////////////////////////////////////////////////////////// +void HIDInputManager::buildMappings() +{ + // Reset the mappings + for (int i = 0; i < Keyboard::KeyCount; ++i) + m_mapping[i] = Keyboard::sUnknown; + for (int i = 0; i < Keyboard::sCodeCount; ++i) + m_gnippam[i] = Keyboard::Unknown; - // The key is not a localized one so we try to find a - // corresponding code through virtual key code - if (code == Keyboard::Unknown) - code = nonLocalizedKeys(virtualCode); + // Get the current keyboard layout + TISInputSourceRef tis = TISCopyCurrentKeyboardLayoutInputSource(); + CFDataRef layoutData = static_cast(TISGetInputSourceProperty(tis, kTISPropertyUnicodeKeyLayoutData)); - // A code was found, wonderful! - if (code != Keyboard::Unknown) + if (layoutData == 0) + { + sf::err() << "Cannot get the keyboard layout\n"; + CFRelease(tis); + return; + } + + UCKeyboardLayout* layout = reinterpret_cast(CFDataGetBytePtr(layoutData)); + + // For each scancode having a IOHIDElement, we translate the corresponding + // virtual code to a localized Key. + for (int i = 0; i < Keyboard::sCodeCount; ++i) + { + Keyboard::Scancode scan = static_cast(i); + UInt8 virtualCode = scanToVirtualCode(scan); + + if (virtualCode == 0xff) continue; + + // Unicode string length is usually less or equal to 4 + UniCharCount const MAX_LENGTH = 4; + UniChar string[MAX_LENGTH]; + UniCharCount length = 0; + UInt32 deadKeyState = 0; // unused value + UInt32 const modifiers = 0x100; // no modifiers + + // Use current layout for translation + OSStatus error = UCKeyTranslate( + layout, virtualCode, kUCKeyActionDown, modifiers, LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, &deadKeyState, MAX_LENGTH, &length, string + ); + + if (error != noErr) { - // Ok, everything went fine. Now we have a unique - // corresponding sf::Keyboard::Key to one IOHIDElementRef - m_keys[code].push_back(key); - - // And don't forget to keep the reference alive for our usage - CFRetain(m_keys[code].back()); + sf::err() << "Cannot translate the virtual key code, error: " << error << "\n"; + continue; } - //////////////////////////////////////////////////////////// - // These are known to be unbound: - // Supposed Virtual | HID | Supposed Key - // =============================================== - // 0x1b | 0x2d | Hyphen - // 0x39 | 0x39 | CapsLock - // 0x47 | 0x53 | NumLock - // 0x6e | 0x65 | Application - // 0x4c | 0x77 | Select + Keyboard::Key code = (length > 0) ? localizedKey(string[0]) : Keyboard::Unknown; + if (code == Keyboard::Unknown) code = localizedKeyFallback(scan); - //if (code == Keyboard::Unknown) { // The key is unknown. - // sf::err() << "This is an unknown key. Virtual key code is 0x" - // << std::hex - // << (UInt32)virtualCode - // << " and HID usage code is 0x" - // << usageCode - // << std::dec - // << "." - // << std::endl; - //} + if (code == Keyboard::Unknown) continue; - } /* if (error == noErr) */ - else - { - sf::err() << "Cannot translate the virtual key code, error: " - << error - << std::endl; + // Register the bi-mapping + m_mapping[code] = scan; + m_gnippam[scan] = code; } + + CFRelease(tis); } //////////////////////////////////////////////////////////// void HIDInputManager::freeUp() { - m_isValid = false; - - if (m_layoutData != 0) - CFRelease(m_layoutData); - m_layoutData = 0; - // Do not release m_layout! It is owned by m_layoutData. if (m_manager != 0) CFRelease(m_manager); m_manager = 0; @@ -338,32 +392,28 @@ CFSetRef HIDInputManager::copyDevices(UInt32 page, UInt32 usage) IOHIDManagerSetDeviceMatching(m_manager, mask); CFRelease(mask); - mask = 0; + mask = NULL; CFSetRef devices = IOHIDManagerCopyDevices(m_manager); if (devices == NULL) return NULL; // Is there at least one device? - CFIndex deviceCount = CFSetGetCount(devices); - if (deviceCount < 1) + if (CFSetGetCount(devices) < 1) { CFRelease(devices); return NULL; } - + return devices; } + +//////////////////////////////////////////////////////////// bool HIDInputManager::isPressed(IOHIDElements& elements) { - if (!m_isValid) - return false; - - // state = true if at least one corresponding HID button is pressed - bool state = false; - - for (IOHIDElements::iterator it = elements.begin(); it != elements.end(); /* noop */) + bool pressed = false; + for (IOHIDElements::iterator it = elements.begin(); it != elements.end() && !pressed; /* noop */) { IOHIDValueRef value = 0; @@ -372,493 +422,886 @@ bool HIDInputManager::isPressed(IOHIDElements& elements) if (!value) { - // This means some kind of error / disconnection so we remove this - // element from our buttons + // This means some kind of error / disconnection so we remove this element from our database. CFRelease(*it); it = elements.erase(it); } - else if (IOHIDValueGetIntegerValue(value) == 1) - { - // This means the button is pressed - state = true; - break; // Stop here - } else { - // This means the button is released + pressed = (IOHIDValueGetIntegerValue(value) == 1); ++it; } + } - return state; + return pressed; } //////////////////////////////////////////////////////////// -UInt8 HIDInputManager::usageToVirtualCode(UInt32 usage) +sf::Keyboard::Scancode HIDInputManager::usageToScancode(UInt32 usage) { - // Some usage key doesn't have any corresponding virtual - // code or it was not found (return 0xff). switch (usage) { - case kHIDUsage_KeyboardErrorRollOver: return 0xff; - case kHIDUsage_KeyboardPOSTFail: return 0xff; - case kHIDUsage_KeyboardErrorUndefined: return 0xff; + case kHIDUsage_KeyboardErrorRollOver: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardPOSTFail: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardErrorUndefined: return sf::Keyboard::sUnknown; - 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_KeyboardA: return sf::Keyboard::sA; + case kHIDUsage_KeyboardB: return sf::Keyboard::sB; + case kHIDUsage_KeyboardC: return sf::Keyboard::sC; + case kHIDUsage_KeyboardD: return sf::Keyboard::sD; + case kHIDUsage_KeyboardE: return sf::Keyboard::sE; + case kHIDUsage_KeyboardF: return sf::Keyboard::sF; + case kHIDUsage_KeyboardG: return sf::Keyboard::sG; + case kHIDUsage_KeyboardH: return sf::Keyboard::sH; + case kHIDUsage_KeyboardI: return sf::Keyboard::sI; + case kHIDUsage_KeyboardJ: return sf::Keyboard::sJ; + case kHIDUsage_KeyboardK: return sf::Keyboard::sK; + case kHIDUsage_KeyboardL: return sf::Keyboard::sL; + case kHIDUsage_KeyboardM: return sf::Keyboard::sM; + case kHIDUsage_KeyboardN: return sf::Keyboard::sN; + case kHIDUsage_KeyboardO: return sf::Keyboard::sO; + case kHIDUsage_KeyboardP: return sf::Keyboard::sP; + case kHIDUsage_KeyboardQ: return sf::Keyboard::sQ; + case kHIDUsage_KeyboardR: return sf::Keyboard::sR; + case kHIDUsage_KeyboardS: return sf::Keyboard::sS; + case kHIDUsage_KeyboardT: return sf::Keyboard::sT; + case kHIDUsage_KeyboardU: return sf::Keyboard::sU; + case kHIDUsage_KeyboardV: return sf::Keyboard::sV; + case kHIDUsage_KeyboardW: return sf::Keyboard::sW; + case kHIDUsage_KeyboardX: return sf::Keyboard::sX; + case kHIDUsage_KeyboardY: return sf::Keyboard::sY; + case kHIDUsage_KeyboardZ: return sf::Keyboard::sZ; - 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_Keyboard1: return sf::Keyboard::sNum1; + case kHIDUsage_Keyboard2: return sf::Keyboard::sNum2; + case kHIDUsage_Keyboard3: return sf::Keyboard::sNum3; + case kHIDUsage_Keyboard4: return sf::Keyboard::sNum4; + case kHIDUsage_Keyboard5: return sf::Keyboard::sNum5; + case kHIDUsage_Keyboard6: return sf::Keyboard::sNum6; + case kHIDUsage_Keyboard7: return sf::Keyboard::sNum7; + case kHIDUsage_Keyboard8: return sf::Keyboard::sNum8; + case kHIDUsage_Keyboard9: return sf::Keyboard::sNum9; + case kHIDUsage_Keyboard0: return sf::Keyboard::sNum0; - 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_KeyboardReturnOrEnter: return sf::Keyboard::sEnter; + case kHIDUsage_KeyboardEscape: return sf::Keyboard::sEscape; + case kHIDUsage_KeyboardDeleteOrBackspace: return sf::Keyboard::sBackspace; + case kHIDUsage_KeyboardTab: return sf::Keyboard::sTab; + case kHIDUsage_KeyboardSpacebar: return sf::Keyboard::sSpace; + case kHIDUsage_KeyboardHyphen: return sf::Keyboard::sHyphen; + case kHIDUsage_KeyboardEqualSign: return sf::Keyboard::sEquals; + case kHIDUsage_KeyboardOpenBracket: return sf::Keyboard::sLBracket; + case kHIDUsage_KeyboardCloseBracket: return sf::Keyboard::sRBracket; + case kHIDUsage_KeyboardBackslash: return sf::Keyboard::sBackslash; + case kHIDUsage_KeyboardNonUSPound: return sf::Keyboard::sDash; + case kHIDUsage_KeyboardSemicolon: return sf::Keyboard::sSemicolon; + case kHIDUsage_KeyboardQuote: return sf::Keyboard::sQuote; + case kHIDUsage_KeyboardGraveAccentAndTilde: return sf::Keyboard::sGraveAccent; + case kHIDUsage_KeyboardComma: return sf::Keyboard::sComma; + case kHIDUsage_KeyboardPeriod: return sf::Keyboard::sPeriod; + case kHIDUsage_KeyboardSlash: return sf::Keyboard::sForwardSlash; + case kHIDUsage_KeyboardCapsLock: return sf::Keyboard::sCapsLock; - 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_KeyboardF1: return sf::Keyboard::sF1; + case kHIDUsage_KeyboardF2: return sf::Keyboard::sF2; + case kHIDUsage_KeyboardF3: return sf::Keyboard::sF3; + case kHIDUsage_KeyboardF4: return sf::Keyboard::sF4; + case kHIDUsage_KeyboardF5: return sf::Keyboard::sF5; + case kHIDUsage_KeyboardF6: return sf::Keyboard::sF6; + case kHIDUsage_KeyboardF7: return sf::Keyboard::sF7; + case kHIDUsage_KeyboardF8: return sf::Keyboard::sF8; + case kHIDUsage_KeyboardF9: return sf::Keyboard::sF9; + case kHIDUsage_KeyboardF10: return sf::Keyboard::sF10; + case kHIDUsage_KeyboardF11: return sf::Keyboard::sF11; + case kHIDUsage_KeyboardF12: return sf::Keyboard::sF12; - 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_KeyboardPrintScreen: return sf::Keyboard::sPrintScreen; + case kHIDUsage_KeyboardScrollLock: return sf::Keyboard::sScrollLock; + case kHIDUsage_KeyboardPause: return sf::Keyboard::sPause; + case kHIDUsage_KeyboardInsert: return sf::Keyboard::sInsert; + case kHIDUsage_KeyboardHome: return sf::Keyboard::sHome; + case kHIDUsage_KeyboardPageUp: return sf::Keyboard::sPageUp; + case kHIDUsage_KeyboardDeleteForward: return sf::Keyboard::sDelete; + case kHIDUsage_KeyboardEnd: return sf::Keyboard::sEnd; + case kHIDUsage_KeyboardPageDown: return sf::Keyboard::sPageDown; - case kHIDUsage_KeyboardRightArrow: return 0x7c; - case kHIDUsage_KeyboardLeftArrow: return 0x7b; - case kHIDUsage_KeyboardDownArrow: return 0x7d; - case kHIDUsage_KeyboardUpArrow: return 0x7e; + case kHIDUsage_KeyboardRightArrow: return sf::Keyboard::sRight; + case kHIDUsage_KeyboardLeftArrow: return sf::Keyboard::sLeft; + case kHIDUsage_KeyboardDownArrow: return sf::Keyboard::sDown; + case kHIDUsage_KeyboardUpArrow: return sf::Keyboard::sUp; - 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_KeypadNumLock: return sf::Keyboard::sNumLock; + case kHIDUsage_KeypadSlash: return sf::Keyboard::sDivide; + case kHIDUsage_KeypadAsterisk: return sf::Keyboard::sMultiply; + case kHIDUsage_KeypadHyphen: return sf::Keyboard::sMinus; + case kHIDUsage_KeypadPlus: return sf::Keyboard::sPlus; + case kHIDUsage_KeypadEnter: return sf::Keyboard::sReturn; - 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_Keypad1: return sf::Keyboard::sNumpad1; + case kHIDUsage_Keypad2: return sf::Keyboard::sNumpad2; + case kHIDUsage_Keypad3: return sf::Keyboard::sNumpad3; + case kHIDUsage_Keypad4: return sf::Keyboard::sNumpad4; + case kHIDUsage_Keypad5: return sf::Keyboard::sNumpad5; + case kHIDUsage_Keypad6: return sf::Keyboard::sNumpad6; + case kHIDUsage_Keypad7: return sf::Keyboard::sNumpad7; + case kHIDUsage_Keypad8: return sf::Keyboard::sNumpad8; + case kHIDUsage_Keypad9: return sf::Keyboard::sNumpad9; + case kHIDUsage_Keypad0: return sf::Keyboard::sNumpad0; - 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_KeypadPeriod: return sf::Keyboard::sDecimal; + case kHIDUsage_KeyboardNonUSBackslash: return sf::Keyboard::sReverseSolidus; + case kHIDUsage_KeyboardApplication: return sf::Keyboard::sApplication; + case kHIDUsage_KeyboardPower: return sf::Keyboard::sUnknown; + case kHIDUsage_KeypadEqualSign: return sf::Keyboard::sPadEquals; - 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_KeyboardF13: return sf::Keyboard::sF13; + case kHIDUsage_KeyboardF14: return sf::Keyboard::sF14; + case kHIDUsage_KeyboardF15: return sf::Keyboard::sF15; + case kHIDUsage_KeyboardF16: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardF17: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardF18: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardF19: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardF20: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardF21: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardF22: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardF23: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardF24: return sf::Keyboard::sUnknown; - 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_KeyboardExecute: return sf::Keyboard::sExecute; + case kHIDUsage_KeyboardHelp: return sf::Keyboard::sHelp; + case kHIDUsage_KeyboardMenu: return sf::Keyboard::sMenu; + case kHIDUsage_KeyboardSelect: return sf::Keyboard::sSelect; + case kHIDUsage_KeyboardStop: return sf::Keyboard::sStop; + case kHIDUsage_KeyboardAgain: return sf::Keyboard::sAgain; + case kHIDUsage_KeyboardUndo: return sf::Keyboard::sUndo; + case kHIDUsage_KeyboardCut: return sf::Keyboard::sCut; + case kHIDUsage_KeyboardCopy: return sf::Keyboard::sCopy; + case kHIDUsage_KeyboardPaste: return sf::Keyboard::sPaste; + case kHIDUsage_KeyboardFind: return sf::Keyboard::sFind; - case kHIDUsage_KeyboardMute: return 0xff; - case kHIDUsage_KeyboardVolumeUp: return 0xff; - case kHIDUsage_KeyboardVolumeDown: return 0xff; + case kHIDUsage_KeyboardMute: return sf::Keyboard::sMute; + case kHIDUsage_KeyboardVolumeUp: return sf::Keyboard::sVolumeUp; + case kHIDUsage_KeyboardVolumeDown: return sf::Keyboard::sVolumeDown; - case kHIDUsage_KeyboardLockingCapsLock: return 0xff; - case kHIDUsage_KeyboardLockingNumLock: return 0xff; - case kHIDUsage_KeyboardLockingScrollLock: return 0xff; + case kHIDUsage_KeyboardLockingCapsLock: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLockingNumLock: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLockingScrollLock: return sf::Keyboard::sUnknown; - 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_KeypadComma: return sf::Keyboard::sUnknown; + case kHIDUsage_KeypadEqualSignAS400: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational1: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational2: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational3: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational4: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational5: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational6: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational7: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational8: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardInternational9: return sf::Keyboard::sUnknown; - 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_KeyboardLANG1: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLANG2: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLANG3: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLANG4: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLANG5: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLANG6: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLANG7: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLANG8: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardLANG9: return sf::Keyboard::sUnknown; - 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; + case kHIDUsage_KeyboardAlternateErase: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardSysReqOrAttention: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardCancel: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardClear: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardPrior: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardReturn: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardSeparator: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardOut: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardOper: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardClearOrAgain: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardCrSelOrProps: return sf::Keyboard::sUnknown; + case kHIDUsage_KeyboardExSel: return sf::Keyboard::sUnknown; /* 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; + case kHIDUsage_KeyboardLeftControl: return sf::Keyboard::sLControl; + case kHIDUsage_KeyboardLeftShift: return sf::Keyboard::sLShift; + case kHIDUsage_KeyboardLeftAlt: return sf::Keyboard::sLAlt; + case kHIDUsage_KeyboardLeftGUI: return sf::Keyboard::sLSystem; + case kHIDUsage_KeyboardRightControl: return sf::Keyboard::sRControl; + case kHIDUsage_KeyboardRightShift: return sf::Keyboard::sRShift; + case kHIDUsage_KeyboardRightAlt: return sf::Keyboard::sRAlt; + case kHIDUsage_KeyboardRightGUI: return sf::Keyboard::sRSystem; /* 0xe8-0xffff Reserved */ - case kHIDUsage_Keyboard_Reserved: return 0xff; - default: return 0xff; + case kHIDUsage_Keyboard_Reserved: return sf::Keyboard::sUnknown; + default: return sf::Keyboard::sUnknown; } } //////////////////////////////////////////////////////// -Keyboard::Key HIDInputManager::localizedKeys(UniChar ch) +Keyboard::Key HIDInputManager::localizedKey(UniChar ch) { + // Apple is using the private range 0xE000 - 0xF8FF for special keys. + // Otherwise one can refer to the usual Unicode table. switch (ch) { - case 'a': - case 'A': return sf::Keyboard::A; + case 0x41: return sf::Keyboard::A; // uppercase A + case 0x42: return sf::Keyboard::B; + case 0x43: return sf::Keyboard::C; + case 0x44: return sf::Keyboard::D; + case 0x45: return sf::Keyboard::E; + case 0x46: return sf::Keyboard::F; + case 0x47: return sf::Keyboard::G; + case 0x48: return sf::Keyboard::H; + case 0x49: return sf::Keyboard::I; + case 0x4a: return sf::Keyboard::J; + case 0x4b: return sf::Keyboard::K; + case 0x4c: return sf::Keyboard::L; + case 0x4d: return sf::Keyboard::M; + case 0x4e: return sf::Keyboard::N; + case 0x4f: return sf::Keyboard::O; + case 0x50: return sf::Keyboard::P; + case 0x51: return sf::Keyboard::Q; + case 0x52: return sf::Keyboard::R; + case 0x53: return sf::Keyboard::S; + case 0x54: return sf::Keyboard::T; + case 0x55: return sf::Keyboard::U; + case 0x56: return sf::Keyboard::V; + case 0x57: return sf::Keyboard::W; + case 0x58: return sf::Keyboard::X; + case 0x59: return sf::Keyboard::Y; - case 'b': - case 'B': return sf::Keyboard::B; + case 0x5a: return sf::Keyboard::Z; // lowercase A + case 0x61: return sf::Keyboard::A; + case 0x62: return sf::Keyboard::B; + case 0x63: return sf::Keyboard::C; + case 0x64: return sf::Keyboard::D; + case 0x65: return sf::Keyboard::E; + case 0x66: return sf::Keyboard::F; + case 0x67: return sf::Keyboard::G; + case 0x68: return sf::Keyboard::H; + case 0x69: return sf::Keyboard::I; + case 0x6a: return sf::Keyboard::J; + case 0x6b: return sf::Keyboard::K; + case 0x6c: return sf::Keyboard::L; + case 0x6d: return sf::Keyboard::M; + case 0x6e: return sf::Keyboard::N; + case 0x6f: return sf::Keyboard::O; + case 0x70: return sf::Keyboard::P; + case 0x71: return sf::Keyboard::Q; + case 0x72: return sf::Keyboard::R; + case 0x73: return sf::Keyboard::S; + case 0x74: return sf::Keyboard::T; + case 0x75: return sf::Keyboard::U; + case 0x76: return sf::Keyboard::V; + case 0x77: return sf::Keyboard::W; + case 0x78: return sf::Keyboard::X; + case 0x79: return sf::Keyboard::Y; + case 0x7a: return sf::Keyboard::Z; - case 'c': - case 'C': return sf::Keyboard::C; + case 0x30: return sf::Keyboard::Num0; + case 0x31: return sf::Keyboard::Num1; + case 0x32: return sf::Keyboard::Num2; + case 0x33: return sf::Keyboard::Num3; + case 0x34: return sf::Keyboard::Num4; + case 0x35: return sf::Keyboard::Num5; + case 0x36: return sf::Keyboard::Num6; + case 0x37: return sf::Keyboard::Num7; + case 0x38: return sf::Keyboard::Num8; + case 0x39: return sf::Keyboard::Num9; - case 'd': - case 'D': return sf::Keyboard::D; + case 0x1b: return sf::Keyboard::Escape; - case 'e': - case 'E': return sf::Keyboard::E; + /* Those are not represented using Unicode. + * case 0x: return sf::Keyboard::LControl; + * case 0x: return sf::Keyboard::LShift; + * case 0x: return sf::Keyboard::LAlt; + * case 0x: return sf::Keyboard::LSystem; + * case 0x: return sf::Keyboard::RControl; + * case 0x: return sf::Keyboard::RShift; + * case 0x: return sf::Keyboard::RAlt; + * case 0x: return sf::Keyboard::RSystem; + */ - case 'f': - case 'F': return sf::Keyboard::F; + case NSMenuFunctionKey: return sf::Keyboard::Menu; - case 'g': - case 'G': return sf::Keyboard::G; + case 0x5b: return sf::Keyboard::LBracket; + case 0x5d: return sf::Keyboard::RBracket; + case 0x3b: return sf::Keyboard::SemiColon; + case 0x2c: return sf::Keyboard::Comma; + case 0x2e: return sf::Keyboard::Period; + case 0x27: return sf::Keyboard::Quote; + case 0x2044: return sf::Keyboard::Slash; // 0x2f is Divide + case 0x5c: return sf::Keyboard::BackSlash; + case 0x7e: return sf::Keyboard::Tilde; + case 0x3d: return sf::Keyboard::Equal; + case 0x2013: return sf::Keyboard::Dash; // 0x2d is Subtract + case 0x20: return sf::Keyboard::Space; + case 0x0d: return sf::Keyboard::Return; + case 0x7f: return sf::Keyboard::BackSpace; // NOTE backspace & delete are swapped on Mac. + case 0x09: return sf::Keyboard::Tab; - case 'h': - case 'H': return sf::Keyboard::H; + 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 'i': - case 'I': return sf::Keyboard::I; + case 0x2b: return sf::Keyboard::Add; + case 0x2d: return sf::Keyboard::Subtract; + case 0x2a: return sf::Keyboard::Multiply; + case 0x2f: return sf::Keyboard::Divide; - case 'j': - case 'J': return sf::Keyboard::J; + 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 'k': - case 'K': return sf::Keyboard::K; + /* Those are not represented using Unicode. + * case 0x: return sf::Keyboard::Numpad0; + * case 0x: return sf::Keyboard::Numpad1; + * case 0x: return sf::Keyboard::Numpad2; + * case 0x: return sf::Keyboard::Numpad3; + * case 0x: return sf::Keyboard::Numpad4; + * case 0x: return sf::Keyboard::Numpad5; + * case 0x: return sf::Keyboard::Numpad6; + * case 0x: return sf::Keyboard::Numpad7; + * case 0x: return sf::Keyboard::Numpad8; + * case 0x: return sf::Keyboard::Numpad9; + */ - case 'l': - case 'L': return sf::Keyboard::L; + 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 'm': - case 'M': return sf::Keyboard::M; + case NSPauseFunctionKey: return sf::Keyboard::Pause; - 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::Unknown; + default: return sf::Keyboard::Unknown; } } //////////////////////////////////////////////////////// -Keyboard::Key HIDInputManager::nonLocalizedKeys(UniChar virtualKeycode) +UniChar HIDInputManager::toUnicode(Keyboard::Key key) { - // (Some) 0x code based on https://forums.macrumors.com/showthread.php?t=780577 - // Some sf::Keyboard::Key are present twice. + switch (key) + { + case sf::Keyboard::A: return 0x41; + case sf::Keyboard::B: return 0x42; + case sf::Keyboard::C: return 0x43; + case sf::Keyboard::D: return 0x44; + case sf::Keyboard::E: return 0x45; + case sf::Keyboard::F: return 0x46; + case sf::Keyboard::G: return 0x47; + case sf::Keyboard::H: return 0x48; + case sf::Keyboard::I: return 0x49; + case sf::Keyboard::J: return 0x4a; + case sf::Keyboard::K: return 0x4b; + case sf::Keyboard::L: return 0x4c; + case sf::Keyboard::M: return 0x4d; + case sf::Keyboard::N: return 0x4e; + case sf::Keyboard::O: return 0x4f; + case sf::Keyboard::P: return 0x50; + case sf::Keyboard::Q: return 0x51; + case sf::Keyboard::R: return 0x52; + case sf::Keyboard::S: return 0x53; + case sf::Keyboard::T: return 0x54; + case sf::Keyboard::U: return 0x55; + case sf::Keyboard::V: return 0x56; + case sf::Keyboard::W: return 0x57; + case sf::Keyboard::X: return 0x58; + case sf::Keyboard::Y: return 0x59; + case sf::Keyboard::Z: return 0x5a; + + case sf::Keyboard::Num0: return 0x30; + case sf::Keyboard::Num1: return 0x31; + case sf::Keyboard::Num2: return 0x32; + case sf::Keyboard::Num3: return 0x33; + case sf::Keyboard::Num4: return 0x34; + case sf::Keyboard::Num5: return 0x35; + case sf::Keyboard::Num6: return 0x36; + case sf::Keyboard::Num7: return 0x37; + case sf::Keyboard::Num8: return 0x38; + case sf::Keyboard::Num9: return 0x39; + + case sf::Keyboard::Escape: return 0x1b; + + /* Not representable as Unicode: + * case sf::Keyboard::LControl: return 0x; + * case sf::Keyboard::LShift: return 0x; + * case sf::Keyboard::LAlt: return 0x; + * case sf::Keyboard::LSystem: return 0x; + * case sf::Keyboard::RControl: return 0x; + * case sf::Keyboard::RShift: return 0x; + * case sf::Keyboard::RAlt: return 0x; + * case sf::Keyboard::RSystem: return 0x; + */ + + case sf::Keyboard::Menu: return NSMenuFunctionKey; + + case sf::Keyboard::LBracket: return 0x5b; + case sf::Keyboard::RBracket: return 0x5d; + case sf::Keyboard::SemiColon: return 0x3b; + case sf::Keyboard::Comma: return 0x2c; + case sf::Keyboard::Period: return 0x2e; + case sf::Keyboard::Quote: return 0x27; + case sf::Keyboard::Slash: return 0x2044; // 0x2f is Divide + case sf::Keyboard::BackSlash: return 0x5c; + case sf::Keyboard::Tilde: return 0x7e; + case sf::Keyboard::Equal: return 0x3d; + case sf::Keyboard::Dash: return 0x2013; // 0x2d is Subtract + case sf::Keyboard::Space: return 0x20; + case sf::Keyboard::Return: return 0x0d; + case sf::Keyboard::BackSpace: return 0x7f; // NOTE backspace & delete are swapped on Mac. + case sf::Keyboard::Tab: return 0x09; + + case sf::Keyboard::PageUp: return NSPageUpFunctionKey; + case sf::Keyboard::PageDown: return NSPageDownFunctionKey; + case sf::Keyboard::End: return NSEndFunctionKey; + case sf::Keyboard::Home: return NSHomeFunctionKey; + case sf::Keyboard::Insert: return NSInsertFunctionKey; + case sf::Keyboard::Delete: return NSDeleteFunctionKey; + + case sf::Keyboard::Add: return 0x2b; + case sf::Keyboard::Subtract: return 0x2d; + case sf::Keyboard::Multiply: return 0x2a; + case sf::Keyboard::Divide: return 0x2f; + + case sf::Keyboard::Left: return NSLeftArrowFunctionKey; + case sf::Keyboard::Right: return NSRightArrowFunctionKey; + case sf::Keyboard::Up: return NSUpArrowFunctionKey; + case sf::Keyboard::Down: return NSDownArrowFunctionKey; + + /* Those are not represented using Unicode. + * case sf::Keyboard::Numpad0: return 0x; + * case sf::Keyboard::Numpad1: return 0x; + * case sf::Keyboard::Numpad2: return 0x; + * case sf::Keyboard::Numpad3: return 0x; + * case sf::Keyboard::Numpad4: return 0x; + * case sf::Keyboard::Numpad5: return 0x; + * case sf::Keyboard::Numpad6: return 0x; + * case sf::Keyboard::Numpad7: return 0x; + * case sf::Keyboard::Numpad8: return 0x; + * case sf::Keyboard::Numpad9: return 0x; + */ + + case sf::Keyboard::F1: return NSF1FunctionKey; + case sf::Keyboard::F2: return NSF2FunctionKey; + case sf::Keyboard::F3: return NSF3FunctionKey; + case sf::Keyboard::F4: return NSF4FunctionKey; + case sf::Keyboard::F5: return NSF5FunctionKey; + case sf::Keyboard::F6: return NSF6FunctionKey; + case sf::Keyboard::F7: return NSF7FunctionKey; + case sf::Keyboard::F8: return NSF8FunctionKey; + case sf::Keyboard::F9: return NSF9FunctionKey; + case sf::Keyboard::F10: return NSF10FunctionKey; + case sf::Keyboard::F11: return NSF11FunctionKey; + case sf::Keyboard::F12: return NSF12FunctionKey; + case sf::Keyboard::F13: return NSF13FunctionKey; + case sf::Keyboard::F14: return NSF14FunctionKey; + case sf::Keyboard::F15: return NSF15FunctionKey; + + case sf::Keyboard::Pause: return NSPauseFunctionKey; + + default: return 0x00; + } +} + + +//////////////////////////////////////////////////////// +Keyboard::Scancode HIDInputManager::nonLocalizedKey(UniChar virtualKeycode) +{ + // See Chapter 2, esp. Figure 2-10 of + // https://developer.apple.com/legacy/library/documentation/mac/pdf/MacintoshToolboxEssentials.pdf + // Additional virtual codes come from + // /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h 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; + case 0x00: return sf::Keyboard::sA; + case 0x0b: return sf::Keyboard::sB; + case 0x08: return sf::Keyboard::sC; + case 0x02: return sf::Keyboard::sD; + case 0x0e: return sf::Keyboard::sE; + case 0x03: return sf::Keyboard::sF; + case 0x05: return sf::Keyboard::sG; + case 0x04: return sf::Keyboard::sH; + case 0x22: return sf::Keyboard::sI; + case 0x26: return sf::Keyboard::sJ; + case 0x28: return sf::Keyboard::sK; + case 0x25: return sf::Keyboard::sL; + case 0x2e: return sf::Keyboard::sM; + case 0x2d: return sf::Keyboard::sN; + case 0x1f: return sf::Keyboard::sO; + case 0x23: return sf::Keyboard::sP; + case 0x0c: return sf::Keyboard::sQ; + case 0x0f: return sf::Keyboard::sR; + case 0x01: return sf::Keyboard::sS; + case 0x11: return sf::Keyboard::sT; + case 0x20: return sf::Keyboard::sU; + case 0x09: return sf::Keyboard::sV; + case 0x0d: return sf::Keyboard::sW; + case 0x07: return sf::Keyboard::sX; + case 0x10: return sf::Keyboard::sY; + case 0x06: return sf::Keyboard::sZ; - // 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 0x12: return sf::Keyboard::sNum1; + case 0x13: return sf::Keyboard::sNum2; + case 0x14: return sf::Keyboard::sNum3; + case 0x15: return sf::Keyboard::sNum4; + case 0x17: return sf::Keyboard::sNum5; + case 0x16: return sf::Keyboard::sNum6; + case 0x1a: return sf::Keyboard::sNum7; + case 0x1c: return sf::Keyboard::sNum8; + case 0x19: return sf::Keyboard::sNum9; + case 0x1d: return sf::Keyboard::sNum0; - case 0x35: return sf::Keyboard::Escape; + case 0x24: return sf::Keyboard::sEnter; + case 0x35: return sf::Keyboard::sEscape; + case 0x33: return sf::Keyboard::sBackspace; + case 0x30: return sf::Keyboard::sTab; + case 0x31: return sf::Keyboard::sSpace; + // case 0x27: return sf::Keyboard::sHyphen; // TODO 0x27 is for Quote + case 0x18: return sf::Keyboard::sEquals; + case 0x21: return sf::Keyboard::sLBracket; + case 0x1e: return sf::Keyboard::sRBracket; + case 0x2a: return sf::Keyboard::sBackslash; + case 0x1b: return sf::Keyboard::sDash; + case 0x29: return sf::Keyboard::sSemicolon; + case 0x27: return sf::Keyboard::sQuote; + case 0x32: return sf::Keyboard::sGraveAccent; + case 0x2b: return sf::Keyboard::sComma; + case 0x2f: return sf::Keyboard::sPeriod; + case 0x2c: return sf::Keyboard::sForwardSlash; - // 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 0x7a: return sf::Keyboard::sF1; + case 0x78: return sf::Keyboard::sF2; + case 0x63: return sf::Keyboard::sF3; + case 0x76: return sf::Keyboard::sF4; + case 0x60: return sf::Keyboard::sF5; + case 0x61: return sf::Keyboard::sF6; + case 0x62: return sf::Keyboard::sF7; + case 0x64: return sf::Keyboard::sF8; + case 0x65: return sf::Keyboard::sF9; + case 0x6d: return sf::Keyboard::sF10; + case 0x67: return sf::Keyboard::sF11; + case 0x6f: return sf::Keyboard::sF12; + case 0x69: return sf::Keyboard::sF13; + case 0x6b: return sf::Keyboard::sF14; + case 0x71: return sf::Keyboard::sF15; - case 0x7f: return sf::Keyboard::Menu; - case NSMenuFunctionKey: return sf::Keyboard::Menu; + case 0x39: return sf::Keyboard::sCapsLock; - 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; + /* TODO Those are missing: + * case 0x: return sf::Keyboard::sPrintScreen; + * case 0x: return sf::Keyboard::sScrollLock; + * case 0x: return sf::Keyboard::sPause; + */ - // 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 0x72: return sf::Keyboard::sInsert; + case 0x73: return sf::Keyboard::sHome; + case 0x74: return sf::Keyboard::sPageUp; + case 0x75: return sf::Keyboard::sDelete; + case 0x77: return sf::Keyboard::sEnd; + case 0x79: return sf::Keyboard::sPageDown; - case 0x51: /* keypad */ return sf::Keyboard::Equal; - case 0x18: /* keyboard */ return sf::Keyboard::Equal; - case 0x32: return sf::Keyboard::Hyphen; - case 0x31: return sf::Keyboard::Space; - case 0x4c: /* keypad */ return sf::Keyboard::Enter; - case 0x24: /* keyboard */ return sf::Keyboard::Enter; - case 0x33: return sf::Keyboard::Backspace; - case 0x30: return sf::Keyboard::Tab; + case 0x7c: return sf::Keyboard::sRight; + case 0x7b: return sf::Keyboard::sLeft; + case 0x7d: return sf::Keyboard::sDown; + case 0x7e: return sf::Keyboard::sUp; - // Duplicates (see next section). - 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 0x47: return sf::Keyboard::sNumLock; + case 0x4b: return sf::Keyboard::sDivide; + case 0x43: return sf::Keyboard::sMultiply; + case 0x4e: return sf::Keyboard::sMinus; + case 0x45: return sf::Keyboard::sPlus; + case 0x51: return sf::Keyboard::sPadEquals; + case 0x4c: return sf::Keyboard::sReturn; + case 0x41: return sf::Keyboard::sDecimal; - 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 0x53: return sf::Keyboard::sNumpad1; + case 0x54: return sf::Keyboard::sNumpad2; + case 0x55: return sf::Keyboard::sNumpad3; + case 0x56: return sf::Keyboard::sNumpad4; + case 0x57: return sf::Keyboard::sNumpad5; + case 0x58: return sf::Keyboard::sNumpad6; + case 0x59: return sf::Keyboard::sNumpad7; + case 0x5b: return sf::Keyboard::sNumpad8; + case 0x5c: return sf::Keyboard::sNumpad9; + case 0x52: return sf::Keyboard::sNumpad0; - case 0x72: return sf::Keyboard::Insert; - case NSInsertFunctionKey: return sf::Keyboard::Insert; - case 0x75: return sf::Keyboard::Delete; - case NSDeleteFunctionKey: return sf::Keyboard::Delete; + /* TODO Those are missing: + * case 0x: return sf::Keyboard::sReverseSolidus; + * case 0x: return sf::Keyboard::sApplication; + * case 0x: return sf::Keyboard::sExecute; + * case 0x72: return sf::Keyboard::sHelp; // 0x72 is for Insert + * case 0x: return sf::Keyboard::sMenu; + * case 0x: return sf::Keyboard::sSelect; + * case 0x: return sf::Keyboard::sStop; + * case 0x: return sf::Keyboard::sAgain; + * case 0x: return sf::Keyboard::sUndo; + * case 0x: return sf::Keyboard::sCut; + * case 0x: return sf::Keyboard::sCopy; + * case 0x: return sf::Keyboard::sPaste; + * case 0x: return sf::Keyboard::sFind; + */ - case 0x45: return sf::Keyboard::Add; - case 0x4e: return sf::Keyboard::Subtract; - case 0x43: return sf::Keyboard::Multiply; - case 0x4b: return sf::Keyboard::Divide; + case 0x4a: return sf::Keyboard::sMute; + case 0x48: return sf::Keyboard::sVolumeUp; + case 0x49: return sf::Keyboard::sVolumeDown; - // Duplicates (see next section). - case 0x7b: return sf::Keyboard::Left; - case 0x7c: return sf::Keyboard::Right; - case 0x7e: return sf::Keyboard::Up; - case 0x7d: return sf::Keyboard::Down; + /* NOTE Those are symmetric so we leave them out. + * Thankfully handled through modifiers and not virtual codes. + * case 0x3b: return sf::Keyboard::sLControl; + * case 0x38: return sf::Keyboard::sLShift; + * case 0x3a: return sf::Keyboard::sLAlt; + * case 0x37: return sf::Keyboard::sLSystem; + * case 0x3b: return sf::Keyboard::sRControl; + * case 0x38: return sf::Keyboard::sRShift; + * case 0x3a: return sf::Keyboard::sRAlt; + * case 0x37: return sf::Keyboard::sRSystem; + */ - case NSLeftArrowFunctionKey: return sf::Keyboard::Left; - case NSRightArrowFunctionKey: return sf::Keyboard::Right; - case NSUpArrowFunctionKey: return sf::Keyboard::Up; - case NSDownArrowFunctionKey: return sf::Keyboard::Down; + default: return sf::Keyboard::sUnknown; + } +} - 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 section). - 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; +//////////////////////////////////////////////////////// +UInt8 HIDInputManager::scanToVirtualCode(Keyboard::Scancode code) +{ + switch (code) + { + case sf::Keyboard::sA: return 0x00; + case sf::Keyboard::sB: return 0x0b; + case sf::Keyboard::sC: return 0x08; + case sf::Keyboard::sD: return 0x02; + case sf::Keyboard::sE: return 0x0e; + case sf::Keyboard::sF: return 0x03; + case sf::Keyboard::sG: return 0x05; + case sf::Keyboard::sH: return 0x04; + case sf::Keyboard::sI: return 0x22; + case sf::Keyboard::sJ: return 0x26; + case sf::Keyboard::sK: return 0x28; + case sf::Keyboard::sL: return 0x25; + case sf::Keyboard::sM: return 0x2e; + case sf::Keyboard::sN: return 0x2d; + case sf::Keyboard::sO: return 0x1f; + case sf::Keyboard::sP: return 0x23; + case sf::Keyboard::sQ: return 0x0c; + case sf::Keyboard::sR: return 0x0f; + case sf::Keyboard::sS: return 0x01; + case sf::Keyboard::sT: return 0x11; + case sf::Keyboard::sU: return 0x20; + case sf::Keyboard::sV: return 0x09; + case sf::Keyboard::sW: return 0x0d; + case sf::Keyboard::sX: return 0x07; + case sf::Keyboard::sY: return 0x10; + case sf::Keyboard::sZ: return 0x06; - 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 sf::Keyboard::sNum1: return 0x12; + case sf::Keyboard::sNum2: return 0x13; + case sf::Keyboard::sNum3: return 0x14; + case sf::Keyboard::sNum4: return 0x15; + case sf::Keyboard::sNum5: return 0x17; + case sf::Keyboard::sNum6: return 0x16; + case sf::Keyboard::sNum7: return 0x1a; + case sf::Keyboard::sNum8: return 0x1c; + case sf::Keyboard::sNum9: return 0x19; + case sf::Keyboard::sNum0: return 0x1d; - case NSPauseFunctionKey: return sf::Keyboard::Pause; + case sf::Keyboard::sEnter: return 0x24; + case sf::Keyboard::sEscape: return 0x35; + case sf::Keyboard::sBackspace: return 0x33; + case sf::Keyboard::sTab: return 0x30; + case sf::Keyboard::sSpace: return 0x31; - // keycode 0x1b is not bound to any key. - // This key is ' on CH-FR, ) on FR and - on US layouts. + // case sf::Keyboard::sHyphen: return 0; // 0x27 is for Quote - // An unknown key. - default: return sf::Keyboard::Unknown; + case sf::Keyboard::sEquals: return 0x18; + case sf::Keyboard::sLBracket: return 0x21; + case sf::Keyboard::sRBracket: return 0x1e; + case sf::Keyboard::sBackslash: return 0x2a; + case sf::Keyboard::sDash: return 0x1b; + case sf::Keyboard::sSemicolon: return 0x29; + case sf::Keyboard::sQuote: return 0x27; + case sf::Keyboard::sGraveAccent: return 0x32; + case sf::Keyboard::sComma: return 0x2b; + case sf::Keyboard::sPeriod: return 0x2f; + case sf::Keyboard::sForwardSlash: return 0x2c; + + case sf::Keyboard::sF1: return 0x7a; + case sf::Keyboard::sF2: return 0x78; + case sf::Keyboard::sF3: return 0x63; + case sf::Keyboard::sF4: return 0x76; + case sf::Keyboard::sF5: return 0x60; + case sf::Keyboard::sF6: return 0x61; + case sf::Keyboard::sF7: return 0x62; + case sf::Keyboard::sF8: return 0x64; + case sf::Keyboard::sF9: return 0x65; + case sf::Keyboard::sF10: return 0x6d; + case sf::Keyboard::sF11: return 0x67; + case sf::Keyboard::sF12: return 0x6f; + case sf::Keyboard::sF13: return 0x69; + case sf::Keyboard::sF14: return 0x6b; + case sf::Keyboard::sF15: return 0x71; + + case sf::Keyboard::sCapsLock: return 0x39; + + /* TODO Those are missing: + * case sf::Keyboard::sPrintScreen: return 0; + * case sf::Keyboard::sScrollLock: return 0; + * case sf::Keyboard::sPause: return 0; + */ + case sf::Keyboard::sInsert: return 0x72; + case sf::Keyboard::sHome: return 0x73; + case sf::Keyboard::sPageUp: return 0x74; + case sf::Keyboard::sDelete: return 0x75; + case sf::Keyboard::sEnd: return 0x77; + case sf::Keyboard::sPageDown: return 0x79; + + case sf::Keyboard::sRight: return 0x7c; + case sf::Keyboard::sLeft: return 0x7b; + case sf::Keyboard::sDown: return 0x7d; + case sf::Keyboard::sUp: return 0x7e; + + case sf::Keyboard::sNumLock: return 0x47; + case sf::Keyboard::sDivide: return 0x4b; + case sf::Keyboard::sMultiply: return 0x43; + case sf::Keyboard::sMinus: return 0x4e; + case sf::Keyboard::sPlus: return 0x45; + case sf::Keyboard::sPadEquals: return 0x51; + case sf::Keyboard::sReturn: return 0x4c; + case sf::Keyboard::sDecimal: return 0x41; + + case sf::Keyboard::sNumpad1: return 0x53; + case sf::Keyboard::sNumpad2: return 0x54; + case sf::Keyboard::sNumpad3: return 0x55; + case sf::Keyboard::sNumpad4: return 0x56; + case sf::Keyboard::sNumpad5: return 0x57; + case sf::Keyboard::sNumpad6: return 0x58; + case sf::Keyboard::sNumpad7: return 0x59; + case sf::Keyboard::sNumpad8: return 0x5b; + case sf::Keyboard::sNumpad9: return 0x5c; + case sf::Keyboard::sNumpad0: return 0x52; + + /* TODO Those are missing: + * case sf::Keyboard::sReverseSolidus: return 0; + * case sf::Keyboard::sApplication: return 0; + * case sf::Keyboard::sExecute: return 0; + * case sf::Keyboard::sHelp: return 0; + * case sf::Keyboard::sMenu: return 0; + * case sf::Keyboard::sSelect: return 0; + * case sf::Keyboard::sStop: return 0; + * case sf::Keyboard::sAgain: return 0; + * case sf::Keyboard::sUndo: return 0; + * case sf::Keyboard::sCut: return 0; + * case sf::Keyboard::sCopy: return 0; + * case sf::Keyboard::sPaste: return 0; + * case sf::Keyboard::sFind: return 0; + */ + + case sf::Keyboard::sMute: return 0x4a; + case sf::Keyboard::sVolumeUp: return 0x48; + case sf::Keyboard::sVolumeDown: return 0x49; + + case sf::Keyboard::sLControl: return 0x3b; + case sf::Keyboard::sLShift: return 0x38; + case sf::Keyboard::sLAlt: return 0x3a; + case sf::Keyboard::sLSystem: return 0x37; + case sf::Keyboard::sRControl: return 0x3b; + case sf::Keyboard::sRShift: return 0x38; + case sf::Keyboard::sRAlt: return 0x3a; + case sf::Keyboard::sRSystem: return 0x37; + + default: return 0x00; + } +} + + +//////////////////////////////////////////////////////// +Keyboard::Key HIDInputManager::localizedKeyFallback(Keyboard::Scancode code) +{ + switch (code) + { + case sf::Keyboard::sEnter: return sf::Keyboard::Return; + case sf::Keyboard::sEscape: return sf::Keyboard::Escape; + case sf::Keyboard::sBackspace: return sf::Keyboard::BackSpace; + case sf::Keyboard::sTab: return sf::Keyboard::Tab; + case sf::Keyboard::sSpace: return sf::Keyboard::Space; + + case sf::Keyboard::sF1: return sf::Keyboard::F1; + case sf::Keyboard::sF2: return sf::Keyboard::F2; + case sf::Keyboard::sF3: return sf::Keyboard::F3; + case sf::Keyboard::sF4: return sf::Keyboard::F4; + case sf::Keyboard::sF5: return sf::Keyboard::F5; + case sf::Keyboard::sF6: return sf::Keyboard::F6; + case sf::Keyboard::sF7: return sf::Keyboard::F7; + case sf::Keyboard::sF8: return sf::Keyboard::F8; + case sf::Keyboard::sF9: return sf::Keyboard::F9; + case sf::Keyboard::sF10: return sf::Keyboard::F10; + case sf::Keyboard::sF11: return sf::Keyboard::F11; + case sf::Keyboard::sF12: return sf::Keyboard::F12; + case sf::Keyboard::sF13: return sf::Keyboard::F13; + case sf::Keyboard::sF14: return sf::Keyboard::F14; + case sf::Keyboard::sF15: return sf::Keyboard::F15; + + case sf::Keyboard::sPause: return sf::Keyboard::Pause; + case sf::Keyboard::sInsert: return sf::Keyboard::Insert; + case sf::Keyboard::sHome: return sf::Keyboard::Home; + case sf::Keyboard::sPageUp: return sf::Keyboard::PageUp; + case sf::Keyboard::sDelete: return sf::Keyboard::Delete; + case sf::Keyboard::sEnd: return sf::Keyboard::End; + case sf::Keyboard::sPageDown: return sf::Keyboard::PageDown; + + case sf::Keyboard::sRight: return sf::Keyboard::Right; + case sf::Keyboard::sLeft: return sf::Keyboard::Left; + case sf::Keyboard::sDown: return sf::Keyboard::Down; + case sf::Keyboard::sUp: return sf::Keyboard::Up; + + case sf::Keyboard::sDivide: return sf::Keyboard::Divide; + case sf::Keyboard::sMultiply: return sf::Keyboard::Multiply; + case sf::Keyboard::sMinus: return sf::Keyboard::Subtract; + case sf::Keyboard::sPlus: return sf::Keyboard::Add; + + case sf::Keyboard::sNumpad0: return sf::Keyboard::Numpad1; + case sf::Keyboard::sNumpad1: return sf::Keyboard::Numpad2; + case sf::Keyboard::sNumpad2: return sf::Keyboard::Numpad3; + case sf::Keyboard::sNumpad3: return sf::Keyboard::Numpad4; + case sf::Keyboard::sNumpad4: return sf::Keyboard::Numpad5; + case sf::Keyboard::sNumpad5: return sf::Keyboard::Numpad6; + case sf::Keyboard::sNumpad6: return sf::Keyboard::Numpad7; + case sf::Keyboard::sNumpad7: return sf::Keyboard::Numpad8; + case sf::Keyboard::sNumpad8: return sf::Keyboard::Numpad9; + case sf::Keyboard::sNumpad9: return sf::Keyboard::Numpad0; + + case sf::Keyboard::sLControl: return sf::Keyboard::LControl; + case sf::Keyboard::sLShift: return sf::Keyboard::LShift; + case sf::Keyboard::sLAlt: return sf::Keyboard::LAlt; + case sf::Keyboard::sLSystem: return sf::Keyboard::LSystem; + case sf::Keyboard::sRControl: return sf::Keyboard::RControl; + case sf::Keyboard::sRShift: return sf::Keyboard::RShift; + case sf::Keyboard::sRAlt: return sf::Keyboard::RAlt; + case sf::Keyboard::sRSystem: return sf::Keyboard::RSystem; + + default: return sf::Keyboard::Unknown; } } diff --git a/src/SFML/Window/OSX/InputImpl.mm b/src/SFML/Window/OSX/InputImpl.mm index c27aa38b8..201090c9a 100644 --- a/src/SFML/Window/OSX/InputImpl.mm +++ b/src/SFML/Window/OSX/InputImpl.mm @@ -40,9 +40,6 @@ /// 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 @@ -123,6 +120,7 @@ SFOpenGLView* getSFOpenGLViewFromSFMLWindow(const WindowBase& window) return view; } + //////////////////////////////////////////////////////////// bool InputImpl::isKeyPressed(Keyboard::Key key) { @@ -131,6 +129,34 @@ bool InputImpl::isKeyPressed(Keyboard::Key key) } +//////////////////////////////////////////////////////////// +bool InputImpl::isKeyPressed(Keyboard::Scancode code) +{ + return HIDInputManager::getInstance().isKeyPressed(code); +} + + +//////////////////////////////////////////////////////////// +Keyboard::Key InputImpl::localize(Keyboard::Scancode code) +{ + return HIDInputManager::getInstance().localize(code); +} + + +//////////////////////////////////////////////////////////// +Keyboard::Scancode InputImpl::unlocalize(Keyboard::Key key) +{ + return HIDInputManager::getInstance().unlocalize(key); +} + + +//////////////////////////////////////////////////////////// +String InputImpl::localizedRepresentation(Keyboard::Scancode code) +{ + return HIDInputManager::getInstance().localizedRepresentation(code); +} + + //////////////////////////////////////////////////////////// void InputImpl::setVirtualKeyboardVisible(bool /*visible*/) { diff --git a/src/SFML/Window/OSX/SFKeyboardModifiersHelper.h b/src/SFML/Window/OSX/SFKeyboardModifiersHelper.h index a7010053d..b3f375ba6 100644 --- a/src/SFML/Window/OSX/SFKeyboardModifiersHelper.h +++ b/src/SFML/Window/OSX/SFKeyboardModifiersHelper.h @@ -56,7 +56,8 @@ void initialiseKeyboardHelper(void); /// \brief Set up a SFML key event based on the given modifiers flags and key code /// //////////////////////////////////////////////////////////// -sf::Event::KeyEvent keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key); +sf::Event::KeyEvent keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key, + sf::Keyboard::Scancode code); //////////////////////////////////////////////////////////// diff --git a/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm b/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm index 80494a4cd..1f74c511c 100644 --- a/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm +++ b/src/SFML/Window/OSX/SFKeyboardModifiersHelper.mm @@ -100,6 +100,7 @@ BOOL isKeyMaskActive(NSUInteger modifiers, NSUInteger mask); //////////////////////////////////////////////////////////// void processOneModifier(NSUInteger modifiers, NSUInteger mask, BOOL& wasDown, sf::Keyboard::Key key, + sf::Keyboard::Scancode code, sf::priv::WindowImplCocoa& requester); @@ -113,6 +114,7 @@ void processLeftRightModifiers(NSUInteger modifiers, NSUInteger leftMask, NSUInteger rightMask, BOOL& leftWasDown, BOOL& rightWasDown, sf::Keyboard::Key leftKey, sf::Keyboard::Key rightKey, + sf::Keyboard::Scancode leftCode, sf::Keyboard::Scancode rightCode, sf::priv::WindowImplCocoa& requester); @@ -144,14 +146,15 @@ void initialiseKeyboardHelper(void) //////////////////////////////////////////////////////// -sf::Event::KeyEvent keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key) +sf::Event::KeyEvent keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key, sf::Keyboard::Scancode code) { sf::Event::KeyEvent event; - event.code = key; - event.alt = modifiers & NSAlternateKeyMask; - event.control = modifiers & NSControlKeyMask; - event.shift = modifiers & NSShiftKeyMask; - event.system = modifiers & NSCommandKeyMask; + event.code = key; + event.scancode = code; + event.alt = modifiers & NSAlternateKeyMask; + event.control = modifiers & NSControlKeyMask; + event.shift = modifiers & NSShiftKeyMask; + event.system = modifiers & NSCommandKeyMask; return event; } @@ -166,6 +169,7 @@ void handleModifiersChanged(NSUInteger modifiers, sf::priv::WindowImplCocoa& req NSLeftShiftKeyMask, NSRightShiftKeyMask, state.leftShiftWasDown, state.rightShiftWasDown, sf::Keyboard::LShift, sf::Keyboard::RShift, + sf::Keyboard::sLShift, sf::Keyboard::sRShift, requester ); @@ -175,6 +179,7 @@ void handleModifiersChanged(NSUInteger modifiers, sf::priv::WindowImplCocoa& req NSLeftCommandKeyMask, NSRightCommandKeyMask, state.leftCommandWasDown, state.rightCommandWasDown, sf::Keyboard::LSystem, sf::Keyboard::RSystem, + sf::Keyboard::sLSystem, sf::Keyboard::sRSystem, requester ); @@ -184,6 +189,7 @@ void handleModifiersChanged(NSUInteger modifiers, sf::priv::WindowImplCocoa& req NSLeftAlternateKeyMask, NSRightAlternateKeyMask, state.leftAlternateWasDown, state.rightAlternateWasDown, sf::Keyboard::LAlt, sf::Keyboard::RAlt, + sf::Keyboard::sLAlt, sf::Keyboard::sRAlt, requester ); @@ -193,6 +199,7 @@ void handleModifiersChanged(NSUInteger modifiers, sf::priv::WindowImplCocoa& req NSLeftControlKeyMask, NSRightControlKeyMask, state.leftControlWasDown, state.rightControlWasDown, sf::Keyboard::LControl, sf::Keyboard::RControl, + sf::Keyboard::sLControl, sf::Keyboard::sRControl, requester ); } @@ -211,10 +218,11 @@ BOOL isKeyMaskActive(NSUInteger modifiers, NSUInteger mask) //////////////////////////////////////////////////////// void processOneModifier(NSUInteger modifiers, NSUInteger mask, BOOL& wasDown, sf::Keyboard::Key key, + sf::Keyboard::Scancode code, sf::priv::WindowImplCocoa& requester) { // Setup a potential event key. - sf::Event::KeyEvent event = keyEventWithModifiers(modifiers, key); + sf::Event::KeyEvent event = keyEventWithModifiers(modifiers, key, code); // State BOOL isDown = isKeyMaskActive(modifiers, mask); @@ -239,10 +247,11 @@ void processLeftRightModifiers(NSUInteger modifiers, NSUInteger leftMask, NSUInteger rightMask, BOOL& leftWasDown, BOOL& rightWasDown, sf::Keyboard::Key leftKey, sf::Keyboard::Key rightKey, + sf::Keyboard::Scancode leftCode, sf::Keyboard::Scancode rightCode, sf::priv::WindowImplCocoa& requester) { - processOneModifier(modifiers, leftMask, leftWasDown, leftKey, requester); - processOneModifier(modifiers, rightMask, rightWasDown, rightKey, requester); + processOneModifier(modifiers, leftMask, leftWasDown, leftKey, leftCode, requester); + processOneModifier(modifiers, rightMask, rightWasDown, rightKey, rightCode, requester); } diff --git a/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm b/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm index d03f419b7..4c0f8883f 100644 --- a/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm +++ b/src/SFML/Window/OSX/SFOpenGLView+keyboard.mm @@ -94,7 +94,7 @@ { sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; - if (key.code != sf::Keyboard::Unknown) // The key is recognized. + if ((key.code != sf::Keyboard::Unknown) || (key.scancode != sf::Keyboard::sUnknown)) m_requester->keyDown(key); } @@ -188,21 +188,17 @@ //////////////////////////////////////////////////////// +(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event { - // Key code - sf::Keyboard::Key key = sf::Keyboard::Unknown; - - // First we look if the key down is from a list of characters - // that depend on keyboard localization. + // We look for the key in a list of characters that depend on keyboard localization, + // if the key is not "dead". NSString* string = [event charactersIgnoringModifiers]; - if ([string length] > 0) - key = sf::priv::HIDInputManager::localizedKeys([string characterAtIndex:0]); + sf::Keyboard::Key key = ([string length] > 0) + ? sf::priv::HIDInputManager::localizedKey([string characterAtIndex:0]) + : sf::Keyboard::Unknown; - // If the key is not a localized one, we try to find a corresponding code - // through virtual key code. - if (key == sf::Keyboard::Unknown) - key = sf::priv::HIDInputManager::nonLocalizedKeys([event keyCode]); + // The scancode always depends on the hardware keyboard, not some OS setting. + sf::Keyboard::Scancode code = sf::priv::HIDInputManager::nonLocalizedKey([event keyCode]); - return keyEventWithModifiers([event modifierFlags], key); + return keyEventWithModifiers([event modifierFlags], key, code); }