diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 386c0778..23d3ed05 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -111,7 +111,7 @@ elseif(SFML_OS_MACOSX) ${SRCROOT}/OSX/cpp_objc_conversion.h ${SRCROOT}/OSX/cpp_objc_conversion.mm ${SRCROOT}/OSX/cg_sf_conversion.hpp - ${SRCROOT}/OSX/cg_sf_conversion.cpp + ${SRCROOT}/OSX/cg_sf_conversion.mm ${SRCROOT}/OSX/InputImpl.mm ${SRCROOT}/OSX/InputImpl.hpp ${SRCROOT}/OSX/HIDInputManager.hpp @@ -120,6 +120,7 @@ elseif(SFML_OS_MACOSX) ${SRCROOT}/OSX/HIDJoystickManager.cpp ${SRCROOT}/OSX/JoystickImpl.cpp ${SRCROOT}/OSX/JoystickImpl.hpp + ${SRCROOT}/OSX/Scaling.h ${SRCROOT}/OSX/SensorImpl.cpp ${SRCROOT}/OSX/SensorImpl.hpp ${SRCROOT}/OSX/SFApplication.h diff --git a/src/SFML/Window/OSX/SFWindowController.mm b/src/SFML/Window/OSX/SFWindowController.mm index 1d2a9150..3073caff 100644 --- a/src/SFML/Window/OSX/SFWindowController.mm +++ b/src/SFML/Window/OSX/SFWindowController.mm @@ -33,6 +33,7 @@ #include #include +#import #import #import #import @@ -161,6 +162,7 @@ { // Create a screen-sized window on the main display sf::VideoMode desktop = sf::VideoMode::getDesktopMode(); + sf::priv::scaleInWidthHeight(desktop, nil); NSRect windowRect = NSMakeRect(0, 0, desktop.width, desktop.height); m_window = [[SFWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask diff --git a/src/SFML/Window/OSX/Scaling.h b/src/SFML/Window/OSX/Scaling.h new file mode 100644 index 00000000..5a2af08f --- /dev/null +++ b/src/SFML/Window/OSX/Scaling.h @@ -0,0 +1,103 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2015 Marco Antognini (antognini.marco@gmail.com), +// Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#import + +#import + +namespace sf +{ +namespace priv +{ + +//////////////////////////////////////////////////////////// +/// \brief Get the scale factor of the main screen +/// +//////////////////////////////////////////////////////////// +inline CGFloat getDefaultScaleFactor() +{ + return [[NSScreen mainScreen] backingScaleFactor]; +} + +//////////////////////////////////////////////////////////// +/// \brief Scale SFML coordinates to backing coordinates +/// +/// \param in SFML coordinates to be converted +/// \param delegate an object implementing WindowImplDelegateProtocol, or nil for default scale +/// +//////////////////////////////////////////////////////////// +template +void scaleIn(T& in, id delegate) +{ + in /= delegate ? [delegate displayScaleFactor] : getDefaultScaleFactor(); +} + +template +void scaleInWidthHeight(T& in, id delegate) +{ + scaleIn(in.width, delegate); + scaleIn(in.height, delegate); +} + +template +void scaleInXY(T& in, id delegate) +{ + scaleIn(in.x, delegate); + scaleIn(in.y, delegate); +} + +//////////////////////////////////////////////////////////// +/// \brief Scale backing coordinates to SFML coordinates +/// +/// \param out backing coordinates to be converted +/// \param delegate an object implementing WindowImplDelegateProtocol, or nil for default scale +/// +//////////////////////////////////////////////////////////// +template +void scaleOut(T& out, id delegate) +{ + out *= delegate ? [delegate displayScaleFactor] : getDefaultScaleFactor(); +} + +template +void scaleOutWidthHeight(T& out, id delegate) +{ + scaleOut(out.width, delegate); + scaleOut(out.height, delegate); +} + +template +void scaleOutXY(T& out, id delegate) +{ + scaleOut(out.x, delegate); + scaleOut(out.y, delegate); +} + +} // namespace priv +} // namespace sf + diff --git a/src/SFML/Window/OSX/VideoModeImpl.cpp b/src/SFML/Window/OSX/VideoModeImpl.cpp index d83d17d7..b6137553 100644 --- a/src/SFML/Window/OSX/VideoModeImpl.cpp +++ b/src/SFML/Window/OSX/VideoModeImpl.cpp @@ -50,6 +50,8 @@ std::vector VideoModeImpl::getFullscreenModes() return modes; } + VideoMode desktop = getDesktopMode(); + // Loop on each mode and convert it into a sf::VideoMode object. const CFIndex modesCount = CFArrayGetCount(cgmodes); for (CFIndex i = 0; i < modesCount; i++) @@ -58,6 +60,10 @@ std::vector VideoModeImpl::getFullscreenModes() VideoMode mode = convertCGModeToSFMode(cgmode); + // Skip if bigger than desktop as we currently don't perform hard resolution switch + if ((mode.width > desktop.width) || (mode.height > desktop.height)) + continue; + // If not yet listed we add it to our modes array. if (std::find(modes.begin(), modes.end(), mode) == modes.end()) modes.push_back(mode); @@ -73,12 +79,21 @@ std::vector VideoModeImpl::getFullscreenModes() //////////////////////////////////////////////////////////// VideoMode VideoModeImpl::getDesktopMode() { + VideoMode mode; // RVO + + // Rely exclusively on mode and convertCGModeToSFMode + // instead of display id and CGDisplayPixelsHigh/Wide. + CGDirectDisplayID display = CGMainDisplayID(); - return VideoMode(CGDisplayPixelsWide(display), - CGDisplayPixelsHigh(display), - displayBitsPerPixel(display)); + CGDisplayModeRef cgmode = CGDisplayCopyDisplayMode(display); + + mode = convertCGModeToSFMode(cgmode); + + CGDisplayModeRelease(cgmode); + + return mode; } } // namespace priv - } // namespace sf + diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm index 24765ee0..b7dc45db 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.mm +++ b/src/SFML/Window/OSX/WindowImplCocoa.mm @@ -28,10 +28,10 @@ //////////////////////////////////////////////////////////// #include #include -#include #import #import +#import #import #import #import @@ -43,76 +43,6 @@ namespace sf namespace priv { -//////////////////////////////////////////////////////////// -/// \brief Get the scale factor of the main screen -/// -//////////////////////////////////////////////////////////// -CGFloat getDefaultScaleFactor() -{ - return [[NSScreen mainScreen] backingScaleFactor]; -} - -//////////////////////////////////////////////////////////// -/// \brief Scale SFML coordinates to backing coordinates -/// -/// Use -[NSScreen backingScaleFactor] to find out if the user -/// has a retina display or not. -/// -/// \param in SFML coordinates to be converted -/// \param delegate a object implementing WindowImplDelegateProtocol, or nil for default scale -/// -//////////////////////////////////////////////////////////// -template -void scaleIn(T& in, id delegate) -{ - in /= delegate ? [delegate displayScaleFactor] : getDefaultScaleFactor(); -} - -template -void scaleInWidthHeight(T& in, id delegate) -{ - scaleIn(in.width, delegate); - scaleIn(in.height, delegate); -} - -template -void scaleInXY(T& in, id delegate) -{ - scaleIn(in.x, delegate); - scaleIn(in.y, delegate); -} - -//////////////////////////////////////////////////////////// -/// \brief Scale backing coordinates to SFML coordinates -/// -/// Use -[NSScreen backingScaleFactor] to find out if the user -/// has a retina display or not. -/// -/// \param out backing coordinates to be converted -/// \param delegate a object implementing WindowImplDelegateProtocol, or nil for default scale -/// -//////////////////////////////////////////////////////////// -template -void scaleOut(T& out, id delegate) -{ - out *= delegate ? [delegate displayScaleFactor] : getDefaultScaleFactor(); -} - -template -void scaleOutWidthHeight(T& out, id delegate) -{ - scaleOut(out.width, delegate); - scaleOut(out.height, delegate); -} - -template -void scaleOutXY(T& out, id delegate) -{ - scaleOut(out.x, delegate); - scaleOut(out.y, delegate); -} - - //////////////////////////////////////////////////////////// /// According to Apple's documentation, each invocation of /// unhide must be balanced by an invocation of hide in @@ -583,3 +513,4 @@ bool WindowImplCocoa::hasFocus() const } // namespace priv } // namespace sf + diff --git a/src/SFML/Window/OSX/cg_sf_conversion.cpp b/src/SFML/Window/OSX/cg_sf_conversion.mm similarity index 65% rename from src/SFML/Window/OSX/cg_sf_conversion.cpp rename to src/SFML/Window/OSX/cg_sf_conversion.mm index 60318cd7..30a4ea67 100644 --- a/src/SFML/Window/OSX/cg_sf_conversion.cpp +++ b/src/SFML/Window/OSX/cg_sf_conversion.mm @@ -29,6 +29,8 @@ #include #include +#import + namespace sf { namespace priv @@ -74,51 +76,22 @@ size_t displayBitsPerPixel(CGDirectDisplayID displayId) //////////////////////////////////////////////////////////// VideoMode convertCGModeToSFMode(CGDisplayModeRef cgmode) { - return VideoMode(CGDisplayModeGetWidth(cgmode), - CGDisplayModeGetHeight(cgmode), - modeBitsPerPixel(cgmode)); -} - - -//////////////////////////////////////////////////////////// -CGDisplayModeRef convertSFModeToCGMode(VideoMode sfmode) -{ - // Starting with 10.6 we should query the display all the modes and - // search for the best one. - - // Will return NULL if sfmode is not in VideoMode::GetFullscreenModes. - CGDisplayModeRef cgbestMode = NULL; - - // Retrieve all modes available for main screen only. - CFArrayRef cgmodes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); - - if (cgmodes == NULL) // Should not happen but anyway... - { - sf::err() << "Couldn't get VideoMode for main display."; - return NULL; - } - - // Loop on each mode and convert it into a sf::VideoMode object. - const CFIndex modesCount = CFArrayGetCount(cgmodes); - for (CFIndex i = 0; i < modesCount; i++) - { - CGDisplayModeRef cgmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(cgmodes, i); - - VideoMode mode = convertCGModeToSFMode(cgmode); - - if (mode == sfmode) - cgbestMode = cgmode; - } - - // Clean up memory. - CFRelease(cgmodes); - - if (cgbestMode == NULL) - sf::err() << "Couldn't convert the given sf:VideoMode into a CGDisplayMode." - << std::endl; - - return cgbestMode; + // The main documentation says the sizes returned by + // CGDisplayModeGetWidth and CGDisplayModeGetHeight + // are expressed in pixels. However, some additional + // documentation [1] states they actually return + // values in points starting with 10.8. + // + // We therefore needs to use the scaling factor to + // convert the dimensions properly. + // + // [1]: "APIs for Supporting High Resolution" > "Additions and Changes for OS X v10.8" + // https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/APIs/APIs.html#//apple_ref/doc/uid/TP40012302-CH5-SW27 + VideoMode mode(CGDisplayModeGetWidth(cgmode), CGDisplayModeGetHeight(cgmode), modeBitsPerPixel(cgmode)); + scaleOutWidthHeight(mode, nil); + return mode; } } // namespace priv } // namespace sf +