Add support of scancodes for macOS
This commit is contained in:
parent
75ef99e2ca
commit
e806048904
@ -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.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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*/)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user