1
0
forked from 0ad/0ad

Scale the cursor according to the GUI scale (HiDPI support).

Differential Revision: https://code.wildfiregames.com/D320
Fixes #3875
Patch By: Dariost
Reviewed By: domdomegg
This was SVN commit r19667.
This commit is contained in:
elexis 2017-05-27 09:24:04 +00:00
parent a3913080cc
commit 9ff7ec3465
3 changed files with 30 additions and 18 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2014 Wildfire Games /* Copyright (c) 2017 Wildfire Games
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@ -52,7 +52,7 @@ class SDLCursor
SDL_Cursor* cursor; SDL_Cursor* cursor;
public: public:
Status create(const PIVFS& vfs, const VfsPath& pathname, int hotspotx_, int hotspoty_) Status create(const PIVFS& vfs, const VfsPath& pathname, int hotspotx_, int hotspoty_, double scale)
{ {
shared_ptr<u8> file; size_t fileSize; shared_ptr<u8> file; size_t fileSize;
RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, file, fileSize)); RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, file, fileSize));
@ -70,6 +70,16 @@ public:
surface = SDL_CreateRGBSurfaceFrom(bgra_img, (int)t.m_Width, (int)t.m_Height, 32, (int)t.m_Width*4, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); surface = SDL_CreateRGBSurfaceFrom(bgra_img, (int)t.m_Width, (int)t.m_Height, 32, (int)t.m_Width*4, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
if (!surface) if (!surface)
return ERR::FAIL; return ERR::FAIL;
if (scale != 1.0)
{
SDL_Surface* scaled_surface = SDL_CreateRGBSurface(0, surface->w * scale, surface->h * scale, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
if (!scaled_surface)
return ERR::FAIL;
if (SDL_BlitScaled(surface, NULL, scaled_surface, NULL))
return ERR::FAIL;
SDL_FreeSurface(surface);
surface = scaled_surface;
}
cursor = SDL_CreateColorCursor(surface, hotspotx_, hotspoty_); cursor = SDL_CreateColorCursor(surface, hotspotx_, hotspoty_);
if (!cursor) if (!cursor)
return ERR::FAIL; return ERR::FAIL;
@ -99,15 +109,15 @@ class GLCursor
int hotspotx, hotspoty; int hotspotx, hotspoty;
public: public:
Status create(const PIVFS& vfs, const VfsPath& pathname, int hotspotx_, int hotspoty_) Status create(const PIVFS& vfs, const VfsPath& pathname, int hotspotx_, int hotspoty_, double scale)
{ {
ht = ogl_tex_load(vfs, pathname); ht = ogl_tex_load(vfs, pathname);
RETURN_STATUS_IF_ERR(ht); RETURN_STATUS_IF_ERR(ht);
size_t width, height; size_t width, height;
(void)ogl_tex_get_size(ht, &width, &height, 0); (void)ogl_tex_get_size(ht, &width, &height, 0);
w = (GLint)width; w = (GLint)(width * scale);
h = (GLint)height; h = (GLint)(height * scale);
hotspotx = hotspotx_; hotspoty = hotspoty_; hotspotx = hotspotx_; hotspoty = hotspoty_;
@ -169,6 +179,8 @@ enum CursorKind
struct Cursor struct Cursor
{ {
double scale;
// require kind == CK_OpenGL after reload // require kind == CK_OpenGL after reload
bool forceGL; bool forceGL;
@ -185,6 +197,7 @@ H_TYPE_DEFINE(Cursor);
static void Cursor_init(Cursor* c, va_list args) static void Cursor_init(Cursor* c, va_list args)
{ {
c->scale = va_arg(args, double);
c->forceGL = (va_arg(args, int) != 0); c->forceGL = (va_arg(args, int) != 0);
} }
@ -227,13 +240,11 @@ static Status Cursor_reload(Cursor* c, const PIVFS& vfs, const VfsPath& name, Ha
const VfsPath pathnameImage = pathname.ChangeExtension(L".png"); const VfsPath pathnameImage = pathname.ChangeExtension(L".png");
// try loading as SDL2 cursor // try loading as SDL2 cursor
if (!c->forceGL && c->sdl_cursor.create(vfs, pathnameImage, hotspotx, hotspoty) == INFO::OK) if (!c->forceGL && c->sdl_cursor.create(vfs, pathnameImage, hotspotx, hotspoty, c->scale) == INFO::OK)
c->kind = CK_SDL; c->kind = CK_SDL;
// fall back to GLCursor (system cursor code is disabled or failed) // fall back to GLCursor (system cursor code is disabled or failed)
else if(c->gl_cursor.create(vfs, pathnameImage, hotspotx, hotspoty) == INFO::OK) else if (c->gl_cursor.create(vfs, pathnameImage, hotspotx, hotspoty, c->scale) == INFO::OK)
{
c->kind = CK_OpenGL; c->kind = CK_OpenGL;
}
// everything failed, leave cursor unchanged // everything failed, leave cursor unchanged
else else
c->kind = CK_Default; c->kind = CK_Default;
@ -297,9 +308,9 @@ static Status Cursor_to_string(const Cursor* c, wchar_t* buf)
// in other words, we continually create/free the cursor resource in // in other words, we continually create/free the cursor resource in
// cursor_draw and trust h_mgr's caching to absorb it. // cursor_draw and trust h_mgr's caching to absorb it.
static Handle cursor_load(const PIVFS& vfs, const VfsPath& name, bool forceGL) static Handle cursor_load(const PIVFS& vfs, const VfsPath& name, double scale, bool forceGL)
{ {
return h_alloc(H_Cursor, vfs, name, 0, (int)forceGL); return h_alloc(H_Cursor, vfs, name, 0, scale, (int)forceGL);
} }
void cursor_shutdown() void cursor_shutdown()
@ -313,7 +324,7 @@ static Status cursor_free(Handle& h)
} }
Status cursor_draw(const PIVFS& vfs, const wchar_t* name, int x, int y, bool forceGL) Status cursor_draw(const PIVFS& vfs, const wchar_t* name, int x, int y, double scale, bool forceGL)
{ {
// hide the cursor // hide the cursor
if(!name) if(!name)
@ -322,7 +333,7 @@ Status cursor_draw(const PIVFS& vfs, const wchar_t* name, int x, int y, bool for
return INFO::OK; return INFO::OK;
} }
Handle hc = cursor_load(vfs, name, forceGL); Handle hc = cursor_load(vfs, name, scale, forceGL);
// TODO: if forceGL changes at runtime after a cursor is first created, // TODO: if forceGL changes at runtime after a cursor is first created,
// we might reuse a cached version of the cursor with the old forceGL flag // we might reuse a cached version of the cursor with the old forceGL flag

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2010 Wildfire Games /* Copyright (c) 2017 Wildfire Games
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@ -39,12 +39,13 @@
* mouse Y coordinate to be subtracted from the client area height. * mouse Y coordinate to be subtracted from the client area height.
* Making the caller responsible for this avoids a dependency on * Making the caller responsible for this avoids a dependency on
* the g_yres global variable.) * the g_yres global variable.)
* @param scale Scale factor for drawing size the cursor.
* @param forceGL Require the OpenGL cursor implementation, not hardware cursor * @param forceGL Require the OpenGL cursor implementation, not hardware cursor
* *
* Uses a hardware mouse cursor where available, otherwise a * Uses a hardware mouse cursor where available, otherwise a
* portable OpenGL implementation. * portable OpenGL implementation.
**/ **/
extern Status cursor_draw(const PIVFS& vfs, const wchar_t* name, int x, int y, bool forceGL); extern Status cursor_draw(const PIVFS& vfs, const wchar_t* name, int x, int y, double scale, bool forceGL);
/** /**
* Forcibly frees all cursor handles. * Forcibly frees all cursor handles.

View File

@ -281,7 +281,7 @@ void Render()
CStrW cursorName = g_CursorName; CStrW cursorName = g_CursorName;
if (cursorName.empty()) if (cursorName.empty())
{ {
cursor_draw(g_VFS, NULL, g_mouse_x, g_yres-g_mouse_y, false); cursor_draw(g_VFS, NULL, g_mouse_x, g_yres-g_mouse_y, 1.0 / g_GuiScale, false);
} }
else else
{ {
@ -306,7 +306,7 @@ void Render()
#if OS_ANDROID #if OS_ANDROID
#warning TODO: cursors for Android #warning TODO: cursors for Android
#else #else
if (cursor_draw(g_VFS, cursorName.c_str(), g_mouse_x, g_yres-g_mouse_y, forceGL) < 0) if (cursor_draw(g_VFS, cursorName.c_str(), g_mouse_x, g_yres-g_mouse_y, 1.0 / g_GuiScale, forceGL) < 0)
LOGWARNING("Failed to draw cursor '%s'", utf8_from_wstring(cursorName)); LOGWARNING("Failed to draw cursor '%s'", utf8_from_wstring(cursorName));
#endif #endif
@ -598,7 +598,7 @@ static void ShutdownPs()
UnloadHotkeys(); UnloadHotkeys();
// disable the special Windows cursor, or free textures for OGL cursors // disable the special Windows cursor, or free textures for OGL cursors
cursor_draw(g_VFS, 0, g_mouse_x, g_yres-g_mouse_y, false); cursor_draw(g_VFS, 0, g_mouse_x, g_yres-g_mouse_y, 1.0, false);
} }