Added opt-in support for high-dpi mode in OS X when on a retina display (resolves issue #761).

Added a ‘highdpi’ boolean flag to t.window/love.window.setMode (defaults to false.)
When the window is actually in high-dpi mode on a supported display, the graphics width and height and the mouse position are in pixels, rather than ‘window coordinates’.

Added love.window.getPixelScale. Returns the scale factor of the window from user-space points to pixels (e.g. it will be 1 normally, and 2 on a retina display in OS X with high-dpi mode enabled.)
This commit is contained in:
Alex Szpakowski
2014-01-17 21:11:20 -04:00
parent 29f47d9a10
commit 309193895a
10 changed files with 308 additions and 148 deletions
+96 -39
View File
@@ -63,21 +63,21 @@ Window::~Window()
Window::_currentMode::_currentMode()
: width(800)
, height(600)
, attribs()
, settings()
, icon(0)
{
}
bool Window::setWindow(int width, int height, WindowAttributes *attribs)
bool Window::setWindow(int width, int height, WindowSettings *settings)
{
graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics.");
if (gfx)
if (gfx != nullptr)
gfx->unSetMode();
WindowAttributes f;
WindowSettings f;
if (attribs)
f = *attribs;
if (settings)
f = *settings;
f.minwidth = std::max(f.minwidth, 1);
f.minheight = std::max(f.minheight, 1);
@@ -116,15 +116,28 @@ bool Window::setWindow(int width, int height, WindowAttributes *attribs)
if (f.borderless)
sdlflags |= SDL_WINDOW_BORDERLESS;
#if SDL_VERSION_ATLEAST(2,0,1)
if (f.highdpi)
sdlflags |= SDL_WINDOW_ALLOW_HIGHDPI;
#endif
// Destroy and recreate the window if the dimensions or flags have changed.
if (window)
{
int curdisplay = SDL_GetWindowDisplayIndex(window);
Uint32 wflags = SDL_GetWindowFlags(window);
wflags &= (SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS);
Uint32 testflags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP
| SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS;
#if SDL_VERSION_ATLEAST(2,0,1)
testflags |= SDL_WINDOW_ALLOW_HIGHDPI;
#endif
wflags &= testflags;
if (sdlflags != wflags || width != curMode.width || height != curMode.height
|| f.display != curdisplay || f.fsaa != curMode.attribs.fsaa)
|| f.display != curdisplay || f.fsaa != curMode.settings.fsaa)
{
SDL_DestroyWindow(window);
window = 0;
@@ -182,10 +195,19 @@ bool Window::setWindow(int width, int height, WindowAttributes *attribs)
created = true;
updateAttributes(f);
updateSettings(f);
if (gfx)
gfx->setMode(curMode.width, curMode.height);
if (gfx != nullptr)
{
int width = curMode.width;
int height = curMode.height;
#if SDL_VERSION_ATLEAST(2,0,1)
SDL_GL_GetDrawableSize(window, &width, &height);
#endif
gfx->setMode(width, height);
}
// Make sure the mouse keeps its previous grab setting.
setMouseGrab(mouseGrabbed);
@@ -250,8 +272,8 @@ bool Window::setContext(int fsaa, bool vsync)
fsaa = (buffers > 0) ? samples : 0;
}
curMode.attribs.fsaa = fsaa;
curMode.attribs.vsync = SDL_GL_GetSwapInterval() != 0;
curMode.settings.fsaa = fsaa;
curMode.settings.vsync = SDL_GL_GetSwapInterval() != 0;
return true;
}
@@ -271,7 +293,7 @@ void Window::setWindowGLAttributes(int fsaa) const
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
}
void Window::updateAttributes(const WindowAttributes &newattribs)
void Window::updateSettings(const WindowSettings &newsettings)
{
Uint32 wflags = SDL_GetWindowFlags(window);
@@ -280,54 +302,60 @@ void Window::updateAttributes(const WindowAttributes &newattribs)
if ((wflags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
curMode.attribs.fullscreen = true;
curMode.attribs.fstype = FULLSCREEN_TYPE_DESKTOP;
curMode.settings.fullscreen = true;
curMode.settings.fstype = FULLSCREEN_TYPE_DESKTOP;
}
else if ((wflags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN)
{
curMode.attribs.fullscreen = true;
curMode.attribs.fstype = FULLSCREEN_TYPE_NORMAL;
curMode.settings.fullscreen = true;
curMode.settings.fstype = FULLSCREEN_TYPE_NORMAL;
}
else
{
curMode.attribs.fullscreen = false;
curMode.attribs.fstype = newattribs.fstype;
curMode.settings.fullscreen = false;
curMode.settings.fstype = newsettings.fstype;
}
// The min width/height is set to 0 internally in SDL when in fullscreen.
if (curMode.attribs.fullscreen)
if (curMode.settings.fullscreen)
{
curMode.attribs.minwidth = newattribs.minwidth;
curMode.attribs.minheight = newattribs.minheight;
curMode.settings.minwidth = newsettings.minwidth;
curMode.settings.minheight = newsettings.minheight;
}
else
SDL_GetWindowMinimumSize(window, &curMode.attribs.minwidth, &curMode.attribs.minheight);
SDL_GetWindowMinimumSize(window, &curMode.settings.minwidth, &curMode.settings.minheight);
curMode.attribs.resizable = (wflags & SDL_WINDOW_RESIZABLE) != 0;
curMode.attribs.borderless = (wflags & SDL_WINDOW_BORDERLESS) != 0;
curMode.attribs.centered = newattribs.centered;
curMode.attribs.display = std::max(SDL_GetWindowDisplayIndex(window), 0);
curMode.settings.resizable = (wflags & SDL_WINDOW_RESIZABLE) != 0;
curMode.settings.borderless = (wflags & SDL_WINDOW_BORDERLESS) != 0;
curMode.settings.centered = newsettings.centered;
curMode.settings.display = std::max(SDL_GetWindowDisplayIndex(window), 0);
#if SDL_VERSION_ATLEAST(2,0,1)
curMode.settings.highdpi = (wflags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
#else
curMode.settings.highdpi = false;
#endif
// Only minimize on focus loss if the window is in exclusive-fullscreen
// mode (mimics behaviour of SDL 2.0.2+).
// In OS X we always disable this to prevent dock minimization weirdness.
#ifndef LOVE_MACOSX
if (curMode.attribs.fullscreen && curMode.attribs.fstype == FULLSCREEN_TYPE_NORMAL)
if (curMode.settings.fullscreen && curMode.settings.fstype == FULLSCREEN_TYPE_NORMAL)
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1");
else
#endif
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
}
void Window::getWindow(int &width, int &height, WindowAttributes &attribs)
void Window::getWindow(int &width, int &height, WindowSettings &settings)
{
// Window position may be different from creation - update display index.
if (window)
curMode.attribs.display = std::max(SDL_GetWindowDisplayIndex(window), 0);
curMode.settings.display = std::max(SDL_GetWindowDisplayIndex(window), 0);
width = curMode.width;
height = curMode.height;
attribs = curMode.attribs;
settings = curMode.settings;
}
bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
@@ -335,9 +363,9 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
if (!window)
return false;
WindowAttributes newattribs = curMode.attribs;
newattribs.fullscreen = fullscreen;
newattribs.fstype = fstype;
WindowSettings newsettings = curMode.settings;
newsettings.fullscreen = fullscreen;
newsettings.fstype = fstype;
Uint32 sdlflags = 0;
@@ -361,12 +389,21 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
if (SDL_SetWindowFullscreen(window, sdlflags) == 0)
{
SDL_GL_MakeCurrent(window, context);
updateAttributes(newattribs);
updateSettings(newsettings);
// Update the viewport size now instead of waiting for event polling.
graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics.");
if (gfx)
gfx->setViewportSize(curMode.width, curMode.height);
if (gfx != nullptr)
{
int width = curMode.width;
int height = curMode.height;
#if SDL_VERSION_ATLEAST(2,0,1)
SDL_GL_GetDrawableSize(window, &width, &height);
#endif
gfx->setViewportSize(width, height);
}
return true;
}
@@ -376,7 +413,7 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
bool Window::setFullscreen(bool fullscreen)
{
return setFullscreen(fullscreen, curMode.attribs.fstype);
return setFullscreen(fullscreen, curMode.settings.fstype);
}
int Window::getDisplayCount() const
@@ -559,6 +596,26 @@ bool Window::isMouseGrabbed() const
return mouseGrabbed;
}
double Window::getPixelScale() const
{
double scale = 1.0;
#if SDL_VERSION_ATLEAST(2,0,1)
if (window)
{
int wheight;
SDL_GetWindowSize(window, nullptr, &wheight);
int dheight = wheight;
SDL_GL_GetDrawableSize(window, nullptr, &dheight);
scale = (double) dheight / wheight;
}
#endif
return scale;
}
const void *Window::getHandle() const
{
return window;
+7 -5
View File
@@ -41,8 +41,8 @@ public:
Window();
~Window();
bool setWindow(int width = 800, int height = 600, WindowAttributes *attribs = 0);
void getWindow(int &width, int &height, WindowAttributes &attribs);
bool setWindow(int width = 800, int height = 600, WindowSettings *settings = nullptr);
void getWindow(int &width, int &height, WindowSettings &settings);
bool setFullscreen(bool fullscreen, FullscreenType fstype);
bool setFullscreen(bool fullscreen);
@@ -79,6 +79,8 @@ public:
void setMouseGrab(bool grab);
bool isMouseGrabbed() const;
double getPixelScale() const;
const void *getHandle() const;
static love::window::Window *createSingleton();
@@ -91,8 +93,8 @@ private:
bool setContext(int fsaa, bool vsync);
void setWindowGLAttributes(int fsaa) const;
// Update the saved window attribs based on the window's actual state.
void updateAttributes(const WindowAttributes &newattribs);
// Update the saved window settings based on the window's actual state.
void updateSettings(const WindowSettings &newsettings);
std::string windowTitle;
@@ -102,7 +104,7 @@ private:
int width;
int height;
WindowAttributes attribs;
WindowSettings settings;
love::image::ImageData *icon;
} curMode;