Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL2: Support highdpi #14703

Merged
merged 2 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions builtin/settingtypes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2187,9 +2187,6 @@ curl_file_download_timeout (cURL file download timeout) int 300000 5000 21474836

[**Miscellaneous]

# Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k screens.
screen_dpi (DPI) int 72 1

# Adjust the detected display density, used for scaling UI elements.
display_density_factor (Display Density Scaling Factor) float 1 0.5 5.0

Expand Down
3 changes: 3 additions & 0 deletions irr/include/IEventReceiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ enum EAPPLICATION_EVENT_TYPE
//! The application received a memory warning.
EAET_MEMORY_WARNING,

//! The display density changed (only works on SDL).
EAET_DPI_CHANGED,

//! No real event, but to get number of event types.
EAET_COUNT
};
Expand Down
79 changes: 50 additions & 29 deletions irr/src/CIrrDeviceSDL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters &param) :
SDL_SetHint(SDL_HINT_TV_REMOTE_AS_JOYSTICK, "0");
#endif

#if SDL_VERSION_ATLEAST(2, 24, 0)
// highdpi support on Windows
SDL_SetHint(SDL_HINT_WINDOWS_DPI_SCALING, "1");
#endif

// Minetest has its own code to synthesize mouse events from touch events,
// so we prevent SDL from doing it.
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
Expand Down Expand Up @@ -475,6 +480,7 @@ bool CIrrDeviceSDL::createWindow()
bool CIrrDeviceSDL::createWindowWithContext()
{
u32 SDL_Flags = 0;
SDL_Flags |= SDL_WINDOW_ALLOW_HIGHDPI;
grorp marked this conversation as resolved.
Show resolved Hide resolved

SDL_Flags |= getFullscreenFlag(CreationParams.Fullscreen);
if (Resizable)
Expand Down Expand Up @@ -589,13 +595,16 @@ bool CIrrDeviceSDL::createWindowWithContext()
return false;
}

