summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lang/english.txt8
-rw-r--r--src/settings_gui.cpp108
-rw-r--r--src/video/allegro_v.cpp10
-rw-r--r--src/video/allegro_v.h2
-rw-r--r--src/video/cocoa/cocoa_v.h2
-rw-r--r--src/video/cocoa/cocoa_v.mm25
-rw-r--r--src/video/sdl2_v.cpp11
-rw-r--r--src/video/sdl2_v.h2
-rw-r--r--src/video/video_driver.hpp9
-rw-r--r--src/video/win32_v.cpp21
-rw-r--r--src/video/win32_v.h2
-rw-r--r--src/widgets/settings_widget.h1
12 files changed, 173 insertions, 28 deletions
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 6e803a37c..73fdefd2d 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1021,6 +1021,14 @@ STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Normal
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Double size
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :Quad size
+STR_GAME_OPTIONS_GRAPHICS :{BLACK}Graphics
+
+STR_GAME_OPTIONS_REFRESH_RATE :{BLACK}Display refresh rate
+STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}Select the screen refresh rate to use
+STR_GAME_OPTIONS_REFRESH_RATE_OTHER :other
+STR_GAME_OPTIONS_REFRESH_RATE_ITEM :{NUM}Hz
+STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}Refresh rates higher than 60Hz might impact performance.
+
STR_GAME_OPTIONS_BASE_GRF :{BLACK}Base graphics set
STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}Select the base graphics set to use
STR_GAME_OPTIONS_BASE_GRF_STATUS :{RED}{NUM} missing/corrupted file{P "" s}
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
index 0ef8176bc..1d38c4e43 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -38,8 +38,10 @@
#include "video/video_driver.hpp"
#include <vector>
+#include <iterator>
#include "safeguards.h"
+#include "video/video_driver.hpp"
static const StringID _autosave_dropdown[] = {
@@ -140,6 +142,22 @@ void ShowBaseSetTextfileWindow(TextfileType file_type, const TBaseSet* baseset,
new BaseSetTextfileWindow<TBaseSet>(file_type, baseset, content_type);
}
+std::set<int> _refresh_rates = { 30, 60, 75, 90, 100, 120, 144, 240 };
+
+/**
+ * Add the refresh rate from the config and the refresh rates from all the monitors to
+ * our list of refresh rates shown in the GUI.
+ */
+static void AddRefreshRatesAndSelect()
+{
+ /* Add the refresh rate as selected in the config. */
+ _refresh_rates.insert(_settings_client.gui.refresh_rate);
+
+ /* Add all the refresh rates of all monitors connected to the machine. */
+ std::vector<int> monitorRates = VideoDriver::GetInstance()->GetListOfMonitorRefreshRates();
+ std::copy(monitorRates.begin(), monitorRates.end(), std::inserter(_refresh_rates, _refresh_rates.end()));
+}
+
struct GameOptionsWindow : Window {
GameSettings *opt;
bool reload;
@@ -149,6 +167,8 @@ struct GameOptionsWindow : Window {
this->opt = &GetGameSettings();
this->reload = false;
+ AddRefreshRatesAndSelect();
+
this->InitNested(WN_GAME_OPTIONS_GAME_OPTIONS);
this->OnInvalidateData(0);
}
@@ -215,6 +235,16 @@ struct GameOptionsWindow : Window {
}
break;
+ case WID_GO_REFRESH_RATE_DROPDOWN: // Setup refresh rate dropdown
+ for (auto it = _refresh_rates.begin(); it != _refresh_rates.end(); it++) {
+ auto i = std::distance(_refresh_rates.begin(), it);
+ if (*it == _settings_client.gui.refresh_rate) *selected_index = i;
+ auto item = new DropDownListParamStringItem(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, i, false);
+ item->SetParam(0, *it);
+ list.emplace_back(item);
+ }
+ break;
+
case WID_GO_GUI_ZOOM_DROPDOWN: {
*selected_index = _gui_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _gui_zoom + 1 : 0;
const StringID *items = _gui_zoom_dropdown;
@@ -252,17 +282,18 @@ struct GameOptionsWindow : Window {
void SetStringParameters(int widget) const override
{
switch (widget) {
- case WID_GO_CURRENCY_DROPDOWN: SetDParam(0, _currency_specs[this->opt->locale.currency].name); break;
- case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break;
- case WID_GO_LANG_DROPDOWN: SetDParamStr(0, _current_language->own_name); break;
- case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _resolutions.size() ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
- case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[_gui_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _gui_zoom_cfg + 1 : 0]); break;
- case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[_font_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _font_zoom_cfg + 1 : 0]); break;
- case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name.c_str()); break;
- case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
- case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->name.c_str()); break;
- case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->name.c_str()); break;
- case WID_GO_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
+ case WID_GO_CURRENCY_DROPDOWN: SetDParam(0, _currency_specs[this->opt->locale.currency].name); break;
+ case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break;
+ case WID_GO_LANG_DROPDOWN: SetDParamStr(0, _current_language->own_name); break;
+ case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _resolutions.size() ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
+ case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[_gui_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _gui_zoom_cfg + 1 : 0]); break;
+ case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[_font_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _font_zoom_cfg + 1 : 0]); break;
+ case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name.c_str()); break;
+ case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
+ case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->name.c_str()); break;
+ case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->name.c_str()); break;
+ case WID_GO_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
+ case WID_GO_REFRESH_RATE_DROPDOWN: SetDParam(0, _settings_client.gui.refresh_rate); break;
}
}
@@ -451,6 +482,16 @@ struct GameOptionsWindow : Window {
}
break;
+ case WID_GO_REFRESH_RATE_DROPDOWN: {
+ _settings_client.gui.refresh_rate = *std::next(_refresh_rates.begin(), index);
+ if (_settings_client.gui.refresh_rate > 60) {
+ /* Show warning to the user that this refresh rate might not be suitable on
+ * larger maps with many NewGRFs and vehicles. */
+ ShowErrorMessage(STR_GAME_OPTIONS_REFRESH_RATE_WARNING, INVALID_STRING_ID, WL_INFO);
+ }
+ break;
+ }
+
case WID_GO_GUI_ZOOM_DROPDOWN: {
int8 new_zoom = index > 0 ? ZOOM_LVL_OUT_4X - index + 1 : ZOOM_LVL_CFG_AUTO;
if (new_zoom != _gui_zoom_cfg) {
@@ -528,36 +569,47 @@ static const NWidgetPart _nested_game_options_widgets[] = {
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_AUTOSAVE_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP), SetFill(1, 0),
EndContainer(),
- NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP), SetFill(1, 0), SetPadding(0, 0, 3, 0),
- NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0), SetPadding(0, 0, 3, 0),
- NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0),
- NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_VIDEO_ACCELERATION, STR_NULL),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_ACCEL_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP),
- EndContainer(),
+ NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_GUI_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0),
+ EndContainer(),
+ NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_CURRENCY_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0),
EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
EndContainer(),
NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_LANG_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0),
EndContainer(),
- NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_CURRENCY_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0),
- EndContainer(),
- NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_GUI_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0),
- EndContainer(),
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_FONT_ZOOM, STR_NULL),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_FONT_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0),
EndContainer(),
EndContainer(),
EndContainer(),
+ NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GRAPHICS, STR_NULL), SetPadding(0, 10, 0, 10),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(NWID_VERTICAL),
+ NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL), SetPadding(0, 0, 2, 0),
+ NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_REFRESH_RATE, STR_NULL), SetPadding(0, 0, 2, 0),
+ NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL), SetPadding(0, 0, 2, 0),
+ NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_VIDEO_ACCELERATION, STR_NULL),
+ EndContainer(),
+ NWidget(NWID_VERTICAL),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP), SetFill(1, 0), SetPadding(0, 0, 2, 0),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_REFRESH_RATE_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP), SetFill(1, 0), SetPadding(0, 0, 2, 0),
+ NWidget(NWID_HORIZONTAL), SetPadding(0, 0, 2, 0),
+ NWidget(NWID_SPACER), SetMinimalSize(1, 0), SetFill(1, 0),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(NWID_SPACER), SetMinimalSize(1, 0), SetFill(1, 0),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_ACCEL_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP),
+ EndContainer(),
+ EndContainer(),
+ EndContainer(),
+ EndContainer(),
+
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
diff --git a/src/video/allegro_v.cpp b/src/video/allegro_v.cpp
index 0c064873b..3d8ca65aa 100644
--- a/src/video/allegro_v.cpp
+++ b/src/video/allegro_v.cpp
@@ -236,6 +236,16 @@ bool VideoDriver_Allegro::ClaimMousePointer()
return true;
}
+std::vector<int> VideoDriver_Allegro::GetListOfMonitorRefreshRates()
+{
+ std::vector<int> rates = {};
+
+ int refresh_rate = get_refresh_rate();
+ if (refresh_rate != 0) rates.push_back(refresh_rate);
+
+ return rates;
+}
+
struct AllegroVkMapping {
uint16 vk_from;
byte vk_count;
diff --git a/src/video/allegro_v.h b/src/video/allegro_v.h
index d67778b7f..d1576fea9 100644
--- a/src/video/allegro_v.h
+++ b/src/video/allegro_v.h
@@ -31,6 +31,8 @@ public:
bool ClaimMousePointer() override;
+ std::vector<int> GetListOfMonitorRefreshRates() override;
+
const char *GetName() const override { return "allegro"; }
protected:
diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h
index 371e4b5bc..3d3db5454 100644
--- a/src/video/cocoa/cocoa_v.h
+++ b/src/video/cocoa/cocoa_v.h
@@ -47,6 +47,8 @@ public:
void EditBoxLostFocus() override;
+ std::vector<int> GetListOfMonitorRefreshRates() override;
+
/* --- The following methods should be private, but can't be due to Obj-C limitations. --- */
void MainLoopReal();
diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm
index 8d1fd4447..9fb74cd04 100644
--- a/src/video/cocoa/cocoa_v.mm
+++ b/src/video/cocoa/cocoa_v.mm
@@ -43,6 +43,7 @@
#import <sys/param.h> /* for MAXPATHLEN */
#import <sys/time.h> /* gettimeofday */
+#include <array>
/**
* Important notice regarding all modifications!!!!!!!
@@ -229,6 +230,30 @@ void VideoDriver_Cocoa::EditBoxLostFocus()
}
/**
+ * Get refresh rates of all connected monitors.
+ */
+std::vector<int> VideoDriver_Cocoa::GetListOfMonitorRefreshRates()
+{
+ std::vector<int> rates{};
+
+ if (MacOSVersionIsAtLeast(10, 6, 0)) {
+ std::array<CGDirectDisplayID, 16> displays;
+
+ uint32_t count = 0;
+ CGGetActiveDisplayList(displays.size(), displays.data(), &count);
+
+ for (uint32_t i = 0; i < count; i++) {
+ CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
+ int rate = (int)CGDisplayModeGetRefreshRate(mode);
+ if (rate > 0) rates.push_back(rate);
+ CGDisplayModeRelease(mode);
+ }
+ }
+
+ return rates;
+}
+
+/**
* Get the resolution of the main screen.
*/
Dimension VideoDriver_Cocoa::GetScreenSize() const
diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp
index 62675280c..2d8558534 100644
--- a/src/video/sdl2_v.cpp
+++ b/src/video/sdl2_v.cpp
@@ -237,6 +237,17 @@ void VideoDriver_SDL_Base::EditBoxLostFocus()
}
}
+std::vector<int> VideoDriver_SDL_Base::GetListOfMonitorRefreshRates()
+{
+ std::vector<int> rates = {};
+ for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
+ SDL_DisplayMode mode = {};
+ if (SDL_GetDisplayMode(i, 0, &mode) != 0) continue;
+ if (mode.refresh_rate != 0) rates.push_back(mode.refresh_rate);
+ }
+ return rates;
+}
+
struct SDLVkMapping {
SDL_Keycode vk_from;
diff --git a/src/video/sdl2_v.h b/src/video/sdl2_v.h
index b1a64dd9c..bd43f71f8 100644
--- a/src/video/sdl2_v.h
+++ b/src/video/sdl2_v.h
@@ -39,6 +39,8 @@ public:
void EditBoxLostFocus() override;
+ std::vector<int> GetListOfMonitorRefreshRates() override;
+
const char *GetName() const override { return "sdl"; }
protected:
diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp
index 4b2de253a..8c2b9d437 100644
--- a/src/video/video_driver.hpp
+++ b/src/video/video_driver.hpp
@@ -150,6 +150,15 @@ public:
virtual void EditBoxGainedFocus() {}
/**
+ * Get a list of refresh rates of each available monitor.
+ * @return A vector of the refresh rates of all available monitors.
+ */
+ virtual std::vector<int> GetListOfMonitorRefreshRates()
+ {
+ return {};
+ }
+
+ /**
* Get a suggested default GUI zoom taking screen DPI into account.
*/
virtual ZoomLevel GetSuggestedUIZoom()
diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp
index 8030380ce..a802cdafa 100644
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -916,6 +916,27 @@ void VideoDriver_Win32Base::EditBoxLostFocus()
SetCandidatePos(this->main_wnd);
}
+std::vector<int> VideoDriver_Win32Base::GetListOfMonitorRefreshRates()
+{
+ std::vector<int> rates = {};
+ EnumDisplayMonitors(nullptr, nullptr, [](HMONITOR hMonitor, HDC hDC, LPRECT rc, LPARAM data) -> BOOL {
+ auto &list = *reinterpret_cast<std::vector<int>*>(data);
+
+ MONITORINFOEX monitorInfo = {};
+ monitorInfo.cbSize = sizeof(MONITORINFOEX);
+ GetMonitorInfo(hMonitor, &monitorInfo);
+
+ DEVMODE devMode = {};
+ devMode.dmSize = sizeof(DEVMODE);
+ devMode.dmDriverExtra = 0;
+ EnumDisplaySettings(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &devMode);
+
+ if (devMode.dmDisplayFrequency != 0) list.push_back(devMode.dmDisplayFrequency);
+ return true;
+ }, reinterpret_cast<LPARAM>(&rates));
+ return rates;
+}
+
Dimension VideoDriver_Win32Base::GetScreenSize() const
{
return { static_cast<uint>(GetSystemMetrics(SM_CXSCREEN)), static_cast<uint>(GetSystemMetrics(SM_CYSCREEN)) };
diff --git a/src/video/win32_v.h b/src/video/win32_v.h
index 93ebdd83e..f6ca291f1 100644
--- a/src/video/win32_v.h
+++ b/src/video/win32_v.h
@@ -33,6 +33,8 @@ public:
void EditBoxLostFocus() override;
+ std::vector<int> GetListOfMonitorRefreshRates() override;
+
protected:
HWND main_wnd; ///< Handle to system window.
bool fullscreen; ///< Whether to use (true) fullscreen mode.
diff --git a/src/widgets/settings_widget.h b/src/widgets/settings_widget.h
index 0b816ee1f..7f8b0e111 100644
--- a/src/widgets/settings_widget.h
+++ b/src/widgets/settings_widget.h
@@ -33,6 +33,7 @@ enum GameOptionsWidgets {
WID_GO_BASE_MUSIC_DESCRIPTION = WID_GO_BASE_MUSIC_TEXTFILE + TFT_END, ///< Description of selected base music set.
WID_GO_FONT_ZOOM_DROPDOWN, ///< Dropdown for the font zoom level.
WID_GO_VIDEO_ACCEL_BUTTON, ///< Toggle for video acceleration.
+ WID_GO_REFRESH_RATE_DROPDOWN, ///< Dropdown for all available refresh rates.
};
/** Widgets of the #GameSettingsWindow class. */