diff --git a/src/gfx.cpp b/src/gfx.cpp index 8dfc5683fa..87b6c7c50e 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1325,6 +1325,10 @@ void ScreenSizeChanged() /* screen size changed and the old bitmap is invalid now, so we don't want to undraw it */ _cursor.visible = false; + + if (VideoDriver::GetInstance() != nullptr) { + if (AdjustGUIZoom(true)) ReInitAllWindows(true); + } } void UndrawMouseCursor() @@ -1785,7 +1789,12 @@ void UpdateGUIZoom() { /* Determine real GUI zoom to use. */ if (_gui_scale_cfg == -1) { - _gui_scale = VideoDriver::GetInstance()->GetSuggestedUIScale(); + /* Minimum design size of the game is 640x480. */ + float xs = _screen.width / 640.f; + float ys = _screen.height / 480.f; + int scale = std::min(xs, ys) * 100; + /* Round down scaling to 25% increments and clamp to limits. */ + _gui_scale = Clamp((scale / 25) * 25, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE); } else { _gui_scale = Clamp(_gui_scale_cfg, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE); } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 800c4ef71b..034a5da24b 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -417,10 +417,11 @@ struct GameOptionsWindow : Window { GameSettings *opt = nullptr; bool reload = false; + bool gui_scale_changed = false; int gui_scale = 0; static inline WidgetID active_tab = WID_GO_TAB_GENERAL; - GameOptionsWindow(WindowDesc &desc) : Window(desc), filter_editbox(50), gui_scale(_gui_scale) + GameOptionsWindow(WindowDesc &desc) : Window(desc), filter_editbox(50) { this->opt = &GetGameSettings(); @@ -453,6 +454,7 @@ struct GameOptionsWindow : Window { void OnInit() override { _setting_circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED)); + this->gui_scale = _gui_scale; } void Close([[maybe_unused]] int data = 0) override @@ -1057,7 +1059,16 @@ struct GameOptionsWindow : Window { #endif /* HAS_TRUETYPE_FONT */ case WID_GO_GUI_SCALE: + /* Any click on the slider deactivates automatic interface scaling, setting it to the current value before being adjusted. */ + if (_gui_scale_cfg == -1) { + _gui_scale_cfg = this->gui_scale; + this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, false); + this->SetWidgetDirty(WID_GO_GUI_SCALE_AUTO); + this->SetWidgetDirty(WID_GO_GUI_SCALE_AUTO_TEXT); + } + if (ClickSliderWidget(this->GetWidget(widget)->GetCurrentRect(), pt, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, _ctrl_pressed ? 0 : SCALE_NMARKS, this->gui_scale)) { + this->gui_scale_changed = true; this->SetWidgetDirty(widget); } @@ -1383,8 +1394,9 @@ struct GameOptionsWindow : Window { void OnMouseLoop() override { - if (_left_button_down || this->gui_scale == _gui_scale) return; + if (_left_button_down || !this->gui_scale_changed) return; + this->gui_scale_changed = false; _gui_scale_cfg = this->gui_scale; if (AdjustGUIZoom(false)) { diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 727a9b140b..738a796805 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -64,7 +64,6 @@ protected: bool buffer_locked; ///< Video buffer was locked by the main thread. Dimension GetScreenSize() const override; - float GetDPIScale() override; void InputLoop() override; bool LockVideoBuffer() override; void UnlockVideoBuffer() override; diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 6960b0f925..31f390fe09 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -283,12 +283,6 @@ Dimension VideoDriver_Cocoa::GetScreenSize() const return { static_cast(NSWidth(frame)), static_cast(NSHeight(frame)) }; } -/** Get DPI scale of our window. */ -float VideoDriver_Cocoa::GetDPIScale() -{ - return this->cocoaview != nil ? [ this->cocoaview getContentsScale ] : 1.0f; -} - /** Lock video buffer for drawing if it isn't already mapped. */ bool VideoDriver_Cocoa::LockVideoBuffer() { diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp index c6229da341..d302ca1a03 100644 --- a/src/video/video_driver.hpp +++ b/src/video/video_driver.hpp @@ -166,16 +166,6 @@ public: return {}; } - /** - * Get a suggested default GUI scale taking screen DPI into account. - */ - virtual int GetSuggestedUIScale() - { - float dpi_scale = this->GetDPIScale(); - - return Clamp(dpi_scale * 100, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE); - } - virtual std::string_view GetInfoString() const { return this->GetName(); @@ -233,12 +223,6 @@ protected: */ virtual Dimension GetScreenSize() const { return { DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT }; } - /** - * Get DPI scaling factor of the screen OTTD is displayed on. - * @return 1.0 for default platform DPI, > 1.0 for higher DPI values, and < 1.0 for smaller DPI values. - */ - virtual float GetDPIScale() { return 1.0f; } - /** * Apply resolution auto-detection and clamp to sensible defaults. */ diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 33dc0a8b21..728b2be9f9 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -1079,47 +1079,6 @@ Dimension VideoDriver_Win32Base::GetScreenSize() const return { static_cast(GetSystemMetrics(SM_CXSCREEN)), static_cast(GetSystemMetrics(SM_CYSCREEN)) }; } -float VideoDriver_Win32Base::GetDPIScale() -{ - typedef UINT (WINAPI *PFNGETDPIFORWINDOW)(HWND hwnd); - typedef UINT (WINAPI *PFNGETDPIFORSYSTEM)(VOID); - typedef HRESULT (WINAPI *PFNGETDPIFORMONITOR)(HMONITOR hMonitor, int dpiType, UINT *dpiX, UINT *dpiY); - - static PFNGETDPIFORWINDOW _GetDpiForWindow = nullptr; - static PFNGETDPIFORSYSTEM _GetDpiForSystem = nullptr; - static PFNGETDPIFORMONITOR _GetDpiForMonitor = nullptr; - - static bool init_done = false; - if (!init_done) { - init_done = true; - static LibraryLoader _user32("user32.dll"); - static LibraryLoader _shcore("shcore.dll"); - _GetDpiForWindow = _user32.GetFunction("GetDpiForWindow"); - _GetDpiForSystem = _user32.GetFunction("GetDpiForSystem"); - _GetDpiForMonitor = _shcore.GetFunction("GetDpiForMonitor"); - } - - UINT cur_dpi = 0; - - if (cur_dpi == 0 && _GetDpiForWindow != nullptr && this->main_wnd != nullptr) { - /* Per window DPI is supported since Windows 10 Ver 1607. */ - cur_dpi = _GetDpiForWindow(this->main_wnd); - } - if (cur_dpi == 0 && _GetDpiForMonitor != nullptr && this->main_wnd != nullptr) { - /* Per monitor is supported since Windows 8.1. */ - UINT dpiX, dpiY; - if (SUCCEEDED(_GetDpiForMonitor(MonitorFromWindow(this->main_wnd, MONITOR_DEFAULTTOPRIMARY), 0 /* MDT_EFFECTIVE_DPI */, &dpiX, &dpiY))) { - cur_dpi = dpiX; // X and Y are always identical. - } - } - if (cur_dpi == 0 && _GetDpiForSystem != nullptr) { - /* Fall back to system DPI. */ - cur_dpi = _GetDpiForSystem(); - } - - return cur_dpi > 0 ? cur_dpi / 96.0f : 1.0f; // Default Windows DPI value is 96. -} - bool VideoDriver_Win32Base::LockVideoBuffer() { if (this->buffer_locked) return false; diff --git a/src/video/win32_v.h b/src/video/win32_v.h index 9b2cb8535e..f0426a29c0 100644 --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -49,7 +49,6 @@ protected: bool buffer_locked; ///< Video buffer was locked by the main thread. Dimension GetScreenSize() const override; - float GetDPIScale() override; void InputLoop() override; bool LockVideoBuffer() override; void UnlockVideoBuffer() override;