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

HighDPI UI behavouir #467

Merged
merged 9 commits into from
Apr 21, 2024
45 changes: 45 additions & 0 deletions src/window/gui/Gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARA

#endif

#ifndef USER_DEFAULT_SCREEN_DPI
#define USER_DEFAULT_SCREEN_DPI 96
#endif

namespace LUS {
#define TOGGLE_BTN ImGuiKey_F1
#define TOGGLE_PAD_BTN ImGuiKey_GamepadBack
Expand Down Expand Up @@ -279,6 +283,8 @@ void Gui::Update(WindowEvent event) {
mNeedsConsoleVariableSave = false;
}

float dpi = 0;

switch (Context::GetInstance()->GetWindow()->GetWindowBackend()) {
#ifdef __WIIU__
case WindowBackend::GX2:
Expand All @@ -289,6 +295,17 @@ void Gui::Update(WindowEvent event) {
case WindowBackend::SDL_METAL:
ImGui_ImplSDL2_ProcessEvent(static_cast<const SDL_Event*>(event.Sdl.Event));

if (static_cast<const SDL_Event*>(event.Sdl.Event)->window.event == SDL_WINDOWEVENT_DISPLAY_CHANGED ||
mDpiInit) {
int display = 0;
if (Context::GetInstance()->GetWindow()->GetWindowBackend() == WindowBackend::SDL_OPENGL)
display = SDL_GetWindowDisplayIndex(static_cast<SDL_Window*>(mImpl.Opengl.Window));
else
display = SDL_GetWindowDisplayIndex(static_cast<SDL_Window*>(mImpl.Metal.Window));

SDL_GetDisplayDPI(display, &dpi, nullptr, nullptr);
}

#ifdef __SWITCH__
LUS::Switch::ImGuiProcessEvent(mImGuiIo->WantTextInput);
#endif
Expand All @@ -301,11 +318,29 @@ void Gui::Update(WindowEvent event) {
case WindowBackend::DX11:
ImGui_ImplWin32_WndProcHandler(static_cast<HWND>(event.Win32.Handle), event.Win32.Msg, event.Win32.Param1,
event.Win32.Param2);

if (event.Win32.Msg == WM_DPICHANGED || mDpiInit)
dpi = (float)GetDpiForWindow(static_cast<HWND>(event.Win32.Handle));
Copy link
Contributor

@Spodi Spodi Apr 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetDpiForWindow is Win 10 and up only. Definitely breaks compatibility with Win 8.1, wich the last release of SoH still worked with (another user on Discord confirmed it working).
You can probably use GetDpiScaleForMonitor instead like this:

if (event.Win32.Msg == WM_DPICHANGED || mDpiInit) {
    HMONITOR monitor = MonitorFromWindow(static_cast<HWND>(event.Win32.Handle), MONITOR_DEFAULTTONEAREST);
    dpi = (float)GetDpiScaleForMonito(monitor);
}

EDIT: Apparently you need to link more dependencies with the Windows default. Urg

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There also is ImGui's ImGui_ImplWin32_GetDpiScaleForMonitor for Windows. This is already a scale however.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you're right. I didn't see that.

What i could do is this:

if (event.Win32.Msg == WM_DPICHANGED || mDpiInit) {
    HMONITOR monitor = MonitorFromWindow(static_cast<HWND>(event.Win32.Handle), MONITOR_DEFAULTTONEAREST);
    dpi = (float)ImGui_ImplWin32_GetDpiScaleForMonitor(monitor) * USER_DEFAULT_SCREEN_DPI;
}

ImGui_ImplWin32_GetDpiScaleForMonitor gives me the dvided by 96 scale value.
Better would be to link aginst Shcore.lib and just use GetDpiForMonitor instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better idea is that we just get the scale in both windows events and save the extra step. I updated the code.

break;
#endif
default:
break;
}

if (dpi > 0) {
if (mDpiInit) {
mLastDpiScale = 1.f;
mDpiInit = false;
}

float scale = dpi / USER_DEFAULT_SCREEN_DPI;
float diff = scale / mLastDpiScale;
mLastDpiScale = scale;

ImGui::GetStyle().ScaleAllSizes(diff);
ImFont* font = ImGui::GetFont();
font->Scale *= diff;
}
}

bool Gui::ImGuiGamepadNavigationEnabled() {
Expand All @@ -322,12 +357,22 @@ void Gui::UnblockImGuiGamepadNavigation() {
}
}

float Gui::GetCurrentDpiScale() {
if (mLastDpiScale <= 0)
return 1.f;

return mLastDpiScale;
}

void Gui::DrawMenu() {
LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")->Update();
ImGuiBackendNewFrame();
ImGuiWMNewFrame();
ImGui::NewFrame();

if (mLastDpiScale == 0)
mDpiInit = true;

const std::shared_ptr<Window> wnd = Context::GetInstance()->GetWindow();
const std::shared_ptr<Config> conf = Context::GetInstance()->GetConfig();

Expand Down
4 changes: 4 additions & 0 deletions src/window/gui/Gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class Gui {
bool ImGuiGamepadNavigationEnabled();
void BlockImGuiGamepadNavigation();
void UnblockImGuiGamepadNavigation();
float GetCurrentDpiScale();

protected:
void ImGuiWMInit();
Expand All @@ -111,6 +112,9 @@ class Gui {
std::shared_ptr<GuiMenuBar> mMenuBar;
std::map<std::string, GuiTextureMetadata> mGuiTextures;
std::map<std::string, std::shared_ptr<GuiWindow>> mGuiWindows;

bool mDpiInit = false;
float mLastDpiScale = 0;
};
} // namespace LUS

Expand Down