// Update Width and Height to match the actual window size.
// In fullscreen mode, the window size specified in SIrrlichtCreationParameters
// is ignored, so we cannot rely on it.
int w = 0, h = 0;
SDL_GetWindowSize(Window, &w, &h);
Width = w;
Height = h;
updateSizeAndScale();
if (ScaleX != 1.0f || ScaleY != 1.0f) {
// The given window size is in pixels, not in screen coordinates.
// We can only do the conversion now since we didn't know the scale before.
SDL_SetWindowSize(Window, CreationParams.WindowSize.Width / ScaleX,
CreationParams.WindowSize.Height / ScaleY);
// Re-center, otherwise large, non-maximized windows go offscreen.
SDL_SetWindowPosition(Window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
updateSizeAndScale();
}

return true;
#endif // !_IRR_EMSCRIPTEN_PLATFORM_
Expand Down Expand Up @@ -659,10 +668,10 @@ bool CIrrDeviceSDL::run()

irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT;
irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED;
MouseX = irrevent.MouseInput.X = SDL_event.motion.x;
MouseY = irrevent.MouseInput.Y = SDL_event.motion.y;
MouseXRel = SDL_event.motion.xrel;
MouseYRel = SDL_event.motion.yrel;
MouseX = irrevent.MouseInput.X = SDL_event.motion.x * ScaleX;
MouseY = irrevent.MouseInput.Y = SDL_event.motion.y * ScaleY;
MouseXRel = SDL_event.motion.xrel * ScaleX;
MouseYRel = SDL_event.motion.yrel * ScaleY;
irrevent.MouseInput.ButtonStates = MouseButtonStates;
irrevent.MouseInput.Shift = (keymod & KMOD_SHIFT) != 0;
irrevent.MouseInput.Control = (keymod & KMOD_CTRL) != 0;
Expand Down Expand Up @@ -694,8 +703,8 @@ bool CIrrDeviceSDL::run()
SDL_Keymod keymod = SDL_GetModState();

irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT;
irrevent.MouseInput.X = SDL_event.button.x;
irrevent.MouseInput.Y = SDL_event.button.y;
irrevent.MouseInput.X = SDL_event.button.x * ScaleX;
irrevent.MouseInput.Y = SDL_event.button.y * ScaleY;
irrevent.MouseInput.Shift = (keymod & KMOD_SHIFT) != 0;
irrevent.MouseInput.Control = (keymod & KMOD_CTRL) != 0;

Expand Down Expand Up @@ -827,14 +836,25 @@ bool CIrrDeviceSDL::run()
case SDL_WINDOWEVENT:
switch (SDL_event.window.event) {
case SDL_WINDOWEVENT_RESIZED:
if ((SDL_event.window.data1 != (int)Width) || (SDL_event.window.data2 != (int)Height)) {
Width = SDL_event.window.data1;
Height = SDL_event.window.data2;
case SDL_WINDOWEVENT_SIZE_CHANGED:
#if SDL_VERSION_ATLEAST(2, 0, 18)
case SDL_WINDOWEVENT_DISPLAY_CHANGED:
#endif
u32 old_w = Width, old_h = Height;
f32 old_scale_x = ScaleX, old_scale_y = ScaleY;
updateSizeAndScale();
if (old_w != Width || old_h != Height) {
if (VideoDriver)
VideoDriver->OnResize(core::dimension2d<u32>(Width, Height));
}
if (old_scale_x != ScaleX || old_scale_y != ScaleY) {
irrevent.EventType = EET_APPLICATION_EVENT;
irrevent.ApplicationEvent.EventType = EAET_DPI_CHANGED;
postEventFromUser(irrevent);
}
break;
}
break;

case SDL_USEREVENT:
irrevent.EventType = irr::EET_USER_EVENT;
Expand Down Expand Up @@ -1030,25 +1050,26 @@ bool CIrrDeviceSDL::activateJoysticks(core::array<SJoystickInfo> &joystickInfo)
return false;
}

//! Get the display density in dots per inch.
float CIrrDeviceSDL::getDisplayDensity() const
void CIrrDeviceSDL::updateSizeAndScale()
{
if (!Window)
return 0.0f;

int window_w;
int window_h;
int window_w, window_h;
SDL_GetWindowSize(Window, &window_w, &window_h);

int drawable_w;
int drawable_h;
int drawable_w, drawable_h;
SDL_GL_GetDrawableSize(Window, &drawable_w, &drawable_h);
sfan5 marked this conversation as resolved.
Show resolved Hide resolved

// assume 96 dpi
float dpi_w = (float)drawable_w / (float)window_w * 96.0f;
float dpi_h = (float)drawable_h / (float)window_h * 96.0f;
ScaleX = (float)drawable_w / (float)window_w;
ScaleY = (float)drawable_h / (float)window_h;

Width = drawable_w;
Height = drawable_h;
}

return std::max(dpi_w, dpi_h);
//! Get the display density in dots per inch.
float CIrrDeviceSDL::getDisplayDensity() const
{
// assume 96 dpi
return std::max(ScaleX * 96.0f, ScaleY * 96.0f);
}

void CIrrDeviceSDL::SwapWindow()
Expand Down
5 changes: 4 additions & 1 deletion irr/src/CIrrDeviceSDL.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ class CIrrDeviceSDL : public CIrrDeviceStub
//! Sets the new position of the cursor.
void setPosition(s32 x, s32 y) override
{
SDL_WarpMouseInWindow(Device->Window, x, y);
SDL_WarpMouseInWindow(Device->Window,
x / Device->ScaleX, y / Device->ScaleY);

if (SDL_GetRelativeMouseMode()) {
// There won't be an event for this warp (details on libsdl-org/SDL/issues/6034)
Expand Down Expand Up @@ -300,6 +301,8 @@ class CIrrDeviceSDL : public CIrrDeviceStub
u32 MouseButtonStates;

u32 Width, Height;
f32 ScaleX = 1.0f, ScaleY = 1.0f;
void updateSizeAndScale();

bool Resizable;

Expand Down
2 changes: 2 additions & 0 deletions irr/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# When enabling SDL2 by default on macOS, don't forget to change
# "NSHighResolutionCapable" to true in "Info.plist".
if(NOT APPLE)
set(DEFAULT_SDL2 ON)
endif()
Expand Down
2 changes: 2 additions & 0 deletions misc/minetest.exe.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
</trustInfo>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- https://learn.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process#setting-default-awareness-with-the-application-manifest -->
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
<heapType xmlns="http://schemas.microsoft.com/SMI/2020/WindowsSettings">SegmentHeap</heapType>
</windowsSettings>
Expand Down
2 changes: 2 additions & 0 deletions src/client/clientlauncher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ static void dump_start_data(const GameStartData &data)
ClientLauncher::~ClientLauncher()
{
delete input;
g_settings->deregisterChangedCallback("dpi_change_notifier", setting_changed_callback, this);
g_settings->deregisterChangedCallback("gui_scaling", setting_changed_callback, this);

delete g_fontengine;
Expand Down Expand Up @@ -129,6 +130,7 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)

guienv = m_rendering_engine->get_gui_env();
config_guienv();
g_settings->registerChangedCallback("dpi_change_notifier", setting_changed_callback, this);
g_settings->registerChangedCallback("gui_scaling", setting_changed_callback, this);

g_fontengine = new FontEngine(guienv);
Expand Down
2 changes: 1 addition & 1 deletion src/client/fontengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ FontEngine::FontEngine(gui::IGUIEnvironment* env) :
"mono_font_path", "mono_font_path_bold", "mono_font_path_italic",
"mono_font_path_bold_italic",
"fallback_font_path",
"screen_dpi", "gui_scaling",
"dpi_change_notifier", "gui_scaling",
};

for (auto name : settings)
Expand Down
2 changes: 2 additions & 0 deletions src/client/hud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Hud::Hud(Client *client, LocalPlayer *player,
this->inventory = inventory;

readScalingSetting();
g_settings->registerChangedCallback("dpi_change_notifier", setting_changed_callback, this);
g_settings->registerChangedCallback("hud_scaling", setting_changed_callback, this);

for (auto &hbar_color : hbar_colors)
Expand Down Expand Up @@ -153,6 +154,7 @@ void Hud::readScalingSetting()

Hud::~Hud()
{
g_settings->deregisterChangedCallback("dpi_change_notifier", setting_changed_callback, this);
g_settings->deregisterChangedCallback("hud_scaling", setting_changed_callback, this);

if (m_selection_mesh)
Expand Down
9 changes: 9 additions & 0 deletions src/client/inputhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
return true;
}

if (event.EventType == EET_APPLICATION_EVENT &&
event.ApplicationEvent.EventType == EAET_DPI_CHANGED) {
// This is a fake setting so that we can use (de)registerChangedCallback
// not only to listen for gui/hud_scaling changes, but also for DPI changes.
g_settings->setU16("dpi_change_notifier",
g_settings->getU16("dpi_change_notifier") + 1);
return true;
}

// This is separate from other keyboard handling so that it also works in menus.
if (event.EventType == EET_KEY_INPUT_EVENT) {
const KeyPress keyCode(event.KeyInput);
Expand Down
16 changes: 6 additions & 10 deletions src/client/renderingengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,18 +462,14 @@ const VideoDriverInfo &RenderingEngine::getVideoDriverInfo(irr::video::E_DRIVER_

float RenderingEngine::getDisplayDensity()
{
float user_factor = g_settings->getFloat("display_density_factor", 0.5f, 5.0f);
#ifndef __ANDROID__
static float cached_display_density = [&] {
float dpi = get_raw_device()->getDisplayDensity();
// fall back to manually specified dpi
if (dpi == 0.0f)
dpi = g_settings->getFloat("screen_dpi");
return dpi / 96.0f;
}();
return std::max(cached_display_density * g_settings->getFloat("display_density_factor"), 0.5f);

float dpi = get_raw_device()->getDisplayDensity();
if (dpi == 0.0f)
dpi = 96.0f;
return std::max(dpi / 96.0f * user_factor, 0.5f);
#else // __ANDROID__
return porting::getDisplayDensity();
return porting::getDisplayDensity() * user_factor;
#endif // __ANDROID__
}

Expand Down
2 changes: 1 addition & 1 deletion src/defaultsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,8 @@ void set_default_settings()
settings->setDefault("server_description", "");

settings->setDefault("enable_console", "false");
settings->setDefault("screen_dpi", "72");
settings->setDefault("display_density_factor", "1");
settings->setDefault("dpi_change_notifier", "0");

// Altered settings for macOS
#if defined(__MACH__) && defined(__APPLE__)
Expand Down
Loading