Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Support Retina Displays and other High DPI Displays #353

mjbshaw opened this Issue · 11 comments

4 participants


I have a MacBook Pro with Retina Display. Creating an 800x600 window (for example, building and running the default sample code in a new SFML project in Xcode) results in a 1600x1200 window with a scaling factor 2 applied (much like any window created that doesn't support Apple's Retina Display, typically windows not using Cocoa or not setting NSHighResolutionCapable to true in the Info.plist file). This results in a very pixelated look.

If SFML could support high DPI displays, graphics would look sharper.

One potential issue with supporting high DPI displays is maintaining support for low DPI displays. Some apps may do their calculations in pixels, and thus on a high DPI display their end results are much smaller than they are on low DPI displays. A potential solution to this problem is providing a method in SFML to obtain the window's DPI and requiring the developer to make their app DPI independent however they may choose to do so. If a user would rather not handle DPI independence and would prefer the graphics to just be scaled up (like they currently are) on high DPI displays, that could also be provided as an option in SFML (I think).

This issue will become even more important if SFML supports mobile platforms like iOS or Android in the future.


Could you provide :

  • a minimal code that reproduce the issue,
  • a screenshot of the issue
  • the exact version of SFML you're using and
  • the exact OS version you have ?



Yes. This code is straight from the default code when creating a new SFML App project with Xcode. I've just removed the comments and the music for conciseness.

SFML version: 2.0 Snapshot from revision 802b937 (on Jan. 24th, 2013)
SFML compilation commands:
OS X version: 10.8.2
Xcode 4.6 project settings: Base SDK 10.8; Deployment Target 10.7 (also tried with 10.8); Using clang++ with C++11 support
Hardware: MacBook Pro with Retina Display, Mid 2012


#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>

#include "ResourcePath.hpp"

