mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 04:41:05 +08:00
Improved OSX/Joysticks performance
This commit is contained in:
parent
b93e980e27
commit
732b789e2e
@ -71,6 +71,8 @@ else() # MACOSX
|
||||
${SRCROOT}/OSX/InputImpl.hpp
|
||||
${SRCROOT}/OSX/HIDInputManager.hpp
|
||||
${SRCROOT}/OSX/HIDInputManager.mm
|
||||
${SRCROOT}/OSX/HIDJoystickManager.hpp
|
||||
${SRCROOT}/OSX/HIDJoystickManager.cpp
|
||||
${SRCROOT}/OSX/JoystickImpl.cpp
|
||||
${SRCROOT}/OSX/JoystickImpl.hpp
|
||||
${SRCROOT}/OSX/SFApplication.h
|
||||
|
@ -47,9 +47,6 @@ namespace priv
|
||||
/// keyboard and mouse states. It's only purpose is
|
||||
/// to help sf::priv::InputImpl class.
|
||||
///
|
||||
/// HIDInputManager provides a function to get all connected joysticks
|
||||
/// to help sf::priv::JoystickImpl.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class HIDInputManager : NonCopyable
|
||||
{
|
||||
@ -84,14 +81,6 @@ public :
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool IsMouseButtonPressed(Mouse::Button button);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief List all connected joysticks
|
||||
///
|
||||
/// \return a retained CFSetRef of IOHIDDeviceRef or NULL
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CFSetRef CopyJoystickDevices();
|
||||
|
||||
public :
|
||||
|
||||
@ -106,6 +95,16 @@ public :
|
||||
////////////////////////////////////////////////////////////
|
||||
static long GetLocationID(IOHIDDeviceRef device);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a mask (dictionary) for an IOHIDManager
|
||||
///
|
||||
/// \param page HID page
|
||||
/// \param usage HID usage page
|
||||
/// \return a retained CFDictionaryRef
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static CFDictionaryRef CopyDevicesMask(UInt32 page, UInt32 usage);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Try to convert a character into a SFML key code.
|
||||
///
|
||||
@ -208,16 +207,6 @@ private :
|
||||
////////////////////////////////////////////////////////////
|
||||
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.
|
||||
///
|
||||
|
@ -127,13 +127,6 @@ bool HIDInputManager::IsMouseButtonPressed(Mouse::Button button)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
CFSetRef HIDInputManager::CopyJoystickDevices()
|
||||
{
|
||||
return CopyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
long HIDInputManager::GetLocationID(IOHIDDeviceRef device)
|
||||
{
|
||||
@ -156,6 +149,28 @@ long HIDInputManager::GetLocationID(IOHIDDeviceRef device)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
CFDictionaryRef HIDInputManager::CopyDevicesMask(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;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
HIDInputManager::HIDInputManager()
|
||||
: amIValid(true)
|
||||
@ -514,35 +529,13 @@ void HIDInputManager::FreeUp()
|
||||
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);
|
||||
CFDictionaryRef mask = CopyDevicesMask(page, usage);
|
||||
|
||||
IOHIDManagerSetDeviceMatching(myManager, mask);
|
||||
|
||||
|
127
src/SFML/Window/OSX/HIDJoystickManager.cpp
Normal file
127
src/SFML/Window/OSX/HIDJoystickManager.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com),
|
||||
// Laurent Gomila (laurent.gom@gmail.com),
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/OSX/HIDJoystickManager.hpp>
|
||||
#include <SFML/Window/OSX/HIDInputManager.hpp>
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
HIDJoystickManager& HIDJoystickManager::GetInstance()
|
||||
{
|
||||
static HIDJoystickManager manager;
|
||||
return manager;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int HIDJoystickManager::GetJoystickCount()
|
||||
{
|
||||
Update();
|
||||
return myJoystickCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
CFSetRef HIDJoystickManager::CopyJoysticks()
|
||||
{
|
||||
CFSetRef devices = IOHIDManagerCopyDevices(myHIDManager);
|
||||
return devices;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
HIDJoystickManager::HIDJoystickManager()
|
||||
: myHIDManager(0)
|
||||
, myJoystickCount(0)
|
||||
{
|
||||
myHIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
|
||||
CFDictionaryRef mask = HIDInputManager::CopyDevicesMask(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_Joystick);
|
||||
IOHIDManagerSetDeviceMatching(myHIDManager, mask);
|
||||
CFRelease(mask);
|
||||
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(myHIDManager, pluggedIn, this);
|
||||
IOHIDManagerRegisterDeviceRemovalCallback(myHIDManager, pluggedOut, this);
|
||||
|
||||
IOHIDManagerScheduleWithRunLoop(myHIDManager,
|
||||
CFRunLoopGetCurrent(),
|
||||
kCFRunLoopDefaultMode);
|
||||
|
||||
IOHIDManagerOpen(myHIDManager, kIOHIDOptionsTypeNone);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
HIDJoystickManager::~HIDJoystickManager()
|
||||
{
|
||||
IOHIDManagerUnscheduleFromRunLoop(myHIDManager,
|
||||
CFRunLoopGetCurrent(),
|
||||
kCFRunLoopDefaultMode);
|
||||
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(myHIDManager, NULL, 0);
|
||||
IOHIDManagerRegisterDeviceRemovalCallback(myHIDManager, NULL, 0);
|
||||
|
||||
IOHIDManagerClose(myHIDManager, kIOHIDOptionsTypeNone);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void HIDJoystickManager::Update()
|
||||
{
|
||||
SInt32 status = kCFRunLoopRunHandledSource;
|
||||
|
||||
while (status == kCFRunLoopRunHandledSource) {
|
||||
status = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void HIDJoystickManager::pluggedIn(void * context, IOReturn, void *, IOHIDDeviceRef)
|
||||
{
|
||||
HIDJoystickManager* manager = (HIDJoystickManager*)context;
|
||||
manager->myJoystickCount++;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void HIDJoystickManager::pluggedOut(void * context, IOReturn, void *, IOHIDDeviceRef)
|
||||
{
|
||||
HIDJoystickManager* manager = (HIDJoystickManager*)context;
|
||||
manager->myJoystickCount--;
|
||||
}
|
||||
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
128
src/SFML/Window/OSX/HIDJoystickManager.hpp
Normal file
128
src/SFML/Window/OSX/HIDJoystickManager.hpp
Normal file
@ -0,0 +1,128 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_HIDJOYSTICKMANAGER_HPP
|
||||
#define SFML_HIDJOYSTICKMANAGER_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <IOKit/hid/IOHIDManager.h>
|
||||
#include <IOKit/hid/IOHIDDevice.h>
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief This class manage as a singleton instance the
|
||||
/// joysticks. It's only purpose is
|
||||
/// to help sf::priv::JoystickImpl class.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class HIDJoystickManager : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the unique instance of the class
|
||||
///
|
||||
/// \note Private use only
|
||||
///
|
||||
/// \return Reference to the HIDJoystickManager instance
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static HIDJoystickManager& GetInstance();
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the number of currently connected joystick
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int GetJoystickCount();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Copy the devices assosiated with this HID manager
|
||||
///
|
||||
/// \return a retained CFSetRef of IOHIDDeviceRef or NULL
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CFSetRef CopyJoysticks();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
HIDJoystickManager();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~HIDJoystickManager();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Make sur all event have been processed in the run loop
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void Update();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Private "plug-in" callback
|
||||
/// \note Only 'context' parametre is used.
|
||||
/// \see IOHIDDeviceCallback
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void pluggedIn(void * context, IOReturn, void *, IOHIDDeviceRef);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Private "plug-out" callback
|
||||
/// \note Only 'context' parametre is used.
|
||||
/// \see IOHIDDeviceCallback
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void pluggedOut(void * context, IOReturn, void *, IOHIDDeviceRef);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
IOHIDManagerRef myHIDManager; ///< HID Manager
|
||||
unsigned int myJoystickCount;///< Number of joysticks currently connected
|
||||
};
|
||||
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
#endif
|
@ -28,6 +28,8 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/JoystickImpl.hpp>
|
||||
#include <SFML/Window/OSX/HIDInputManager.hpp>
|
||||
#include <SFML/Window/OSX/HIDJoystickManager.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
@ -50,49 +52,62 @@ bool JoystickImpl::IsConnected(unsigned int index)
|
||||
|
||||
// Otherwise, let's check if it is now connected :
|
||||
else { // i.e., myLocationIDs[index] == 0
|
||||
|
||||
// Get all devices
|
||||
CFSetRef devices = HIDInputManager::GetInstance().CopyJoystickDevices();
|
||||
|
||||
if (devices != NULL) {
|
||||
// if there is more connected joystick to the HID manager than
|
||||
// opened joystick devices then we find the new one.
|
||||
|
||||
unsigned int openedCount = 0;
|
||||
for (unsigned int i(0); i < sf::Joystick::Count; ++i) {
|
||||
if (myLocationIDs[i] != 0) openedCount++;
|
||||
}
|
||||
|
||||
unsigned int connectedCount = HIDJoystickManager::GetInstance().GetJoystickCount();
|
||||
|
||||
if (connectedCount > openedCount) {
|
||||
|
||||
// Get all devices
|
||||
CFSetRef devices = HIDJoystickManager::GetInstance().CopyJoysticks();
|
||||
|
||||
CFIndex size = CFSetGetCount(devices);
|
||||
|
||||
if (size > 0) {
|
||||
|
||||
CFTypeRef array[size]; // array of IOHIDDeviceRef
|
||||
CFSetGetValues(devices, array);
|
||||
if (devices != NULL) {
|
||||
|
||||
// If there exists a device d s.t. there is no j s.t.
|
||||
// myLocationIDs[j] == d's location then we have a new device.
|
||||
CFIndex size = CFSetGetCount(devices);
|
||||
|
||||
for (CFIndex didx(0); didx < size; ++didx) {
|
||||
IOHIDDeviceRef d = (IOHIDDeviceRef)array[didx];
|
||||
Location dloc = HIDInputManager::GetLocationID(d);
|
||||
if (size > 0) {
|
||||
|
||||
bool foundJ = false;
|
||||
for (unsigned int j(0); j < Joystick::Count; ++j) {
|
||||
if (myLocationIDs[j] == dloc) {
|
||||
foundJ = true;
|
||||
break; // no need to loop again
|
||||
CFTypeRef array[size]; // array of IOHIDDeviceRef
|
||||
CFSetGetValues(devices, array);
|
||||
|
||||
// If there exists a device d s.t. there is no j s.t.
|
||||
// myLocationIDs[j] == d's location then we have a new device.
|
||||
|
||||
for (CFIndex didx(0); didx < size; ++didx) {
|
||||
IOHIDDeviceRef d = (IOHIDDeviceRef)array[didx];
|
||||
Location dloc = HIDInputManager::GetLocationID(d);
|
||||
|
||||
bool foundJ = false;
|
||||
for (unsigned int j(0); j < Joystick::Count; ++j) {
|
||||
if (myLocationIDs[j] == dloc) {
|
||||
foundJ = true;
|
||||
break; // no need to loop again
|
||||
}
|
||||
}
|
||||
|
||||
if (foundJ) {
|
||||
// This is a known device
|
||||
// Nothing else to do
|
||||
} else {
|
||||
// This is a new device
|
||||
// We set it up for Open(..)
|
||||
myLocationIDs[index] = dloc;
|
||||
state = true;
|
||||
break; // We stop looking for a new device
|
||||
}
|
||||
}
|
||||
|
||||
if (foundJ) {
|
||||
// This is a known device
|
||||
// Nothing else to do
|
||||
} else {
|
||||
// This is a new device
|
||||
// We set it up for Open(..)
|
||||
myLocationIDs[index] = dloc;
|
||||
state = true;
|
||||
break; // We stop looking for a new device
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(devices);
|
||||
}
|
||||
|
||||
CFRelease(devices);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,7 +122,7 @@ bool JoystickImpl::Open(unsigned int index)
|
||||
Location deviceLoc = myLocationIDs[index]; // The device we need to load
|
||||
|
||||
// Get all devices
|
||||
CFSetRef devices = HIDInputManager::GetInstance().CopyJoystickDevices();
|
||||
CFSetRef devices = HIDJoystickManager::GetInstance().CopyJoysticks();
|
||||
if (devices == NULL) {
|
||||
return false;
|
||||
}
|
||||
@ -274,7 +289,7 @@ JoystickState JoystickImpl::Update()
|
||||
Location selfLoc = myLocationIDs[myIndex];
|
||||
|
||||
// Get all devices
|
||||
CFSetRef devices = HIDInputManager::GetInstance().CopyJoystickDevices();
|
||||
CFSetRef devices = HIDJoystickManager::GetInstance().CopyJoysticks();
|
||||
if (devices == NULL) {
|
||||
return disconnectedState;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ private :
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef long Location;
|
||||
typedef long Location;
|
||||
typedef std::map<sf::Joystick::Axis, IOHIDElementRef> AxisMap;
|
||||
typedef std::vector<IOHIDElementRef> ButtonsVector;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user