Revamp the macOS implementation of scancodes

- Describe keys in separate words when applicable on macOS
- Use "Option" instead of "Alt" to describe keys on macOS
- Filter key up events like key down events
- Use localize to generate keyboard events
  That is better than translating to text because several keys can
  generate the same text.
- Add fallback mapping for NumpadEnter
- Handle swapped virtual key codes with ISO keyboard
This commit is contained in:
kimci86 2022-09-21 20:46:30 +02:00 committed by Lukas Dürrenberger
parent 89ea3af65e
commit 1cbd6e9d12
3 changed files with 996 additions and 949 deletions

View File

@ -89,7 +89,7 @@ public:
static CFDictionaryRef copyDevicesMask(UInt32 page, UInt32 usage); static CFDictionaryRef copyDevicesMask(UInt32 page, UInt32 usage);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Try to convert a character into a SFML key code. /// \brief Try to convert a character into a SFML key code
/// ///
/// Return sf::Keyboard::Unknown if it doesn't match any 'localized' keys. /// Return sf::Keyboard::Unknown if it doesn't match any 'localized' keys.
/// ///
@ -102,7 +102,7 @@ public:
static Keyboard::Key localizedKey(UniChar ch); static Keyboard::Key localizedKey(UniChar ch);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Opposite transformation as localizedKeys /// \brief Opposite transformation as localizedKeys
/// ///
/// Return 0x00 (NULL) for non-convertible keys/numpad numbers. /// Return 0x00 (NULL) for non-convertible keys/numpad numbers.
/// For letters, uppercase codes are returned. /// For letters, uppercase codes are returned.
@ -112,7 +112,7 @@ public:
static UniChar toUnicode(Keyboard::Key key); static UniChar toUnicode(Keyboard::Key key);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Try to convert a virtual keycode (HID level) into a /// \brief Try to convert a virtual keycode (HID level) into a
/// SFML scancode. /// SFML scancode.
/// ///
/// Return sf::Keyboard::Scan::Unknown if the keycode is unknown. /// Return sf::Keyboard::Scan::Unknown if the keycode is unknown.
@ -152,14 +152,6 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
String getDescription(Keyboard::Scancode code); String getDescription(Keyboard::Scancode code);
////////////////////////////////////////////////////////////
/// Regenerate the mappings from/to Key and Scancode.
///
/// This function is public to allow regular update calls
/// from the manager in case there's a keyboard layout change.
///
////////////////////////////////////////////////////////////
void buildMappings();
private: private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -213,6 +205,19 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void loadKey(IOHIDElementRef key); void loadKey(IOHIDElementRef key);
////////////////////////////////////////////////////////////
/// \brief Regenerate the mappings from/to Key and Scancode
///
////////////////////////////////////////////////////////////
void buildMappings();
////////////////////////////////////////////////////////////
/// \brief Callback to regenerate mappings from/to Key and
/// Scancode when there's a keyboard layout change
///
////////////////////////////////////////////////////////////
static void keyboardChanged(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Release all resources /// \brief Release all resources
/// ///
@ -275,9 +280,9 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
IOHIDManagerRef m_manager; ///< Underlying HID Manager IOHIDManagerRef m_manager; ///< Underlying HID Manager
IOHIDElements m_keys[Keyboard::Scan::ScancodeCount]; ///< All the keys on any connected keyboard IOHIDElements m_keys[Keyboard::Scan::ScancodeCount]; ///< All the keys on any connected keyboard
Keyboard::Scancode m_keyToScancodeMapping[Keyboard::KeyCount]; ///< Mapping from Key to Scancode Keyboard::Scancode m_keyToScancodeMapping[Keyboard::KeyCount]; ///< Mapping from Key to Scancode
Keyboard::Key m_scancodeToKeyMapping[Keyboard::Scan::ScancodeCount]; ///< Mapping from Scancode to Key Keyboard::Key m_scancodeToKeyMapping[Keyboard::Scan::ScancodeCount]; ///< Mapping from Scancode to Key
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -288,7 +293,7 @@ private:
/// HID keys. /// HID keys.
/// ///
/// The mappings (both directions) get invalidated when the /// The mappings (both directions) get invalidated when the
/// keyboard layout changes. They both default to (s)Unknown. /// keyboard layout changes. They both default to (Scan::)Unknown.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
}; };

File diff suppressed because it is too large Load Diff

View File

@ -166,7 +166,7 @@
sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; 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::Scan::Unknown))
m_requester->keyUp(key); m_requester->keyUp(key);
} }
@ -188,16 +188,12 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
+(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event +(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event
{ {
// 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];
sf::Keyboard::Key key = ([string length] > 0)
? sf::priv::HIDInputManager::localizedKey([string characterAtIndex:0])
: sf::Keyboard::Unknown;
// The scancode always depends on the hardware keyboard, not some OS setting. // The scancode always depends on the hardware keyboard, not some OS setting.
sf::Keyboard::Scancode code = sf::priv::HIDInputManager::nonLocalizedKey([event keyCode]); sf::Keyboard::Scancode code = sf::priv::HIDInputManager::nonLocalizedKey([event keyCode]);
// Get the corresponding key under the current keyboard layout.
sf::Keyboard::Key key = sf::Keyboard::localize(code);
return keyEventWithModifiers([event modifierFlags], key, code); return keyEventWithModifiers([event modifierFlags], key, code);
} }