int main(int, char const**)
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");

    sf::Image icon;
    if (!icon.loadFromFile(resourcePath() + "icon.png")) {
        return EXIT_FAILURE;
    window.setIcon(icon.getSize().x, icon.getSize().y, icon.getPixelsPtr());

    sf::Texture texture;
    if (!texture.loadFromFile(resourcePath() + "cute_image.jpg")) {
        return EXIT_FAILURE;
    sf::Sprite sprite(texture);

    sf::Font font;
    if (!font.loadFromFile(resourcePath() + "sansation.ttf")) {
        return EXIT_FAILURE;
    sf::Text text("Hello SFML", font, 50);

    while (window.isOpen())
        sf::Event event;
        while (window.pollEvent(event))
            if (event.type == sf::Event::Closed) {

            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {




    return EXIT_SUCCESS;



#include <string>

std::string resourcePath(void);


#include "ResourcePath.hpp"
#import <Foundation/Foundation.h>

std::string resourcePath(void)
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    std::string rpath;
    NSBundle* bundle = [NSBundle mainBundle];

    if (bundle == nil) {
#ifdef DEBUG
        NSLog(@"bundle is nil... thus no resources path can be found.");
    } else {
        NSString* path = [bundle resourcePath];
        rpath = [path UTF8String] + std::string("/");

    [pool drain];

    return rpath;

Screenshot of the program. Notice the actual program is 1600x1200 pixels, with everything scaled by 2.
Screen Shot 2013-02-16 at 8 41 07 AM

For reference, when I open the "cute.png" image with Preview, it looks like this (it shows it as 800x600 native pixels, which is a quarter of the size it is in the program).
Screen Shot 2013-02-16 at 8 42 35 AM

Again, for another reference, here's a screenshot of running the app alongside the image opened in Preview so you can see the size comparison. Notice the image in Preview is only a quarter of the size of the app. Also notice the text in the app is more pixelated. Even outside of the rendering window, with the title's app, the text is pixelated compared to the Preview window's title text. This is because the app is getting naively scaled up by a factor of two by the OS because (for whatever reason) the app doesn't support my screen's high DPI.
Screen Shot 2013-02-16 at 8 53 29 AM

And here's a screenshot of the app's info. Notice the "Open in Low Resolution" is checked and unable to be unchecked. I have shrunk this image so it's not so big; the important part is the "Open in Low Resolution" checkbox.
Screen Shot 2013-02-16 at 9 04 34 AM_SMALL

If you need any additional details, please just let me know.


Thanks for all the details. It's indeed a bug.

@mantognini mantognini was assigned

Any suggestions for a fix?


Not yet.


Hi there - wondering if there are any suggestions for a fix now?

My workaround has been to rescaling every sprite by 50%, plus dividing any sprite translations by 2 (yeah, if I move a sprite by 1 pixel, it actually moves by 2). For rotations around center, the setOrigin is being done with the straight result from getGlobalBounds (width and height), without diving by 2.

Is there any simpler workaround? I mean... that one did sound pretty straightforward to me - it's a little ugly, though, but it works. However, as I'm new to SFML, I may be missing something... so, if you can suggest any simpler workaround, that would be greatly appreciated!


Well, this is not the way to go to fix it. The user code should not be aware of the kind of display and perform special operation to "fix" it.

Currently, I don't have time to work on it. But if anyone has a proper fix I would be happy to hear about it.


I've been looking into this more and I just want to post some of the things I've found (hopefully it helps narrow things down for you). I was able to get high DPI windows created by applying the following diff:

diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt
index 67e17b9..eecf155 100644
--- a/src/SFML/Window/CMakeLists.txt
+++ b/src/SFML/Window/CMakeLists.txt
@@ -118,7 +118,7 @@ if(WINDOWS)
     set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} ${X11_X11_LIB} ${X11_Xrandr_LIB})
-    set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
+    set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} "-framework Foundation -framework AppKit -framework IOKit")

 # define the sfml-window target
diff --git a/src/SFML/Window/OSX/HIDInputManager.hpp b/src/SFML/Window/OSX/HIDInputManager.hpp
index e6f7229..69d6d72 100644
--- a/src/SFML/Window/OSX/HIDInputManager.hpp
+++ b/src/SFML/Window/OSX/HIDInputManager.hpp
@@ -33,7 +33,7 @@
 #include <SFML/Window/JoystickImpl.hpp>
 #include <SFML/Window/Keyboard.hpp>
 #include <SFML/Window/Mouse.hpp>
-#include <Carbon/Carbon.h>
+#include <CoreServices/CoreServices.h>
 #include <IOKit/hid/IOHIDManager.h>
 #include <IOKit/hid/IOHIDDevice.h>
 #include <vector>
@@ -237,8 +237,8 @@ private :
     // Member data
     bool              m_isValid;                    ///< If any error occurs this variable is false
-    CFDataRef         m_layoutData;                 ///< CFData containing the layout
-    UCKeyboardLayout* m_layout;                     ///< Current Keyboard Layout
+    //CFDataRef         m_layoutData;                 ///< CFData containing the layout
+    //UCKeyboardLayout* m_layout;                     ///< Current Keyboard Layout
     IOHIDManagerRef   m_manager;                    ///< HID Manager

     typedef std::vector<IOHIDElementRef> IOHIDElements;
diff --git a/src/SFML/Window/OSX/ b/src/SFML/Window/OSX/
index 72f5e5c..c615ea8 100644
--- a/src/SFML/Window/OSX/
+++ b/src/SFML/Window/OSX/
@@ -174,10 +174,11 @@ CFDictionaryRef HIDInputManager::copyDevicesMask(UInt32 page, UInt32 usage)
 : m_isValid(true)
-, m_layoutData(0)
-, m_layout(0)
+//, m_layoutData(0)
+//, m_layout(0)
 , m_manager(0)
+#if 0
     // Get the current keyboard layout
     TISInputSourceRef tis = TISCopyCurrentKeyboardLayoutInputSource(); 
     m_layoutData = (CFDataRef)TISGetInputSourceProperty(tis, 
@@ -195,6 +196,7 @@ HIDInputManager::HIDInputManager()

     // The TIS is no more needed

     // Create an HID Manager reference
     m_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
@@ -381,6 +383,7 @@ void HIDInputManager::loadMouse(IOHIDDeviceRef mouse)
 void HIDInputManager::loadKey(IOHIDElementRef key)
+#if 0
     // Get its virtual code
     UInt32 usageCode   = IOHIDElementGetUsage(key);
     UInt8  virtualCode = usageToVirtualCode(usageCode);
@@ -473,6 +476,7 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
                   << error
                   << std::endl;

@@ -511,7 +515,7 @@ void HIDInputManager::freeUp()
     m_isValid = false;

-    if (m_layoutData    != 0)   CFRelease(m_layoutData);
+    //if (m_layoutData    != 0)   CFRelease(m_layoutData);
     // Do not release m_layout ! It is owned by m_layoutData.
     if (m_manager       != 0)   CFRelease(m_manager);

diff --git a/src/SFML/Window/OSX/ b/src/SFML/Window/OSX/
index 9922b52..7a10055 100644
--- a/src/SFML/Window/OSX/
+++ b/src/SFML/Window/OSX/
@@ -132,6 +132,8 @@ NSUInteger keepOnlyMaskFromData(NSUInteger data, NSUInteger mask);
+    [self  setWantsBestResolutionOpenGLSurface:YES];

     return self;

This diff consists of two parts:

  • The first part is removing references to the Carbon library (in CMakeLists.txt, HIDInputManager.hpp, and
  • Add [self setWantsBestResolutionOpenGLSurface:YES]; to SFOpenGLView (by default, OpenGL views don't use high resolution).

Obviously, this diff is not acceptable to be applied (I brutally removed the Carbon code and broke the keyboard stuff). However, I just wanted to show you what kind of changes need to be made. Hopefully there's some Cocoa functions (or other non-Carbon functions) to allow you to do the keyboard key mapping. I'm useless in that area :)

If there is any way I can help or any other information I can provide, let me know!


I forgot I also had to add:


To the app's Info.plist


Thanks for your research.

Is there any specific reason that forced you to remove carbon ?


Is there any specific reason that forced you to remove carbon ?

Yeah, there is. I misunderstood some documentation :) It's not a necessary change. I'll put together a pull request.

@mantognini mantognini closed this issue from a commit
@mantognini mantognini Add support for retina displays (close #353)
Based on PR #388 by Michael Bradshaw

Convert size to match the size requested by the user.
@mantognini mantognini modified the milestone: 2.2, 2.x
@mantognini mantognini added the resolved label
@Foaly Foaly referenced this issue from a commit
@mantognini mantognini Add support for retina displays (close #353)
Based on PR #388 by Michael Bradshaw

Convert size to match the size requested by the user.
@dacap dacap referenced this issue in aseprite/aseprite

Compiled version doesn't work on Retina OS X #589

@mantognini mantognini was unassigned by mjbshaw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.