Improved coding style of OS X implementation

And fixed some typos.
This commit is contained in:
Marco Antognini 2014-04-11 10:40:00 +02:00
parent 2204838384
commit b868833191
33 changed files with 876 additions and 750 deletions

View File

@ -24,7 +24,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Ensure at least one autorelease pool is available on this thread. /// \brief Ensure at least one autorelease pool is available on this thread
/// ///
/// Increment a retain count. /// Increment a retain count.
/// See SPECIAL CONSIDERATION in implementation file. /// See SPECIAL CONSIDERATION in implementation file.
@ -35,14 +35,14 @@ void retainPool(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Release the pool. /// \brief Release the pool.
/// ///
/// Drain the pool if it is no more needed (retain count is zero). /// Drain the pool if it is no more needed (retain count is zero)
/// See SPECIAL CONSIDERATION in implementation file. /// See SPECIAL CONSIDERATION in implementation file.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void releasePool(void); void releasePool(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Drain the pool. /// \brief Drain the pool
/// ///
/// releasePool must be called at least once before drainPool. /// releasePool must be called at least once before drainPool.
/// ///

View File

@ -26,12 +26,12 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/ThreadLocalPtr.hpp>
#import <Foundation/Foundation.h>
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h> #import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
#import <Foundation/Foundation.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -43,7 +43,7 @@
/// We use an sf::ThreadLocalPtr to have one PoolWrapper in each thread. /// We use an sf::ThreadLocalPtr to have one PoolWrapper in each thread.
/// ///
/// SPECIAL CONSIDERATION: /// SPECIAL CONSIDERATION:
/// ======================= /// ======================
/// This implies that if retainPool is called X times in a thread Y then /// 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. /// releasePool must be called X times too in the same thread Y.
/// ///
@ -54,10 +54,11 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief C++ Wrapper of Obj-C Autorelease Pool. /// \brief C++ Wrapper of Obj-C Autorelease Pool
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class PoolWrapper : NonCopyable { class PoolWrapper : NonCopyable
{
public : public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -101,9 +102,9 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
PoolWrapper::PoolWrapper() PoolWrapper::PoolWrapper() :
: m_count(0) m_count(0),
, m_pool(0) m_pool(0)
{ {
/* Nothing else */ /* Nothing else */
} }
@ -113,17 +114,16 @@ PoolWrapper::PoolWrapper()
PoolWrapper::~PoolWrapper() PoolWrapper::~PoolWrapper()
{ {
#ifdef SFML_DEBUG #ifdef SFML_DEBUG
if (m_count < 0) { if (m_count < 0)
sf::err() << "~PoolWrapper : m_count is less than zero! " sf::err() << "~PoolWrapper : m_count is less than zero! "
"You called releasePool from a thread too many times." "You called releasePool from a thread too many times."
<< std::endl; << std::endl;
} else if (m_count > 0) { else if (m_count > 0)
sf::err() << "~PoolWrapper : m_count is greater than zero! " sf::err() << "~PoolWrapper : m_count is greater than zero! "
"You called releasePool from a thread to few times." "You called releasePool from a thread to few times."
<< std::endl; << std::endl;
} else { // m_count == 0 else // m_count == 0
sf::err() << "~PoolWrapper is HAPPY!" << std::endl; sf::err() << "~PoolWrapper is HAPPY!" << std::endl;
}
#endif #endif
} }
@ -135,14 +135,12 @@ void PoolWrapper::retain()
++m_count; ++m_count;
// Allocate pool if required. // Allocate pool if required.
if (m_pool == 0) { if (m_pool == 0)
m_pool = [[NSAutoreleasePool alloc] init]; m_pool = [[NSAutoreleasePool alloc] init];
}
#ifdef SFML_DEBUG #ifdef SFML_DEBUG
if (m_count <= 0) { if (m_count <= 0)
sf::err() << "PoolWrapper::retain : m_count <= 0! " << std::endl; sf::err() << "PoolWrapper::retain : m_count <= 0! " << std::endl;
}
#endif #endif
} }
@ -154,14 +152,12 @@ void PoolWrapper::release()
--m_count; --m_count;
// Drain pool if required. // Drain pool if required.
if (m_count == 0) { if (m_count == 0)
drain(); drain();
}
#ifdef SFML_DEBUG #ifdef SFML_DEBUG
if (m_count < 0) { if (m_count < 0)
sf::err() << "PoolWrapper::release : m_count < 0! " << std::endl; sf::err() << "PoolWrapper::release : m_count < 0! " << std::endl;
}
#endif #endif
} }
@ -170,10 +166,9 @@ void PoolWrapper::drain()
[m_pool drain]; [m_pool drain];
m_pool = 0; m_pool = 0;
if (m_count != 0) { if (m_count != 0)
m_pool = [[NSAutoreleasePool alloc] init]; m_pool = [[NSAutoreleasePool alloc] init];
} }
}
} // namespace priv } // namespace priv
@ -194,9 +189,8 @@ namespace
void retainPool(void) void retainPool(void)
{ {
// First, Check that we have a valid PoolWrapper object in our local pool. // First, Check that we have a valid PoolWrapper object in our local pool.
if (localPool == NULL) { if (localPool == NULL)
localPool = new sf::priv::PoolWrapper(); localPool = new sf::priv::PoolWrapper();
}
// Then retains! // Then retains!
localPool->retain(); localPool->retain();
@ -206,19 +200,13 @@ void retainPool(void)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void releasePool(void) void releasePool(void)
{ {
if (localPool != NULL)
localPool->release();
#ifdef SFML_DEBUG #ifdef SFML_DEBUG
if (localPool == NULL) { else
sf::err() << "releasePool : You must call retainPool at least once " sf::err() << "releasePool : You must call retainPool at least once "
"in this thread before calling releasePool." "in this thread before calling releasePool."
<< std::endl; << std::endl;
} else {
#endif
// Releases, that's all.
localPool->release();
#ifdef SFML_DEBUG
}
#endif #endif
} }
@ -226,14 +214,12 @@ void releasePool(void)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void drainPool() void drainPool()
{ {
if (localPool != NULL) { if (localPool != NULL)
localPool->drain(); localPool->drain();
}
#ifdef SFML_DEBUG #ifdef SFML_DEBUG
else { else
sf::err() << "releasePool must be called at least one before drainPool" sf::err() << "releasePool must be called at least one before drainPool"
<< std::endl; << std::endl;
}
#endif #endif
} }

View File

@ -29,13 +29,13 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <SFML/Window/JoystickImpl.hpp> #include <SFML/Window/JoystickImpl.hpp>
#include <SFML/Window/Keyboard.hpp> #include <SFML/Window/Keyboard.hpp>
#include <SFML/Window/Mouse.hpp> #include <SFML/Window/Mouse.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <Carbon/Carbon.h> #include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/hid/IOHIDDevice.h> #include <IOKit/hid/IOHIDDevice.h>
#include <IOKit/hid/IOHIDManager.h>
#include <vector> #include <vector>
namespace sf namespace sf
@ -46,9 +46,10 @@ namespace priv
typedef std::vector<IOHIDElementRef> IOHIDElements; typedef std::vector<IOHIDElementRef> IOHIDElements;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief This class manage as a singleton instance the /// \brief sf::priv::InputImpl helper
/// keyboard and mouse states. It's only purpose is ///
/// to help sf::priv::InputImpl class. /// This class manage as a singleton instance the keyboard and mouse states.
/// It's only purpose is to help sf::priv::InputImpl class.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class HIDInputManager : NonCopyable class HIDInputManager : NonCopyable
@ -211,7 +212,7 @@ private :
void freeUp(); void freeUp();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Filter the devices and return them. /// \brief Filter the devices and return them
/// ///
/// freeUp is _not_ called by this function. /// freeUp is _not_ called by this function.
/// ///

View File

@ -63,15 +63,13 @@ long HIDInputManager::getLocationID(IOHIDDeviceRef device)
// Get a unique ID: its usb location ID // Get a unique ID: its usb location ID
CFTypeRef typeRef = IOHIDDeviceGetProperty(device, CFTypeRef typeRef = IOHIDDeviceGetProperty(device,
CFSTR(kIOHIDLocationIDKey)); CFSTR(kIOHIDLocationIDKey));
if (!typeRef || CFGetTypeID(typeRef) != CFNumberGetTypeID()) { if (!typeRef || (CFGetTypeID(typeRef) != CFNumberGetTypeID()))
return 0; return 0;
}
CFNumberRef locRef = (CFNumberRef)typeRef; CFNumberRef locRef = (CFNumberRef)typeRef;
if (!CFNumberGetValue(locRef, kCFNumberLongType, &loc)) { if (!CFNumberGetValue(locRef, kCFNumberLongType, &loc))
return 0; return 0;
}
return loc; return loc;
} }
@ -100,18 +98,19 @@ CFDictionaryRef HIDInputManager::copyDevicesMask(UInt32 page, UInt32 usage)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
HIDInputManager::HIDInputManager() HIDInputManager::HIDInputManager() :
: m_isValid(true) m_isValid(true),
, m_layoutData(0) m_layoutData(0),
, m_layout(0) m_layout(0),
, m_manager(0) m_manager(0)
{ {
// Get the current keyboard layout // Get the current keyboard layout
TISInputSourceRef tis = TISCopyCurrentKeyboardLayoutInputSource(); TISInputSourceRef tis = TISCopyCurrentKeyboardLayoutInputSource();
m_layoutData = (CFDataRef)TISGetInputSourceProperty(tis, m_layoutData = (CFDataRef)TISGetInputSourceProperty(tis,
kTISPropertyUnicodeKeyLayoutData); kTISPropertyUnicodeKeyLayoutData);
if (m_layoutData == 0) { if (m_layoutData == 0)
{
sf::err() << "Cannot get the keyboard layout" << std::endl; sf::err() << "Cannot get the keyboard layout" << std::endl;
freeUp(); freeUp();
return; return;
@ -130,9 +129,9 @@ HIDInputManager::HIDInputManager()
// Open the HID Manager reference // Open the HID Manager reference
IOReturn openStatus = IOHIDManagerOpen(m_manager, kIOHIDOptionsTypeNone); IOReturn openStatus = IOHIDManagerOpen(m_manager, kIOHIDOptionsTypeNone);
if (openStatus != kIOReturnSuccess) { if (openStatus != kIOReturnSuccess)
{
sf::err() << "Error when opening the HID manager" << std::endl; sf::err() << "Error when opening the HID manager" << std::endl;
freeUp(); freeUp();
return; return;
} }
@ -168,7 +167,8 @@ void HIDInputManager::initializeKeyboard()
// Get only keyboards // Get only keyboards
CFSetRef keyboards = copyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard); CFSetRef keyboards = copyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
if (keyboards == NULL) { if (keyboards == NULL)
{
freeUp(); freeUp();
return; return;
} }
@ -179,10 +179,9 @@ void HIDInputManager::initializeKeyboard()
CFTypeRef devicesArray[keyboardCount]; CFTypeRef devicesArray[keyboardCount];
CFSetGetValues(keyboards, devicesArray); CFSetGetValues(keyboards, devicesArray);
for (CFIndex i = 0; i < keyboardCount; ++i) { for (CFIndex i = 0; i < keyboardCount; ++i)
{
IOHIDDeviceRef keyboard = (IOHIDDeviceRef)devicesArray[i]; IOHIDDeviceRef keyboard = (IOHIDDeviceRef)devicesArray[i];
loadKeyboard(keyboard); loadKeyboard(keyboard);
} }
@ -203,7 +202,8 @@ void HIDInputManager::initializeMouse()
// Get only mouses // Get only mouses
CFSetRef mouses = copyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse); CFSetRef mouses = copyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse);
if (mouses == NULL) { if (mouses == NULL)
{
freeUp(); freeUp();
return; return;
} }
@ -214,10 +214,9 @@ void HIDInputManager::initializeMouse()
CFTypeRef devicesArray[mouseCount]; CFTypeRef devicesArray[mouseCount];
CFSetGetValues(mouses, devicesArray); CFSetGetValues(mouses, devicesArray);
for (CFIndex i = 0; i < mouseCount; ++i) { for (CFIndex i = 0; i < mouseCount; ++i)
{
IOHIDDeviceRef mouse = (IOHIDDeviceRef)devicesArray[i]; IOHIDDeviceRef mouse = (IOHIDDeviceRef)devicesArray[i];
loadMouse(mouse); loadMouse(mouse);
} }
@ -235,7 +234,8 @@ void HIDInputManager::loadKeyboard(IOHIDDeviceRef keyboard)
CFArrayRef keys = IOHIDDeviceCopyMatchingElements(keyboard, CFArrayRef keys = IOHIDDeviceCopyMatchingElements(keyboard,
NULL, NULL,
kIOHIDOptionsTypeNone); kIOHIDOptionsTypeNone);
if (keys == NULL) { if (keys == NULL)
{
sf::err() << "We got a keyboard without any keys (1)" << std::endl; sf::err() << "We got a keyboard without any keys (1)" << std::endl;
return; return;
} }
@ -243,24 +243,23 @@ void HIDInputManager::loadKeyboard(IOHIDDeviceRef keyboard)
// How many elements are there? // How many elements are there?
CFIndex keysCount = CFArrayGetCount(keys); CFIndex keysCount = CFArrayGetCount(keys);
if (keysCount == 0) { if (keysCount == 0)
{
sf::err() << "We got a keyboard without any keys (2)" << std::endl; sf::err() << "We got a keyboard without any keys (2)" << std::endl;
CFRelease(keys); CFRelease(keys);
return; return;
} }
// Go through all connected elements. // Go through all connected elements.
for (CFIndex i = 0; i < keysCount; ++i) { for (CFIndex i = 0; i < keysCount; ++i)
{
IOHIDElementRef aKey = (IOHIDElementRef) CFArrayGetValueAtIndex(keys, i); IOHIDElementRef aKey = (IOHIDElementRef) CFArrayGetValueAtIndex(keys, i);
// Skip non-matching keys elements // Skip non-matching keys elements
if (IOHIDElementGetUsagePage(aKey) != kHIDPage_KeyboardOrKeypad) { if (IOHIDElementGetUsagePage(aKey) != kHIDPage_KeyboardOrKeypad)
continue; continue;
}
loadKey(aKey); loadKey(aKey);
} }
// Release unused stuff // Release unused stuff
@ -274,7 +273,8 @@ void HIDInputManager::loadMouse(IOHIDDeviceRef mouse)
CFArrayRef buttons = IOHIDDeviceCopyMatchingElements(mouse, CFArrayRef buttons = IOHIDDeviceCopyMatchingElements(mouse,
NULL, NULL,
kIOHIDOptionsTypeNone); kIOHIDOptionsTypeNone);
if (buttons == NULL) { if (buttons == NULL)
{
sf::err() << "We got a mouse without any buttons (1)" << std::endl; sf::err() << "We got a mouse without any buttons (1)" << std::endl;
return; return;
} }
@ -282,21 +282,21 @@ void HIDInputManager::loadMouse(IOHIDDeviceRef mouse)
// How many elements are there? // How many elements are there?
CFIndex buttonCount = CFArrayGetCount(buttons); CFIndex buttonCount = CFArrayGetCount(buttons);
if (buttonCount == 0) { if (buttonCount == 0)
{
sf::err() << "We got a mouse without any buttons (2)" << std::endl; sf::err() << "We got a mouse without any buttons (2)" << std::endl;
CFRelease(buttons); CFRelease(buttons);
return; return;
} }
// Go through all connected elements. // Go through all connected elements.
for (CFIndex i = 0; i < buttonCount; ++i) { for (CFIndex i = 0; i < buttonCount; ++i)
{
IOHIDElementRef aButton = (IOHIDElementRef) CFArrayGetValueAtIndex(buttons, i); IOHIDElementRef aButton = (IOHIDElementRef) CFArrayGetValueAtIndex(buttons, i);
// Skip non-matching keys elements // Skip non-matching keys elements
if (IOHIDElementGetUsagePage(aButton) != kHIDPage_Button) { if (IOHIDElementGetUsagePage(aButton) != kHIDPage_Button)
continue; continue;
}
loadButton(aButton); loadButton(aButton);
} }
@ -313,9 +313,8 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
UInt32 usageCode = IOHIDElementGetUsage(key); UInt32 usageCode = IOHIDElementGetUsage(key);
UInt8 virtualCode = usageToVirtualCode(usageCode); UInt8 virtualCode = usageToVirtualCode(usageCode);
if (virtualCode == 0xff) { if (virtualCode == 0xff)
return; // no corresponding virtual code -> skip return; // no corresponding virtual code -> skip
}
// Now translate the virtual code to unicode according to // Now translate the virtual code to unicode according to
// the current keyboard layout // the current keyboard layout
@ -339,7 +338,8 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
&actualStringLength, // length of what we get &actualStringLength, // length of what we get
unicodeString); // what we get unicodeString); // what we get
if (error == noErr) { if (error == noErr)
{
// Translation went fine // Translation went fine
// The corresponding SFML key code // The corresponding SFML key code
@ -347,27 +347,23 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
// First we look if the key down is from a list of characters // First we look if the key down is from a list of characters
// that depend on keyboard localization // that depend on keyboard localization
if (actualStringLength > 0) { if (actualStringLength > 0)
code = localizedKeys(unicodeString[0]); code = localizedKeys(unicodeString[0]);
}
// The key is not a localized one so we try to find a // The key is not a localized one so we try to find a
// corresponding code through virtual key code // corresponding code through virtual key code
if (code == Keyboard::Unknown) { if (code == Keyboard::Unknown)
code = nonLocalizedKeys(virtualCode); code = nonLocalizedKeys(virtualCode);
}
// A code was found, wonderful! // A code was found, wonderful!
if (code != Keyboard::Unknown) { if (code != Keyboard::Unknown)
{
// Ok, everything went fine. Now we have a unique // Ok, everything went fine. Now we have a unique
// corresponding sf::Keyboard::Key to one IOHIDElementRef // corresponding sf::Keyboard::Key to one IOHIDElementRef
m_keys[code].push_back(key); m_keys[code].push_back(key);
// And don't forget to keep the reference alive for our usage // And don't forget to keep the reference alive for our usage
CFRetain(m_keys[code].back()); CFRetain(m_keys[code].back());
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -392,8 +388,8 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
//} //}
} /* if (error == noErr) */ } /* if (error == noErr) */
else { else
{
sf::err() << "Cannot translate the virtual key code, error : " sf::err() << "Cannot translate the virtual key code, error : "
<< error << error
<< std::endl; << std::endl;
@ -411,7 +407,8 @@ void HIDInputManager::loadButton(IOHIDElementRef button)
// Extends kHIDUsage_Button_* enum with: // Extends kHIDUsage_Button_* enum with:
#define kHIDUsage_Button_5 0x05 #define kHIDUsage_Button_5 0x05
switch (usage) { switch (usage)
{
case kHIDUsage_Button_1: dest = Mouse::Left; break; case kHIDUsage_Button_1: dest = Mouse::Left; break;
case kHIDUsage_Button_2: dest = Mouse::Right; break; case kHIDUsage_Button_2: dest = Mouse::Right; break;
case kHIDUsage_Button_3: dest = Mouse::Middle; break; case kHIDUsage_Button_3: dest = Mouse::Middle; break;
@ -420,9 +417,9 @@ void HIDInputManager::loadButton(IOHIDElementRef button)
default: dest = Mouse::ButtonCount; break; default: dest = Mouse::ButtonCount; break;
} }
if (dest != Mouse::ButtonCount) { if (dest != Mouse::ButtonCount)
{
// We know what kind of button it is! // We know what kind of button it is!
m_buttons[dest].push_back(button); m_buttons[dest].push_back(button);
// And don't forget to keep the reference alive for our usage // And don't forget to keep the reference alive for our usage
@ -436,21 +433,25 @@ void HIDInputManager::freeUp()
{ {
m_isValid = false; m_isValid = false;
if (m_layoutData != 0) CFRelease(m_layoutData); if (m_layoutData != 0)
CFRelease(m_layoutData);
// Do not release m_layout! It is owned by m_layoutData. // Do not release m_layout! It is owned by m_layoutData.
if (m_manager != 0) CFRelease(m_manager); if (m_manager != 0)
CFRelease(m_manager);
for (unsigned int i = 0; i < Keyboard::KeyCount; ++i) { for (unsigned int i = 0; i < Keyboard::KeyCount; ++i)
for (IOHIDElements::iterator it = m_keys[i].begin(); it != m_keys[i].end(); ++it) { {
for (IOHIDElements::iterator it = m_keys[i].begin(); it != m_keys[i].end(); ++it)
CFRelease(*it); CFRelease(*it);
}
m_keys[i].clear(); m_keys[i].clear();
} }
for (unsigned int i = 0; i < Mouse::ButtonCount; ++i) { for (unsigned int i = 0; i < Mouse::ButtonCount; ++i)
for (IOHIDElements::iterator it = m_buttons[i].begin(); it != m_buttons[i].end(); ++it) { {
for (IOHIDElements::iterator it = m_buttons[i].begin(); it != m_buttons[i].end(); ++it)
CFRelease(*it); CFRelease(*it);
}
m_buttons[i].clear(); m_buttons[i].clear();
} }
} }
@ -468,13 +469,13 @@ CFSetRef HIDInputManager::copyDevices(UInt32 page, UInt32 usage)
mask = 0; mask = 0;
CFSetRef devices = IOHIDManagerCopyDevices(m_manager); CFSetRef devices = IOHIDManagerCopyDevices(m_manager);
if (devices == NULL) { if (devices == NULL)
return NULL; return NULL;
}
// Is there at least one device? // Is there at least one device?
CFIndex deviceCount = CFSetGetCount(devices); CFIndex deviceCount = CFSetGetCount(devices);
if (deviceCount < 1) { if (deviceCount < 1)
{
CFRelease(devices); CFRelease(devices);
return NULL; return NULL;
} }
@ -484,7 +485,8 @@ CFSetRef HIDInputManager::copyDevices(UInt32 page, UInt32 usage)
bool HIDInputManager::isPressed(IOHIDElements& elements) bool HIDInputManager::isPressed(IOHIDElements& elements)
{ {
if (!m_isValid) { if (!m_isValid)
{
sf::err() << "HIDInputManager is invalid." << std::endl; sf::err() << "HIDInputManager is invalid." << std::endl;
return false; return false;
} }
@ -492,33 +494,31 @@ bool HIDInputManager::isPressed(IOHIDElements& elements)
// state = true if at least one corresponding HID button is pressed // state = true if at least one corresponding HID button is pressed
bool state = false; bool state = false;
for (IOHIDElements::iterator it = elements.begin(); it != elements.end();) { for (IOHIDElements::iterator it = elements.begin(); it != elements.end(); /* noop */)
{
IOHIDValueRef value = 0; IOHIDValueRef value = 0;
IOHIDDeviceRef device = IOHIDElementGetDevice(*it); IOHIDDeviceRef device = IOHIDElementGetDevice(*it);
IOHIDDeviceGetValue(device, *it, &value); IOHIDDeviceGetValue(device, *it, &value);
if (!value) { if (!value)
{
// This means some kind of error / disconnection so we remove this // This means some kind of error / disconnection so we remove this
// element from our buttons // element from our buttons
CFRelease(*it); CFRelease(*it);
it = elements.erase(it); it = elements.erase(it);
}
} else if (IOHIDValueGetIntegerValue(value) == 1) { else if (IOHIDValueGetIntegerValue(value) == 1)
{
// This means the button is pressed // This means the button is pressed
state = true; state = true;
break; // Stop here break; // Stop here
}
} else { else
{
// This means the button is released // This means the button is released
++it; ++it;
} }
} }
return state; return state;
@ -530,7 +530,8 @@ UInt8 HIDInputManager::usageToVirtualCode(UInt32 usage)
{ {
// Some usage key doesn't have any corresponding virtual // Some usage key doesn't have any corresponding virtual
// code or it was not found (return 0xff). // code or it was not found (return 0xff).
switch (usage) { switch (usage)
{
case kHIDUsage_KeyboardErrorRollOver: return 0xff; case kHIDUsage_KeyboardErrorRollOver: return 0xff;
case kHIDUsage_KeyboardPOSTFail: return 0xff; case kHIDUsage_KeyboardPOSTFail: return 0xff;
case kHIDUsage_KeyboardErrorUndefined: return 0xff; case kHIDUsage_KeyboardErrorUndefined: return 0xff;
@ -734,7 +735,8 @@ UInt8 HIDInputManager::usageToVirtualCode(UInt32 usage)
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
Keyboard::Key HIDInputManager::localizedKeys(UniChar ch) Keyboard::Key HIDInputManager::localizedKeys(UniChar ch)
{ {
switch (ch) { switch (ch)
{
case 'a': case 'a':
case 'A': return sf::Keyboard::A; case 'A': return sf::Keyboard::A;
@ -824,7 +826,8 @@ Keyboard::Key HIDInputManager::nonLocalizedKeys(UniChar virtualKeycode)
{ {
// (Some) 0x code based on http://forums.macrumors.com/showthread.php?t=780577 // (Some) 0x code based on http://forums.macrumors.com/showthread.php?t=780577
// Some sf::Keyboard::Key are present twice. // Some sf::Keyboard::Key are present twice.
switch (virtualKeycode) { switch (virtualKeycode)
{
// These cases should not be used but anyway... // These cases should not be used but anyway...
case 0x00: return sf::Keyboard::A; case 0x00: return sf::Keyboard::A;
case 0x0b: return sf::Keyboard::B; case 0x0b: return sf::Keyboard::B;

View File

@ -26,8 +26,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/HIDJoystickManager.hpp>
#include <SFML/Window/OSX/HIDInputManager.hpp> #include <SFML/Window/OSX/HIDInputManager.hpp>
#include <SFML/Window/OSX/HIDJoystickManager.hpp>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Private data // Private data
@ -36,7 +36,7 @@ namespace
{ {
// Using a custom run loop mode solve some issues that appears when SFML // Using a custom run loop mode solve some issues that appears when SFML
// is used with Cocoa. // is used with Cocoa.
CFStringRef const RunLoopMode = CFSTR("SFML_RUN_LOOP_MODE"); const CFStringRef RunLoopMode = CFSTR("SFML_RUN_LOOP_MODE");
} }
@ -69,9 +69,9 @@ CFSetRef HIDJoystickManager::copyJoysticks()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
HIDJoystickManager::HIDJoystickManager() HIDJoystickManager::HIDJoystickManager() :
: m_manager(0) m_manager(0),
, m_joystickCount(0) m_joystickCount(0)
{ {
m_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); m_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
@ -123,7 +123,8 @@ void HIDJoystickManager::update()
{ {
SInt32 status = kCFRunLoopRunHandledSource; SInt32 status = kCFRunLoopRunHandledSource;
while (status == kCFRunLoopRunHandledSource) { while (status == kCFRunLoopRunHandledSource)
{
status = CFRunLoopRunInMode(RunLoopMode, 0, true); status = CFRunLoopRunInMode(RunLoopMode, 0, true);
} }
} }

View File

@ -30,17 +30,18 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp> #include <SFML/System/NonCopyable.hpp>
#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/hid/IOHIDDevice.h> #include <IOKit/hid/IOHIDDevice.h>
#include <IOKit/hid/IOHIDManager.h>
namespace sf namespace sf
{ {
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief This class manage as a singleton instance the /// \brief sf::priv::InputImpl helper
/// joysticks. It's only purpose is ///
/// to help sf::priv::JoystickImpl class. /// This class manage as a singleton instance the joysticks.
/// It's only purpose is to help sf::priv::JoystickImpl class.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class HIDJoystickManager : NonCopyable class HIDJoystickManager : NonCopyable
@ -66,7 +67,7 @@ public :
unsigned int getJoystickCount(); unsigned int getJoystickCount();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Copy the devices assosiated with this HID manager /// \brief Copy the devices associated with this HID manager
/// ///
/// \return a retained CFSetRef of IOHIDDeviceRef or NULL /// \return a retained CFSetRef of IOHIDDeviceRef or NULL
/// ///
@ -88,7 +89,7 @@ private :
~HIDJoystickManager(); ~HIDJoystickManager();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Make sur all event have been processed in the run loop /// \brief Make sure all event have been processed in the run loop
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void update(); void update();
@ -97,7 +98,7 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Private "plug-in" callback /// \brief Private "plug-in" callback
/// \note Only 'context' parametre is used. /// \note Only 'context' parameter is used.
/// \see IOHIDDeviceCallback /// \see IOHIDDeviceCallback
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -105,7 +106,7 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Private "plug-out" callback /// \brief Private "plug-out" callback
/// \note Only 'context' parametre is used. /// \note Only 'context' parameter is used.
/// \see IOHIDDeviceCallback /// \see IOHIDDeviceCallback
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -26,14 +26,14 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/InputImpl.hpp>
#include <SFML/Window/VideoMode.hpp> #include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/Window.hpp> #include <SFML/Window/Window.hpp>
#include <SFML/System/Err.hpp> #include <SFML/Window/OSX/InputImpl.hpp>
#include <SFML/Window/OSX/HIDInputManager.hpp> #include <SFML/Window/OSX/HIDInputManager.hpp>
#include <SFML/System/Err.hpp>
#import <AppKit/AppKit.h>
#import <SFML/Window/OSX/SFOpenGLView.h> #import <SFML/Window/OSX/SFOpenGLView.h>
#import <AppKit/AppKit.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// In order to keep track of the keyboard's state and mouse buttons' state /// In order to keep track of the keyboard's state and mouse buttons' state
@ -62,42 +62,44 @@ SFOpenGLView* getSFOpenGLViewFromSFMLWindow(const Window& window)
// Get our SFOpenGLView from ... // Get our SFOpenGLView from ...
SFOpenGLView* view = nil; SFOpenGLView* view = nil;
if ([nsHandle isKindOfClass:[NSWindow class]]) { if ([nsHandle isKindOfClass:[NSWindow class]])
{
// If system handle is a window then from its content view. // If system handle is a window then from its content view.
view = [nsHandle contentView]; view = [nsHandle contentView];
// Subview doesn't match ? // Subview doesn't match ?
if (![view isKindOfClass:[SFOpenGLView class]]) { if (![view isKindOfClass:[SFOpenGLView class]])
{
sf::err() << "The content view is not a valid SFOpenGLView" sf::err() << "The content view is not a valid SFOpenGLView"
<< std::endl; << std::endl;
view = nil; view = nil;
} }
} else if ([nsHandle isKindOfClass:[NSView class]]) { }
else if ([nsHandle isKindOfClass:[NSView class]])
{
// If system handle is a view then from a subview of kind SFOpenGLView. // If system handle is a view then from a subview of kind SFOpenGLView.
NSArray* subviews = [nsHandle subviews]; NSArray* subviews = [nsHandle subviews];
for (NSView* subview in subviews) { for (NSView* subview in subviews)
if ([subview isKindOfClass:[SFOpenGLView class]]) { {
if ([subview isKindOfClass:[SFOpenGLView class]])
{
view = (SFOpenGLView*)subview; view = (SFOpenGLView*)subview;
break; break;
} }
} }
// No matching subview ? // No matching subview ?
if (view == nil) { if (view == nil)
sf::err() << "Cannot find a valid SFOpenGLView subview." << std::endl; sf::err() << "Cannot find a valid SFOpenGLView subview." << std::endl;
} }
else
} else { {
if (nsHandle != 0) { if (nsHandle != 0)
sf::err() << "The system handle is neither a <NSWindow*> nor <NSView*>" sf::err() << "The system handle is neither a <NSWindow*> nor <NSView*>"
<< "object. This shouldn't happen." << "object. This shouldn't happen."
<< std::endl; << std::endl;
} else { // Else: this probably means the SFML window was previously closed.
// This probably means the SFML window was previously closed.
}
} }
return view; return view;
@ -134,9 +136,8 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo)
SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo); SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo);
// No view ? // No view ?
if (view == nil) { if (view == nil)
return Vector2i(); return Vector2i();
}
// Use -cursorPositionFromEvent: with nil. // Use -cursorPositionFromEvent: with nil.
NSPoint pos = [view cursorPositionFromEvent:nil]; NSPoint pos = [view cursorPositionFromEvent:nil];
@ -168,9 +169,8 @@ void InputImpl::setMousePosition(const Vector2i& position, const Window& relativ
SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo); SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo);
// No view ? // No view ?
if (view == nil) { if (view == nil)
return; return;
}
// Let SFOpenGLView compute the position in global coordinate // Let SFOpenGLView compute the position in global coordinate
NSPoint p = NSMakePoint(position.x, position.y); NSPoint p = NSMakePoint(position.x, position.y);

View File

@ -69,57 +69,60 @@ bool JoystickImpl::isConnected(unsigned int index)
bool state = false; // Is the index-th joystick connected? bool state = false; // Is the index-th joystick connected?
// First, let's check if the device was previously detected: // First, let's check if the device was previously detected:
if (m_locationIDs[index] != 0)
if (m_locationIDs[index] != 0) { {
state = true; state = true;
} }
else
// Otherwise, let's check if it is now connected : {
else { // i.e., m_locationIDs[index] == 0 // Otherwise, let's check if it is now connected
// i.e., m_locationIDs[index] == 0
// if there is more connected joystick to the HID manager than // if there is more connected joystick to the HID manager than
// opened joystick devices then we find the new one. // opened joystick devices then we find the new one.
unsigned int openedCount = 0; unsigned int openedCount = 0;
for (unsigned int i(0); i < sf::Joystick::Count; ++i) { for (unsigned int i(0); i < sf::Joystick::Count; ++i)
if (m_locationIDs[i] != 0) openedCount++; {
if (m_locationIDs[i] != 0)
openedCount++;
} }
unsigned int connectedCount = HIDJoystickManager::getInstance().getJoystickCount(); unsigned int connectedCount = HIDJoystickManager::getInstance().getJoystickCount();
if (connectedCount > openedCount) { if (connectedCount > openedCount)
{
// Get all devices // Get all devices
CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks();
if (devices != NULL) { if (devices != NULL)
{
CFIndex size = CFSetGetCount(devices); CFIndex size = CFSetGetCount(devices);
if (size > 0)
if (size > 0) { {
CFTypeRef array[size]; // array of IOHIDDeviceRef CFTypeRef array[size]; // array of IOHIDDeviceRef
CFSetGetValues(devices, array); CFSetGetValues(devices, array);
// If there exists a device d s.t. there is no j s.t. // If there exists a device d s.t. there is no j s.t.
// m_locationIDs[j] == d's location then we have a new device. // m_locationIDs[j] == d's location then we have a new device.
for (CFIndex didx(0); didx < size; ++didx) { for (CFIndex didx(0); didx < size; ++didx)
{
IOHIDDeviceRef d = (IOHIDDeviceRef)array[didx]; IOHIDDeviceRef d = (IOHIDDeviceRef)array[didx];
Location dloc = HIDInputManager::getLocationID(d); Location dloc = HIDInputManager::getLocationID(d);
bool foundJ = false; bool foundJ = false;
for (unsigned int j(0); j < Joystick::Count; ++j) { for (unsigned int j(0); j < Joystick::Count; ++j)
if (m_locationIDs[j] == dloc) { {
if (m_locationIDs[j] == dloc)
{
foundJ = true; foundJ = true;
break; // no need to loop again break; // no need to loop again
} }
} }
if (foundJ) { if (!foundJ) {
// This is a known device
// Nothing else to do
} else {
// This is a new device // This is a new device
// We set it up for Open(..) // We set it up for Open(..)
m_locationIDs[index] = dloc; m_locationIDs[index] = dloc;
@ -127,7 +130,6 @@ bool JoystickImpl::isConnected(unsigned int index)
break; // We stop looking for a new device break; // We stop looking for a new device
} }
} }
} }
CFRelease(devices); CFRelease(devices);
@ -147,9 +149,8 @@ bool JoystickImpl::open(unsigned int index)
// Get all devices // Get all devices
CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks();
if (devices == NULL) { if (devices == NULL)
return false; return false;
}
// Get a usable copy of the joysticks devices. // Get a usable copy of the joysticks devices.
CFIndex joysticksCount = CFSetGetCount(devices); CFIndex joysticksCount = CFSetGetCount(devices);
@ -158,15 +159,18 @@ bool JoystickImpl::open(unsigned int index)
// Get the desired joystick. // Get the desired joystick.
IOHIDDeviceRef self = 0; IOHIDDeviceRef self = 0;
for (CFIndex i(0); i < joysticksCount; ++i) { for (CFIndex i(0); i < joysticksCount; ++i)
{
IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i]; IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i];
if (deviceLoc == HIDInputManager::getLocationID(d)) { if (deviceLoc == HIDInputManager::getLocationID(d))
{
self = d; self = d;
break; // We found it so we stop looping. break; // We found it so we stop looping.
} }
} }
if (self == 0) { if (self == 0)
{
// This shouldn't happen! // This shouldn't happen!
CFRelease(devices); CFRelease(devices);
return false; return false;
@ -177,11 +181,10 @@ bool JoystickImpl::open(unsigned int index)
m_identification.productId = getDeviceUint(self, CFSTR(kIOHIDProductIDKey)); m_identification.productId = getDeviceUint(self, CFSTR(kIOHIDProductIDKey));
// Get a list of all elements attached to the device. // Get a list of all elements attached to the device.
CFArrayRef elements = IOHIDDeviceCopyMatchingElements(self, CFArrayRef elements = IOHIDDeviceCopyMatchingElements(self, NULL, kIOHIDOptionsTypeNone);
NULL,
kIOHIDOptionsTypeNone);
if (elements == NULL) { if (elements == NULL)
{
CFRelease(devices); CFRelease(devices);
return false; return false;
} }
@ -189,7 +192,8 @@ bool JoystickImpl::open(unsigned int index)
// How many elements are there? // How many elements are there?
CFIndex elementsCount = CFArrayGetCount(elements); CFIndex elementsCount = CFArrayGetCount(elements);
if (elementsCount == 0) { if (elementsCount == 0)
{
// What is a joystick with no element? // What is a joystick with no element?
CFRelease(elements); CFRelease(elements);
CFRelease(devices); CFRelease(devices);
@ -197,48 +201,28 @@ bool JoystickImpl::open(unsigned int index)
} }
// Go through all connected elements. // Go through all connected elements.
for (int i = 0; i < elementsCount; ++i) { for (int i = 0; i < elementsCount; ++i)
{
IOHIDElementRef element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i); IOHIDElementRef element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i);
switch (IOHIDElementGetType(element))
switch (IOHIDElementGetType(element)) { {
case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Misc:
switch (IOHIDElementGetUsage(element)) { switch (IOHIDElementGetUsage(element))
{
case kHIDUsage_GD_X: case kHIDUsage_GD_X: m_axis[Joystick::X] = element; break;
m_axis[Joystick::X] = element; case kHIDUsage_GD_Y: m_axis[Joystick::Y] = element; break;
break; case kHIDUsage_GD_Z: m_axis[Joystick::Z] = element; break;
case kHIDUsage_GD_Rx: m_axis[Joystick::U] = element; break;
case kHIDUsage_GD_Y: case kHIDUsage_GD_Ry: m_axis[Joystick::V] = element; break;
m_axis[Joystick::Y] = element; case kHIDUsage_GD_Rz: m_axis[Joystick::R] = element; break;
break;
case kHIDUsage_GD_Z:
m_axis[Joystick::Z] = element;
break;
case kHIDUsage_GD_Rx:
m_axis[Joystick::U] = element;
break;
case kHIDUsage_GD_Ry:
m_axis[Joystick::V] = element;
break;
case kHIDUsage_GD_Rz:
m_axis[Joystick::R] = element;
break;
// kHIDUsage_GD_Vx, kHIDUsage_GD_Vy, kHIDUsage_GD_Vz are ignored. // kHIDUsage_GD_Vx, kHIDUsage_GD_Vy, kHIDUsage_GD_Vz are ignored.
} }
break; break;
case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Button:
if (m_buttons.size() < Joystick::ButtonCount) { // If we have free slot... if (m_buttons.size() < Joystick::ButtonCount) // If we have free slot...
m_buttons.push_back(element); // ...we add this element to the list m_buttons.push_back(element); // ...we add this element to the list
} else { // Else: too many buttons. We ignore this one.
// Too many buttons. We ignore this one.
}
break; break;
default: // Make compiler happy default: // Make compiler happy
@ -253,13 +237,11 @@ bool JoystickImpl::open(unsigned int index)
// Note : Joy::AxisPovX/Y are not supported (yet). // Note : Joy::AxisPovX/Y are not supported (yet).
// Maybe kIOHIDElementTypeInput_Axis is the corresponding type but I can't test. // Maybe kIOHIDElementTypeInput_Axis is the corresponding type but I can't test.
// Retain all these objets for personal use // Retain all these objects for personal use
for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it) { for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it)
CFRetain(*it); CFRetain(*it);
} for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it)
for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it) {
CFRetain(it->second); CFRetain(it->second);
}
// Note : we didn't retain element in the switch because we might have multiple // Note : we didn't retain element in the switch because we might have multiple
// Axis X (for example) and we want to keep only the last one. So to prevent // Axis X (for example) and we want to keep only the last one. So to prevent
@ -275,14 +257,12 @@ bool JoystickImpl::open(unsigned int index)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void JoystickImpl::close() void JoystickImpl::close()
{ {
for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it) { for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it)
CFRelease(*it); CFRelease(*it);
}
m_buttons.clear(); m_buttons.clear();
for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it) { for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it)
CFRelease(it->second); CFRelease(it->second);
}
m_axis.clear(); m_axis.clear();
// And we unregister this joystick // And we unregister this joystick
@ -329,9 +309,8 @@ JoystickState JoystickImpl::update()
// Get all devices // Get all devices
CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks();
if (devices == NULL) { if (devices == NULL)
return disconnectedState; return disconnectedState;
}
// Get a usable copy of the joysticks devices. // Get a usable copy of the joysticks devices.
CFIndex joysticksCount = CFSetGetCount(devices); CFIndex joysticksCount = CFSetGetCount(devices);
@ -340,9 +319,11 @@ JoystickState JoystickImpl::update()
// Search for it // Search for it
bool found = false; bool found = false;
for (CFIndex i(0); i < joysticksCount; ++i) { for (CFIndex i(0); i < joysticksCount; ++i)
{
IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i]; IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i];
if (selfLoc == HIDInputManager::getLocationID(d)) { if (selfLoc == HIDInputManager::getLocationID(d))
{
found = true; found = true;
break; // Stop looping break; // Stop looping
} }
@ -351,22 +332,20 @@ JoystickState JoystickImpl::update()
// Release unused stuff // Release unused stuff
CFRelease(devices); CFRelease(devices);
// Was it found ? // If not found we consider it disconnected
if (found) { if (!found)
// Yes, so we can continue.
} else {
// No, so we stop here
return disconnectedState; return disconnectedState;
}
// Update buttons' state // Update buttons' state
unsigned int i = 0; unsigned int i = 0;
for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it, ++i) { for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it, ++i)
{
IOHIDValueRef value = 0; IOHIDValueRef value = 0;
IOHIDDeviceGetValue(IOHIDElementGetDevice(*it), *it, &value); IOHIDDeviceGetValue(IOHIDElementGetDevice(*it), *it, &value);
// Check for plug out. // Check for plug out.
if (!value) { if (!value)
{
// No value? Hum... Seems like the joystick is gone // No value? Hum... Seems like the joystick is gone
return disconnectedState; return disconnectedState;
} }
@ -376,12 +355,14 @@ JoystickState JoystickImpl::update()
} }
// Update axes' state // Update axes' state
for (AxisMap::iterator it = m_axis.begin(); it != m_axis.end(); ++it) { for (AxisMap::iterator it = m_axis.begin(); it != m_axis.end(); ++it)
{
IOHIDValueRef value = 0; IOHIDValueRef value = 0;
IOHIDDeviceGetValue(IOHIDElementGetDevice(it->second), it->second, &value); IOHIDDeviceGetValue(IOHIDElementGetDevice(it->second), it->second, &value);
// Check for plug out. // Check for plug out.
if (!value) { if (!value)
{
// No value? Hum... Seems like the joystick is gone // No value? Hum... Seems like the joystick is gone
return disconnectedState; return disconnectedState;
} }
@ -401,11 +382,10 @@ JoystickState JoystickImpl::update()
double scaledMin = -100; double scaledMin = -100;
double scaledMax = 100; double scaledMax = 100;
double physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical); double physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical);
float scaledValue = ((physicalValue - physicalMin) * (scaledMax - scaledMin) / (physicalMax - physicalMin)) + scaledMin; float scaledValue = (((physicalValue - physicalMin) * (scaledMax - scaledMin)) / (physicalMax - physicalMin)) + scaledMin;
state.axes[it->first] = scaledValue; state.axes[it->first] = scaledValue;
} }
return state; return state;
} }
@ -414,13 +394,13 @@ JoystickState JoystickImpl::update()
std::string JoystickImpl::getDeviceString(IOHIDDeviceRef ref, CFStringRef prop) std::string JoystickImpl::getDeviceString(IOHIDDeviceRef ref, CFStringRef prop)
{ {
CFTypeRef typeRef = IOHIDDeviceGetProperty(ref, prop); CFTypeRef typeRef = IOHIDDeviceGetProperty(ref, prop);
if (ref && CFGetTypeID(typeRef) == CFStringGetTypeID()) if (ref && (CFGetTypeID(typeRef) == CFStringGetTypeID()))
{ {
CFStringRef str = static_cast<CFStringRef>(typeRef); CFStringRef str = static_cast<CFStringRef>(typeRef);
return stringFromCFString(str); return stringFromCFString(str);
} }
err() << "Unable to read string value for property '" << stringFromCFString(prop) << "' for joystick at index " << m_index << std::endl; sf::err() << "Unable to read string value for property '" << stringFromCFString(prop) << "' for joystick at index " << m_index << std::endl;
return "Unknown Joystick"; return "Unknown Joystick";
} }
@ -429,14 +409,14 @@ std::string JoystickImpl::getDeviceString(IOHIDDeviceRef ref, CFStringRef prop)
unsigned int JoystickImpl::getDeviceUint(IOHIDDeviceRef ref, CFStringRef prop) unsigned int JoystickImpl::getDeviceUint(IOHIDDeviceRef ref, CFStringRef prop)
{ {
CFTypeRef typeRef = IOHIDDeviceGetProperty(ref, prop); CFTypeRef typeRef = IOHIDDeviceGetProperty(ref, prop);
if (ref && CFGetTypeID(typeRef) == CFNumberGetTypeID()) if (ref && (CFGetTypeID(typeRef) == CFNumberGetTypeID()))
{ {
SInt32 value; SInt32 value;
CFNumberGetValue((CFNumberRef)typeRef, kCFNumberSInt32Type, &value); CFNumberGetValue((CFNumberRef)typeRef, kCFNumberSInt32Type, &value);
return value; return value;
} }
err() << "Unable to read uint value for property '" << stringFromCFString(prop) << "' for joystick at index " << m_index << std::endl; sf::err() << "Unable to read uint value for property '" << stringFromCFString(prop) << "' for joystick at index " << m_index << std::endl;
return 0; return 0;
} }

View File

@ -119,7 +119,7 @@ private :
/// \param ref HID device /// \param ref HID device
/// \param prop Property to retrieve from the device /// \param prop Property to retrieve from the device
/// ///
/// \return Value for the property as a string /// \return Value of the property
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::string getDeviceString(IOHIDDeviceRef ref, CFStringRef prop); std::string getDeviceString(IOHIDDeviceRef ref, CFStringRef prop);
@ -130,7 +130,7 @@ private :
/// \param ref HID device /// \param ref HID device
/// \param prop Property to retrieve from the device /// \param prop Property to retrieve from the device
/// ///
/// \return Value for the propery as an unsigned int /// \return Value of the property
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int getDeviceUint(IOHIDDeviceRef ref, CFStringRef prop); unsigned int getDeviceUint(IOHIDDeviceRef ref, CFStringRef prop);
@ -141,6 +141,7 @@ private :
/// \param cfString CFStringRef to convert /// \param cfString CFStringRef to convert
/// ///
/// \return std::string /// \return std::string
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::string stringFromCFString(CFStringRef cfString); std::string stringFromCFString(CFStringRef cfString);

View File

@ -26,8 +26,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Event processing & Menu bar initialisation /// \brief Event processing & Menu bar initialisation
@ -55,6 +55,7 @@
/// ///
/// This overload of -[NSApplication sendEvent:] is used to /// This overload of -[NSApplication sendEvent:] is used to
/// fix KeyRelease events when the command key is down. /// fix KeyRelease events when the command key is down.
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)sendEvent:(NSEvent*)anEvent; -(void)sendEvent:(NSEvent*)anEvent;

View File

@ -56,7 +56,8 @@
// Set the main menu bar // Set the main menu bar
NSMenu* mainMenu = [NSApp mainMenu]; NSMenu* mainMenu = [NSApp mainMenu];
if (mainMenu != nil) return; if (mainMenu != nil)
return;
mainMenu = [[NSMenu alloc] initWithTitle:@""]; mainMenu = [[NSMenu alloc] initWithTitle:@""];
[NSApp setMainMenu:mainMenu]; [NSApp setMainMenu:mainMenu];
@ -224,14 +225,12 @@
NSString* appName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"]; NSString* appName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"];
// Then, try non-localized name // Then, try non-localized name
if (appName == nil || [appName length] == 0) { if ((appName == nil) || ([appName length] == 0))
appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
}
// Finally, fallback to the process info // Finally, fallback to the process info
if (appName == nil || [appName length] == 0) { if ((appName == nil) || ([appName length] == 0))
appName = [[NSProcessInfo processInfo] processName]; appName = [[NSProcessInfo processInfo] processName];
}
return appName; return appName;
} }
@ -252,8 +251,7 @@
// custom OpenGL view. See -[SFOpenGLView sfKeyUp:] for more details. // custom OpenGL view. See -[SFOpenGLView sfKeyUp:] for more details.
id firstResponder = [[anEvent window] firstResponder]; id firstResponder = [[anEvent window] firstResponder];
if ([anEvent type] != NSKeyUp if (([anEvent type] != NSKeyUp) || (![firstResponder tryToPerform:@selector(sfKeyUp:) with:anEvent])) {
|| ![firstResponder tryToPerform:@selector(sfKeyUp:) with:anEvent]) {
// It's either not a key up event or no responder has a sfKeyUp // It's either not a key up event or no responder has a sfKeyUp
// message implemented. // message implemented.
[super sendEvent:anEvent]; [super sendEvent:anEvent];

View File

@ -26,8 +26,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -36,7 +36,18 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@interface SFApplicationDelegate : NSObject <NSApplicationDelegate> @interface SFApplicationDelegate : NSObject <NSApplicationDelegate>
////////////////////////////////////////////////////////////
/// \brief React to a termination notification
///
/// Send a close message to all windows and cancel the termination.
///
////////////////////////////////////////////////////////////
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender; -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
////////////////////////////////////////////////////////////
/// \brief Exit the app when all windows are closed
///
////////////////////////////////////////////////////////////
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication; -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication;
@end @end

View File

@ -39,8 +39,9 @@ namespace priv
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SFContext::SFContext(SFContext* shared) SFContext::SFContext(SFContext* shared) :
: m_view(0), m_window(0) m_view(0),
m_window(0)
{ {
// Ask for a pool. // Ask for a pool.
retainPool(); retainPool();
@ -54,8 +55,9 @@ SFContext::SFContext(SFContext* shared)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SFContext::SFContext(SFContext* shared, const ContextSettings& settings, SFContext::SFContext(SFContext* shared, const ContextSettings& settings,
const WindowImpl* owner, unsigned int bitsPerPixel) const WindowImpl* owner, unsigned int bitsPerPixel) :
: m_view(0), m_window(0) m_view(0),
m_window(0)
{ {
// Ask for a pool. // Ask for a pool.
retainPool(); retainPool();
@ -64,15 +66,16 @@ SFContext::SFContext(SFContext* shared, const ContextSettings& settings,
createContext(shared, bitsPerPixel, settings); createContext(shared, bitsPerPixel, settings);
// Apply context. // Apply context.
WindowImplCocoa const * ownerCocoa = static_cast<WindowImplCocoa const *>(owner); const WindowImplCocoa* ownerCocoa = static_cast<const WindowImplCocoa*>(owner);
ownerCocoa->applyContext(m_context); ownerCocoa->applyContext(m_context);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SFContext::SFContext(SFContext* shared, const ContextSettings& settings, SFContext::SFContext(SFContext* shared, const ContextSettings& settings,
unsigned int width, unsigned int height) unsigned int width, unsigned int height) :
: m_view(0), m_window(0) m_view(0),
m_window(0)
{ {
// Ensure the process is setup in order to create a valid window. // Ensure the process is setup in order to create a valid window.
WindowImplCocoa::setUpProcess(); WindowImplCocoa::setUpProcess();
@ -142,16 +145,17 @@ void SFContext::createContext(SFContext* shared,
unsigned int bitsPerPixel, unsigned int bitsPerPixel,
const ContextSettings& settings) const ContextSettings& settings)
{ {
// Choose the attributs of OGL context. // Choose the attributes of OGL context.
std::vector<NSOpenGLPixelFormatAttribute> attrs; std::vector<NSOpenGLPixelFormatAttribute> attrs;
attrs.reserve(20); // max attributs (estimation). attrs.reserve(20); // max attributes (estimation).
// These casts are safe. C++ is much more strict than Obj-C. // These casts are safe. C++ is much more strict than Obj-C.
attrs.push_back(NSOpenGLPFAClosestPolicy); attrs.push_back(NSOpenGLPFAClosestPolicy);
attrs.push_back(NSOpenGLPFADoubleBuffer); attrs.push_back(NSOpenGLPFADoubleBuffer);
if (bitsPerPixel > 24) { if (bitsPerPixel > 24)
{
attrs.push_back(NSOpenGLPFAAlphaSize); attrs.push_back(NSOpenGLPFAAlphaSize);
attrs.push_back((NSOpenGLPixelFormatAttribute)8); attrs.push_back((NSOpenGLPixelFormatAttribute)8);
} }
@ -162,7 +166,8 @@ void SFContext::createContext(SFContext* shared,
attrs.push_back(NSOpenGLPFAStencilSize); attrs.push_back(NSOpenGLPFAStencilSize);
attrs.push_back((NSOpenGLPixelFormatAttribute)settings.stencilBits); attrs.push_back((NSOpenGLPixelFormatAttribute)settings.stencilBits);
if (settings.antialiasingLevel > 0) { if (settings.antialiasingLevel > 0)
{
/* /*
* Antialiasing techniques are described in the * Antialiasing techniques are described in the
* "OpenGL Programming Guide for Mac OS X" document. * "OpenGL Programming Guide for Mac OS X" document.
@ -191,10 +196,11 @@ void SFContext::createContext(SFContext* shared,
attrs.push_back((NSOpenGLPixelFormatAttribute)0); // end of array attrs.push_back((NSOpenGLPixelFormatAttribute)0); // end of array
// Create the pixel pormat. // Create the pixel format.
NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attrs[0]]; NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attrs[0]];
if (pixFmt == nil) { if (pixFmt == nil)
{
sf::err() << "Error. Unable to find a suitable pixel format." << std::endl; sf::err() << "Error. Unable to find a suitable pixel format." << std::endl;
return; return;
} }
@ -206,9 +212,8 @@ void SFContext::createContext(SFContext* shared,
m_context = [[NSOpenGLContext alloc] initWithFormat:pixFmt m_context = [[NSOpenGLContext alloc] initWithFormat:pixFmt
shareContext:sharedContext]; shareContext:sharedContext];
if (m_context == nil) { if (m_context == nil)
sf::err() << "Error. Unable to create the context." << std::endl; sf::err() << "Error. Unable to create the context." << std::endl;
}
// Free up. // Free up.
[pixFmt release]; [pixFmt release];

View File

@ -44,24 +44,25 @@ namespace sf {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Init the global state (only if needed). It needs to be /// \brief Initialize the global state (only if needed)
/// Called before any event, e.g. in the window constructor. ///
/// It needs to be called before any event, e.g. in the window constructor.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void initialiseKeyboardHelper(); void initialiseKeyboardHelper(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Set up a SFML key event based on the given modifiers /// \brief Set up a SFML key event based on the given modifiers flags and key code
/// flags and key code.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sf::Event::KeyEvent keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key); sf::Event::KeyEvent keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Handle the state of modifiers keys and send key /// \brief Handle the state of modifiers keys
/// release & pressed events to the requester. ///
/// Send key released & pressed events to the requester.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void handleModifiersChanged(NSUInteger modifiers, sf::priv::WindowImplCocoa& requester); void handleModifiersChanged(NSUInteger modifiers, sf::priv::WindowImplCocoa& requester);

View File

@ -78,15 +78,16 @@ static BOOL isStateInitialized = NO;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Carefully observe if the key mask is on in the modifiers /// \brief Carefully observe if the key mask is on in the modifiers
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
BOOL isKeyMaskActive(NSUInteger modifiers, NSUInteger mask); BOOL isKeyMaskActive(NSUInteger modifiers, NSUInteger mask);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Handle one modifier key mask, update the key state and /// \brief Handle one modifier key mask
/// send events to the requester ///
/// Update the key state and send events to the requester
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void processOneModifier(NSUInteger modifiers, NSUInteger mask, void processOneModifier(NSUInteger modifiers, NSUInteger mask,
@ -95,8 +96,9 @@ void processOneModifier(NSUInteger modifiers, NSUInteger mask,
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Handle left & right modifier keys, update the keys state and /// \brief Handle left & right modifier keys
/// send events to the requester ///
/// Update the keys state and send events to the requester
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void processLeftRightModifiers(NSUInteger modifiers, void processLeftRightModifiers(NSUInteger modifiers,
@ -113,7 +115,7 @@ void processLeftRightModifiers(NSUInteger modifiers,
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
void initialiseKeyboardHelper() void initialiseKeyboardHelper(void)
{ {
if (isStateInitialized) return; if (isStateInitialized) return;
@ -210,13 +212,13 @@ void processOneModifier(NSUInteger modifiers, NSUInteger mask,
BOOL isDown = isKeyMaskActive(modifiers, mask); BOOL isDown = isKeyMaskActive(modifiers, mask);
// Check for key pressed event // Check for key pressed event
if (isDown && !wasDown) { if (isDown && !wasDown)
requester.keyDown(event); requester.keyDown(event);
}
// And check for key released event // And check for key released event
else if (!isDown && wasDown) { else if (!isDown && wasDown)
requester.keyUp(event); requester.keyUp(event);
}
// else isDown == wasDown, so no change // else isDown == wasDown, so no change
// Update state // Update state

View File

@ -46,7 +46,7 @@ namespace sf {
/// The SFWindowController should call -[SFOpenGLView exitFullscreen] /// The SFWindowController should call -[SFOpenGLView exitFullscreen]
/// and -[SFOpenGLView enterFullscreen] when appropriate. /// and -[SFOpenGLView enterFullscreen] when appropriate.
/// ///
/// In order to send correct mouse coordonate to the requester when /// In order to send correct mouse coordinate to the requester when
/// the window is in fullscreen we use m_realSize to represent the /// the window is in fullscreen we use m_realSize to represent the
/// back buffer size (see SFWindowController). If 'm_realSize' is /// back buffer size (see SFWindowController). If 'm_realSize' is
/// bound to its default value we don't recompute the mouse position /// bound to its default value we don't recompute the mouse position
@ -56,12 +56,13 @@ namespace sf {
/// but the actual logic is done in SFKeyboardModifiersHelper.(h|mm). /// but the actual logic is done in SFKeyboardModifiersHelper.(h|mm).
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@interface SFOpenGLView : NSOpenGLView { @interface SFOpenGLView : NSOpenGLView
sf::priv::WindowImplCocoa* m_requester; {
BOOL m_useKeyRepeat; sf::priv::WindowImplCocoa* m_requester; ///< View's requester
BOOL m_mouseIsIn; BOOL m_useKeyRepeat; ///< Key repeat setting
NSTrackingArea* m_trackingArea; BOOL m_mouseIsIn; ///< Mouse positional state
NSSize m_realSize; NSTrackingArea* m_trackingArea; ///< Mouse tracking area
NSSize m_realSize; ///< Actual size of the view
// Hidden text view used to convert key event to actual chars. // Hidden text view used to convert key event to actual chars.
// We use a silent responder to prevent sound alerts. // We use a silent responder to prevent sound alerts.
@ -70,49 +71,73 @@ namespace sf {
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create the SFML opengl view to fit the given area. /// \brief Create the SFML OpenGL view
///
/// \param frameRect dimension of the view
///
/// \return an initialized view
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(id)initWithFrame:(NSRect)frameRect; -(id)initWithFrame:(NSRect)frameRect;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Handle going in and out of fullscreen mode. /// \brief Handle going in fullscreen mode
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)enterFullscreen; -(void)enterFullscreen;
////////////////////////////////////////////////////////////
/// \brief Handle exiting fullscreen mode
///
////////////////////////////////////////////////////////////
-(void)exitFullscreen; -(void)exitFullscreen;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Apply the given resquester to the view. /// \brief Apply the given requester to the view
///
/// \param requester new 'requester' of the view
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester; -(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Set the real size of view (it should be the back buffer size). /// \brief Set the real size of view (it should be the back buffer size)
///
/// If not set, or set to its default value NSZeroSize, the view /// If not set, or set to its default value NSZeroSize, the view
/// won't recompute the mouse coordinates before sending them /// won't recompute the mouse coordinates before sending them
/// to the requester. /// to the requester.
/// ///
/// \param newSize actual size of the view
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)setRealSize:(NSSize)newSize; -(void)setRealSize:(NSSize)newSize;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Compute the position in global coordinate /// \brief Compute the position in global coordinate
/// of the given point in SFML coordinate. ///
/// \param point a point in SFML coordinate
///
/// \return the global coordinates of the point
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(NSPoint)computeGlobalPositionOfRelativePoint:(NSPoint)point; -(NSPoint)computeGlobalPositionOfRelativePoint:(NSPoint)point;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Adjust key repeat configuration. /// \brief Enable key repeat
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)enableKeyRepeat; -(void)enableKeyRepeat;
////////////////////////////////////////////////////////////
/// \brief Disable key repeat
///
////////////////////////////////////////////////////////////
-(void)disableKeyRepeat; -(void)disableKeyRepeat;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Compute the position of the cursor. /// \brief Compute the position of the cursor
///
/// \param eventOrNil
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(NSPoint)cursorPositionFromEvent:(NSEvent*)eventOrNil; -(NSPoint)cursorPositionFromEvent:(NSEvent*)eventOrNil;

View File

@ -30,16 +30,20 @@
#include <SFML/Window/OSX/HIDInputManager.hpp> // For localizedKeys and nonLocalizedKeys #include <SFML/Window/OSX/HIDInputManager.hpp> // For localizedKeys and nonLocalizedKeys
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#import <SFML/Window/OSX/SFKeyboardModifiersHelper.h>
#import <SFML/Window/OSX/SFOpenGLView.h> #import <SFML/Window/OSX/SFOpenGLView.h>
#import <SFML/Window/OSX/SFSilentResponder.h> #import <SFML/Window/OSX/SFSilentResponder.h>
#import <SFML/Window/OSX/SFKeyboardModifiersHelper.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Returns true if `event` represents a representable character. /// \brief Check if the event represent some Unicode text
/// ///
/// The event is assumed to be a key down event. /// The event is assumed to be a key down event.
/// False is returned if the event is either escape or a non text unicode. /// False is returned if the event is either escape or a non text Unicode.
///
/// \param event a key down event
///
/// \return true if event represents a Unicode character, false otherwise
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
BOOL isValidTextUnicode(NSEvent* event); BOOL isValidTextUnicode(NSEvent* event);
@ -52,40 +56,48 @@ BOOL isValidTextUnicode(NSEvent* event);
@interface SFOpenGLView () @interface SFOpenGLView ()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Handle view resized event. /// \brief Handle view resized event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)viewDidEndLiveResize; -(void)viewDidEndLiveResize;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Establish if the mouse is inside or outside the OpenGL view. /// \brief Determine where the mouse is
///
/// \return true when the mouse is inside the OpenGL view, false otherwise
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(BOOL)isMouseInside; -(BOOL)isMouseInside;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Update the mouse state (in or out) and fire an event /// \brief Update the mouse state (in or out)
/// if its state has changed. ///
/// Fire an event if its state has changed.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)updateMouseState; -(void)updateMouseState;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Convert the NSEvent mouse button type to SFML type. /// \brief Convert the NSEvent mouse button type to SFML type
/// ///
/// Returns ButtonCount if the button is unknown /// \param event a mouse button event
///
/// \return Left, Right, ..., or ButtonCount if the button is unknown
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent*)event; -(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent*)event;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Convert a key down/up NSEvent into an SFML key event. /// \brief Convert a key down/up NSEvent into an SFML key event
/// Based on localizedKeys and nonLocalizedKeys function.
/// ///
/// Return sf::Keyboard::Unknown as Code if the key is unknown. /// The conversion is based on localizedKeys and nonLocalizedKeys functions.
///
/// \param event a key event
///
/// \return sf::Keyboard::Unknown as Code if the key is unknown
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
+(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent *)anEvent; +(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event;
@end @end
@ -97,7 +109,8 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(id)initWithFrame:(NSRect)frameRect -(id)initWithFrame:(NSRect)frameRect
{ {
if ((self = [super initWithFrame:frameRect])) { if ((self = [super initWithFrame:frameRect]))
{
[self setRequesterTo:0]; [self setRequesterTo:0];
[self enableKeyRepeat]; [self enableKeyRepeat];
m_realSize = NSZeroSize; m_realSize = NSZeroSize;
@ -130,9 +143,8 @@ BOOL isValidTextUnicode(NSEvent* event);
[self addTrackingArea:m_trackingArea]; [self addTrackingArea:m_trackingArea];
// Fire an mouse entered event if needed // Fire an mouse entered event if needed
if (!m_mouseIsIn && m_requester != 0) { if (!m_mouseIsIn && (m_requester != 0))
m_requester->mouseMovedIn(); m_requester->mouseMovedIn();
}
// Update status // Update status
m_mouseIsIn = YES; m_mouseIsIn = YES;
@ -145,9 +157,8 @@ BOOL isValidTextUnicode(NSEvent* event);
[self removeTrackingArea:m_trackingArea]; [self removeTrackingArea:m_trackingArea];
// Fire an mouse left event if needed // Fire an mouse left event if needed
if (m_mouseIsIn && m_requester != 0) { if (m_mouseIsIn && (m_requester != 0))
m_requester->mouseMovedOut(); m_requester->mouseMovedOut();
}
// Update status // Update status
m_mouseIsIn = NO; m_mouseIsIn = NO;
@ -172,9 +183,10 @@ BOOL isValidTextUnicode(NSEvent* event);
-(NSPoint)computeGlobalPositionOfRelativePoint:(NSPoint)point -(NSPoint)computeGlobalPositionOfRelativePoint:(NSPoint)point
{ {
// Recompute the mouse pos if required. // Recompute the mouse pos if required.
if (!NSEqualSizes(m_realSize, NSZeroSize)) { if (!NSEqualSizes(m_realSize, NSZeroSize))
point.x = point.x / m_realSize.width * [self frame].size.width; {
point.y = point.y / m_realSize.height * [self frame].size.height; point.x = (point.x / m_realSize.width) * [self frame].size.width;
point.y = (point.y / m_realSize.height) * [self frame].size.height;
} }
// Note : -[NSWindow convertBaseToScreen:] is deprecated on 10.7 // Note : -[NSWindow convertBaseToScreen:] is deprecated on 10.7
@ -194,8 +206,8 @@ BOOL isValidTextUnicode(NSEvent* event);
// Convert it to screen coordinates // Convert it to screen coordinates
point = [[self window] convertBaseToScreen:point]; point = [[self window] convertBaseToScreen:point];
// Flip screen coodinates to match CGDisplayMoveCursorToPoint referential. // Flip screen coordinates to match CGDisplayMoveCursorToPoint referential.
float const screenHeight = [[[self window] screen] frame].size.height; const float screenHeight = [[[self window] screen] frame].size.height;
point.y = screenHeight - point.y; point.y = screenHeight - point.y;
return point; return point;
@ -237,7 +249,8 @@ BOOL isValidTextUnicode(NSEvent* event);
[self update]; [self update];
// Send an event // Send an event
if (m_requester == 0) return; if (m_requester == 0)
return;
// The new size // The new size
NSSize newSize = [self frame].size; NSSize newSize = [self frame].size;
@ -251,11 +264,7 @@ BOOL isValidTextUnicode(NSEvent* event);
NSPoint relativeToWindow = [[self window] mouseLocationOutsideOfEventStream]; NSPoint relativeToWindow = [[self window] mouseLocationOutsideOfEventStream];
NSPoint relativeToView = [self convertPoint:relativeToWindow fromView:nil]; NSPoint relativeToView = [self convertPoint:relativeToWindow fromView:nil];
if (NSPointInRect(relativeToView, [self frame])) { return NSPointInRect(relativeToView, [self frame]);
return YES;
}
return NO;
} }
@ -266,12 +275,11 @@ BOOL isValidTextUnicode(NSEvent* event);
m_mouseIsIn = [self isMouseInside]; m_mouseIsIn = [self isMouseInside];
// Send event if needed. // Send event if needed.
if (mouseWasIn && !m_mouseIsIn) { if (mouseWasIn && !m_mouseIsIn)
[self mouseExited:nil]; [self mouseExited:nil];
} else if (!mouseWasIn && m_mouseIsIn) { else if (!mouseWasIn && m_mouseIsIn)
[self mouseEntered:nil]; [self mouseEntered:nil];
} }
}
#pragma mark #pragma mark
@ -351,9 +359,9 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)scrollWheel:(NSEvent*)theEvent -(void)scrollWheel:(NSEvent*)theEvent
{ {
if (m_requester != 0) { if (m_requester != 0)
{
NSPoint loc = [self cursorPositionFromEvent:theEvent]; NSPoint loc = [self cursorPositionFromEvent:theEvent];
m_requester->mouseWheelScrolledAt([theEvent deltaY], loc.x, loc.y); m_requester->mouseWheelScrolledAt([theEvent deltaY], loc.x, loc.y);
} }
@ -369,36 +377,36 @@ BOOL isValidTextUnicode(NSEvent* event);
// a) the event is nil, meaning that the method was // a) the event is nil, meaning that the method was
// called from our code (e.g. updateMouseState) // called from our code (e.g. updateMouseState)
// b) the mouse was outside the view. // b) the mouse was outside the view.
BOOL shouldFire = (theEvent == nil || m_mouseIsIn == NO); BOOL shouldFire = ((theEvent == nil) || (m_mouseIsIn == NO));
// Update status // Update status
m_mouseIsIn = YES; m_mouseIsIn = YES;
if (m_requester == 0) return; if (m_requester == 0)
return;
// Fire (or not) an event // Fire (or not) an event
if (shouldFire) { if (shouldFire)
m_requester->mouseMovedIn(); m_requester->mouseMovedIn();
} }
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)mouseExited:(NSEvent*)theEvent -(void)mouseExited:(NSEvent*)theEvent
{ {
// Similarly to mouseEntered: // Similarly to mouseEntered:
BOOL shouldFire = (theEvent == nil || m_mouseIsIn == YES); BOOL shouldFire = ((theEvent == nil) || (m_mouseIsIn == YES));
// Update status // Update status
m_mouseIsIn = NO; m_mouseIsIn = NO;
if (m_requester == 0) return; if (m_requester == 0)
return;
// Fire (or not) an event // Fire (or not) an event
if (shouldFire) { if (shouldFire)
m_requester->mouseMovedOut(); m_requester->mouseMovedOut();
} }
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
@ -428,16 +436,17 @@ BOOL isValidTextUnicode(NSEvent* event);
{ {
sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent]; sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent];
if (m_requester != 0) { if (m_requester != 0)
{
NSPoint loc = [self cursorPositionFromEvent:theEvent]; NSPoint loc = [self cursorPositionFromEvent:theEvent];
if (button != sf::Mouse::ButtonCount) { if (button != sf::Mouse::ButtonCount)
m_requester->mouseDownAt(button, loc.x, loc.y); m_requester->mouseDownAt(button, loc.x, loc.y);
} }
}
// If the event is not forwarded by mouseDown or rightMouseDown... // If the event is not forwarded by mouseDown or rightMouseDown...
if (button != sf::Mouse::Left && button != sf::Mouse::Right) { if ((button != sf::Mouse::Left) && (button != sf::Mouse::Right))
{
// ... transmit to non-SFML responder // ... transmit to non-SFML responder
[[self nextResponder] otherMouseDown:theEvent]; [[self nextResponder] otherMouseDown:theEvent];
} }
@ -449,16 +458,17 @@ BOOL isValidTextUnicode(NSEvent* event);
{ {
sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent]; sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent];
if (m_requester != 0) { if (m_requester != 0)
{
NSPoint loc = [self cursorPositionFromEvent:theEvent]; NSPoint loc = [self cursorPositionFromEvent:theEvent];
if (button != sf::Mouse::ButtonCount) { if (button != sf::Mouse::ButtonCount)
m_requester->mouseUpAt(button, loc.x, loc.y); m_requester->mouseUpAt(button, loc.x, loc.y);
} }
}
// If the event is not forwarded by mouseUp or rightMouseUp... // If the event is not forwarded by mouseUp or rightMouseUp...
if (button != sf::Mouse::Left && button != sf::Mouse::Right) { if ((button != sf::Mouse::Left) && (button != sf::Mouse::Right))
{
// ... transmit to non-SFML responder // ... transmit to non-SFML responder
[[self nextResponder] otherMouseUp:theEvent]; [[self nextResponder] otherMouseUp:theEvent];
} }
@ -490,21 +500,22 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)otherMouseDragged:(NSEvent*)theEvent -(void)otherMouseDragged:(NSEvent*)theEvent
{ {
if (m_requester != 0) { if (m_requester != 0)
{
NSPoint loc = [self cursorPositionFromEvent:theEvent]; NSPoint loc = [self cursorPositionFromEvent:theEvent];
// Make sure the point is inside the view. // Make sure the point is inside the view.
// (mouseEntered: and mouseExited: are not immediately called // (mouseEntered: and mouseExited: are not immediately called
// when the mouse is dragged. That would be too easy!) // when the mouse is dragged. That would be too easy!)
[self updateMouseState]; [self updateMouseState];
if (m_mouseIsIn) { if (m_mouseIsIn)
m_requester->mouseMovedAt(loc.x, loc.y); m_requester->mouseMovedAt(loc.x, loc.y);
} }
}
// If the event is not forwarded by mouseDragged or rightMouseDragged... // If the event is not forwarded by mouseDragged or rightMouseDragged...
sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent]; sf::Mouse::Button button = [self mouseButtonFromEvent:theEvent];
if (button != sf::Mouse::Left && button != sf::Mouse::Right) { if ((button != sf::Mouse::Left) && (button != sf::Mouse::Right))
{
// ... transmit to non-SFML responder // ... transmit to non-SFML responder
[[self nextResponder] otherMouseUp:theEvent]; [[self nextResponder] otherMouseUp:theEvent];
} }
@ -516,10 +527,13 @@ BOOL isValidTextUnicode(NSEvent* event);
{ {
NSPoint loc; NSPoint loc;
// If no event given then get current mouse pos. // If no event given then get current mouse pos.
if (eventOrNil == nil) { if (eventOrNil == nil)
{
NSPoint rawPos = [[self window] mouseLocationOutsideOfEventStream]; NSPoint rawPos = [[self window] mouseLocationOutsideOfEventStream];
loc = [self convertPoint:rawPos fromView:nil]; loc = [self convertPoint:rawPos fromView:nil];
} else { }
else
{
loc = [self convertPoint:[eventOrNil locationInWindow] fromView:nil]; loc = [self convertPoint:[eventOrNil locationInWindow] fromView:nil];
} }
@ -528,9 +542,10 @@ BOOL isValidTextUnicode(NSEvent* event);
loc.y = h - loc.y; loc.y = h - loc.y;
// Recompute the mouse pos if required. // Recompute the mouse pos if required.
if (!NSEqualSizes(m_realSize, NSZeroSize)) { if (!NSEqualSizes(m_realSize, NSZeroSize))
loc.x = loc.x * m_realSize.width / [self frame].size.width; {
loc.y = loc.y * m_realSize.height / [self frame].size.height; loc.x = (loc.x * m_realSize.width) / [self frame].size.width;
loc.y = (loc.y * m_realSize.height) / [self frame].size.height;
} }
return loc; return loc;
@ -540,7 +555,8 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent*)event -(sf::Mouse::Button)mouseButtonFromEvent:(NSEvent*)event
{ {
switch ([event buttonNumber]) { switch ([event buttonNumber])
{
case 0: return sf::Mouse::Left; case 0: return sf::Mouse::Left;
case 1: return sf::Mouse::Right; case 1: return sf::Mouse::Right;
case 2: return sf::Mouse::Middle; case 2: return sf::Mouse::Middle;
@ -561,24 +577,27 @@ BOOL isValidTextUnicode(NSEvent* event);
// Transmit to non-SFML responder // Transmit to non-SFML responder
[[self nextResponder] keyDown:theEvent]; [[self nextResponder] keyDown:theEvent];
if (m_requester == 0) return; if (m_requester == 0)
return;
// Handle key down event // Handle key down event
if (m_useKeyRepeat || ![theEvent isARepeat]) { if (m_useKeyRepeat || ![theEvent isARepeat])
{
sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent];
if (key.code != sf::Keyboard::Unknown) { // The key is recognized. if (key.code != sf::Keyboard::Unknown) // The key is recognized.
m_requester->keyDown(key); m_requester->keyDown(key);
} }
}
// Handle text entred event: // Handle text entred event:
// Ignore event if we don't want repeated keystrokes // Ignore event if we don't want repeated keystrokes
if (m_useKeyRepeat || ![theEvent isARepeat]) { if (m_useKeyRepeat || ![theEvent isARepeat])
{
// Ignore escape key and other non text keycode (See NSEvent.h) // Ignore escape key and other non text keycode (See NSEvent.h)
// because they produce a sound alert. // because they produce a sound alert.
if (isValidTextUnicode(theEvent)) { if (isValidTextUnicode(theEvent))
{
// Send the event to the hidden text view for processing // Send the event to the hidden text view for processing
[m_hiddenTextView interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; [m_hiddenTextView interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
} }
@ -591,25 +610,27 @@ BOOL isValidTextUnicode(NSEvent* event);
unsigned short keycode = [theEvent keyCode]; unsigned short keycode = [theEvent keyCode];
// Backspace // Backspace
if (keycode == 0x33) { if (keycode == 0x33)
{
// Send the correct unicode value (i.e. 8) instead of 127 (which is 'delete') // Send the correct unicode value (i.e. 8) instead of 127 (which is 'delete')
m_requester->textEntered(8); m_requester->textEntered(8);
} }
// Delete // Delete
else if (keycode == 0x75 || keycode == NSDeleteFunctionKey) { else if ((keycode == 0x75) || (keycode == NSDeleteFunctionKey))
{
// Instead of the value 63272 we send 127. // Instead of the value 63272 we send 127.
m_requester->textEntered(127); m_requester->textEntered(127);
} }
// Otherwise, let's see what our hidden field has computed // Otherwise, let's see what our hidden field has computed
else { else
{
NSString* string = [m_hiddenTextView string]; NSString* string = [m_hiddenTextView string];
// Send each character to SFML event requester // Send each character to SFML event requester
for (NSUInteger index = 0; index < [string length]; ++index) { for (NSUInteger index = 0; index < [string length]; ++index)
m_requester->textEntered([string characterAtIndex:index]); m_requester->textEntered([string characterAtIndex:index]);
}
// Empty our hidden cache // Empty our hidden cache
[m_hiddenTextView setString:@""]; [m_hiddenTextView setString:@""];
@ -631,14 +652,14 @@ BOOL isValidTextUnicode(NSEvent* event);
// Transmit to non-SFML responder // Transmit to non-SFML responder
[[self nextResponder] keyUp:theEvent]; [[self nextResponder] keyUp:theEvent];
if (m_requester == 0) return; if (m_requester == 0)
return;
sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent];
if (key.code != sf::Keyboard::Unknown) { // The key is recognized. if (key.code != sf::Keyboard::Unknown) // The key is recognized.
m_requester->keyUp(key); m_requester->keyUp(key);
} }
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
@ -647,7 +668,8 @@ BOOL isValidTextUnicode(NSEvent* event);
// Transmit to non-SFML responder // Transmit to non-SFML responder
[[self nextResponder] flagsChanged:theEvent]; [[self nextResponder] flagsChanged:theEvent];
if (m_requester == 0) return; if (m_requester == 0)
return;
NSUInteger modifiers = [theEvent modifierFlags]; NSUInteger modifiers = [theEvent modifierFlags];
handleModifiersChanged(modifiers, *m_requester); handleModifiersChanged(modifiers, *m_requester);
@ -655,35 +677,33 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
+(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent *)anEvent +(sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event
{ {
// Key code // Key code
sf::Keyboard::Key key = sf::Keyboard::Unknown; sf::Keyboard::Key key = sf::Keyboard::Unknown;
// First we look if the key down is from a list of characters // First we look if the key down is from a list of characters
// that depend on keyboard localization. // that depend on keyboard localization.
NSString* string = [anEvent charactersIgnoringModifiers]; NSString* string = [event charactersIgnoringModifiers];
if ([string length] > 0) { if ([string length] > 0)
key = sf::priv::HIDInputManager::localizedKeys([string characterAtIndex:0]); key = sf::priv::HIDInputManager::localizedKeys([string characterAtIndex:0]);
}
// If the key is not a localized one, we try to find a corresponding code // If the key is not a localized one, we try to find a corresponding code
// through virtual key code. // through virtual key code.
if (key == sf::Keyboard::Unknown) { if (key == sf::Keyboard::Unknown)
key = sf::priv::HIDInputManager::nonLocalizedKeys([anEvent keyCode]); key = sf::priv::HIDInputManager::nonLocalizedKeys([event keyCode]);
}
//#ifdef SFML_DEBUG // Don't bother the final customers with annoying messages. //#ifdef SFML_DEBUG // Don't bother the final customers with annoying messages.
// if (key.code == sf::Keyboard::Unknown) { // The key is unknown. // if (key.code == sf::Keyboard::Unknown) { // The key is unknown.
// sf::err() << "This is an unknow key. Virtual key code is 0x" // sf::err() << "This is an unknow key. Virtual key code is 0x"
// << std::hex // << std::hex
// << [anEvent keyCode] // << [event keyCode]
// << "." // << "."
// << std::endl; // << std::endl;
// } // }
//#endif //#endif
return keyEventWithModifiers([anEvent modifierFlags], key); return keyEventWithModifiers([event modifierFlags], key);
} }
@end @end
@ -693,12 +713,17 @@ BOOL isValidTextUnicode(NSEvent* event);
BOOL isValidTextUnicode(NSEvent* event) BOOL isValidTextUnicode(NSEvent* event)
{ {
if ([event keyCode] == 0x35) { // Escape if ([event keyCode] == 0x35) // Escape
{
return false; return false;
} else if ([[event characters] length] > 0) { }
else if ([[event characters] length] > 0)
{
unichar code = [[event characters] characterAtIndex:0]; unichar code = [[event characters] characterAtIndex:0];
return code < 0xF700 || code > 0xF8FF; return ((code < 0xF700) || (code > 0xF8FF));
} else { }
else
{
return true; return true;
} }
} }

View File

@ -32,6 +32,7 @@
/// \brief Silent Responder used to prevent sound alert with key event /// \brief Silent Responder used to prevent sound alert with key event
/// ///
/// Mainly used by SFOpenGLView and its hidden text view. /// Mainly used by SFOpenGLView and its hidden text view.
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@interface SFSilentResponder : NSResponder @interface SFSilentResponder : NSResponder

View File

@ -34,16 +34,25 @@
@class SFOpenGLView; @class SFOpenGLView;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Implementation of WindowImplDelegateProtocol for view managment. /// \brief Implementation of WindowImplDelegateProtocol for view management
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@interface SFViewController : NSObject <WindowImplDelegateProtocol> { @interface SFViewController : NSObject <WindowImplDelegateProtocol>
NSView* m_view; {
SFOpenGLView* m_oglView; NSView* m_view; ///< Underlying Cocoa view
sf::priv::WindowImplCocoa* m_requester; SFOpenGLView* m_oglView; ///< OpenGL view
sf::priv::WindowImplCocoa* m_requester; ///< View's requester
} }
////////////////////////////////////////////////////////////
/// \brief Initialize the view controller
///
/// \param view view to be controlled
///
/// \return an initialized view controller
///
////////////////////////////////////////////////////////////
-(id)initWithView:(NSView*)view; -(id)initWithView:(NSView*)view;
@end @end

View File

@ -26,30 +26,29 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#import <SFML/Window/OSX/SFViewController.h>
#import <SFML/Window/OSX/SFOpenGLView.h>
#import <SFML/Window/OSX/SFApplication.h>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <SFML/Window/OSX/WindowImplCocoa.hpp> #include <SFML/Window/OSX/WindowImplCocoa.hpp>
#import <SFML/Window/OSX/SFApplication.h>
#import <SFML/Window/OSX/SFOpenGLView.h>
#import <SFML/Window/OSX/SFViewController.h>
@implementation SFViewController @implementation SFViewController
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(id)initWithView:(NSView *)view -(id)initWithView:(NSView *)view
{ {
if ((self = [super init])) { if ((self = [super init]))
{
m_requester = 0; m_requester = 0;
// Retain the view for our own use. // Retain the view for our own use.
m_view = [view retain]; m_view = [view retain];
if (m_view == nil) { if (m_view == nil)
{
sf::err() sf::err() << "No view was given to initWithWindow:." << std::endl;
<< "No view was given to initWithWindow:."
<< std::endl;
return self; return self;
} }
@ -59,10 +58,9 @@
frame.origin.y = 0; frame.origin.y = 0;
m_oglView = [[SFOpenGLView alloc] initWithFrame:frame]; m_oglView = [[SFOpenGLView alloc] initWithFrame:frame];
if (m_oglView == nil) { if (m_oglView == nil)
{
sf::err() sf::err() << "Could not create an instance of NSOpenGLView "
<< "Could not create an instance of NSOpenGLView "
<< "in (SFViewController -initWithView:)." << "in (SFViewController -initWithView:)."
<< std::endl; << std::endl;
@ -132,7 +130,7 @@
////////////////////////////////////////////////////////. ////////////////////////////////////////////////////////.
-(void)setWindowPositionToX:(int)x Y:(int)y -(void)setWindowPositionToX:(int)x Y:(int)y
{ {
sf::err() << "Cannot move SFML area when SFML is integrated in a NSView. Use the view hanlder directly instead." << std::endl; sf::err() << "Cannot move SFML area when SFML is integrated in a NSView. Use the view handler directly instead." << std::endl;
} }
@ -201,7 +199,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)setIconTo:(unsigned int)width -(void)setIconTo:(unsigned int)width
by:(unsigned int)height by:(unsigned int)height
with:(sf::Uint8 const *)pixels with:(const sf::Uint8*)pixels
{ {
sf::err() << "Cannot set an icon when SFML is integrated in a NSView." << std::endl; sf::err() << "Cannot set an icon when SFML is integrated in a NSView." << std::endl;
} }
@ -211,23 +209,21 @@
-(void)processEvent -(void)processEvent
{ {
// If we are not on the main thread we stop here and advice the user. // If we are not on the main thread we stop here and advice the user.
if ([NSThread currentThread] != [NSThread mainThread]) { if ([NSThread currentThread] != [NSThread mainThread])
{
/* /*
* See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html * See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
* for more information. * for more information.
*/ */
sf::err() sf::err() << "Cannot fetch event from a worker thread. (OS X restriction)" << std::endl;
<< "Cannot fetch event from a worker thread. (OS X restriction)"
<< std::endl;
return; return;
} }
// If we don't have a requester we don't fetch event. // If we don't have a requester we don't fetch event.
if (m_requester != 0) { if (m_requester != 0)
[SFApplication processEvent]; [SFApplication processEvent];
} }
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////

View File

@ -29,23 +29,38 @@
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Here we redefine some methods to allow grabing fullscreen events. /// \brief Here we redefine some methods to allow grabbing fullscreen events
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@interface SFWindow : NSWindow @interface SFWindow : NSWindow
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// These two methods must return YES to grab fullscreen events. /// \brief Allow to grab fullscreen events
///
/// acceptsFirstResponder and canBecomeKeyWindow messages must
/// return YES to grab fullscreen events.
///
/// See http://stackoverflow.com/questions/999464/fullscreen-key-down-actions /// See http://stackoverflow.com/questions/999464/fullscreen-key-down-actions
/// for more informations ///
/// \return YES
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(BOOL)acceptsFirstResponder; -(BOOL)acceptsFirstResponder;
////////////////////////////////////////////////////////////
/// \brief Allow to grab fullscreen events
///
/// See acceptsFirstResponder documentation above.
///
/// \return YES
///
////////////////////////////////////////////////////////////
-(BOOL)canBecomeKeyWindow; -(BOOL)canBecomeKeyWindow;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Override default implementation of keyDown: to prevent /// \brief Prevent system alert
/// system alert ///
/// \param theEvent a Cocoa event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)keyDown:(NSEvent*)theEvent; -(void)keyDown:(NSEvent*)theEvent;
@ -53,12 +68,18 @@
@end @end
////////////////////////////////////////////////////////////
/// \brief Extension of NSWindow
///
/// Add some extra messages for SFML internal usage.
///
////////////////////////////////////////////////////////////
@interface NSWindow (SFML) @interface NSWindow (SFML)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Proxy for performClose: for the app delegate /// Proxy for performClose: for the app delegate
/// ///
/// Always return nil /// \return nil
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(id)sfClose; -(id)sfClose;

View File

@ -26,7 +26,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#import "SFWindow.h" #import <SFML/Window/OSX/SFWindow.h>
@implementation SFWindow @implementation SFWindow

View File

@ -26,9 +26,10 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#import <SFML/Window/OSX/WindowImplDelegateProtocol.h>
#include <SFML/Window/VideoMode.hpp> #include <SFML/Window/VideoMode.hpp>
#import <SFML/Window/OSX/WindowImplDelegateProtocol.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Predefine some classes /// Predefine some classes
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -41,7 +42,7 @@ namespace sf {
@class SFOpenGLView; @class SFOpenGLView;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Implementation of WindowImplDelegateProtocol for window managment. /// \brief Implementation of WindowImplDelegateProtocol for window management
/// ///
/// Key and mouse events are delegated to its view. /// Key and mouse events are delegated to its view.
/// Window events are managed by this class. /// Window events are managed by this class.
@ -54,26 +55,38 @@ namespace sf {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 // NSWindowDelegate is only define since 10.6 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 // NSWindowDelegate is only define since 10.6
@interface SFWindowController : NSResponder <WindowImplDelegateProtocol> { @interface SFWindowController : NSResponder <WindowImplDelegateProtocol>
#else #else
@interface SFWindowController : NSResponder <WindowImplDelegateProtocol, NSWindowDelegate> { @interface SFWindowController : NSResponder <WindowImplDelegateProtocol, NSWindowDelegate>
#endif #endif
NSWindow* m_window; {
SFOpenGLView* m_oglView; NSWindow* m_window; ///< Underlying Cocoa window to be controlled
sf::priv::WindowImplCocoa* m_requester; SFOpenGLView* m_oglView; ///< OpenGL view for rendering
sf::VideoMode* m_fullscreenMode; // Note : C++ ctor/dtor are not called for Obj-C fields. sf::priv::WindowImplCocoa* m_requester; ///< Requester
sf::VideoMode* m_fullscreenMode; ///< Fullscreen mode
/// Note: C++ ctor/dtor are not called for Obj-C fields! Use manual allocation instead.
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create the SFML window with an external Cocoa window. /// \brief Create the SFML window with an external Cocoa window
///
/// \param window Cocoa window to be controlled
///
/// \return an initialized controller
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(id)initWithWindow:(NSWindow*)window; -(id)initWithWindow:(NSWindow*)window;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create the SFML window "from scratch" (full SFML handling). /// \brief Create the SFML window "from scratch" (SFML handle everything)
///
/// \param mode Video mode
/// \param style Window's style, as described by sf::Style
///
/// \return an initialized controller
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(id)initWithMode:(sf::VideoMode const &)mode andStyle:(unsigned long)style; -(id)initWithMode:(const sf::VideoMode&)mode andStyle:(unsigned long)style;
@end @end

View File

@ -26,33 +26,37 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/WindowImplCocoa.hpp>
#include <SFML/Window/VideoMode.hpp> #include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/WindowHandle.hpp> #include <SFML/Window/WindowHandle.hpp>
#include <SFML/Window/WindowStyle.hpp> #include <SFML/Window/WindowStyle.hpp>
#include <SFML/Window/OSX/WindowImplCocoa.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <ApplicationServices/ApplicationServices.h> #include <ApplicationServices/ApplicationServices.h>
#import <SFML/Window/OSX/SFWindowController.h>
#import <SFML/Window/OSX/SFApplication.h> #import <SFML/Window/OSX/SFApplication.h>
#import <SFML/Window/OSX/SFOpenGLView.h> #import <SFML/Window/OSX/SFOpenGLView.h>
#import <SFML/Window/OSX/SFWindow.h> #import <SFML/Window/OSX/SFWindow.h>
#import <SFML/Window/OSX/SFWindowController.h>
#import <OpenGL/OpenGL.h> #import <OpenGL/OpenGL.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// SFWindowController class : Privates Methods Declaration /// SFWindowController class: private interface
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@interface SFWindowController () @interface SFWindowController ()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Retrieves the screen height. /// \brief Retrieves the screen height
///
/// \return screen height
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(float)screenHeight; -(float)screenHeight;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Retrives the title bar height. /// \brief Retrieves the title bar height
///
/// \return title bar height
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(float)titlebarHeight; -(float)titlebarHeight;
@ -67,32 +71,28 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(id)initWithWindow:(NSWindow*)window -(id)initWithWindow:(NSWindow*)window
{ {
if ((self = [super init])) { if ((self = [super init]))
{
m_requester = 0; m_requester = 0;
m_fullscreenMode = new sf::VideoMode(); m_fullscreenMode = new sf::VideoMode();
// Retain the window for our own use. // Retain the window for our own use.
m_window = [window retain]; m_window = [window retain];
if (m_window == nil) { if (m_window == nil)
{
sf::err() sf::err() << "No window was given to initWithWindow:." << std::endl;
<< "No window was given to initWithWindow:."
<< std::endl;
return self; return self;
} }
// Create the view. // Create the view.
m_oglView = [[SFOpenGLView alloc] initWithFrame:[[m_window contentView] frame]]; m_oglView = [[SFOpenGLView alloc] initWithFrame:[[m_window contentView] frame]];
if (m_oglView == nil) { if (m_oglView == nil)
{
sf::err() sf::err() << "Could not create an instance of NSOpenGLView "
<< "Could not create an instance of NSOpenGLView "
<< "in (SFWindowController -initWithWindow:)." << "in (SFWindowController -initWithWindow:)."
<< std::endl; << std::endl;
return self; return self;
} }
@ -105,49 +105,56 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(id)initWithMode:(sf::VideoMode const &)mode andStyle:(unsigned long)style -(id)initWithMode:(const sf::VideoMode&)mode andStyle:(unsigned long)style
{ {
// If we are not on the main thread we stop here and advice the user. // If we are not on the main thread we stop here and advice the user.
if ([NSThread currentThread] != [NSThread mainThread]) { if ([NSThread currentThread] != [NSThread mainThread])
{
/* /*
* See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html * See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
* for more information. * for more information.
*/ */
sf::err() sf::err() << "Cannot create a window from a worker thread. (OS X limitation)" << std::endl;
<< "Cannot create a window from a worker thread. (OS X limitation)"
<< std::endl;
return nil; return nil;
} }
if ((self = [super init])) { if ((self = [super init]))
{
m_requester = 0; m_requester = 0;
m_fullscreenMode = new sf::VideoMode(); m_fullscreenMode = new sf::VideoMode();
// Create our window size. // Create our window size.
NSRect rect = NSZeroRect; NSRect rect = NSZeroRect;
if (style & sf::Style::Fullscreen && mode != sf::VideoMode::getDesktopMode()) { if ((style & sf::Style::Fullscreen) && (mode != sf::VideoMode::getDesktopMode()))
{
// We use desktop mode to size the window // We use desktop mode to size the window
// but we set the back buffer size to 'mode' in applyContext method. // but we set the back buffer size to 'mode' in applyContext method.
*m_fullscreenMode = mode; *m_fullscreenMode = mode;
sf::VideoMode dm = sf::VideoMode::getDesktopMode(); sf::VideoMode dm = sf::VideoMode::getDesktopMode();
rect = NSMakeRect(0, 0, dm.width, dm.height); rect = NSMakeRect(0, 0, dm.width, dm.height);
}
} else { // no fullscreen requested. else
{
// no fullscreen requested.
rect = NSMakeRect(0, 0, mode.width, mode.height); rect = NSMakeRect(0, 0, mode.width, mode.height);
} }
// Convert the SFML window style to Cocoa window style. // Convert the SFML window style to Cocoa window style.
unsigned int nsStyle = NSBorderlessWindowMask; unsigned int nsStyle = NSBorderlessWindowMask;
if (!(style & sf::Style::Fullscreen)) { // if fullscrean we keep our NSBorderlessWindowMask.
if (style & sf::Style::Titlebar) nsStyle |= NSTitledWindowMask | NSMiniaturizableWindowMask; // if fullscrean we keep our NSBorderlessWindowMask.
if (!(style & sf::Style::Fullscreen))
{
if (style & sf::Style::Titlebar)
nsStyle |= NSTitledWindowMask | NSMiniaturizableWindowMask;
if (style & sf::Style::Resize) nsStyle |= NSResizableWindowMask; if (style & sf::Style::Resize)
nsStyle |= NSResizableWindowMask;
if (style & sf::Style::Close) nsStyle |= NSClosableWindowMask; if (style & sf::Style::Close)
nsStyle |= NSClosableWindowMask;
} }
@ -166,9 +173,9 @@
[...] [...]
*/ */
if (m_window == nil) { if (m_window == nil)
sf::err() {
<< "Could not create an instance of NSWindow " sf::err() << "Could not create an instance of NSWindow "
<< "in (SFWindowController -initWithMode:andStyle:)." << "in (SFWindowController -initWithMode:andStyle:)."
<< std::endl; << std::endl;
@ -176,7 +183,8 @@
} }
// Apply special feature for fullscreen window. // Apply special feature for fullscreen window.
if (style & sf::Style::Fullscreen) { if (style & sf::Style::Fullscreen)
{
// We place the window above everything else. // We place the window above everything else.
[m_window setOpaque:YES]; [m_window setOpaque:YES];
[m_window setHidesOnDeactivate:YES]; [m_window setHidesOnDeactivate:YES];
@ -195,15 +203,15 @@
*/ */
} }
// Center the window to be cool =) // Centre the window to be cool =)
[m_window center]; [m_window center];
// Create the view. // Create the view.
m_oglView = [[SFOpenGLView alloc] initWithFrame:[[m_window contentView] frame]]; m_oglView = [[SFOpenGLView alloc] initWithFrame:[[m_window contentView] frame]];
if (m_oglView == nil) { if (m_oglView == nil)
sf::err() {
<< "Could not create an instance of NSOpenGLView " sf::err() << "Could not create an instance of NSOpenGLView "
<< "in (SFWindowController -initWithMode:andStyle:)." << "in (SFWindowController -initWithMode:andStyle:)."
<< std::endl; << std::endl;
@ -211,12 +219,14 @@
} }
// If a fullscreen window was requested... // If a fullscreen window was requested...
if (style & sf::Style::Fullscreen) { if (style & sf::Style::Fullscreen)
{
/// ... we tell the OpenGL view /// ... we tell the OpenGL view
[m_oglView enterFullscreen]; [m_oglView enterFullscreen];
// ... and if the resolution is not the default one... // ... and if the resolution is not the default one...
if (mode != sf::VideoMode::getDesktopMode()) { if (mode != sf::VideoMode::getDesktopMode())
{
// ... we set the "real size" of the view (that is the back buffer size). // ... we set the "real size" of the view (that is the back buffer size).
[m_oglView setRealSize:NSMakeSize(m_fullscreenMode->width, m_fullscreenMode->height)]; [m_oglView setRealSize:NSMakeSize(m_fullscreenMode->width, m_fullscreenMode->height)];
} }
@ -291,21 +301,21 @@
-(NSPoint)position -(NSPoint)position
{ {
// First, get the top left corner of the view in its own base system // First, get the top left corner of the view in its own base system
NSPoint const origin = [m_oglView frame].origin; const NSPoint origin = [m_oglView frame].origin;
NSSize const size = [m_oglView frame].size; const NSSize size = [m_oglView frame].size;
NSPoint const topLeftCornerOfView = NSMakePoint(origin.x, origin.y + size.height); const NSPoint topLeftCornerOfView = NSMakePoint(origin.x, origin.y + size.height);
NSPoint const positionInView = [m_oglView convertPointToBase:topLeftCornerOfView]; const NSPoint positionInView = [m_oglView convertPointToBase:topLeftCornerOfView];
// Then, convert it to window base system // Then, convert it to window base system
NSPoint const positionInWindow = [m_oglView convertPoint:positionInView toView:nil]; const NSPoint positionInWindow = [m_oglView convertPoint:positionInView toView:nil];
// here nil denotes the window containing the view // here nil denotes the window containing the view
// Next, convert it to the screen base system // Next, convert it to the screen base system
NSPoint const positionInScreen = [[m_oglView window] convertBaseToScreen:positionInWindow]; const NSPoint positionInScreen = [[m_oglView window] convertBaseToScreen:positionInWindow];
// Finally, flip for SFML window coordinate system // Finally, flip for SFML window coordinate system
// Don't forget to discard the title bar ! // Don't forget to discard the title bar !
NSPoint const positionInSFML = NSMakePoint(positionInScreen.x, const NSPoint positionInSFML = NSMakePoint(positionInScreen.x,
([self screenHeight] - [self titlebarHeight]) - positionInScreen.y); ([self screenHeight] - [self titlebarHeight]) - positionInScreen.y);
return positionInSFML; return positionInSFML;
@ -328,12 +338,11 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(NSSize)size -(NSSize)size
{ {
if (*m_fullscreenMode == sf::VideoMode()) { if (*m_fullscreenMode == sf::VideoMode())
return [m_oglView frame].size; return [m_oglView frame].size;
} else { else
return NSMakeSize(m_fullscreenMode->width, m_fullscreenMode->height); return NSMakeSize(m_fullscreenMode->width, m_fullscreenMode->height);
} }
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
@ -405,7 +414,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)setIconTo:(unsigned int)width -(void)setIconTo:(unsigned int)width
by:(unsigned int)height by:(unsigned int)height
with:(sf::Uint8 const *)pixels with:(const sf::Uint8*)pixels
{ {
// Create an empty image representation. // Create an empty image representation.
NSBitmapImageRep* bitmap = NSBitmapImageRep* bitmap =
@ -425,12 +434,12 @@
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 // We may need to define NSUInteger. #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 // We may need to define NSUInteger.
#define NSUInteger unsigned int #define NSUInteger unsigned int
#endif #endif
for (unsigned int y = 0; y < height; ++y) { for (unsigned int y = 0; y < height; ++y)
for (unsigned int x = 0; x < width; ++x, pixels+=4) { {
for (unsigned int x = 0; x < width; ++x, pixels+=4)
{
NSUInteger pixel[4] = { pixels[0], pixels[1], pixels[2], pixels[3] }; NSUInteger pixel[4] = { pixels[0], pixels[1], pixels[2], pixels[3] };
[bitmap setPixel:pixel [bitmap setPixel:pixel atX:x y:y];
atX:x
y:y];
} }
} }
@ -451,23 +460,21 @@
-(void)processEvent -(void)processEvent
{ {
// If we are not on the main thread we stop here and advice the user. // If we are not on the main thread we stop here and advice the user.
if ([NSThread currentThread] != [NSThread mainThread]) { if ([NSThread currentThread] != [NSThread mainThread])
{
/* /*
* See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html * See http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
* for more information. * for more information.
*/ */
sf::err() sf::err() << "Cannot fetch event from a worker thread. (OS X restriction)" << std::endl;
<< "Cannot fetch event from a worker thread. (OS X restriction)"
<< std::endl;
return; return;
} }
// If we don't have a requester we don't fetch event. // If we don't have a requester we don't fetch event.
if (m_requester != 0) { if (m_requester != 0)
[SFApplication processEvent]; [SFApplication processEvent];
} }
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
@ -479,7 +486,8 @@
// If fullscreen was requested and the mode used to create the window // If fullscreen was requested and the mode used to create the window
// was not the desktop mode, we change the back buffer size of the // was not the desktop mode, we change the back buffer size of the
// context. // context.
if (*m_fullscreenMode != sf::VideoMode()) { if (*m_fullscreenMode != sf::VideoMode())
{
CGLContextObj cgcontext = (CGLContextObj)[context CGLContextObj]; CGLContextObj cgcontext = (CGLContextObj)[context CGLContextObj];
GLint dim[2] = {m_fullscreenMode->width, m_fullscreenMode->height}; GLint dim[2] = {m_fullscreenMode->width, m_fullscreenMode->height};
@ -497,7 +505,8 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(BOOL)windowShouldClose:(id)sender -(BOOL)windowShouldClose:(id)sender
{ {
if (m_requester == 0) return YES; if (m_requester == 0)
return YES;
m_requester->windowClosed(); m_requester->windowClosed();
return NO; return NO;
@ -508,28 +517,28 @@
-(void)windowDidBecomeKey:(NSNotification*)notification -(void)windowDidBecomeKey:(NSNotification*)notification
{ {
// Send event. // Send event.
if (m_requester == 0) return; if (m_requester == 0)
return;
m_requester->windowGainedFocus(); m_requester->windowGainedFocus();
if (*m_fullscreenMode != sf::VideoMode()) { if (*m_fullscreenMode != sf::VideoMode())
[m_oglView enterFullscreen]; [m_oglView enterFullscreen];
} }
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)windowDidResignKey:(NSNotification*)notification -(void)windowDidResignKey:(NSNotification*)notification
{ {
// Send event. // Send event.
if (m_requester == 0) return; if (m_requester == 0)
return;
m_requester->windowLostFocus(); m_requester->windowLostFocus();
if (*m_fullscreenMode != sf::VideoMode()) { if (*m_fullscreenMode != sf::VideoMode())
[m_oglView exitFullscreen]; [m_oglView exitFullscreen];
} }
}
#pragma mark #pragma mark

View File

@ -50,23 +50,24 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
// Retrieve array of dictionaries representing display modes. // Retrieve array of dictionaries representing display modes.
CFArrayRef displayModes = CGDisplayAvailableModes(CGMainDisplayID()); CFArrayRef displayModes = CGDisplayAvailableModes(CGMainDisplayID());
if (displayModes == NULL) { if (displayModes == NULL)
sf::err() << "Couldn't get VideoMode for main display."; {
sf::err() << "Couldn't get VideoMode for main display." << std::endl;
return modes; return modes;
} }
// Loop on each mode and convert it into a sf::VideoMode object. // Loop on each mode and convert it into a sf::VideoMode object.
CFIndex const modesCount = CFArrayGetCount(displayModes); const CFIndex modesCount = CFArrayGetCount(displayModes);
for (CFIndex i = 0; i < modesCount; i++) { for (CFIndex i = 0; i < modesCount; i++)
{
CFDictionaryRef dictionary = (CFDictionaryRef)CFArrayGetValueAtIndex(displayModes, i); CFDictionaryRef dictionary = (CFDictionaryRef)CFArrayGetValueAtIndex(displayModes, i);
VideoMode mode = convertCGModeToSFMode(dictionary); VideoMode mode = convertCGModeToSFMode(dictionary);
// If not yet listed we add it to our modes array. // If not yet listed we add it to our modes array.
if (std::find(modes.begin(), modes.end(), mode) == modes.end()) { if (std::find(modes.begin(), modes.end(), mode) == modes.end())
modes.push_back(mode); modes.push_back(mode);
} }
}
return modes; return modes;
@ -77,23 +78,24 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
// Retrieve all modes available for main screen only. // Retrieve all modes available for main screen only.
CFArrayRef cgmodes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); CFArrayRef cgmodes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL);
if (cgmodes == NULL) { if (cgmodes == NULL)
sf::err() << "Couldn't get VideoMode for main display."; {
sf::err() << "Couldn't get VideoMode for main display." << std::endl;
return modes; return modes;
} }
// Loop on each mode and convert it into a sf::VideoMode object. // Loop on each mode and convert it into a sf::VideoMode object.
CFIndex const modesCount = CFArrayGetCount(cgmodes); const CFIndex modesCount = CFArrayGetCount(cgmodes);
for (CFIndex i = 0; i < modesCount; i++) { for (CFIndex i = 0; i < modesCount; i++)
{
CGDisplayModeRef cgmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(cgmodes, i); CGDisplayModeRef cgmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(cgmodes, i);
VideoMode mode = convertCGModeToSFMode(cgmode); VideoMode mode = convertCGModeToSFMode(cgmode);
// If not yet listed we add it to our modes array. // If not yet listed we add it to our modes array.
if (std::find(modes.begin(), modes.end(), mode) == modes.end()) { if (std::find(modes.begin(), modes.end(), mode) == modes.end())
modes.push_back(mode); modes.push_back(mode);
} }
}
// Clean up memory. // Clean up memory.
CFRelease(cgmodes); CFRelease(cgmodes);

View File

@ -34,7 +34,7 @@
#include <SFML/System/String.hpp> #include <SFML/System/String.hpp>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Predefine OBJC classes /// Predefine OBJ-C classes
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#ifdef __OBJC__ #ifdef __OBJC__
@ -77,7 +77,7 @@ public :
/// ///
/// \param mode Video mode to use /// \param mode Video mode to use
/// \param title Title of the window /// \param title Title of the window
/// \param style Window style (resizable, fixed, or fullscren) /// \param style Window style (resizeable, fixed, or fullscren)
/// \param settings Additional settings for the underlying OpenGL context /// \param settings Additional settings for the underlying OpenGL context
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -90,7 +90,7 @@ public :
~WindowImplCocoa(); ~WindowImplCocoa();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Window Closed Event called by the cocoa window object. /// \brief Window Closed Event called by the cocoa window object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
@ -98,18 +98,18 @@ public :
void windowClosed(void); void windowClosed(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Window Resized Event called by the cocoa window object. /// \brief Window Resized Event called by the cocoa window object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param width /// \param width new width
/// \param height /// \param height new height
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void windowResized(unsigned int width, unsigned int height); void windowResized(unsigned int width, unsigned int height);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Window Lost Focus Event called by the cocoa window object. /// \brief Window Lost Focus Event called by the cocoa window object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
@ -117,7 +117,7 @@ public :
void windowLostFocus(void); void windowLostFocus(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Window Get Focus Event called by the cocoa window object. /// \brief Window Get Focus Event called by the cocoa window object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
@ -125,54 +125,54 @@ public :
void windowGainedFocus(void); void windowGainedFocus(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse Down Event called by the cocoa view object. /// \brief Mouse Down Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param button /// \param button active button
/// \param x /// \param x mouse x position
/// \param y /// \param y mouse y position
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void mouseDownAt(Mouse::Button button, int x, int y); void mouseDownAt(Mouse::Button button, int x, int y);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse Up Event called by the cocoa view object. /// \brief Mouse Up Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param button /// \param button active button
/// \param x /// \param x mouse x position
/// \param y /// \param y mouse y position
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void mouseUpAt(Mouse::Button button, int x, int y); void mouseUpAt(Mouse::Button button, int x, int y);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse Moved Event called by the cocoa view object. /// \brief Mouse Moved Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param x /// \param x mouse x position
/// \param y /// \param y mouse y position
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void mouseMovedAt(int x, int y); void mouseMovedAt(int x, int y);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse Wheel Scrolled Event called by the cocoa view object. /// \brief Mouse Wheel Scrolled Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param delta /// \param delta scrolling delta
/// \param x /// \param x mouse x position
/// \param y /// \param y mouse y position
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void mouseWheelScrolledAt(float delta, int x, int y); void mouseWheelScrolledAt(float delta, int x, int y);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse In Event called by the cocoa view object. /// \brief Mouse In Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
@ -180,7 +180,7 @@ public :
void mouseMovedIn(void); void mouseMovedIn(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse Out Event called by the cocoa view object. /// \brief Mouse Out Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
@ -188,37 +188,37 @@ public :
void mouseMovedOut(void); void mouseMovedOut(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Key Down Event called by the cocoa view object. /// \brief Key Down Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param key /// \param key active key
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void keyDown(Event::KeyEvent key); void keyDown(Event::KeyEvent key);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Key Up Event called by the cocoa view object. /// \brief Key Up Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param key /// \param key active key
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void keyUp(Event::KeyEvent key); void keyUp(Event::KeyEvent key);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Text Entred Event called by the cocoa view object. /// \brief Text Entred Event called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param charcode Input unicode /// \param charcode Unicode input
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void textEntered(unichar charcode); void textEntered(unichar charcode);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Apply the context to the view. /// \brief Apply the context to the view
/// ///
/// Called by the SFML context object to finalize its creation. /// Called by the SFML context object to finalize its creation.
/// ///
@ -228,7 +228,9 @@ public :
void applyContext(NSOpenGLContextRef context) const; void applyContext(NSOpenGLContextRef context) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Change the type of the current process to become a full GUI app. /// \brief Change the type of the current process
///
/// The type of the process is changed to become a full GUI app.
/// Also ensure NSApp is constructed. /// Also ensure NSApp is constructed.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -30,13 +30,13 @@
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <SFML/System/String.hpp> #include <SFML/System/String.hpp>
#import <SFML/Window/OSX/SFWindowController.h>
#import <SFML/Window/OSX/SFViewController.h>
#import <SFML/Window/OSX/cpp_objc_conversion.h>
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h> #import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
#import <SFML/Window/OSX/cpp_objc_conversion.h>
#import <SFML/Window/OSX/SFApplication.h> #import <SFML/Window/OSX/SFApplication.h>
#import <SFML/Window/OSX/SFApplicationDelegate.h> #import <SFML/Window/OSX/SFApplicationDelegate.h>
#import <SFML/Window/OSX/SFKeyboardModifiersHelper.h> #import <SFML/Window/OSX/SFKeyboardModifiersHelper.h>
#import <SFML/Window/OSX/SFViewController.h>
#import <SFML/Window/OSX/SFWindowController.h>
namespace sf namespace sf
{ {
@ -47,28 +47,28 @@ namespace priv
#pragma mark WindowImplCocoa's ctor/dtor #pragma mark WindowImplCocoa's ctor/dtor
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImplCocoa::WindowImplCocoa(WindowHandle handle) WindowImplCocoa::WindowImplCocoa(WindowHandle handle) :
: m_showCursor(true) m_showCursor(true)
{ {
// Ask for a pool. // Ask for a pool.
retainPool(); retainPool();
// Treat the handle as it real type // Treat the handle as it real type
id nsHandle = (id)handle; id nsHandle = (id)handle;
if ([nsHandle isKindOfClass:[NSWindow class]]) { if ([nsHandle isKindOfClass:[NSWindow class]])
{
// We have a window. // We have a window.
m_delegate = [[SFWindowController alloc] initWithWindow:nsHandle]; m_delegate = [[SFWindowController alloc] initWithWindow:nsHandle];
}
} else if ([nsHandle isKindOfClass:[NSView class]]) { else if ([nsHandle isKindOfClass:[NSView class]])
{
// We have a view. // We have a view.
m_delegate = [[SFViewController alloc] initWithView:nsHandle]; m_delegate = [[SFViewController alloc] initWithView:nsHandle];
}
else
{
} else { sf::err() << "Cannot import this Window Handle because it is neither "
sf::err()
<< "Cannot import this Window Handle because it is neither "
<< "a <NSWindow*> nor <NSView*> object " << "a <NSWindow*> nor <NSView*> object "
<< "(or any of their subclasses). You gave a <" << "(or any of their subclasses). You gave a <"
<< [[nsHandle className] UTF8String] << [[nsHandle className] UTF8String]
@ -89,8 +89,8 @@ WindowImplCocoa::WindowImplCocoa(WindowHandle handle)
WindowImplCocoa::WindowImplCocoa(VideoMode mode, WindowImplCocoa::WindowImplCocoa(VideoMode mode,
const String& title, const String& title,
unsigned long style, unsigned long style,
const ContextSettings& /*settings*/) const ContextSettings& /*settings*/) :
: m_showCursor(true) m_showCursor(true)
{ {
// Transform the app process. // Transform the app process.
setUpProcess(); setUpProcess();
@ -116,9 +116,8 @@ WindowImplCocoa::~WindowImplCocoa()
// Put the next window in front, if any. // Put the next window in front, if any.
NSArray* windows = [NSApp orderedWindows]; NSArray* windows = [NSApp orderedWindows];
if ([windows count] > 0) { if ([windows count] > 0)
[[windows objectAtIndex:0] makeKeyAndOrderFront:nil]; [[windows objectAtIndex:0] makeKeyAndOrderFront:nil];
}
releasePool(); releasePool();
@ -140,21 +139,22 @@ void WindowImplCocoa::setUpProcess(void)
{ {
static bool isTheProcessSetAsApplication = false; static bool isTheProcessSetAsApplication = false;
if (!isTheProcessSetAsApplication) { if (!isTheProcessSetAsApplication)
{
// Do it only once ! // Do it only once !
isTheProcessSetAsApplication = true; isTheProcessSetAsApplication = true;
// Set the process as a normal application so it can get focus. // Set the process as a normal application so it can get focus.
ProcessSerialNumber psn; ProcessSerialNumber psn;
if (!GetCurrentProcess(&psn)) { if (!GetCurrentProcess(&psn))
{
TransformProcessType(&psn, kProcessTransformToForegroundApplication); TransformProcessType(&psn, kProcessTransformToForegroundApplication);
SetFrontProcess(&psn); SetFrontProcess(&psn);
} }
// Register an application delegate if there is none // Register an application delegate if there is none
if (![[SFApplication sharedApplication] delegate]) { if (![[SFApplication sharedApplication] delegate])
[NSApp setDelegate:[[SFApplicationDelegate alloc] init]]; [NSApp setDelegate:[[SFApplicationDelegate alloc] init]];
}
// Create menus for the application (before finishing launching!) // Create menus for the application (before finishing launching!)
[SFApplication setUpMenuBar]; [SFApplication setUpMenuBar];
@ -196,9 +196,8 @@ void WindowImplCocoa::windowResized(unsigned int width, unsigned int height)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::windowLostFocus(void) void WindowImplCocoa::windowLostFocus(void)
{ {
if (!m_showCursor) { if (!m_showCursor)
[m_delegate showMouseCursor]; // Make sur the cursor is visible [m_delegate showMouseCursor]; // Make sure the cursor is visible
}
Event event; Event event;
event.type = Event::LostFocus; event.type = Event::LostFocus;
@ -210,9 +209,8 @@ void WindowImplCocoa::windowLostFocus(void)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::windowGainedFocus(void) void WindowImplCocoa::windowGainedFocus(void)
{ {
if (!m_showCursor) { if (!m_showCursor)
[m_delegate hideMouseCursor]; // Restore user's setting [m_delegate hideMouseCursor]; // Restore user's setting
}
Event event; Event event;
event.type = Event::GainedFocus; event.type = Event::GainedFocus;
@ -276,9 +274,8 @@ void WindowImplCocoa::mouseWheelScrolledAt(float delta, int x, int y)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::mouseMovedIn(void) void WindowImplCocoa::mouseMovedIn(void)
{ {
if (!m_showCursor) { if (!m_showCursor)
[m_delegate hideMouseCursor]; // Restore user's setting [m_delegate hideMouseCursor]; // Restore user's setting
}
Event event; Event event;
event.type = Event::MouseEntered; event.type = Event::MouseEntered;
@ -289,9 +286,8 @@ void WindowImplCocoa::mouseMovedIn(void)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::mouseMovedOut(void) void WindowImplCocoa::mouseMovedOut(void)
{ {
if (!m_showCursor) { if (!m_showCursor)
[m_delegate showMouseCursor]; // Make sur the cursor is visible [m_delegate showMouseCursor]; // Make sure the cursor is visible
}
Event event; Event event;
event.type = Event::MouseLeft; event.type = Event::MouseLeft;
@ -403,12 +399,11 @@ void WindowImplCocoa::setIcon(unsigned int width, unsigned int height, const Uin
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setVisible(bool visible) void WindowImplCocoa::setVisible(bool visible)
{ {
if (visible) { if (visible)
[m_delegate showWindow]; [m_delegate showWindow];
} else { else
[m_delegate hideWindow]; [m_delegate hideWindow];
} }
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -416,23 +411,21 @@ void WindowImplCocoa::setMouseCursorVisible(bool visible)
{ {
m_showCursor = visible; m_showCursor = visible;
if (m_showCursor) { if (m_showCursor)
[m_delegate showMouseCursor]; [m_delegate showMouseCursor];
} else { else
[m_delegate hideMouseCursor]; [m_delegate hideMouseCursor];
} }
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setKeyRepeatEnabled(bool enabled) void WindowImplCocoa::setKeyRepeatEnabled(bool enabled)
{ {
if (enabled) { if (enabled)
[m_delegate enableKeyRepeat]; [m_delegate enableKeyRepeat];
} else { else
[m_delegate disableKeyRepeat]; [m_delegate disableKeyRepeat];
} }
}
} // namespace priv } // namespace priv

View File

@ -26,8 +26,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/WindowHandle.hpp>
#include <SFML/Config.hpp> // for sf::Uint8 #include <SFML/Config.hpp> // for sf::Uint8
#include <SFML/Window/WindowHandle.hpp>
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
@ -38,8 +38,7 @@ namespace sf {
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// This protocol defines the interface of the delegate of /// \brief Interface of the delegate of the window implementation
/// the window implementation.
/// ///
/// We don't create an interface here because Obj-C doesn't allow /// We don't create an interface here because Obj-C doesn't allow
/// multiple inheritance (SFViewController and SFWindowController /// multiple inheritance (SFViewController and SFWindowController
@ -68,90 +67,133 @@ namespace sf {
@protocol WindowImplDelegateProtocol @protocol WindowImplDelegateProtocol
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Set the WindowImpl who requested this delegate /// \brief Set the WindowImpl who requested this delegate
/// (This would be a ctor in C++ or Java where we can prohibit the
/// construction of an object.)
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester; -(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Return the main view or window. /// \brief Get the underlying OS specific handle
///
/// \return Return the main view or window.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(sf::WindowHandle)getSystemHandle; -(sf::WindowHandle)getSystemHandle;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Hide or show the mouse cursor. /// \brief Hide the mouse cursor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)hideMouseCursor; -(void)hideMouseCursor;
////////////////////////////////////////////////////////////
/// \brief Show the mouse cursor
///
////////////////////////////////////////////////////////////
-(void)showMouseCursor; -(void)showMouseCursor;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get window's position. /// \brief Get window position
///
/// \return Top left corner of the window or view
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(NSPoint)position; -(NSPoint)position;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Move the window (not the view if we handle not a window) (SFML Coordinates). /// \brief Move the window
///
/// Doesn't apply if the implementation is 'only' a view.
///
/// \param x x position in SFML coordinates
/// \param y y position in SFML coordinates
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)setWindowPositionToX:(int)x Y:(int)y; -(void)setWindowPositionToX:(int)x Y:(int)y;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get window's size. /// \brief Get window/view's size
///
/// \return the size of the rendering area
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(NSSize)size; -(NSSize)size;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Resize the window/view. /// \brief Resize the window/view
///
/// \param width new width
/// \param height new height
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)resizeTo:(unsigned int)width by:(unsigned int)height; -(void)resizeTo:(unsigned int)width by:(unsigned int)height;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Set the title (does nothing if we manage a view). /// \brief Set the window's title
///
/// Doesn't apply if the implementation is 'only' a view.
///
/// \param title new title
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)changeTitle:(NSString*)title; -(void)changeTitle:(NSString*)title;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Hide or show the window (does nothing if we manage a view). /// \brief Hide the window
///
/// Doesn't apply if the implementation is 'only' a view.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)hideWindow; -(void)hideWindow;
////////////////////////////////////////////////////////////
/// \brief Show the window
///
/// Doesn't apply if the implementation is 'only' a view.
///
////////////////////////////////////////////////////////////
-(void)showWindow; -(void)showWindow;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Close the window (does nothing if we manage a view). /// \brief Close the window
///
/// Doesn't apply if the implementation is 'only' a view.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)closeWindow; -(void)closeWindow;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Enable or disable key repeat. /// \brief Enable key repeat
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)enableKeyRepeat; -(void)enableKeyRepeat;
////////////////////////////////////////////////////////////
/// \brief Disable key repeat
///
////////////////////////////////////////////////////////////
-(void)disableKeyRepeat; -(void)disableKeyRepeat;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Set an icon to the application. /// \brief Set an icon to the application
///
/// \param width icon's width
/// \param height icon's height
/// \param pixels icon's data
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)setIconTo:(unsigned int)width by:(unsigned int)height with:(sf::Uint8 const*)pixels; -(void)setIconTo:(unsigned int)width by:(unsigned int)height with:(const sf::Uint8*)pixels;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Fetch new event /// \brief Fetch new event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)processEvent; -(void)processEvent;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Apply a given context to an OpenGL view. /// \brief Apply a given context to an OpenGL view
///
/// \param context OpenGL context to attach to the OpenGL view
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)applyContext:(NSOpenGLContext*)context; -(void)applyContext:(NSOpenGLContext*)context;

View File

@ -42,20 +42,13 @@ size_t modeBitsPerPixel(CGDisplayModeRef mode)
// Compare encoding. // Compare encoding.
CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode); CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode);
if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
bpp = 32; bpp = 32;
else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
} else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
bpp = 16; bpp = 16;
else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
} else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
bpp = 8; bpp = 8;
}
// Clean up memory. // Clean up memory.
CFRelease(pixEnc); CFRelease(pixEnc);
@ -78,7 +71,7 @@ size_t displayBitsPerPixel(CGDirectDisplayID displayId)
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
// Get bpp for the mode. // Get bpp for the mode.
size_t const bpp = modeBitsPerPixel(mode); const size_t bpp = modeBitsPerPixel(mode);
// Clean up Memory. // Clean up Memory.
CGDisplayModeRelease(mode); CGDisplayModeRelease(mode);
@ -146,31 +139,30 @@ CGDisplayModeRef convertSFModeToCGMode(VideoMode sfmode)
// Retrieve all modes available for main screen only. // Retrieve all modes available for main screen only.
CFArrayRef cgmodes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); CFArrayRef cgmodes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL);
if (cgmodes == NULL) { // Should not happen but anyway... if (cgmodes == NULL) // Should not happen but anyway...
{
sf::err() << "Couldn't get VideoMode for main display."; sf::err() << "Couldn't get VideoMode for main display.";
return NULL; return NULL;
} }
// Loop on each mode and convert it into a sf::VideoMode object. // Loop on each mode and convert it into a sf::VideoMode object.
CFIndex const modesCount = CFArrayGetCount(cgmodes); const CFIndex modesCount = CFArrayGetCount(cgmodes);
for (CFIndex i = 0; i < modesCount; i++) { for (CFIndex i = 0; i < modesCount; i++)
{
CGDisplayModeRef cgmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(cgmodes, i); CGDisplayModeRef cgmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(cgmodes, i);
VideoMode mode = convertCGModeToSFMode(cgmode); VideoMode mode = convertCGModeToSFMode(cgmode);
if (mode == sfmode) { if (mode == sfmode)
cgbestMode = cgmode; cgbestMode = cgmode;
} }
}
// Clean up memory. // Clean up memory.
CFRelease(cgmodes); CFRelease(cgmodes);
if (cgbestMode == NULL) { if (cgbestMode == NULL)
sf::err() sf::err() << "Couldn't convert the given sf:VideoMode into a CGDisplayMode."
<< "Couldn't convert the given sf:VideoMode into a CGDisplayMode."
<< std::endl; << std::endl;
}
return cgbestMode; return cgbestMode;
} }

View File

@ -37,7 +37,7 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get bpp of a video mode for OS 10.6 or later. /// \brief Get bpp of a video mode for OS 10.6 or later
/// ///
/// With OS 10.6 and later, Quartz doesn't use anymore dictionaries /// With OS 10.6 and later, Quartz doesn't use anymore dictionaries
/// to represent video mode. Instead it uses a CGDisplayMode opaque type. /// to represent video mode. Instead it uses a CGDisplayMode opaque type.
@ -48,7 +48,7 @@ size_t modeBitsPerPixel(CGDisplayModeRef mode);
#endif #endif
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get bpp for all OS X version. /// \brief Get bpp for all OS X version
/// ///
/// This function use only non-deprecated way to get the /// This function use only non-deprecated way to get the
/// display bits per pixel information for a given display id. /// display bits per pixel information for a given display id.
@ -57,7 +57,7 @@ size_t modeBitsPerPixel(CGDisplayModeRef mode);
size_t displayBitsPerPixel(CGDirectDisplayID displayId); size_t displayBitsPerPixel(CGDirectDisplayID displayId);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Convert a Quartz video mode into a sf::VideoMode object. /// \brief Convert a Quartz video mode into a sf::VideoMode object
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
@ -67,7 +67,7 @@ VideoMode convertCGModeToSFMode(CGDisplayModeRef cgmode);
#endif #endif
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Convert a sf::VideoMode object into a Quartz video mode. /// \brief Convert a sf::VideoMode object into a Quartz video mode
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060

View File

@ -26,14 +26,19 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <string>
#include <SFML/System/String.hpp> #include <SFML/System/String.hpp>
#include <string>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Returns a NSString construct with +stringWithCString:encoding:. /// \brief Returns a NSString construct with +stringWithCString:encoding:
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
NSString* stringToNSString(std::string const& string); NSString* stringToNSString(const std::string& string);
NSString* sfStringToNSString(sf::String const& string);
////////////////////////////////////////////////////////////
/// \brief Returns a NSString construct with +stringWithCString:encoding:
///
////////////////////////////////////////////////////////////
NSString* sfStringToNSString(const sf::String& string);

View File

@ -28,11 +28,11 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/Utf.hpp> #include <SFML/System/Utf.hpp>
#import <Foundation/Foundation.h>
#import <SFML/Window/OSX/cpp_objc_conversion.h> #import <SFML/Window/OSX/cpp_objc_conversion.h>
#import <Foundation/Foundation.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
NSString* stringToNSString(std::string const& string) NSString* stringToNSString(const std::string& string)
{ {
std::string utf8; utf8.reserve(string.size() + 1); std::string utf8; utf8.reserve(string.size() + 1);
sf::Utf8::fromAnsi(string.begin(), string.end(), std::back_inserter(utf8)); sf::Utf8::fromAnsi(string.begin(), string.end(), std::back_inserter(utf8));
@ -42,7 +42,7 @@ NSString* stringToNSString(std::string const& string)
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
NSString* sfStringToNSString(sf::String const& string) NSString* sfStringToNSString(const sf::String& string)
{ {
sf::Uint32 length = string.getSize() * sizeof(sf::Uint32); sf::Uint32 length = string.getSize() * sizeof(sf::Uint32);
const void* data = reinterpret_cast<const void*>(string.getData()); const void* data = reinterpret_cast<const void*>(string.getData());