1
0
mirror of https://github.com/OpenTTD/OpenTTD synced 2026-01-28 06:34:33 +01:00

Change: Determine automatic interface scale by window size. (#14627)

Replace OS-dependent interface scaling with scaling dependent on the window size.

This works on all platforms and should provide a more comfortable experience for new players. Manual interface scale setting works as before.
This commit is contained in:
Peter Nelson
2025-09-18 18:52:14 +01:00
committed by GitHub
parent 2d13bcb7b9
commit 17fbe0b911
7 changed files with 24 additions and 68 deletions

View File

@@ -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);
}

View File

@@ -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<NWidgetBase>(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)) {

View File

@@ -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;

View File

@@ -283,12 +283,6 @@ Dimension VideoDriver_Cocoa::GetScreenSize() const
return { static_cast<uint>(NSWidth(frame)), static_cast<uint>(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()
{

View File

@@ -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.
*/

View File

@@ -1079,47 +1079,6 @@ Dimension VideoDriver_Win32Base::GetScreenSize() const
return { static_cast<uint>(GetSystemMetrics(SM_CXSCREEN)), static_cast<uint>(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;

View File

@@ -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;