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>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -42,8 +42,8 @@
/// Because NSAutoreleasePool cannot be retain we have to do it ourself. /// Because NSAutoreleasePool cannot be retain we have to do it ourself.
/// 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 :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -95,15 +96,15 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
int m_count; ///< How many times was the pool retained ? int m_count; ///< How many times was the pool retained?
NSAutoreleasePool* m_pool; ///< Our dedicated pool NSAutoreleasePool* m_pool; ///< Our dedicated pool
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
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,9 +166,8 @@ 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];
}
} }
@ -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

@ -60,18 +60,16 @@ long HIDInputManager::getLocationID(IOHIDDeviceRef device)
{ {
long loc = 0; long loc = 0;
// 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,32 +234,32 @@ 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;
} }
// 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,29 +273,30 @@ 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;
} }
// 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;
@ -408,10 +404,11 @@ void HIDInputManager::loadButton(IOHIDElementRef button)
UInt32 usage = IOHIDElementGetUsage(button); UInt32 usage = IOHIDElementGetUsage(button);
Mouse::Button dest = Mouse::ButtonCount; Mouse::Button dest = Mouse::ButtonCount;
// 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)
// Do not release m_layout ! It is owned by m_layoutData. CFRelease(m_layoutData);
if (m_manager != 0) CFRelease(m_manager); // Do not release m_layout! It is owned by m_layoutData.
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,14 +123,15 @@ 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);
} }
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void HIDJoystickManager::pluggedIn(void * context, IOReturn, void *, IOHIDDeviceRef) void HIDJoystickManager::pluggedIn(void* context, IOReturn, void*, IOHIDDeviceRef)
{ {
HIDJoystickManager* manager = (HIDJoystickManager*)context; HIDJoystickManager* manager = (HIDJoystickManager*)context;
manager->m_joystickCount++; manager->m_joystickCount++;
@ -138,7 +139,7 @@ void HIDJoystickManager::pluggedIn(void * context, IOReturn, void *, IOHIDDevice
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void HIDJoystickManager::pluggedOut(void * context, IOReturn, void *, IOHIDDeviceRef) void HIDJoystickManager::pluggedOut(void* context, IOReturn, void*, IOHIDDeviceRef)
{ {
HIDJoystickManager* manager = (HIDJoystickManager*)context; HIDJoystickManager* manager = (HIDJoystickManager*)context;
manager->m_joystickCount--; manager->m_joystickCount--;

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,19 +98,19 @@ 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
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static void pluggedIn(void * context, IOReturn, void *, IOHIDDeviceRef); static void pluggedIn(void* context, IOReturn, void*, IOHIDDeviceRef);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \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
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static void pluggedOut(void * context, IOReturn, void *, IOHIDDeviceRef); static void pluggedOut(void* context, IOReturn, void*, IOHIDDeviceRef);
private : private :

View File

@ -26,20 +26,20 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// 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
/// we use the HID manager. Mouse position is handled differently. /// we use the HID manager. Mouse position is handled differently.
/// ///
/// NB : we probably could use /// NB: we probably could use
/// NSEvent +addGlobalMonitorForEventsMatchingMask:handler: for mouse only. /// NSEvent +addGlobalMonitorForEventsMatchingMask:handler: for mouse only.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -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]]) { {
view = (SFOpenGLView *)subview; if ([subview isKindOfClass:[SFOpenGLView class]])
{
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

@ -66,60 +66,63 @@ void JoystickImpl::cleanup()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool JoystickImpl::isConnected(unsigned int index) 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,68 +181,48 @@ 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;
} }
// 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);
return false; return false;
} }
// 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; // kHIDUsage_GD_Vx, kHIDUsage_GD_Vy, kHIDUsage_GD_Vz are ignored.
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.
} }
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
@ -295,10 +275,10 @@ JoystickCaps JoystickImpl::getCapabilities() const
{ {
JoystickCaps caps; JoystickCaps caps;
// Buttons : // Buttons:
caps.buttonCount = m_buttons.size(); caps.buttonCount = m_buttons.size();
// Axis : // Axis:
for (AxisMap::const_iterator it(m_axis.begin()); it != m_axis.end(); ++it) { for (AxisMap::const_iterator it(m_axis.begin()); it != m_axis.end(); ++it) {
caps.axes[it->first] = true; caps.axes[it->first] = true;
} }
@ -321,17 +301,16 @@ JoystickState JoystickImpl::update()
JoystickState state; // otherwise return that JoystickState state; // otherwise return that
state.connected = true; state.connected = true;
// Note : free up is done in close() which is called, if required, // Note: free up is done in close() which is called, if required,
// by the joystick manager. So we don't release buttons nor axes here. // by the joystick manager. So we don't release buttons nor axes here.
// First, let's determine if the joystick is still connected // First, let's determine if the joystick is still connected
Location selfLoc = m_locationIDs[m_index]; Location selfLoc = m_locationIDs[m_index];
// 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,23 +332,21 @@ 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,19 +355,21 @@ 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;
} }
// We want to bind [physicalMin,physicalMax] to [-100=min,100=max]. // We want to bind [physicalMin,physicalMax] to [-100=min,100=max].
// //
// General formula to bind [a,b] to [c,d] with a linear progression : // General formula to bind [a,b] to [c,d] with a linear progression:
// //
// f : [a, b] -> [c, d] // f : [a, b] -> [c, d]
// x |-> (x-a)(d-c)/(b-a)+c // x |-> (x-a)(d-c)/(b-a)+c
@ -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,8 +55,9 @@
/// ///
/// 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;
@end @end

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];
@ -79,7 +80,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
+(NSMenu *)createAppleMenu +(NSMenu*)createAppleMenu
{ {
// Apple menu is as follow: // Apple menu is as follow:
// //
@ -158,7 +159,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
+(NSMenu *)createFileMenu +(NSMenu*)createFileMenu
{ {
// The File menu is as follow: // The File menu is as follow:
// //
@ -180,7 +181,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
+(NSMenu *)createWindowMenu +(NSMenu*)createWindowMenu
{ {
// The Window menu is as follow: // The Window menu is as follow:
// //
@ -218,20 +219,18 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
+(NSString *)applicationName +(NSString*)applicationName
{ {
// First, try localized name // First, try localized name
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>
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; ////////////////////////////////////////////////////////////
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication; /// \brief React to a termination notification
///
/// Send a close message to all windows and cancel the termination.
///
////////////////////////////////////////////////////////////
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
////////////////////////////////////////////////////////////
/// \brief Exit the app when all windows are closed
///
////////////////////////////////////////////////////////////
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication;
@end @end

View File

@ -33,7 +33,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender
{ {
// TODO generate close event for each SFML window // TODO generate close event for each SFML window
[NSApp makeWindowsPerform:@selector(sfClose) inOrder:NO]; [NSApp makeWindowsPerform:@selector(sfClose) inOrder:NO];
@ -42,7 +42,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
{ {
return YES; return YES;
} }

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,51 +71,75 @@ 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;
@end @end

View File

@ -30,62 +30,74 @@
#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);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// SFOpenGLView class : Privates Methods Declaration /// SFOpenGLView class: Privates Methods Declaration
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@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;
@ -155,7 +166,7 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)setRequesterTo:(sf::priv::WindowImplCocoa *)requester -(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester
{ {
m_requester = requester; m_requester = requester;
} }
@ -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,11 +275,10 @@ 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];
}
} }
@ -316,7 +324,7 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)mouseDown:(NSEvent *)theEvent -(void)mouseDown:(NSEvent*)theEvent
{ {
// Forward to... // Forward to...
[self otherMouseDown:theEvent]; [self otherMouseDown:theEvent];
@ -327,7 +335,7 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)mouseUp:(NSEvent *)theEvent -(void)mouseUp:(NSEvent*)theEvent
{ {
// Forward to... // Forward to...
[self otherMouseUp:theEvent]; [self otherMouseUp:theEvent];
@ -338,7 +346,7 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)mouseMoved:(NSEvent *)theEvent -(void)mouseMoved:(NSEvent*)theEvent
{ {
// Forward to... // Forward to...
[self otherMouseDragged:theEvent]; [self otherMouseDragged:theEvent];
@ -349,11 +357,11 @@ 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);
} }
@ -363,46 +371,46 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)mouseEntered:(NSEvent *)theEvent -(void)mouseEntered:(NSEvent*)theEvent
{ {
// There are two cases when we need to fire an event: // There are two cases when we need to fire an 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();
}
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)rightMouseDown:(NSEvent *)theEvent -(void)rightMouseDown:(NSEvent*)theEvent
{ {
// Forward to... // Forward to...
[self otherMouseDown:theEvent]; [self otherMouseDown:theEvent];
@ -413,7 +421,7 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)rightMouseUp:(NSEvent *)theEvent -(void)rightMouseUp:(NSEvent*)theEvent
{ {
// Forward to... // Forward to...
[self otherMouseUp:theEvent]; [self otherMouseUp:theEvent];
@ -424,20 +432,21 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)otherMouseDown:(NSEvent *)theEvent -(void)otherMouseDown:(NSEvent*)theEvent
{ {
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];
} }
@ -445,20 +454,21 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)otherMouseUp:(NSEvent *)theEvent -(void)otherMouseUp:(NSEvent*)theEvent
{ {
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];
} }
@ -466,7 +476,7 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)rightMouseDragged:(NSEvent *)theEvent -(void)rightMouseDragged:(NSEvent*)theEvent
{ {
// Forward to... // Forward to...
[self otherMouseDragged:theEvent]; [self otherMouseDragged:theEvent];
@ -477,7 +487,7 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)mouseDragged:(NSEvent *)theEvent -(void)mouseDragged:(NSEvent*)theEvent
{ {
// Forward to... // Forward to...
[self otherMouseDragged:theEvent]; [self otherMouseDragged:theEvent];
@ -488,23 +498,24 @@ 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];
} }
@ -512,14 +523,17 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(NSPoint)cursorPositionFromEvent:(NSEvent *)eventOrNil -(NSPoint)cursorPositionFromEvent:(NSEvent*)eventOrNil
{ {
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;
@ -538,9 +553,10 @@ 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;
@ -556,29 +572,32 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)keyDown:(NSEvent *)theEvent -(void)keyDown:(NSEvent*)theEvent
{ {
// 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:@""];
@ -619,7 +640,7 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)sfKeyUp:(NSEvent *)theEvent -(void)sfKeyUp:(NSEvent*)theEvent
{ {
// For some mystic reasons, key released events don't work the same way // For some mystic reasons, key released events don't work the same way
// as key pressed events... We somewhat hijack the event chain of response // as key pressed events... We somewhat hijack the event chain of response
@ -631,23 +652,24 @@ 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);
}
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)flagsChanged:(NSEvent *)theEvent -(void)flagsChanged:(NSEvent*)theEvent
{ {
// 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
} }
-(id)initWithView:(NSView *)view; ////////////////////////////////////////////////////////////
/// \brief Initialize the view controller
///
/// \param view view to be controlled
///
/// \return an initialized view controller
///
////////////////////////////////////////////////////////////
-(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,12 +58,11 @@
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;
return self; return self;
} }
@ -92,7 +90,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)setRequesterTo:(sf::priv::WindowImplCocoa *)requester -(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester
{ {
// Forward to the view. // Forward to the view.
[m_oglView setRequesterTo:requester]; [m_oglView setRequesterTo:requester];
@ -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;
} }
@ -157,7 +155,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)changeTitle:(NSString *)title -(void)changeTitle:(NSString*)title
{ {
sf::err() << "Cannot change the title of the SFML area when SFML is integrated in a NSView." << std::endl; sf::err() << "Cannot change the title of the SFML area when SFML is integrated in a NSView." << 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,27 +209,25 @@
-(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];
}
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)applyContext:(NSOpenGLContext *)context -(void)applyContext:(NSOpenGLContext*)context
{ {
[m_oglView setOpenGLContext:context]; [m_oglView setOpenGLContext:context];
[context setView:m_oglView]; [context setView:m_oglView];

View File

@ -29,36 +29,57 @@
#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;
@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
@ -46,7 +46,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)keyDown:(NSEvent *)theEvent -(void)keyDown:(NSEvent*)theEvent
{ {
// Do nothing except preventing a system alert each time a key is pressed // Do nothing except preventing a system alert each time a key is pressed
// //
@ -54,7 +54,7 @@
// ----------------------- // -----------------------
// Consider overriding NSResponder -keyDown: message in a Cocoa view/window // Consider overriding NSResponder -keyDown: message in a Cocoa view/window
// that contains a SFML rendering area. Doing so will prevent a system // that contains a SFML rendering area. Doing so will prevent a system
// alert to be thrown everytime the user presses a key. // alert to be thrown every time the user presses a key.
} }

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;
@ -65,34 +69,30 @@
#pragma mark SFWindowController's methods #pragma mark SFWindowController's methods
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(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;
} }
@ -162,21 +169,22 @@
[...] [...]
As best as I can figure, this is happening because the NSWindow (and As best as I can figure, this is happening because the NSWindow (and
hence my view) are not visible onscreen yet, and the system doesn't like that. hence my view) are not visible on screen yet, and the system doesn't like that.
[...] [...]
*/ */
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;
return self; return self;
} }
// 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,28 +203,30 @@
*/ */
} }
// 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;
return self; return self;
} }
// 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)];
} }
@ -258,7 +268,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)setRequesterTo:(sf::priv::WindowImplCocoa *)requester -(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester
{ {
// Forward to the view. // Forward to the view.
[m_oglView setRequesterTo:requester]; [m_oglView setRequesterTo:requester];
@ -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,11 +338,10 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(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);
}
} }
@ -359,7 +368,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)changeTitle:(NSString *)title -(void)changeTitle:(NSString*)title
{ {
[m_window setTitle:title]; [m_window setTitle:title];
} }
@ -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,27 +460,25 @@
-(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];
}
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)applyContext:(NSOpenGLContext *)context -(void)applyContext:(NSOpenGLContext*)context
{ {
[m_oglView setOpenGLContext:context]; [m_oglView setOpenGLContext:context];
[context setView:m_oglView]; [context setView:m_oglView];
@ -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;
@ -505,30 +514,30 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(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];
}
} }
@ -538,8 +547,8 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(float)screenHeight -(float)screenHeight
{ {
NSDictionary *deviceDescription = [[m_window screen] deviceDescription]; NSDictionary* deviceDescription = [[m_window screen] deviceDescription];
NSNumber *screenNumber = [deviceDescription valueForKey:@"NSScreenNumber"]; NSNumber* screenNumber = [deviceDescription valueForKey:@"NSScreenNumber"];
CGDirectDisplayID screenID = (CGDirectDisplayID)[screenNumber intValue]; CGDirectDisplayID screenID = (CGDirectDisplayID)[screenNumber intValue];
CGFloat height = CGDisplayPixelsHigh(screenID); CGFloat height = CGDisplayPixelsHigh(screenID);
return height; return height;

View File

@ -50,22 +50,23 @@ 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,22 +78,23 @@ 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.

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,8 +228,10 @@ 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
/// Also ensure NSApp is constructed. ///
/// The type of the process is changed to become a full GUI app.
/// Also ensure NSApp is constructed.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static void setUpProcess(void); static void setUpProcess(void);
@ -332,7 +334,7 @@ private :
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImplDelegateRef m_delegate; ///< Implementation in Obj-C. WindowImplDelegateRef m_delegate; ///< Implementation in Obj-C.
bool m_showCursor; ///< Is the cursor displayed or hidden ? bool m_showCursor; ///< Is the cursor displayed or hidden?
}; };
} // namespace priv } // namespace priv

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,33 +47,33 @@ 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 "
<< "a <NSWindow*> nor <NSView*> object "
sf::err() << "(or any of their subclasses). You gave a <"
<< "Cannot import this Window Handle because it is neither " << [[nsHandle className] UTF8String]
<< "a <NSWindow*> nor <NSView*> object " << "> object."
<< "(or any of their subclasses). You gave a <" << std::endl;
<< [[nsHandle className] UTF8String]
<< "> object."
<< std::endl;
return; return;
} }
@ -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,11 +399,10 @@ 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,22 +411,20 @@ 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];
}
} }

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
@ -47,12 +46,12 @@ namespace sf {
/// we have to duplicate some code. /// we have to duplicate some code.
/// ///
/// Everything is done via a class that implement this protocol. /// Everything is done via a class that implement this protocol.
/// There are two of these classes : /// There are two of these classes:
/// ///
/// SFViewController and SFWindowController /// SFViewController and SFWindowController
/// ///
/// The requester is a WindowImplCocoa. It's used to send back /// The requester is a WindowImplCocoa. It's used to send back
/// event via these functions : /// event via these functions:
/// ///
/// windowClosed, windowResized, windowLostFocus, windowGainedFocus /// windowClosed, windowResized, windowLostFocus, windowGainedFocus
/// ///
@ -61,99 +60,142 @@ namespace sf {
/// ///
/// keyDown, keyUp, textEntered /// keyDown, keyUp, textEntered
/// ///
/// Note : Joysticks are not bound to a view or window /// Note: Joysticks are not bound to a view or window
/// thus they're not managed by a class implementing this protocol. /// thus they're not managed by a class implementing this protocol.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@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;
@end @end

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());