diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 698682e2..c7436701 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -66,11 +66,11 @@ else() # MACOSX ${SRCROOT}/OSX/cpp_objc_conversion.h ${SRCROOT}/OSX/cpp_objc_conversion.mm ${SRCROOT}/OSX/cg_sf_conversion.hpp - ${SRCROOT}/OSX/cg_sf_conversion.cpp - ${SRCROOT}/OSX/Joystick.cpp - ${SRCROOT}/OSX/Joystick.hpp - ${SRCROOT}/OSX/InputImpl.cpp - ${SRCROOT}/OSX/InputImpl.hpp + ${SRCROOT}/OSX/cg_sf_conversion.cpp + ${SRCROOT}/OSX/InputImpl.mm + ${SRCROOT}/OSX/InputImpl.hpp + ${SRCROOT}/OSX/HIDInputManager.hpp + ${SRCROOT}/OSX/HIDInputManager.mm ${SRCROOT}/OSX/JoystickImpl.cpp ${SRCROOT}/OSX/JoystickImpl.hpp ${SRCROOT}/OSX/SFApplication.h @@ -107,7 +107,7 @@ if(WINDOWS) elseif(LINUX) set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} ${X11_X11_LIB} ${X11_Xrandr_LIB}) elseif(MACOSX) - set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} "-framework Foundation -framework AppKit -framework IOKit") + set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} "-framework Foundation -framework AppKit -framework IOKit -framework Carbon") endif() # define the sfml-window target diff --git a/src/SFML/Window/OSX/AutoreleasePoolWrapper.h b/src/SFML/Window/OSX/AutoreleasePoolWrapper.h index 2a67f1b7..47197877 100644 --- a/src/SFML/Window/OSX/AutoreleasePoolWrapper.h +++ b/src/SFML/Window/OSX/AutoreleasePoolWrapper.h @@ -23,6 +23,21 @@ // //////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +/// \brief Ensure at least one autorelease pool is available on this thread. +/// +/// Increment a retain count. +/// See SPECIAL CONSIDERATION in implementation file. +/// +//////////////////////////////////////////////////////////// void RetainPool(void); + +//////////////////////////////////////////////////////////// +/// \brief Release the pool. +/// +/// Drain the pool if it is no more needed (retain count is zero). +/// See SPECIAL CONSIDERATION in implementation file. +/// +//////////////////////////////////////////////////////////// void ReleasePool(void); diff --git a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm index 3391562c..854f44ff 100644 --- a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm +++ b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm @@ -23,102 +23,172 @@ // //////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// #include +#include #include -#import "AutoreleasePoolWrapper.h" + #import +#import -// Here we manage one and only one pool by thread. This prevents draining one -// pool and making other pools invalid which can lead to a crash on 10.5 and an -// annoying message on 10.6 (*** attempt to pop an unknown autorelease pool). -// Because NSAutoreleasePool cannot be retain we have to do it ourself. -// We use an sf::ThreadLocalPtr to have one PoolWrapper in each thread. +//////////////////////////////////////////////////////////// +/// Here we manage one and only one pool by thread. This prevents draining one +/// pool and making other pools invalid which can lead to a crash on 10.5 and an +/// annoying message on 10.6 (*** attempt to pop an unknown autorelease pool). +/// +/// Because NSAutoreleasePool cannot be retain we have to do it ourself. +/// We use an sf::ThreadLocalPtr to have one PoolWrapper in each thread. +/// +/// SPECIAL CONSIDERATION : +/// ======================= +/// This implies that if RetainPool is called X times in a thread Y then +/// ReleasePool must be called X times too in the same thread Y. +/// +//////////////////////////////////////////////////////////// -// This implies that if RetainPool is called X times in a thread Y then -// ReleasePool must be called X times too in the same thread Y. - -class PoolWrapper { -public: - PoolWrapper() - : count(0) - , pool(0) - { - /* Nothing else */ - } +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief C++ Wrapper of Obj-C Autorelease Pool. +/// +//////////////////////////////////////////////////////////// +class PoolWrapper : NonCopyable { +public : - ~PoolWrapper() - { -#ifdef SFML_DEBUG - if (count < 0) { - sf::Err() << "~PoolWrapper : count is less than zero! " - "You called ReleasePool from a thread too many times." - << std::endl; - } else if (count > 0) { - sf::Err() << "~PoolWrapper : count is greater than zero! " - "You called ReleasePool from a thread to few times." - << std::endl; - } else { // count == 0 - sf::Err() << "~PoolWrapper is HAPPY!" << std::endl; - } -#endif - } + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + PoolWrapper(); - void Retain() - { - // Increase counter. - ++count; - - // Allocate pool if required. - if (pool == 0) { - pool = [[NSAutoreleasePool alloc] init]; - } - -#ifdef SFML_DEBUG - if (count <= 0) { - sf::Err() << "PoolWrapper::Retain : count <= 0! " << std::endl; - } -#endif - } + //////////////////////////////////////////////////////////// + /// \brief Default destructor + /// + //////////////////////////////////////////////////////////// + ~PoolWrapper(); - void Release() - { - // Decrease counter. - --count; - - // Drain pool if required. - if (count == 0) { - [pool drain]; - pool = 0; - } - -#ifdef SFML_DEBUG - if (count < 0) { - sf::Err() << "PoolWrapper::Release : count < 0! " << std::endl; - } -#endif - } + //////////////////////////////////////////////////////////// + /// \brief Increment retain count and allocate memory if needed + /// + //////////////////////////////////////////////////////////// + void Retain(); + //////////////////////////////////////////////////////////// + /// \brief Decrement retain count and releasing memory if needed + /// + //////////////////////////////////////////////////////////// + void Release(); private: - int count; ///< How many times the pool was retained ? - NSAutoreleasePool* pool; ///< Our pool. + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + int count; ///< How many times was the pool retained ? + NSAutoreleasePool* pool; ///< Our dedicated pool }; -// Thread shared variable but with local-only shared content. -sf::ThreadLocalPtr localPool; +//////////////////////////////////////////////////////////// +PoolWrapper::PoolWrapper() +: count(0) +, pool(0) +{ + /* Nothing else */ +} + + +//////////////////////////////////////////////////////////// +PoolWrapper::~PoolWrapper() +{ +#ifdef SFML_DEBUG + if (count < 0) { + sf::Err() << "~PoolWrapper : count is less than zero! " + "You called ReleasePool from a thread too many times." + << std::endl; + } else if (count > 0) { + sf::Err() << "~PoolWrapper : count is greater than zero! " + "You called ReleasePool from a thread to few times." + << std::endl; + } else { // count == 0 + sf::Err() << "~PoolWrapper is HAPPY!" << std::endl; + } +#endif +} + + +//////////////////////////////////////////////////////////// +void PoolWrapper::Retain() +{ + // Increase counter. + ++count; + + // Allocate pool if required. + if (pool == 0) { + pool = [[NSAutoreleasePool alloc] init]; + } + +#ifdef SFML_DEBUG + if (count <= 0) { + sf::Err() << "PoolWrapper::Retain : count <= 0! " << std::endl; + } +#endif +} + + +//////////////////////////////////////////////////////////// +void PoolWrapper::Release() +{ + // Decrease counter. + --count; + + // Drain pool if required. + if (count == 0) { + [pool drain]; + pool = 0; + } + +#ifdef SFML_DEBUG + if (count < 0) { + sf::Err() << "PoolWrapper::Release : count < 0! " << std::endl; + } +#endif +} + + +} // namespace priv + +} // namespace sf + +//////////////////////////////////////////////////////////// +// Private data +//////////////////////////////////////////////////////////// +namespace +{ + // This per-thread variable holds the current autorelease pool for each thread + sf::ThreadLocalPtr localPool; +} + + +//////////////////////////////////////////////////////////// void RetainPool(void) { // First, Check that we have a valid PoolWrapper object in our local pool. if (localPool == NULL) { - localPool = new PoolWrapper(); + localPool = new sf::priv::PoolWrapper(); } // Then retains! localPool->Retain(); } + +//////////////////////////////////////////////////////////// void ReleasePool(void) { #ifdef SFML_DEBUG @@ -136,3 +206,4 @@ void ReleasePool(void) } #endif } + diff --git a/src/SFML/Window/OSX/HIDInputManager.hpp b/src/SFML/Window/OSX/HIDInputManager.hpp new file mode 100644 index 00000000..e6e13ad9 --- /dev/null +++ b/src/SFML/Window/OSX/HIDInputManager.hpp @@ -0,0 +1,253 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent.gom@gmail.com), +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_HIDINPUTMANAGER_HPP +#define SFML_HIDINPUTMANAGER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief This class manage as a singleton instance the +/// keyboard and mouse states. It's only purpose is +/// to help sf::priv::InputImpl class. +/// +/// sf::priv::JoystickImpl is not concerned by this class. +/// +//////////////////////////////////////////////////////////// +class HIDInputManager : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Get the unique instance of the class + /// + /// \note Private use only + /// + /// \return Reference to the HIDInputManager instance + /// + //////////////////////////////////////////////////////////// + static HIDInputManager& GetInstance(); + + //////////////////////////////////////////////////////////// + /// \brief Check if a key is pressed + /// + /// \param key Key to check + /// + /// \return True if the key is pressed, false otherwise + /// + //////////////////////////////////////////////////////////// + bool IsKeyPressed(Keyboard::Key key); + + //////////////////////////////////////////////////////////// + /// \brief Check if a mouse button is pressed + /// + /// \param button Button to check + /// + /// \return True if the button is pressed, false otherwise + /// + //////////////////////////////////////////////////////////// + bool IsMouseButtonPressed(Mouse::Button button); + + //////////////////////////////////////////////////////////// + /// Try to convert a character into a SFML key code. + /// + /// Return sf::Keyboard::KeyCount if it doesn't match any 'localized' keys. + /// + /// By 'localized' I mean keys that depend on the keyboard layout + /// and might not be the same as the US keycode in some country + /// (e.g. the keys 'Y' and 'Z' are switched on QWERTZ keyboard and + /// US keyboard layouts.) + /// + //////////////////////////////////////////////////////////// + static Keyboard::Key LocalizedKeys(UniChar ch); + + //////////////////////////////////////////////////////////// + /// Try to convert a virtual keycode into a SFML key code. + /// + /// Return sf::Keyboard::KeyCount if the keycode is unknown. + /// + //////////////////////////////////////////////////////////// + static Keyboard::Key NonLocalizedKeys(UniChar virtualKeycode); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + HIDInputManager(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~HIDInputManager(); + + //////////////////////////////////////////////////////////// + /// \brief Initialize the keyboard part of this class + /// + /// If something went wrong FreeUp is called + /// + //////////////////////////////////////////////////////////// + void InitializeKeyboard(); + + //////////////////////////////////////////////////////////// + /// \brief Initialize the mouse part of this class + /// + /// If something went wrong FreeUp is called + /// + //////////////////////////////////////////////////////////// + void InitializeMouse(); + + //////////////////////////////////////////////////////////// + /// \brief Load the given keyboard into myKeys + /// + /// If the given keyboard has no key this function simply + /// returns. FreeUp is _not_ called because this is not fatal. + /// + /// \param keyboard Keyboard to load + /// + //////////////////////////////////////////////////////////// + void LoadKeyboard(IOHIDDeviceRef keyboard); + + //////////////////////////////////////////////////////////// + /// \brief Load the given mouse into myButtons + /// + /// If the given mouse has no button this function simply + /// returns. FreeUp is _not_ called because this is not fatal. + /// + /// \param mouse Mouse to load + /// + //////////////////////////////////////////////////////////// + void LoadMouse(IOHIDDeviceRef mouse); + + //////////////////////////////////////////////////////////// + /// \brief Load the given key into myKeys + /// + /// FreeUp is _not_ called by this function. + /// + /// \param key Key to load + /// + //////////////////////////////////////////////////////////// + void LoadKey(IOHIDElementRef key); + + //////////////////////////////////////////////////////////// + /// \brief Load the given button into myButtons + /// + /// FreeUp is _not_ called by this function. + /// + /// \param button Button to load + /// + //////////////////////////////////////////////////////////// + void LoadButton(IOHIDElementRef button); + + //////////////////////////////////////////////////////////// + /// \brief Release all resources + /// + /// Close all connections to any devices, if required + /// Set amIValid to false + /// + //////////////////////////////////////////////////////////// + void FreeUp(); + + //////////////////////////////////////////////////////////// + /// \brief Create a mask (dictionary) for an IOHIDManager + /// + /// \param page HID page + /// \param usage HID usage page + /// \return a retained CFDictionaryRef + /// + //////////////////////////////////////////////////////////// + static CFDictionaryRef CopyDevicesMaskForManager(UInt32 page, UInt32 usage); + + //////////////////////////////////////////////////////////// + /// \brief Filter the devices and return them. + /// + /// If something went wrong FreeUp is called + /// + /// \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 + /// + //////////////////////////////////////////////////////////// + CFSetRef CopyDevices(UInt32 page, UInt32 usage); + + //////////////////////////////////////////////////////////// + /// \brief Converte a HID key usage to its corresponding virtual code + /// + /// See IOHIDUsageTables.h + /// + /// \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 + /// + //////////////////////////////////////////////////////////// + static UInt8 UsageToVirtualCode(UInt32 usage); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + bool amIValid; ///< If any error occurs this variable is false + CFDataRef myLayoutData; ///< CFData containing the layout + UCKeyboardLayout* myLayout; ///< Current Keyboard Layout + IOHIDManagerRef myManager; ///< HID Manager + + typedef std::vector IOHIDElements; + IOHIDElements myKeys[Keyboard::KeyCount]; ///< All the keys on any connected keyboard + IOHIDElements myButtons[Mouse::ButtonCount];///< All the buttons on any connected mouse + + //////////////////////////////////////////////////////////// + /// myKeys' index corresponds to sf::Keyboard::Key enum. + /// if no key is assigned with key XYZ then myKeys[XYZ].size() == 0. + /// if there are several keyboards connected and several HID keys associate + /// with the same sf::Keyboard::Key then myKeys[XYZ] contains all these + /// HID keys. + /// + /// myButtons works the same way. + /// + //////////////////////////////////////////////////////////// +}; + +} // namespace priv + +} // namespace sf + +#endif \ No newline at end of file diff --git a/src/SFML/Window/OSX/HIDInputManager.mm b/src/SFML/Window/OSX/HIDInputManager.mm new file mode 100644 index 00000000..a8118db8 --- /dev/null +++ b/src/SFML/Window/OSX/HIDInputManager.mm @@ -0,0 +1,1015 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent.gom@gmail.com), +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +HIDInputManager& HIDInputManager::GetInstance() +{ + static HIDInputManager instance; + return instance; +} + + +//////////////////////////////////////////////////////////// +bool HIDInputManager::IsKeyPressed(Keyboard::Key key) +{ + if (!amIValid) { + sf::Err() << "HIDInputManager is invalid." << std::endl; + return false; + } + + // state = true if at least one corresponding HID key is pressed + bool state = false; + + for (IOHIDElements::iterator it = myKeys[key].begin(); it != myKeys[key].end(); ++it) { + + IOHIDValueRef value = 0; + + IOHIDDeviceRef device = IOHIDElementGetDevice(*it); + IOHIDDeviceGetValue(device, *it, &value); + + if (!value) { + + // This means some kind of error / deconnection so we remove this + // element from our keys + + CFRelease(*it); + it = myKeys[key].erase(it); + + } else if (IOHIDValueGetIntegerValue(value) == 1) { + + // This means the key is pressed + state = true; + break; // Stop here + + } else { + + // This means the key is released + } + + } + + return state; +} + + +//////////////////////////////////////////////////////////// +bool HIDInputManager::IsMouseButtonPressed(Mouse::Button button) +{ + if (!amIValid) { + sf::Err() << "HIDInputManager is invalid." << std::endl; + return false; + } + + // state = true if at least one corresponding HID button is pressed + bool state = false; + + for (IOHIDElements::iterator it = myButtons[button].begin(); it != myButtons[button].end(); ++it) { + + IOHIDValueRef value = 0; + + IOHIDDeviceRef device = IOHIDElementGetDevice(*it); + IOHIDDeviceGetValue(device, *it, &value); + + if (!value) { + + // This means some kind of error / deconnection so we remove this + // element from our buttons + + CFRelease(*it); + it = myButtons[button].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 + } + + } + + return state; +} + + +//////////////////////////////////////////////////////////// +HIDInputManager::HIDInputManager() +: amIValid(true) +, myLayoutData(0) +, myLayout(0) +, myManager(0) +{ + // Get the current keyboard layout + TISInputSourceRef tis = TISCopyCurrentKeyboardLayoutInputSource(); + myLayoutData = (CFDataRef)TISGetInputSourceProperty(tis, + kTISPropertyUnicodeKeyLayoutData); + + if (myLayoutData == 0) { + sf::Err() << "Cannot get the keyboard layout" << std::endl; + FreeUp(); + return; + } + + // Keep a reference for ourself + CFRetain(myLayoutData); + myLayout = (UCKeyboardLayout *)CFDataGetBytePtr(myLayoutData); + + // The TIS is no more needed + CFRelease(tis); + + // Create an HID Manager reference + myManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + + // Open the HID Manager reference + IOReturn openStatus = IOHIDManagerOpen(myManager, kIOHIDOptionsTypeNone); + + if (openStatus != kIOReturnSuccess) { + sf::Err() << "Error when opening the HID manager" << std::endl; + + FreeUp(); + return; + } + + // Initialize the keyboard + InitializeKeyboard(); + + if (!amIValid) { + return; // Something went wrong + } + + // Initialize the mouse + InitializeMouse(); + + if (!amIValid) { + return; // Something went wrong + } +} + + +//////////////////////////////////////////////////////////// +HIDInputManager::~HIDInputManager() +{ + FreeUp(); +} + + +void HIDInputManager::InitializeKeyboard() +{ + //////////////////////////////////////////////////////////// + // The purpose of this function is to initalize myKeys so we can get + // the associate IOHIDElementRef with a sf::Keyboard::Key in ~constant~ time. + + // Get only keyboards + CFSetRef keyboards = CopyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard); + if (keyboards == NULL) { + + // FreeUp was already called + return; + } + + CFIndex keyboardCount = CFSetGetCount(keyboards); // >= 1 (asserted by CopyDevices) + + // Get an iterable array + CFTypeRef devicesArray[keyboardCount]; + CFSetGetValues(keyboards, devicesArray); + + for (CFIndex i = 0; i < keyboardCount; ++i) { + + IOHIDDeviceRef keyboard = (IOHIDDeviceRef)devicesArray[i]; + + LoadKeyboard(keyboard); + } + + // Release unused stuff + CFRelease(keyboards); + + //////////////////////////////////////////////////////////// + // At this point myKeys is filled with as many IOHIDElementRef as possible +} + + +//////////////////////////////////////////////////////////// +void HIDInputManager::InitializeMouse() +{ + //////////////////////////////////////////////////////////// + // The purpose of this function is to initalize myButtons so we can get + // the associate IOHIDElementRef with a sf::Mouse::Button in ~constant~ time. + + // Get only mouses + CFSetRef mouses = CopyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse); + if (mouses == NULL) { + + // FreeUp was already called + return; + } + + CFIndex mouseCount = CFSetGetCount(mouses); // >= 1 (asserted by CopyDevices) + + // Get an iterable array + CFTypeRef devicesArray[mouseCount]; + CFSetGetValues(mouses, devicesArray); + + for (CFIndex i = 0; i < mouseCount; ++i) { + + IOHIDDeviceRef mouse = (IOHIDDeviceRef)devicesArray[i]; + + LoadMouse(mouse); + } + + // Release unused stuff + CFRelease(mouses); + + //////////////////////////////////////////////////////////// + // At this point myButtons is filled with as many IOHIDElementRef as possible +} + + +//////////////////////////////////////////////////////////// +void HIDInputManager::LoadKeyboard(IOHIDDeviceRef keyboard) +{ + CFArrayRef keys = IOHIDDeviceCopyMatchingElements(keyboard, + NULL, + kIOHIDOptionsTypeNone); + if (keys == NULL) { + sf::Err() << "We got a keyboard without any keys (1)" << std::endl; + return; + } + + // How many elements are there ? + CFIndex keysCount = CFArrayGetCount(keys); + + if (keysCount == 0) { + sf::Err() << "We got a keyboard without any keys (2)" << std::endl; + CFRelease(keys); + return; + } + + // Go through all connected elements. + for (CFIndex i = 0; i < keysCount; ++i) { + + IOHIDElementRef aKey = (IOHIDElementRef) CFArrayGetValueAtIndex(keys, i); + + // Skip non-matching keys elements + if (IOHIDElementGetUsagePage(aKey) != kHIDPage_KeyboardOrKeypad) { + continue; + } + + LoadKey(aKey); + + } + + // Release unused stuff + CFRelease(keys); +} + + +//////////////////////////////////////////////////////////// +void HIDInputManager::LoadMouse(IOHIDDeviceRef mouse) +{ + CFArrayRef buttons = IOHIDDeviceCopyMatchingElements(mouse, + NULL, + kIOHIDOptionsTypeNone); + if (buttons == NULL) { + sf::Err() << "We got a mouse without any buttons (1)" << std::endl; + return; + } + + // How many elements are there ? + CFIndex buttonCount = CFArrayGetCount(buttons); + + if (buttonCount == 0) { + sf::Err() << "We got a mouse without any buttons (2)" << std::endl; + CFRelease(buttons); + return; + } + + // Go through all connected elements. + for (CFIndex i = 0; i < buttonCount; ++i) { + + IOHIDElementRef aButton = (IOHIDElementRef) CFArrayGetValueAtIndex(buttons, i); + + // Skip non-matching keys elements + if (IOHIDElementGetUsagePage(aButton) != kHIDPage_Button) { + continue; + } + + LoadButton(aButton); + } + + // Release unused stuff + CFRelease(buttons); +} + + +//////////////////////////////////////////////////////////// +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; + UniChar unicodeString[maxStringLength]; + + OSStatus error; + + error = UCKeyTranslate(myLayout, // current layout + virtualCode, // our key + kUCKeyActionDown, // or kUCKeyActionUp ? + 0x100, // no modifiers + LMGetKbdType(), // keyboard's type + kUCKeyTranslateNoDeadKeysBit,// some sort of option + &deadKeyState, // unused stuff + maxStringLength, // our memory limit + &actualStringLength, // length of what we get + unicodeString); // what we get + + if (error == noErr) { + // Translation went fine + + // The corresponding SFML key code + Keyboard::Key code = Keyboard::KeyCount; // 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]); + } + + // The key is not a localized one so we try to find a + // corresponding code through virtual key code + if (code == Keyboard::KeyCount) { + code = NonLocalizedKeys(virtualCode); + } + + // A code was found, wonderful! + if (code != Keyboard::KeyCount) { + + // Ok, everything went fine. Now we have a unique + // corresponding sf::Keyboard::Key to one IOHIDElementRef + + myKeys[code].push_back(key); + + // And don't forget to keep the reference alive for our usage + CFRetain(myKeys[code].back()); + + } + + //////////////////////////////////////////////////////////// + // These are known to be unbound : + // Supposed Virtual | HID | Supposed Key + // =============================================== + // 0x1b | 0x2d | Hyphen + // 0x39 | 0x39 | CapsLock + // 0x47 | 0x53 | NumLock + // 0x4c | 0x58 | Keypad Enter + // 0x41 | 0x63 | Keypad Period + // 0x6e | 0x65 | Application + // 0x51 | 0x67 | Keypad Equal + // 0x4c | 0x77 | Select + + //if (code == Keyboard::KeyCount) { // The key is unknown. + // sf::Err() << "This is an unknow key. Virtual key code is 0x" + // << std::hex + // << (UInt32)virtualCode + // << " and HID usage code is 0x" + // << usageCode + // << std::dec + // << "." + // << std::endl; + //} + + } /* if (error == noErr) */ + else { + + sf::Err() << "Cannot translate the virtual key code, error : " + << error + << std::endl; + } +} + + +//////////////////////////////////////////////////////////// +void HIDInputManager::LoadButton(IOHIDElementRef button) +{ + // Identify the button + UInt32 usage = IOHIDElementGetUsage(button); + Mouse::Button dest = Mouse::ButtonCount; + + // Extends kHIDUsage_Button_* enum with : +#define kHIDUsage_Button_5 0x05 + + switch (usage) { + case kHIDUsage_Button_1: dest = Mouse::Left; break; + case kHIDUsage_Button_2: dest = Mouse::Right; break; + case kHIDUsage_Button_3: dest = Mouse::Middle; break; + case kHIDUsage_Button_4: dest = Mouse::XButton1; break; + case kHIDUsage_Button_5: dest = Mouse::XButton2; break; + default: dest = Mouse::ButtonCount; break; + } + + if (dest != Mouse::ButtonCount) { + // We know what kind of button it is! + + myButtons[dest].push_back(button); + + // And don't forget to keep the reference alive for our usage + CFRetain(myButtons[dest].back()); + } +} + + +//////////////////////////////////////////////////////////// +void HIDInputManager::FreeUp() +{ + amIValid = false; + + if (myLayoutData != 0) CFRelease(myLayoutData); + // Do not release myLayout ! It is owned by myLayoutData. + if (myManager != 0) CFRelease(myManager); + + for (unsigned int i = 0; i < Keyboard::KeyCount; ++i) { + for (IOHIDElements::iterator it = myKeys[i].begin(); it != myKeys[i].end(); ++it) { + CFRelease(*it); + } + myKeys[i].clear(); + } + + for (unsigned int i = 0; i < Mouse::ButtonCount; ++i) { + for (IOHIDElements::iterator it = myButtons[i].begin(); it != myButtons[i].end(); ++it) { + CFRelease(*it); + } + myButtons[i].clear(); + } +} + + +//////////////////////////////////////////////////////////// +CFDictionaryRef HIDInputManager::CopyDevicesMaskForManager(UInt32 page, UInt32 usage) +{ + // Create the dictionary. + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + // Add the page value. + CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page); + CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), value); + CFRelease(value); + + // Add the usage value (which is only valid if page value exists). + value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); + CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), value); + CFRelease(value); + + return dict; +} + + +//////////////////////////////////////////////////////////// +CFSetRef HIDInputManager::CopyDevices(UInt32 page, UInt32 usage) +{ + // Filter and keep only the requested devices + CFDictionaryRef mask = CopyDevicesMaskForManager(page, usage); + + IOHIDManagerSetDeviceMatching(myManager, mask); + + CFRelease(mask); + mask = 0; + + CFSetRef devices = IOHIDManagerCopyDevices(myManager); + if (devices == NULL) { + sf::Err() << "Cannot find any devices." << std::endl; + FreeUp(); + return NULL; + } + + // Is there at least one keyboard ? + CFIndex deviceCount = CFSetGetCount(devices); + if (deviceCount < 1) { + sf::Err() << "Found no device." << std::endl; + CFRelease(devices); + FreeUp(); + return NULL; + } + + return devices; +} + + +//////////////////////////////////////////////////////////// +UInt8 HIDInputManager::UsageToVirtualCode(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_KeyboardA: return 0x00; + case kHIDUsage_KeyboardB: return 0x0b; + case kHIDUsage_KeyboardC: return 0x08; + case kHIDUsage_KeyboardD: return 0x02; + case kHIDUsage_KeyboardE: return 0x0e; + case kHIDUsage_KeyboardF: return 0x03; + case kHIDUsage_KeyboardG: return 0x05; + case kHIDUsage_KeyboardH: return 0x04; + case kHIDUsage_KeyboardI: return 0x22; + case kHIDUsage_KeyboardJ: return 0x26; + case kHIDUsage_KeyboardK: return 0x28; + case kHIDUsage_KeyboardL: return 0x25; + case kHIDUsage_KeyboardM: return 0x2e; + case kHIDUsage_KeyboardN: return 0x2d; + case kHIDUsage_KeyboardO: return 0x1f; + case kHIDUsage_KeyboardP: return 0x23; + case kHIDUsage_KeyboardQ: return 0x0c; + case kHIDUsage_KeyboardR: return 0x0f; + case kHIDUsage_KeyboardS: return 0x01; + case kHIDUsage_KeyboardT: return 0x11; + case kHIDUsage_KeyboardU: return 0x20; + case kHIDUsage_KeyboardV: return 0x09; + case kHIDUsage_KeyboardW: return 0x0d; + case kHIDUsage_KeyboardX: return 0x07; + case kHIDUsage_KeyboardY: return 0x10; + case kHIDUsage_KeyboardZ: return 0x06; + + case kHIDUsage_Keyboard1: return 0x12; + case kHIDUsage_Keyboard2: return 0x13; + case kHIDUsage_Keyboard3: return 0x14; + case kHIDUsage_Keyboard4: return 0x15; + case kHIDUsage_Keyboard5: return 0x17; + case kHIDUsage_Keyboard6: return 0x16; + case kHIDUsage_Keyboard7: return 0x1a; + case kHIDUsage_Keyboard8: return 0x1c; + case kHIDUsage_Keyboard9: return 0x19; + case kHIDUsage_Keyboard0: return 0x1d; + + case kHIDUsage_KeyboardReturnOrEnter: return 0x24; + case kHIDUsage_KeyboardEscape: return 0x35; + case kHIDUsage_KeyboardDeleteOrBackspace: return 0x33; + case kHIDUsage_KeyboardTab: return 0x30; + case kHIDUsage_KeyboardSpacebar: return 0x31; + case kHIDUsage_KeyboardHyphen: return 0x1b; + case kHIDUsage_KeyboardEqualSign: return 0x18; + case kHIDUsage_KeyboardOpenBracket: return 0x21; + case kHIDUsage_KeyboardCloseBracket: return 0x1e; + case kHIDUsage_KeyboardBackslash: return 0x2a; + case kHIDUsage_KeyboardNonUSPound: return 0xff; + case kHIDUsage_KeyboardSemicolon: return 0x29; + case kHIDUsage_KeyboardQuote: return 0x27; + case kHIDUsage_KeyboardGraveAccentAndTilde: return 0x32; + case kHIDUsage_KeyboardComma: return 0x2b; + case kHIDUsage_KeyboardPeriod: return 0x2F; + case kHIDUsage_KeyboardSlash: return 0x2c; + case kHIDUsage_KeyboardCapsLock: return 0x39; + + case kHIDUsage_KeyboardF1: return 0x7a; + case kHIDUsage_KeyboardF2: return 0x78; + case kHIDUsage_KeyboardF3: return 0x63; + case kHIDUsage_KeyboardF4: return 0x76; + case kHIDUsage_KeyboardF5: return 0x60; + case kHIDUsage_KeyboardF6: return 0x61; + case kHIDUsage_KeyboardF7: return 0x62; + case kHIDUsage_KeyboardF8: return 0x64; + case kHIDUsage_KeyboardF9: return 0x65; + case kHIDUsage_KeyboardF10: return 0x6d; + case kHIDUsage_KeyboardF11: return 0x67; + case kHIDUsage_KeyboardF12: return 0x6f; + + case kHIDUsage_KeyboardPrintScreen: return 0xff; + case kHIDUsage_KeyboardScrollLock: return 0xff; + case kHIDUsage_KeyboardPause: return 0xff; + case kHIDUsage_KeyboardInsert: return 0x72; + case kHIDUsage_KeyboardHome: return 0x73; + case kHIDUsage_KeyboardPageUp: return 0x74; + case kHIDUsage_KeyboardDeleteForward: return 0x75; + case kHIDUsage_KeyboardEnd: return 0x77; + case kHIDUsage_KeyboardPageDown: return 0x79; + + case kHIDUsage_KeyboardRightArrow: return 0x7c; + case kHIDUsage_KeyboardLeftArrow: return 0x7b; + case kHIDUsage_KeyboardDownArrow: return 0x7d; + case kHIDUsage_KeyboardUpArrow: return 0x7e; + + case kHIDUsage_KeypadNumLock: return 0x47; + case kHIDUsage_KeypadSlash: return 0x4b; + case kHIDUsage_KeypadAsterisk: return 0x43; + case kHIDUsage_KeypadHyphen: return 0x4e; + case kHIDUsage_KeypadPlus: return 0x45; + case kHIDUsage_KeypadEnter: return 0x4c; + + case kHIDUsage_Keypad1: return 0x53; + case kHIDUsage_Keypad2: return 0x54; + case kHIDUsage_Keypad3: return 0x55; + case kHIDUsage_Keypad4: return 0x56; + case kHIDUsage_Keypad5: return 0x57; + case kHIDUsage_Keypad6: return 0x58; + case kHIDUsage_Keypad7: return 0x59; + case kHIDUsage_Keypad8: return 0x5b; + case kHIDUsage_Keypad9: return 0x5c; + case kHIDUsage_Keypad0: return 0x52; + + case kHIDUsage_KeypadPeriod: return 0x41; + case kHIDUsage_KeyboardNonUSBackslash: return 0xff; + case kHIDUsage_KeyboardApplication: return 0x6e; + case kHIDUsage_KeyboardPower: return 0xff; + case kHIDUsage_KeypadEqualSign: return 0x51; + + case kHIDUsage_KeyboardF13: return 0x69; + case kHIDUsage_KeyboardF14: return 0x6b; + case kHIDUsage_KeyboardF15: return 0x71; + case kHIDUsage_KeyboardF16: return 0xff; + case kHIDUsage_KeyboardF17: return 0xff; + case kHIDUsage_KeyboardF18: return 0xff; + case kHIDUsage_KeyboardF19: return 0xff; + case kHIDUsage_KeyboardF20: return 0xff; + case kHIDUsage_KeyboardF21: return 0xff; + case kHIDUsage_KeyboardF22: return 0xff; + case kHIDUsage_KeyboardF23: return 0xff; + case kHIDUsage_KeyboardF24: return 0xff; + + case kHIDUsage_KeyboardExecute: return 0xff; + case kHIDUsage_KeyboardHelp: return 0xff; + case kHIDUsage_KeyboardMenu: return 0x7F; + case kHIDUsage_KeyboardSelect: return 0x4c; + case kHIDUsage_KeyboardStop: return 0xff; + case kHIDUsage_KeyboardAgain: return 0xff; + case kHIDUsage_KeyboardUndo: return 0xff; + case kHIDUsage_KeyboardCut: return 0xff; + case kHIDUsage_KeyboardCopy: return 0xff; + case kHIDUsage_KeyboardPaste: return 0xff; + case kHIDUsage_KeyboardFind: return 0xff; + + case kHIDUsage_KeyboardMute: return 0xff; + case kHIDUsage_KeyboardVolumeUp: return 0xff; + case kHIDUsage_KeyboardVolumeDown: return 0xff; + + case kHIDUsage_KeyboardLockingCapsLock: return 0xff; + case kHIDUsage_KeyboardLockingNumLock: return 0xff; + case kHIDUsage_KeyboardLockingScrollLock: return 0xff; + + case kHIDUsage_KeypadComma: return 0xff; + case kHIDUsage_KeypadEqualSignAS400: return 0xff; + case kHIDUsage_KeyboardInternational1: return 0xff; + case kHIDUsage_KeyboardInternational2: return 0xff; + case kHIDUsage_KeyboardInternational3: return 0xff; + case kHIDUsage_KeyboardInternational4: return 0xff; + case kHIDUsage_KeyboardInternational5: return 0xff; + case kHIDUsage_KeyboardInternational6: return 0xff; + case kHIDUsage_KeyboardInternational7: return 0xff; + case kHIDUsage_KeyboardInternational8: return 0xff; + case kHIDUsage_KeyboardInternational9: return 0xff; + + case kHIDUsage_KeyboardLANG1: return 0xff; + case kHIDUsage_KeyboardLANG2: return 0xff; + case kHIDUsage_KeyboardLANG3: return 0xff; + case kHIDUsage_KeyboardLANG4: return 0xff; + case kHIDUsage_KeyboardLANG5: return 0xff; + case kHIDUsage_KeyboardLANG6: return 0xff; + case kHIDUsage_KeyboardLANG7: return 0xff; + case kHIDUsage_KeyboardLANG8: return 0xff; + case kHIDUsage_KeyboardLANG9: return 0xff; + + case kHIDUsage_KeyboardAlternateErase: return 0xff; + case kHIDUsage_KeyboardSysReqOrAttention: return 0xff; + case kHIDUsage_KeyboardCancel: return 0xff; + case kHIDUsage_KeyboardClear: return 0xff; + case kHIDUsage_KeyboardPrior: return 0xff; + case kHIDUsage_KeyboardReturn: return 0xff; + case kHIDUsage_KeyboardSeparator: return 0xff; + case kHIDUsage_KeyboardOut: return 0xff; + case kHIDUsage_KeyboardOper: return 0xff; + case kHIDUsage_KeyboardClearOrAgain: return 0xff; + case kHIDUsage_KeyboardCrSelOrProps: return 0xff; + case kHIDUsage_KeyboardExSel: return 0xff; + + /* 0xa5-0xdf Reserved */ + + case kHIDUsage_KeyboardLeftControl: return 0x3b; + case kHIDUsage_KeyboardLeftShift: return 0x38; + case kHIDUsage_KeyboardLeftAlt: return 0x3a; + case kHIDUsage_KeyboardLeftGUI: return 0x37; + case kHIDUsage_KeyboardRightControl: return 0x3e; + case kHIDUsage_KeyboardRightShift: return 0x3c; + case kHIDUsage_KeyboardRightAlt: return 0x3d; + case kHIDUsage_KeyboardRightGUI: return 0x36; + + /* 0xe8-0xffff Reserved */ + + case kHIDUsage_Keyboard_Reserved: return 0xff; + default: return 0xff; + } +} + + +//////////////////////////////////////////////////////// +Keyboard::Key HIDInputManager::LocalizedKeys(UniChar ch) +{ + switch (ch) { + case 'a': + case 'A': return sf::Keyboard::A; + + case 'b': + case 'B': return sf::Keyboard::B; + + case 'c': + case 'C': return sf::Keyboard::C; + + case 'd': + case 'D': return sf::Keyboard::D; + + case 'e': + case 'E': return sf::Keyboard::E; + + case 'f': + case 'F': return sf::Keyboard::F; + + case 'g': + case 'G': return sf::Keyboard::G; + + case 'h': + case 'H': return sf::Keyboard::H; + + case 'i': + case 'I': return sf::Keyboard::I; + + case 'j': + case 'J': return sf::Keyboard::J; + + case 'k': + case 'K': return sf::Keyboard::K; + + case 'l': + case 'L': return sf::Keyboard::L; + + case 'm': + case 'M': return sf::Keyboard::M; + + case 'n': + case 'N': return sf::Keyboard::N; + + case 'o': + case 'O': return sf::Keyboard::O; + + case 'p': + case 'P': return sf::Keyboard::P; + + case 'q': + case 'Q': return sf::Keyboard::Q; + + case 'r': + case 'R': return sf::Keyboard::R; + + case 's': + case 'S': return sf::Keyboard::S; + + case 't': + case 'T': return sf::Keyboard::T; + + case 'u': + case 'U': return sf::Keyboard::U; + + case 'v': + case 'V': return sf::Keyboard::V; + + case 'w': + case 'W': return sf::Keyboard::W; + + case 'x': + case 'X': return sf::Keyboard::X; + + case 'y': + case 'Y': return sf::Keyboard::Y; + + case 'z': + case 'Z': return sf::Keyboard::Z; + + // The key is not 'localized'. + default: return sf::Keyboard::KeyCount; + } +} + + +//////////////////////////////////////////////////////// +Keyboard::Key HIDInputManager::NonLocalizedKeys(UniChar virtualKeycode) +{ + // (Some) 0x code based on http://forums.macrumors.com/showthread.php?t=780577 + // Some sf::Keyboard::Key are present twice. + switch (virtualKeycode) { + // These cases should not be used but anyway... + case 0x00: return sf::Keyboard::A; + case 0x0b: return sf::Keyboard::B; + case 0x08: return sf::Keyboard::C; + case 0x02: return sf::Keyboard::D; + case 0x0e: return sf::Keyboard::E; + case 0x03: return sf::Keyboard::F; + case 0x05: return sf::Keyboard::G; + case 0x04: return sf::Keyboard::H; + case 0x22: return sf::Keyboard::I; + case 0x26: return sf::Keyboard::J; + case 0x28: return sf::Keyboard::K; + case 0x25: return sf::Keyboard::L; + case 0x2e: return sf::Keyboard::M; + case 0x2d: return sf::Keyboard::N; + case 0x1f: return sf::Keyboard::O; + case 0x23: return sf::Keyboard::P; + case 0x0c: return sf::Keyboard::Q; + case 0x0f: return sf::Keyboard::R; + case 0x01: return sf::Keyboard::S; + case 0x11: return sf::Keyboard::T; + case 0x20: return sf::Keyboard::U; + case 0x09: return sf::Keyboard::V; + case 0x0d: return sf::Keyboard::W; + case 0x07: return sf::Keyboard::X; + case 0x10: return sf::Keyboard::Y; + case 0x06: return sf::Keyboard::Z; + + // These cases should not be used but anyway... + case 0x1d: return sf::Keyboard::Num0; + case 0x12: return sf::Keyboard::Num1; + case 0x13: return sf::Keyboard::Num2; + case 0x14: return sf::Keyboard::Num3; + case 0x15: return sf::Keyboard::Num4; + case 0x17: return sf::Keyboard::Num5; + case 0x16: return sf::Keyboard::Num6; + case 0x1a: return sf::Keyboard::Num7; + case 0x1c: return sf::Keyboard::Num8; + case 0x19: return sf::Keyboard::Num9; + + case 0x35: return sf::Keyboard::Escape; + + // Modifier keys : never happen with keyDown/keyUp methods (?) + case 0x3b: return sf::Keyboard::LControl; + case 0x38: return sf::Keyboard::LShift; + case 0x3a: return sf::Keyboard::LAlt; + case 0x37: return sf::Keyboard::LSystem; + case 0x3e: return sf::Keyboard::RControl; + case 0x3c: return sf::Keyboard::RShift; + case 0x3d: return sf::Keyboard::RAlt; + case 0x36: return sf::Keyboard::RSystem; + + case 0x7f: return sf::Keyboard::Menu; + case NSMenuFunctionKey: return sf::Keyboard::Menu; + + case 0x21: return sf::Keyboard::LBracket; + case 0x1e: return sf::Keyboard::RBracket; + case 0x29: return sf::Keyboard::SemiColon; + case 0x2b: return sf::Keyboard::Comma; +// case 0x41: /* keypad */ return sf::Keyboard::Period; + case 0x2f: /* keyboard */ return sf::Keyboard::Period; + case 0x27: return sf::Keyboard::Quote; + case 0x2c: return sf::Keyboard::Slash; + case 0x2a: return sf::Keyboard::BackSlash; + +#warning sf::Keyboard::Tilde might be in conflict with some other key. + // 0x0a is for "Non-US Backslash" according to HID Calibrator, + // a sample provided by Apple. + case 0x0a: return sf::Keyboard::Tilde; + +// case 0x51: /* keypad */ return sf::Keyboard::Equal; + case 0x18: /* keyboard */ return sf::Keyboard::Equal; + case 0x32: return sf::Keyboard::Dash; + case 0x31: return sf::Keyboard::Space; +// case 0x4c: /* keypad */ return sf::Keyboard::Return; + case 0x24: /* keyboard */ return sf::Keyboard::Return; + case 0x33: return sf::Keyboard::Back; + case 0x30: return sf::Keyboard::Tab; + + // Duplicates (see next §). + case 0x74: return sf::Keyboard::PageUp; + case 0x79: return sf::Keyboard::PageDown; + case 0x77: return sf::Keyboard::End; + case 0x73: return sf::Keyboard::Home; + + case NSPageUpFunctionKey: return sf::Keyboard::PageUp; + case NSPageDownFunctionKey: return sf::Keyboard::PageDown; + case NSEndFunctionKey: return sf::Keyboard::End; + case NSHomeFunctionKey: return sf::Keyboard::Home; + + case 0x72: return sf::Keyboard::Insert; + case NSInsertFunctionKey: return sf::Keyboard::Insert; + case 0x75: return sf::Keyboard::Delete; + case NSDeleteFunctionKey: return sf::Keyboard::Delete; + + case 0x45: return sf::Keyboard::Add; + case 0x4e: return sf::Keyboard::Subtract; + case 0x43: return sf::Keyboard::Multiply; + case 0x4b: return sf::Keyboard::Divide; + + // Duplicates (see next §). + case 0x7b: return sf::Keyboard::Left; + case 0x7c: return sf::Keyboard::Right; + case 0x7e: return sf::Keyboard::Up; + case 0x7d: return sf::Keyboard::Down; + + case NSLeftArrowFunctionKey: return sf::Keyboard::Left; + case NSRightArrowFunctionKey: return sf::Keyboard::Right; + case NSUpArrowFunctionKey: return sf::Keyboard::Up; + case NSDownArrowFunctionKey: return sf::Keyboard::Down; + + case 0x52: return sf::Keyboard::Numpad0; + case 0x53: return sf::Keyboard::Numpad1; + case 0x54: return sf::Keyboard::Numpad2; + case 0x55: return sf::Keyboard::Numpad3; + case 0x56: return sf::Keyboard::Numpad4; + case 0x57: return sf::Keyboard::Numpad5; + case 0x58: return sf::Keyboard::Numpad6; + case 0x59: return sf::Keyboard::Numpad7; + case 0x5b: return sf::Keyboard::Numpad8; + case 0x5c: return sf::Keyboard::Numpad9; + + // Duplicates (see next §). + case 0x7a: return sf::Keyboard::F1; + case 0x78: return sf::Keyboard::F2; + case 0x63: return sf::Keyboard::F3; + case 0x76: return sf::Keyboard::F4; + case 0x60: return sf::Keyboard::F5; + case 0x61: return sf::Keyboard::F6; + case 0x62: return sf::Keyboard::F7; + case 0x64: return sf::Keyboard::F8; + case 0x65: return sf::Keyboard::F9; + case 0x6d: return sf::Keyboard::F10; + case 0x67: return sf::Keyboard::F11; + case 0x6f: return sf::Keyboard::F12; + case 0x69: return sf::Keyboard::F13; + case 0x6b: return sf::Keyboard::F14; + case 0x71: return sf::Keyboard::F15; + + case NSF1FunctionKey: return sf::Keyboard::F1; + case NSF2FunctionKey: return sf::Keyboard::F2; + case NSF3FunctionKey: return sf::Keyboard::F3; + case NSF4FunctionKey: return sf::Keyboard::F4; + case NSF5FunctionKey: return sf::Keyboard::F5; + case NSF6FunctionKey: return sf::Keyboard::F6; + case NSF7FunctionKey: return sf::Keyboard::F7; + case NSF8FunctionKey: return sf::Keyboard::F8; + case NSF9FunctionKey: return sf::Keyboard::F9; + case NSF10FunctionKey: return sf::Keyboard::F10; + case NSF11FunctionKey: return sf::Keyboard::F11; + case NSF12FunctionKey: return sf::Keyboard::F12; + case NSF13FunctionKey: return sf::Keyboard::F13; + case NSF14FunctionKey: return sf::Keyboard::F14; + case NSF15FunctionKey: return sf::Keyboard::F15; + + case NSPauseFunctionKey: return sf::Keyboard::Pause; + +#warning keycode 0x1b is not bound to any key. + // This key is ' on CH-FR, ) on FR and - on US layouts. + + // An unknown key. + default: return sf::Keyboard::KeyCount; + } +} + + +} // namespace priv + +} // namespace sf + diff --git a/src/SFML/Window/OSX/InputImpl.cpp b/src/SFML/Window/OSX/InputImpl.cpp deleted file mode 100644 index cee05ce8..00000000 --- a/src/SFML/Window/OSX/InputImpl.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -bool InputImpl::IsKeyPressed(Keyboard::Key key) -{ - // @to be implemented - return false; -} - - -//////////////////////////////////////////////////////////// -bool InputImpl::IsMouseButtonPressed(Mouse::Button button) -{ - // @to be implemented - return false; -} - - -//////////////////////////////////////////////////////////// -Vector2i InputImpl::GetMousePosition() -{ - // @to be implemented - return Vector2i(); -} - - -//////////////////////////////////////////////////////////// -Vector2i InputImpl::GetMousePosition(const Window& relativeTo) -{ - // @to be implemented - return Vector2i(); -} - - -//////////////////////////////////////////////////////////// -void InputImpl::SetMousePosition(const Vector2i& position) -{ - // @to be implemented -} - - -//////////////////////////////////////////////////////////// -void InputImpl::SetMousePosition(const Vector2i& position, const Window& relativeTo) -{ - // @to be implemented -} - -} // namespace priv - -} // namespace sf diff --git a/src/SFML/Window/OSX/InputImpl.hpp b/src/SFML/Window/OSX/InputImpl.hpp index 15aaf0f5..cfa4aa34 100644 --- a/src/SFML/Window/OSX/InputImpl.hpp +++ b/src/SFML/Window/OSX/InputImpl.hpp @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent.gom@gmail.com), // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. diff --git a/src/SFML/Window/OSX/InputImpl.mm b/src/SFML/Window/OSX/InputImpl.mm new file mode 100644 index 00000000..0690442f --- /dev/null +++ b/src/SFML/Window/OSX/InputImpl.mm @@ -0,0 +1,177 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent.gom@gmail.com), +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + +#import +#import + +//////////////////////////////////////////////////////////// +/// In order to keep track of the keyboard's state and mouse buttons' state +/// we use the HID manager. Mouse position is handled differently. +/// +/// NB : we probably could use +/// NSEvent +addGlobalMonitorForEventsMatchingMask:handler: for mouse only. +/// +//////////////////////////////////////////////////////////// + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Extract the dedicated SFOpenGLView from the SFML window +/// +/// \param window a SFML window +/// \return nil if something went wrong or a SFOpenGLView*. +/// +//////////////////////////////////////////////////////////// +SFOpenGLView* GetSFOpenGLViewFromSFMLWindow(const Window& window) +{ + id nsHandle = (id)window.GetSystemHandle(); + + // Get our SFOpenGLView from ... + SFOpenGLView* view = nil; + if ([nsHandle isKindOfClass:[NSWindow class]]) { + // If system handle is a window then from its content view. + view = [nsHandle contentView]; + + // Subview doesn't match ? + if (![view isKindOfClass:[SFOpenGLView class]]) { + sf::Err() << "The content view is not a valid SFOpenGLView" + << std::endl; + view = nil; + } + + } else if ([nsHandle isKindOfClass:[NSView class]]) { + // If system handle is a view then from a subview of kind SFOpenGLView. + NSArray* subviews = [nsHandle subviews]; + for (NSView* subview in subviews) { + if ([subview isKindOfClass:[SFOpenGLView class]]) { + view = (SFOpenGLView *)subview; + break; + } + } + + // No matching subview ? + if (view == nil) { + sf::Err() << "Cannot find a valid SFOpenGLView subview." << std::endl; + + } + + } else { + + sf::Err() << "The system handle is neither a nor " + << "object. This shouldn't happen." + << std::endl; + + } + + return view; +} + +//////////////////////////////////////////////////////////// +bool InputImpl::IsKeyPressed(Keyboard::Key key) +{ + return HIDInputManager::GetInstance().IsKeyPressed(key); +} + + +//////////////////////////////////////////////////////////// +bool InputImpl::IsMouseButtonPressed(Mouse::Button button) +{ + return HIDInputManager::GetInstance().IsMouseButtonPressed(button); +} + + +//////////////////////////////////////////////////////////// +Vector2i InputImpl::GetMousePosition() +{ + // Reverse Y axis to match SFML coord. + NSPoint pos = [NSEvent mouseLocation]; + pos.y = sf::VideoMode::GetDesktopMode().Height - pos.y; + + return Vector2i(pos.x, pos.y); +} + + +//////////////////////////////////////////////////////////// +Vector2i InputImpl::GetMousePosition(const Window& relativeTo) +{ + SFOpenGLView* view = GetSFOpenGLViewFromSFMLWindow(relativeTo); + + // No view ? + if (view == nil) { + return Vector2i(); + } + + // Use -cursorPositionFromEvent: with nil. + NSPoint pos = [view cursorPositionFromEvent:nil]; + + return Vector2i(pos.x, pos.y); +} + + +//////////////////////////////////////////////////////////// +void InputImpl::SetMousePosition(const Vector2i& position) +{ + // Here we don't need to reverse the coordinates. + CGPoint pos = CGPointMake(position.x, position.y); + + // Place the cursor. + CGEventRef event = CGEventCreateMouseEvent(NULL, + kCGEventMouseMoved, + pos, + /*we don't care about this : */0); + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + // This is a workaround to deprecated CGSetLocalEventsSuppressionInterval. +} + + +//////////////////////////////////////////////////////////// +void InputImpl::SetMousePosition(const Vector2i& position, const Window& relativeTo) +{ + SFOpenGLView* view = GetSFOpenGLViewFromSFMLWindow(relativeTo); + + // No view ? + if (view == nil) { + return; + } + + // Use -setCursorPositionToX:Y:. + [view setCursorPositionToX:position.x Y:position.y]; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/OSX/Joystick.cpp b/src/SFML/Window/OSX/Joystick.cpp deleted file mode 100644 index 6cec8a92..00000000 --- a/src/SFML/Window/OSX/Joystick.cpp +++ /dev/null @@ -1,371 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com), -// Laurent Gomila (laurent.gom@gmail.com), -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - -//////////////////////////////////////////////////////////// -Joystick::Joystick() -: myManager(0) -, myElements(0) -{ - /* Nothing else */ -} - - -//////////////////////////////////////////////////////////// -Joystick::~Joystick() -{ - FreeUp(); -} - - -//////////////////////////////////////////////////////////// -void Joystick::Initialize(unsigned int Index) -{ - // Try to create a joystick manager. - if (!CreateManager()) return; - - // Get the joysticks. - CFSetRef devices = CopyJoysticksOnly(); - - // If none exit the function. - if (devices == NULL) { - FreeUp(); - return; - } - - // Is there enough joystick ? - CFIndex joysticksCount = CFSetGetCount(devices); - if (joysticksCount <= CFIndex(Index)) { - FreeUp(); - return; - } - - // Get a usable copy of the joysticks devices. - CFTypeRef devicesArray[joysticksCount]; - CFSetGetValues(devices, devicesArray); - - // Release unused stuff. - CFRelease(devices); // Maybe we should have a field for that and not release it here... - - // Get the Index-th joystick. - IOHIDDeviceRef device = (IOHIDDeviceRef) devicesArray[Index]; - - // Retrive all connected elements to this joystick. - if (!RetriveElements(device)) { - FreeUp(); - return; - } - - // Happy end! -} - - -//////////////////////////////////////////////////////////// -JoystickState Joystick::UpdateState() -{ - // If we don't have any joystick we exit. - if (myElements == 0) return JoystickState(); - - // Fill a JoystickState instance with the current joystick state. - JoystickState s; - - // Update the buttons. - for (ButtonsVector::size_type i = 0; i < myButtons.size(); ++i) { - IOHIDValueRef value = 0; - IOHIDDeviceGetValue(IOHIDElementGetDevice(myButtons[i]), myButtons[i], &value); - - // Check for plug out. - if (!value) { - // No value ? Hum... Seems like the joystick is gone. - - FreeUp(); - return JoystickState(); - } - - s.Buttons[i] = IOHIDValueGetIntegerValue(value) == 1; // 1 means pressed, others mean released. - } - - for (AxisMap::iterator it = myAxis.begin(); it != myAxis.end(); ++it) { - IOHIDValueRef value = 0; - IOHIDDeviceGetValue(IOHIDElementGetDevice(it->second), it->second, &value); - - // Check for plug out. - if (!value) { - // No value ? Hum... Seems like the joystick is gone. - - FreeUp(); - return JoystickState(); - } - - // We want to bind [physicalMin,physicalMax] to [-100=min,100=max]. - // - // General formula to bind [a,b] to [c,d] with a linear progression : - // - // f : [a, b] -> [c, d] - // x |-> (x-a)(d-c)/(b-a)+c - // - // This method might not be very accurate (the "0 position" can be - // slightly shift with some device) but we don't care because most - // of devices are so sensitive that this is not relevant. - double physicalMax = IOHIDElementGetPhysicalMax(it->second); - double physicalMin = IOHIDElementGetPhysicalMin(it->second); - double scaledMin = -100; - double scaledMax = 100; - double physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical); - float scaledValue = ((physicalValue - physicalMin) * (scaledMax - scaledMin) / (physicalMax - physicalMin)) + scaledMin; - s.Axis[it->first] = scaledValue; - } - - return s; -} - - -//////////////////////////////////////////////////////////// -bool Joystick::HasAxis(Joy::Axis Axis) const -{ - return myAxis.find(Axis) != myAxis.end(); -} - - -//////////////////////////////////////////////////////////// -unsigned int Joystick::GetButtonsCount() const -{ - // Return number of supported buttons. - return myButtons.size(); -} - - -//////////////////////////////////////////////////////////// -CFDictionaryRef Joystick::DevicesMaskForManager(UInt32 page, UInt32 usage) -{ - // Create the dictionary. - CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - // Add the page value. - CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page); - CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), value); - CFRelease(value); - - // Add the usage value (which is only valid if page value exists). - value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); - CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), value); - CFRelease(value); - - return dict; -} - - -//////////////////////////////////////////////////////////// -bool Joystick::CreateManager() -{ - // Create HID Manager reference. - myManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - - // Open a HID Manager reference. - IOReturn openStatus = IOHIDManagerOpen(myManager, kIOHIDOptionsTypeNone); - - if (openStatus != kIOReturnSuccess) { - sf::Err() << "Error when opening the joystick manager : " - << std::hex << openStatus << std::endl; - - CFRelease(myManager); - myManager = 0; - - return false; - } - - // Everything went fine. - return true; -} - - -//////////////////////////////////////////////////////////// -CFSetRef Joystick::CopyJoysticksOnly() -{ - // Create a mask to get only joystick devices. - CFDictionaryRef joysticksMask = DevicesMaskForManager(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick); - - // Sets single matching criteria (dictionary) for device enumeration. - IOHIDManagerSetDeviceMatching(myManager, joysticksMask); - - // No more needed -> free up. - CFRelease(joysticksMask); - - // Retrieve devices. - CFSetRef devices = IOHIDManagerCopyDevices(myManager); - return devices; // The caller is responsible for releasing it. -} - - -//////////////////////////////////////////////////////////// -bool Joystick::RetriveElements(IOHIDDeviceRef device) -{ - // Get a list of all elements attached to the device. - myElements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone); - - if (myElements == NULL) { - // What is a joystick with no element ? Let the user know that. - sf::Err() << "No array of element for this device" << std::endl; - - return false; - } - - // How many elements are there ? - CFIndex elements_count = CFArrayGetCount(myElements); - - if (elements_count == 0) { - // What is a joystick with no element ? Let the user know that. - sf::Err() << "No element attached to this device" << std::endl; - - CFRelease(myElements); - myElements = 0; - - return false; - } - - // Go through all connected elements. - for (int i = 0; i < elements_count; ++i) { - IOHIDElementRef element = (IOHIDElementRef) CFArrayGetValueAtIndex(myElements, i); - - switch (IOHIDElementGetType(element)) { - - case kIOHIDElementTypeInput_Misc: - switch (IOHIDElementGetUsage(element)) { - - case kHIDUsage_GD_X: - myAxis[Joy::AxisX] = element; - break; - - case kHIDUsage_GD_Y: - myAxis[Joy::AxisY] = element; - break; - - case kHIDUsage_GD_Z: - myAxis[Joy::AxisZ] = element; - break; - - case kHIDUsage_GD_Rx: - myAxis[Joy::AxisU] = element; // use same binding as on Linux. - break; - - case kHIDUsage_GD_Ry: - myAxis[Joy::AxisV] = element; // use same binding as on Linux. - break; - - case kHIDUsage_GD_Rz: - myAxis[Joy::AxisR] = element; // use same binding as on Linux. - break; - - // kHIDUsage_GD_Vx, kHIDUsage_GD_Vy, kHIDUsage_GD_Vz are ignored. - } - break; - - case kIOHIDElementTypeInput_Button: - if (myButtons.size() < Joy::ButtonCount) { // If we can managed this button through events... - myButtons.push_back(element); // ...we add this element to the list. - } else { - // Too many buttons. We ignore this one. - } - break; - - default: // Make compiler happy. - break; - } - } - - // Note : Joy::AxisPOV not yet supported. - // Maybe kIOHIDElementTypeInput_Axis is the type but I can't test. - - return true; -} - - -//////////////////////////////////////////////////////////// -void Joystick::FreeUp() -{ - ReleaseElements(); - - ReleaseManager(); -} - - -//////////////////////////////////////////////////////////// -void Joystick::ReleaseManager() -{ - if (myManager != 0) { - // Closes the IOHIDManager - IOReturn closeStatus = IOHIDManagerClose(myManager, kIOHIDOptionsTypeNone); - - if (closeStatus != kIOReturnSuccess) { - // Closing the manager failed. We don't care that much about this. - // It often happens when the connection with the device is closed after - // the device is deconected from the computer. - - /* - sf::Err() << "Error when closing the manager : " - << std::hex << closeStatus << std::endl; - //*/ - } - - // Release the manager. - CFRelease(myManager); - myManager = 0; - } -} - - -//////////////////////////////////////////////////////////// -void Joystick::ReleaseElements() -{ - if (myElements != 0) { - // Release all elements. - CFRelease(myElements); - myElements = 0; - - // Both myAxis and myButton contains only reference from myElements. - // Thus no special cleanup is required on these two. - myButtons.clear(); - myAxis.clear(); - } -} - - -} // namespace priv - -} // namespace sf diff --git a/src/SFML/Window/OSX/Joystick.hpp b/src/SFML/Window/OSX/Joystick.hpp deleted file mode 100644 index 389319bd..00000000 --- a/src/SFML/Window/OSX/Joystick.hpp +++ /dev/null @@ -1,176 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com), -// Laurent Gomila (laurent.gom@gmail.com), -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_JOYSTICKOSX_HPP -#define SFML_JOYSTICKOSX_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief OSX implementation of Joystick -/// -//////////////////////////////////////////////////////////// -class Joystick -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructors initializes all members to 0. - /// That is, it does nothing. - /// - //////////////////////////////////////////////////////////// - Joystick(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// Close all connections to any devices if required. - /// - //////////////////////////////////////////////////////////// - ~Joystick(); - - //////////////////////////////////////////////////////////// - /// \brief Initialize the instance and bind it to a physical joystick - /// - /// \param index Index of the physical joystick to bind to - /// - //////////////////////////////////////////////////////////// - void Initialize(unsigned int index); - - //////////////////////////////////////////////////////////// - /// \brief Update the current joystick and return its new state - /// - /// \return Current state of the joystick - /// - //////////////////////////////////////////////////////////// - JoystickState UpdateState(); - - //////////////////////////////////////////////////////////// - /// \brief Check if the joystick supports the given axis - /// - /// \param axis Axis to check - /// - /// \return True of the axis is supported, false otherwise - /// - //////////////////////////////////////////////////////////// - bool HasAxis(Joy::Axis Axis) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the number of buttons supported by the joystick - /// - /// \return Number of buttons - /// - //////////////////////////////////////////////////////////// - unsigned int GetButtonsCount() const; - -private : - - //////////////////////////////////////////////////////////// - /// \brief Create a mask (dictionary) for an IOHIDManager - /// - /// \param page - /// \param usage - /// - //////////////////////////////////////////////////////////// - static CFDictionaryRef DevicesMaskForManager(UInt32 page, UInt32 usage); - - //////////////////////////////////////////////////////////// - /// \brief Create and open the manager - /// - /// \return Return false if someting went wrong - /// - //////////////////////////////////////////////////////////// - bool CreateManager(); - - //////////////////////////////////////////////////////////// - /// \brief Copy all connected joysticks to the manager - /// - /// \return NULL or a valid (possibly empty) set of devices - /// - //////////////////////////////////////////////////////////// - CFSetRef CopyJoysticksOnly(); - - //////////////////////////////////////////////////////////// - /// \brief Load all connected elements to the given device - /// - /// \param device The desired joystick - /// \return False if something went wrong - /// - //////////////////////////////////////////////////////////// - bool RetriveElements(IOHIDDeviceRef device); - - //////////////////////////////////////////////////////////// - /// \brief Release all resources - /// - /// Close all connections to any devices, if required - /// - //////////////////////////////////////////////////////////// - void FreeUp(); - - //////////////////////////////////////////////////////////// - /// \brief Close and release the manager - /// - //////////////////////////////////////////////////////////// - void ReleaseManager(); - - //////////////////////////////////////////////////////////// - /// \brief Release all elements - /// - //////////////////////////////////////////////////////////// - void ReleaseElements(); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - typedef std::map AxisMap; - typedef std::vector ButtonsVector; - - AxisMap myAxis; ///< Axis (IOHIDElementRef) connected to the joystick. - ButtonsVector myButtons; ///< Buttons (IOHIDElementRef) connected to the joystick. - // Note : Both myAxis and myButton contains only reference from myElements. - // Thus no special cleanup is required on these two. - - IOHIDManagerRef myManager; ///< HID Manager. - CFArrayRef myElements; ///< IOHIDElementRef connected to the joytick. -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_JOYSTICKOSX_HPP diff --git a/src/SFML/Window/OSX/JoystickImpl.cpp b/src/SFML/Window/OSX/JoystickImpl.cpp index c45c6722..cd082fa3 100644 --- a/src/SFML/Window/OSX/JoystickImpl.cpp +++ b/src/SFML/Window/OSX/JoystickImpl.cpp @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent.gom@gmail.com), // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. diff --git a/src/SFML/Window/OSX/JoystickImpl.hpp b/src/SFML/Window/OSX/JoystickImpl.hpp index 970a0dd6..7dbef005 100644 --- a/src/SFML/Window/OSX/JoystickImpl.hpp +++ b/src/SFML/Window/OSX/JoystickImpl.hpp @@ -1,7 +1,8 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent.gom@gmail.com), // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. diff --git a/src/SFML/Window/OSX/SFApplication.h b/src/SFML/Window/OSX/SFApplication.h index d3615eb6..982e4817 100644 --- a/src/SFML/Window/OSX/SFApplication.h +++ b/src/SFML/Window/OSX/SFApplication.h @@ -39,6 +39,7 @@ /// \brief Event processing /// //////////////////////////////////////////////////////////// -+(void)processEvent ++(void)processEvent; + @end diff --git a/src/SFML/Window/OSX/SFOpenGLView.h b/src/SFML/Window/OSX/SFOpenGLView.h index c6021a66..e35c149e 100644 --- a/src/SFML/Window/OSX/SFOpenGLView.h +++ b/src/SFML/Window/OSX/SFOpenGLView.h @@ -100,4 +100,10 @@ namespace sf { -(void)enableKeyRepeat; -(void)disableKeyRepeat; +//////////////////////////////////////////////////////////// +/// Compute the position of the cursor. +/// +//////////////////////////////////////////////////////////// +-(NSPoint)cursorPositionFromEvent:(NSEvent *)eventOrNil; + @end diff --git a/src/SFML/Window/OSX/SFOpenGLView.mm b/src/SFML/Window/OSX/SFOpenGLView.mm index 87fd8df1..f666753f 100644 --- a/src/SFML/Window/OSX/SFOpenGLView.mm +++ b/src/SFML/Window/OSX/SFOpenGLView.mm @@ -27,6 +27,7 @@ // Headers //////////////////////////////////////////////////////////// #include +#include // For LocalizedKeys and NonLocalizedKeys #include #import @@ -60,25 +61,6 @@ NSUInteger EraseMaskFromData(NSUInteger data, NSUInteger mask); //////////////////////////////////////////////////////////// NSUInteger KeepOnlyMaskFromData(NSUInteger data, NSUInteger mask); -//////////////////////////////////////////////////////////// -/// Try to convert a character into a SFML key code. -/// Return sf::Key::Count if it doesn't match any 'localized' keys. -/// -/// By 'localized' I mean keys that depend on the keyboard layout -/// and might not be the same as the US keycode in some country -/// (e.g. the keys 'Y' and 'Z' are switched on QWERTZ keyboard and -/// US keyboard layouts.) -/// -//////////////////////////////////////////////////////////// -sf::Key::Code LocalizedKeys(unichar ch); - -//////////////////////////////////////////////////////////// -/// Try to convert a keycode into a SFML key code. -/// Return sf::Key::Count if the keycode is unknown. -/// -//////////////////////////////////////////////////////////// -sf::Key::Code NonLocalizedKeys(unsigned short keycode); - //////////////////////////////////////////////////////////// /// SFOpenGLView class : Privates Methods Declaration /// @@ -103,14 +85,10 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); //////////////////////////////////////////////////////////// -(void)initModifiersState; -//////////////////////////////////////////////////////////// -/// Compute the position of the cursor. -/// -//////////////////////////////////////////////////////////// --(NSPoint)cursorPositionFromEvent:(NSEvent *)event; - //////////////////////////////////////////////////////////// /// Converte the NSEvent mouse button type to SFML type. +/// +/// Returns ButtonCount if the button is unknown /// //////////////////////////////////////////////////////////// -(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent *)event; @@ -119,7 +97,7 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); /// Convert a key down/up NSEvent into an SFML key event. /// Based on LocalizedKeys and NonLocalizedKeys function. /// -/// Return sf::Key::Count as Code if the key is unknown. +/// Return sf::Keyboard::KeyCount as Code if the key is unknown. /// //////////////////////////////////////////////////////////// +(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent *)anEvent; @@ -198,11 +176,12 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); // Place the cursor. CGEventRef event = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, - CGPointMake(screenCoord.x, screenCoord.y), + CGPointMake(screenCoord.x, + screenCoord.y), /*we don't care about this : */0); CGEventPost(kCGHIDEventTap, event); CFRelease(event); - // This is a workaround to deprecated CGSetLocalEventsSuppressionInterval. + // This is a workaround to deprecated CGSetLocalEventsSuppressionInterval function } @@ -384,7 +363,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent]; - myRequester->MouseDownAt(button, loc.x, loc.y); + if (button != sf::Mouse::ButtonCount) { + myRequester->MouseDownAt(button, loc.x, loc.y); + } +//#ifdef SFML_DEBUG +// else { +// sf::Err() << "Unknown mouse button released." << std::endl; +// } +//#endif } @@ -397,7 +383,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent]; - myRequester->MouseUpAt(button, loc.x, loc.y); + if (button != sf::Mouse::ButtonCount) { + myRequester->MouseUpAt(button, loc.x, loc.y); + } +//#ifdef SFML_DEBUG +// else { +// sf::Err() << "Unknown mouse button released." << std::endl; +// } +//#endif } @@ -431,6 +424,46 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); } +//////////////////////////////////////////////////////// +-(NSPoint)cursorPositionFromEvent:(NSEvent *)eventOrNil +{ + NSPoint loc; + // If no event given then get current mouse pos. + if (eventOrNil == nil) { + NSPoint rawPos = [[self window] mouseLocationOutsideOfEventStream]; + loc = [self convertPoint:rawPos fromView:nil]; + } else { + loc = [self convertPoint:[eventOrNil locationInWindow] fromView:nil]; + } + + // Don't forget to change to SFML coord system. + float h = [self frame].size.height; + loc.y = h - loc.y; + + // Recompute the mouse pos if required. + if (!NSEqualSizes(myRealSize, NSZeroSize)) { + loc.x = loc.x * myRealSize.width / [self frame].size.width; + loc.y = loc.y * myRealSize.height / [self frame].size.height; + } + + return loc; +} + + +//////////////////////////////////////////////////////// +-(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent *)event +{ + switch ([event buttonNumber]) { + case 0: return sf::Mouse::Left; + case 1: return sf::Mouse::Right; + case 2: return sf::Mouse::Middle; + case 3: return sf::Mouse::XButton1; + case 4: return sf::Mouse::XButton2; + default: return sf::Mouse::ButtonCount; // Never happens! (hopefully) + } +} + + #pragma mark #pragma mark Key-event methods @@ -440,14 +473,17 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); { if (myRequester == 0) return; + // Handle key down event if (myUseKeyRepeat || ![theEvent isARepeat]) { sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; - if (key.Code != sf::Key::Count) { // The key is recognized. + if (key.Code != sf::Keyboard::KeyCount) { // The key is recognized. myRequester->KeyDown(key); } } + + // Handle text entred event if ((myUseKeyRepeat || ![theEvent isARepeat]) && [[theEvent characters] length] > 0) { // Ignore escape key and non text keycode. (See NSEvent.h) @@ -478,7 +514,7 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; - if (key.Code != sf::Key::Count) { // The key is recognized. + if (key.Code != sf::Keyboard::KeyCount) { // The key is recognized. myRequester->KeyUp(key); } } @@ -493,7 +529,7 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); // Setup a potential event key. sf::Event::KeyEvent key; - key.Code = sf::Key::Count; + key.Code = sf::Keyboard::KeyCount; key.Alt = modifiers & NSAlternateKeyMask; key.Control = modifiers & NSControlKeyMask; key.Shift = modifiers & NSShiftKeyMask; @@ -522,14 +558,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); // left shift released leftShiftIsDown = NO; - key.Code = sf::Key::LShift; + key.Code = sf::Keyboard::LShift; myRequester->KeyUp(key); } if (!myRightShiftWasDown) { // right shift pressed - key.Code = sf::Key::RShift; + key.Code = sf::Keyboard::RShift; myRequester->KeyDown(key); } } @@ -543,14 +579,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); // right shift released rightShiftIsDown = NO; - key.Code = sf::Key::RShift; + key.Code = sf::Keyboard::RShift; myRequester->KeyUp(key); } if (!myLeftShiftWasDown) { // left shift pressed - key.Code = sf::Key::LShift; + key.Code = sf::Keyboard::LShift; myRequester->KeyDown(key); } } @@ -564,14 +600,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); if (!myRightShiftWasDown) { // right shift pressed - key.Code = sf::Key::RShift; + key.Code = sf::Keyboard::RShift; myRequester->KeyDown(key); } if (!myLeftShiftWasDown) { // left shift pressed - key.Code = sf::Key::LShift; + key.Code = sf::Keyboard::LShift; myRequester->KeyDown(key); } } @@ -583,14 +619,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); if (myRightShiftWasDown) { // right shift released - key.Code = sf::Key::RShift; + key.Code = sf::Keyboard::RShift; myRequester->KeyUp(key); } if (myLeftShiftWasDown) { // left shift released - key.Code = sf::Key::LShift; + key.Code = sf::Keyboard::LShift; myRequester->KeyUp(key); } } @@ -609,14 +645,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); // left command released leftCommandIsDown = NO; - key.Code = sf::Key::LSystem; + key.Code = sf::Keyboard::LSystem; myRequester->KeyUp(key); } if (!myRightCommandWasDown) { // right command pressed - key.Code = sf::Key::RSystem; + key.Code = sf::Keyboard::RSystem; myRequester->KeyDown(key); } } @@ -630,14 +666,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); // right command released rightCommandIsDown = NO; - key.Code = sf::Key::RSystem; + key.Code = sf::Keyboard::RSystem; myRequester->KeyUp(key); } if (!myLeftCommandWasDown) { // left command pressed - key.Code = sf::Key::LSystem; + key.Code = sf::Keyboard::LSystem; myRequester->KeyDown(key); } } @@ -651,14 +687,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); if (!myRightCommandWasDown) { // right command pressed - key.Code = sf::Key::RSystem; + key.Code = sf::Keyboard::RSystem; myRequester->KeyDown(key); } if (!myLeftCommandWasDown) { // left command pressed - key.Code = sf::Key::LSystem; + key.Code = sf::Keyboard::LSystem; myRequester->KeyDown(key); } } @@ -670,14 +706,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); if (myRightCommandWasDown) { // right command released - key.Code = sf::Key::RSystem; + key.Code = sf::Keyboard::RSystem; myRequester->KeyUp(key); } if (myLeftCommandWasDown) { // left command released - key.Code = sf::Key::LSystem; + key.Code = sf::Keyboard::LSystem; myRequester->KeyUp(key); } } @@ -696,14 +732,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); // left alt released leftAlternateIsDown = NO; - key.Code = sf::Key::LAlt; + key.Code = sf::Keyboard::LAlt; myRequester->KeyUp(key); } if (!myRightAlternateWasDown) { // right alt pressed - key.Code = sf::Key::RAlt; + key.Code = sf::Keyboard::RAlt; myRequester->KeyDown(key); } } @@ -717,14 +753,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); // right alt released rightAlternateIsDown = NO; - key.Code = sf::Key::RAlt; + key.Code = sf::Keyboard::RAlt; myRequester->KeyUp(key); } if (!myLeftAlternateWasDown) { // left alt pressed - key.Code = sf::Key::LAlt; + key.Code = sf::Keyboard::LAlt; myRequester->KeyDown(key); } } @@ -738,14 +774,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); if (!myRightAlternateWasDown) { // right alt pressed - key.Code = sf::Key::RAlt; + key.Code = sf::Keyboard::RAlt; myRequester->KeyDown(key); } if (!myLeftAlternateWasDown) { // left alt pressed - key.Code = sf::Key::LAlt; + key.Code = sf::Keyboard::LAlt; myRequester->KeyDown(key); } } @@ -757,14 +793,14 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); if (myRightAlternateWasDown) { // right alt released - key.Code = sf::Key::RAlt; + key.Code = sf::Keyboard::RAlt; myRequester->KeyUp(key); } if (myLeftAlternateWasDown) { // left alt released - key.Code = sf::Key::LAlt; + key.Code = sf::Keyboard::LAlt; myRequester->KeyUp(key); } } @@ -778,7 +814,7 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); if (!myControlWasDown) { // ctrl pressed - key.Code = sf::Key::LControl; + key.Code = sf::Keyboard::LControl; myRequester->KeyDown(key); } } else { // No control key down. @@ -787,7 +823,7 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); if (myControlWasDown) { // ctrl released - key.Code = sf::Key::LControl; + key.Code = sf::Keyboard::LControl; myRequester->KeyUp(key); } } @@ -903,39 +939,6 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); } -//////////////////////////////////////////////////////// --(NSPoint)cursorPositionFromEvent:(NSEvent *)event -{ - NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; - - // Don't forget to change to SFML coord system. - float h = [self frame].size.height; - loc.y = h - loc.y; - - // Recompute the mouse pos if required. - if (!NSEqualSizes(myRealSize, NSZeroSize)) { - loc.x = loc.x * myRealSize.width / [self frame].size.width; - loc.y = loc.y * myRealSize.height / [self frame].size.height; - } - - return loc; -} - - -//////////////////////////////////////////////////////// --(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent *)event -{ - switch ([event buttonNumber]) { - case 0: return sf::Mouse::Left; - case 1: return sf::Mouse::Right; - case 2: return sf::Mouse::Middle; - case 3: return sf::Mouse::XButton1; - case 4: return sf::Mouse::XButton2; - default: return sf::Mouse::ButtonCount; // Never happens! (hopefully) - } -} - - //////////////////////////////////////////////////////// +(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent *)anEvent { @@ -949,28 +952,30 @@ sf::Key::Code NonLocalizedKeys(unsigned short keycode); key.System = modifierFlags & NSCommandKeyMask; // Key code. - key.Code = sf::Key::Count; - // First we look if the key down is from a list of caracter that depend on keyboard localization. + key.Code = sf::Keyboard::KeyCount; + + // First we look if the key down is from a list of caracter + // that depend on keyboard localization. NSString* string = [anEvent charactersIgnoringModifiers]; if ([string length] > 0) { - key.Code = LocalizedKeys([string characterAtIndex:0]); + key.Code = sf::priv::HIDInputManager::LocalizedKeys([string characterAtIndex:0]); } - // The key is not a localized one, the other keys. - if (key.Code == sf::Key::Count) { - key.Code = NonLocalizedKeys([anEvent keyCode]); + // The key is not a localized one, so we try to find a corresponding code + // through virtual key code. + if (key.Code == sf::Keyboard::KeyCount) { + key.Code = sf::priv::HIDInputManager::NonLocalizedKeys([anEvent keyCode]); } -#ifdef SFML_DEBUG // We don't want to bother the final customer with anoying messages. - if (key.Code == sf::Key::Count) { // The key is unknown. - sf::Err() - << "This is an unknow key. Should not happen (?). Keycode is 0x" - << std::hex - << [anEvent keyCode] - << "." - << std::endl; - } -#endif +//#ifdef SFML_DEBUG // Don't bother the final customers with annoying messages. +// if (key.Code == sf::Keyboard::KeyCount) { // The key is unknown. +// sf::Err() << "This is an unknow key. Virtual key code is 0x" +// << std::hex +// << [anEvent keyCode] +// << "." +// << std::endl; +// } +//#endif return key; } @@ -996,256 +1001,3 @@ NSUInteger KeepOnlyMaskFromData(NSUInteger data, NSUInteger mask) } -//////////////////////////////////////////////////////// -sf::Key::Code LocalizedKeys(unichar ch) -{ - switch (ch) { - case 'a': - case 'A': return sf::Key::A; - - case 'b': - case 'B': return sf::Key::B; - - case 'c': - case 'C': return sf::Key::C; - - case 'd': - case 'D': return sf::Key::D; - - case 'e': - case 'E': return sf::Key::E; - - case 'f': - case 'F': return sf::Key::F; - - case 'g': - case 'G': return sf::Key::G; - - case 'h': - case 'H': return sf::Key::H; - - case 'i': - case 'I': return sf::Key::I; - - case 'j': - case 'J': return sf::Key::J; - - case 'k': - case 'K': return sf::Key::K; - - case 'l': - case 'L': return sf::Key::L; - - case 'm': - case 'M': return sf::Key::M; - - case 'n': - case 'N': return sf::Key::N; - - case 'o': - case 'O': return sf::Key::O; - - case 'p': - case 'P': return sf::Key::P; - - case 'q': - case 'Q': return sf::Key::Q; - - case 'r': - case 'R': return sf::Key::R; - - case 's': - case 'S': return sf::Key::S; - - case 't': - case 'T': return sf::Key::T; - - case 'u': - case 'U': return sf::Key::U; - - case 'v': - case 'V': return sf::Key::V; - - case 'w': - case 'W': return sf::Key::W; - - case 'x': - case 'X': return sf::Key::X; - - case 'y': - case 'Y': return sf::Key::Y; - - case 'z': - case 'Z': return sf::Key::Z; - - // The kew is not 'localized'. - default: return sf::Key::Count; - } -} - - -//////////////////////////////////////////////////////// -sf::Key::Code NonLocalizedKeys(unsigned short keycode) -{ - // (Some) 0x code based on http://forums.macrumors.com/showthread.php?t=780577 - // Some sf::Key are present twice. - switch (keycode) { - // These cases should not be used but anyway... - case 0x00: return sf::Key::A; - case 0x0b: return sf::Key::B; - case 0x08: return sf::Key::C; - case 0x02: return sf::Key::D; - case 0x0e: return sf::Key::E; - case 0x03: return sf::Key::F; - case 0x05: return sf::Key::G; - case 0x04: return sf::Key::H; - case 0x22: return sf::Key::I; - case 0x26: return sf::Key::J; - case 0x28: return sf::Key::K; - case 0x25: return sf::Key::L; - case 0x2e: return sf::Key::M; - case 0x2d: return sf::Key::N; - case 0x1f: return sf::Key::O; - case 0x23: return sf::Key::P; - case 0x0c: return sf::Key::Q; - case 0x0f: return sf::Key::R; - case 0x01: return sf::Key::S; - case 0x11: return sf::Key::T; - case 0x20: return sf::Key::U; - case 0x09: return sf::Key::V; - case 0x0d: return sf::Key::W; - case 0x07: return sf::Key::X; - case 0x10: return sf::Key::Y; - case 0x06: return sf::Key::Z; - - // These cases should not be used but anyway... - case 0x1d: return sf::Key::Num0; - case 0x12: return sf::Key::Num1; - case 0x13: return sf::Key::Num2; - case 0x14: return sf::Key::Num3; - case 0x15: return sf::Key::Num4; - case 0x17: return sf::Key::Num5; - case 0x16: return sf::Key::Num6; - case 0x1a: return sf::Key::Num7; - case 0x1c: return sf::Key::Num8; - case 0x19: return sf::Key::Num9; - - case 0x35: return sf::Key::Escape; - - // Modifier keys : never happen with keyDown/keyUp methods (?) - case 0x3b: return sf::Key::LControl; - case 0x38: return sf::Key::LShift; - case 0x3a: return sf::Key::LAlt; - case 0x37: return sf::Key::LSystem; - case 0x3e: return sf::Key::RControl; - case 0x3c: return sf::Key::RShift; - case 0x3d: return sf::Key::RAlt; - case 0x36: return sf::Key::RSystem; - - case NSMenuFunctionKey: return sf::Key::Menu; - - case 0x21: return sf::Key::LBracket; - case 0x1e: return sf::Key::RBracket; - case 0x29: return sf::Key::SemiColon; - case 0x2b: return sf::Key::Comma; - case 0x2f: return sf::Key::Period; - case 0x27: return sf::Key::Quote; - case 0x2c: return sf::Key::Slash; - case 0x2a: return sf::Key::BackSlash; - -#warning sf::Key::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::Key::Tilde; - - case 0x18: return sf::Key::Equal; - case 0x32: return sf::Key::Dash; - case 0x31: return sf::Key::Space; - case 0x24: return sf::Key::Return; - case 0x33: return sf::Key::Back; - case 0x30: return sf::Key::Tab; - - // Duplicates (see next §). - case 0x74: return sf::Key::PageUp; - case 0x79: return sf::Key::PageDown; - case 0x77: return sf::Key::End; - case 0x73: return sf::Key::Home; - - case NSPageUpFunctionKey: return sf::Key::PageUp; - case NSPageDownFunctionKey: return sf::Key::PageDown; - case NSEndFunctionKey: return sf::Key::End; - case NSHomeFunctionKey: return sf::Key::Home; - - case NSInsertFunctionKey: return sf::Key::Insert; - case NSDeleteFunctionKey: return sf::Key::Delete; - - case 0x45: return sf::Key::Add; - case 0x4e: return sf::Key::Subtract; - case 0x43: return sf::Key::Multiply; - case 0x4b: return sf::Key::Divide; - - // Duplicates (see next §). - case 0x7b: return sf::Key::Left; - case 0x7c: return sf::Key::Right; - case 0x7e: return sf::Key::Up; - case 0x7d: return sf::Key::Down; - - case NSLeftArrowFunctionKey: return sf::Key::Left; - case NSRightArrowFunctionKey: return sf::Key::Right; - case NSUpArrowFunctionKey: return sf::Key::Up; - case NSDownArrowFunctionKey: return sf::Key::Down; - - case 0x52: return sf::Key::Numpad0; - case 0x53: return sf::Key::Numpad1; - case 0x54: return sf::Key::Numpad2; - case 0x55: return sf::Key::Numpad3; - case 0x56: return sf::Key::Numpad4; - case 0x57: return sf::Key::Numpad5; - case 0x58: return sf::Key::Numpad6; - case 0x59: return sf::Key::Numpad7; - case 0x5b: return sf::Key::Numpad8; - case 0x5c: return sf::Key::Numpad9; - - // Duplicates (see next §). - case 0x7a: return sf::Key::F1; - case 0x78: return sf::Key::F2; - case 0x63: return sf::Key::F3; - case 0x76: return sf::Key::F4; - case 0x60: return sf::Key::F5; - case 0x61: return sf::Key::F6; - case 0x62: return sf::Key::F7; - case 0x64: return sf::Key::F8; - case 0x65: return sf::Key::F9; - case 0x6d: return sf::Key::F10; - case 0x67: return sf::Key::F11; - case 0x6f: return sf::Key::F12; - case 0x69: return sf::Key::F13; - case 0x6b: return sf::Key::F14; - case 0x71: return sf::Key::F15; - - case NSF1FunctionKey: return sf::Key::F1; - case NSF2FunctionKey: return sf::Key::F2; - case NSF3FunctionKey: return sf::Key::F3; - case NSF4FunctionKey: return sf::Key::F4; - case NSF5FunctionKey: return sf::Key::F5; - case NSF6FunctionKey: return sf::Key::F6; - case NSF7FunctionKey: return sf::Key::F7; - case NSF8FunctionKey: return sf::Key::F8; - case NSF9FunctionKey: return sf::Key::F9; - case NSF10FunctionKey: return sf::Key::F10; - case NSF11FunctionKey: return sf::Key::F11; - case NSF12FunctionKey: return sf::Key::F12; - case NSF13FunctionKey: return sf::Key::F13; - case NSF14FunctionKey: return sf::Key::F14; - case NSF15FunctionKey: return sf::Key::F15; - - case NSPauseFunctionKey: return sf::Key::Pause; - -#warning keycode 0x1b is not bound to any key. - // This key is ' on CH-FR, ) on FR and - on US layouts. - - // An unknown key. - default: return sf::Key::Count; - } -} - diff --git a/src/SFML/Window/OSX/SFViewController.mm b/src/SFML/Window/OSX/SFViewController.mm index 6047fa46..00cd5174 100644 --- a/src/SFML/Window/OSX/SFViewController.mm +++ b/src/SFML/Window/OSX/SFViewController.mm @@ -224,7 +224,7 @@ //////////////////////////////////////////////////////// --(void)processEventWithBlockingMode:(BOOL)block +-(void)processEvent { sf::Err() << "Cannot process event from the view." << std::endl; } diff --git a/src/SFML/Window/OSX/SFWindowController.mm b/src/SFML/Window/OSX/SFWindowController.mm index 1f5a1fa7..2e3bac84 100644 --- a/src/SFML/Window/OSX/SFWindowController.mm +++ b/src/SFML/Window/OSX/SFWindowController.mm @@ -97,7 +97,7 @@ } // Set the view to the window as its content view. - [[myWindow contentView] addSubview:myOGLView]; + [myWindow setContentView:myOGLView]; } return self; diff --git a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h index 0986c3d8..e644eb1f 100644 --- a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h +++ b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h @@ -137,7 +137,7 @@ namespace sf { /// Fetch new event /// //////////////////////////////////////////////////////////// --(void)processEventWithBlockingMode:(BOOL)block; +-(void)processEvent; //////////////////////////////////////////////////////////// /// Apply a given context to an OpenGL view. diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp index 9e863e2f..518ea5d8 100644 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -44,8 +44,8 @@ #elif defined(SFML_SYSTEM_MACOS) - #include - typedef sf::priv::WindowImplCocoa WindowImplType; + #include + typedef sf::priv::WindowImplCocoa WindowImplType; #endif