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:
11
src/gfx.cpp
11
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);
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user