UI: Very basic dynamic DPI support
This commit is contained in:
parent
d439704aa9
commit
aeb0e2557c
|
@ -145,6 +145,7 @@ filter("platforms:Windows")
|
||||||
"glu32",
|
"glu32",
|
||||||
"opengl32",
|
"opengl32",
|
||||||
"comctl32",
|
"comctl32",
|
||||||
|
"shcore",
|
||||||
"shlwapi",
|
"shlwapi",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,8 @@ void Window::Layout() {
|
||||||
|
|
||||||
void Window::Invalidate() {}
|
void Window::Invalidate() {}
|
||||||
|
|
||||||
|
void Window::OnDpiChanged(UIEvent* e) {}
|
||||||
|
|
||||||
void Window::OnResize(UIEvent* e) {
|
void Window::OnResize(UIEvent* e) {
|
||||||
ForEachListener([e](auto listener) { listener->OnResize(e); });
|
ForEachListener([e](auto listener) { listener->OnResize(e); });
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,9 @@ class Window {
|
||||||
virtual bool is_bordered() const { return false; }
|
virtual bool is_bordered() const { return false; }
|
||||||
virtual void set_bordered(bool enabled) {}
|
virtual void set_bordered(bool enabled) {}
|
||||||
|
|
||||||
|
virtual int get_dpi() const { return 96; }
|
||||||
|
virtual float get_dpi_scale() const { return get_dpi() / 96.f; }
|
||||||
|
|
||||||
bool has_focus() const { return has_focus_; }
|
bool has_focus() const { return has_focus_; }
|
||||||
virtual void set_focus(bool value) { has_focus_ = value; }
|
virtual void set_focus(bool value) { has_focus_ = value; }
|
||||||
|
|
||||||
|
@ -70,9 +73,15 @@ class Window {
|
||||||
|
|
||||||
int32_t width() const { return width_; }
|
int32_t width() const { return width_; }
|
||||||
int32_t height() const { return height_; }
|
int32_t height() const { return height_; }
|
||||||
virtual void Resize(int32_t width, int32_t height) = 0;
|
virtual void Resize(int32_t width, int32_t height) {
|
||||||
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
}
|
||||||
virtual void Resize(int32_t left, int32_t top, int32_t right,
|
virtual void Resize(int32_t left, int32_t top, int32_t right,
|
||||||
int32_t bottom) = 0;
|
int32_t bottom) {
|
||||||
|
width_ = right - left;
|
||||||
|
height_ = bottom - top;
|
||||||
|
}
|
||||||
|
|
||||||
GraphicsContext* context() const { return context_.get(); }
|
GraphicsContext* context() const { return context_.get(); }
|
||||||
ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); }
|
ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); }
|
||||||
|
@ -126,6 +135,7 @@ class Window {
|
||||||
virtual void OnClose();
|
virtual void OnClose();
|
||||||
virtual void OnDestroy();
|
virtual void OnDestroy();
|
||||||
|
|
||||||
|
virtual void OnDpiChanged(UIEvent* e);
|
||||||
virtual void OnResize(UIEvent* e);
|
virtual void OnResize(UIEvent* e);
|
||||||
virtual void OnLayout(UIEvent* e);
|
virtual void OnLayout(UIEvent* e);
|
||||||
virtual void OnPaint(UIEvent* e);
|
virtual void OnPaint(UIEvent* e);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ShellScalingApi.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "xenia/base/assert.h"
|
#include "xenia/base/assert.h"
|
||||||
|
@ -48,6 +49,16 @@ bool Win32Window::OnCreate() {
|
||||||
|
|
||||||
static bool has_registered_class = false;
|
static bool has_registered_class = false;
|
||||||
if (!has_registered_class) {
|
if (!has_registered_class) {
|
||||||
|
// Tell Windows that we're DPI aware.
|
||||||
|
auto spda = (HRESULT(*)(PROCESS_DPI_AWARENESS value))GetProcAddress(
|
||||||
|
GetModuleHandle(L"shcore.dll"), "SetProcessDpiAwareness");
|
||||||
|
if (spda) {
|
||||||
|
auto res = spda(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
|
if (res != S_OK) {
|
||||||
|
XELOGE("Failed to set process DPI awareness. (code = 0x%.8X)", res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WNDCLASSEX wcex;
|
WNDCLASSEX wcex;
|
||||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||||
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||||
|
@ -207,22 +218,22 @@ void Win32Window::ToggleFullscreen(bool fullscreen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullscreen_ = fullscreen;
|
|
||||||
|
|
||||||
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
|
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
// Kill our borders and resize to take up entire primary monitor.
|
|
||||||
// http://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx
|
// http://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx
|
||||||
MONITORINFO mi = {sizeof(mi)};
|
MONITORINFO mi = {sizeof(mi)};
|
||||||
if (GetWindowPlacement(hwnd_, &windowed_pos_) &&
|
if (GetWindowPlacement(hwnd_, &windowed_pos_) &&
|
||||||
GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY),
|
GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY),
|
||||||
&mi)) {
|
&mi)) {
|
||||||
|
// Remove the menubar and borders.
|
||||||
SetWindowLong(hwnd_, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);
|
SetWindowLong(hwnd_, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);
|
||||||
::SetMenu(hwnd_, NULL);
|
::SetMenu(hwnd_, NULL);
|
||||||
|
|
||||||
// Call into parent class to get around menu resizing code.
|
// Resize the window to fullscreen.
|
||||||
Resize(mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right,
|
auto& rc = mi.rcMonitor;
|
||||||
mi.rcMonitor.bottom);
|
AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), false);
|
||||||
|
MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
||||||
|
TRUE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Reinstate borders, resize to 1280x720
|
// Reinstate borders, resize to 1280x720
|
||||||
|
@ -234,6 +245,8 @@ void Win32Window::ToggleFullscreen(bool fullscreen) {
|
||||||
::SetMenu(hwnd_, main_menu->handle());
|
::SetMenu(hwnd_, main_menu->handle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fullscreen_ = fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32Window::is_bordered() const {
|
bool Win32Window::is_bordered() const {
|
||||||
|
@ -255,6 +268,15 @@ void Win32Window::set_bordered(bool enabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Win32Window::get_dpi() const {
|
||||||
|
HMONITOR monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY);
|
||||||
|
|
||||||
|
// According to msdn, x and y are identical...
|
||||||
|
UINT dpi_x, dpi_y;
|
||||||
|
GetDpiForMonitor(monitor, MDT_DEFAULT, &dpi_x, &dpi_y);
|
||||||
|
return dpi_x;
|
||||||
|
}
|
||||||
|
|
||||||
void Win32Window::set_cursor_visible(bool value) {
|
void Win32Window::set_cursor_visible(bool value) {
|
||||||
if (is_cursor_visible_ == value) {
|
if (is_cursor_visible_ == value) {
|
||||||
return;
|
return;
|
||||||
|
@ -284,6 +306,11 @@ void Win32Window::set_focus(bool value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::Resize(int32_t width, int32_t height) {
|
void Win32Window::Resize(int32_t width, int32_t height) {
|
||||||
|
if (is_fullscreen()) {
|
||||||
|
// Cannot resize while in fullscreen.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RECT rc = {0, 0, width, height};
|
RECT rc = {0, 0, width, height};
|
||||||
bool has_menu = !is_fullscreen() && (main_menu_ ? true : false);
|
bool has_menu = !is_fullscreen() && (main_menu_ ? true : false);
|
||||||
AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu);
|
AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu);
|
||||||
|
@ -295,15 +322,24 @@ void Win32Window::Resize(int32_t width, int32_t height) {
|
||||||
}
|
}
|
||||||
MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
|
super::Resize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::Resize(int32_t left, int32_t top, int32_t right,
|
void Win32Window::Resize(int32_t left, int32_t top, int32_t right,
|
||||||
int32_t bottom) {
|
int32_t bottom) {
|
||||||
|
if (is_fullscreen()) {
|
||||||
|
// Cannot resize while in fullscreen.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RECT rc = {left, top, right, bottom};
|
RECT rc = {left, top, right, bottom};
|
||||||
bool has_menu = !is_fullscreen() && (main_menu_ ? true : false);
|
bool has_menu = !is_fullscreen() && (main_menu_ ? true : false);
|
||||||
AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu);
|
AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu);
|
||||||
MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
|
super::Resize(left, top, right, bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::OnResize(UIEvent* e) {
|
void Win32Window::OnResize(UIEvent* e) {
|
||||||
|
@ -362,7 +398,7 @@ LRESULT CALLBACK Win32Window::WndProcThunk(HWND hWnd, UINT message,
|
||||||
|
|
||||||
LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||||
LPARAM lParam) {
|
LPARAM lParam) {
|
||||||
if (hWnd != hwnd_) {
|
if (hwnd_ != nullptr && hWnd != hwnd_) {
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,8 +432,14 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||||
|
|
||||||
DragFinish(hDrop);
|
DragFinish(hDrop);
|
||||||
} break;
|
} break;
|
||||||
case WM_NCCREATE:
|
case WM_NCCREATE: {
|
||||||
break;
|
// Tell Windows to automatically scale non-client areas on different DPIs.
|
||||||
|
auto en = (BOOL(*)(HWND hwnd))GetProcAddress(
|
||||||
|
GetModuleHandle(L"user32.dll"), "EnableNonClientDpiScaling");
|
||||||
|
if (en) {
|
||||||
|
en(hWnd);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
break;
|
break;
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
|
@ -418,8 +460,7 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||||
case WM_SIZE: {
|
case WM_SIZE: {
|
||||||
auto e = UIEvent(this);
|
auto e = UIEvent(this);
|
||||||
OnResize(&e);
|
OnResize(&e);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
|
|
||||||
case WM_PAINT: {
|
case WM_PAINT: {
|
||||||
ValidateRect(hwnd_, nullptr);
|
ValidateRect(hwnd_, nullptr);
|
||||||
|
@ -436,6 +477,10 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||||
return 0; // Ignored because of custom paint.
|
return 0; // Ignored because of custom paint.
|
||||||
case WM_DISPLAYCHANGE:
|
case WM_DISPLAYCHANGE:
|
||||||
break;
|
break;
|
||||||
|
case WM_DPICHANGED: {
|
||||||
|
auto e = UIEvent(this);
|
||||||
|
OnDpiChanged(&e);
|
||||||
|
} break;
|
||||||
|
|
||||||
case WM_ACTIVATEAPP:
|
case WM_ACTIVATEAPP:
|
||||||
case WM_SHOWWINDOW: {
|
case WM_SHOWWINDOW: {
|
||||||
|
|
|
@ -40,6 +40,8 @@ class Win32Window : public Window {
|
||||||
bool is_bordered() const override;
|
bool is_bordered() const override;
|
||||||
void set_bordered(bool enabled) override;
|
void set_bordered(bool enabled) override;
|
||||||
|
|
||||||
|
int get_dpi() const override;
|
||||||
|
|
||||||
void set_cursor_visible(bool value) override;
|
void set_cursor_visible(bool value) override;
|
||||||
void set_focus(bool value) override;
|
void set_focus(bool value) override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue