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:
parent
a3913080cc
commit
9ff7ec3465
@ -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
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user