summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrChat <arkolbed@gmail.com>2017-08-03 19:03:26 -0500
committerDrChat <arkolbed@gmail.com>2017-08-03 19:13:51 -0500
commitaeb0e2557cdf6173d1b4aab583f37480f98ea220 (patch)
treef6ac2fc5e3925ea9101aef0c30c0013c12fb9472
parentd439704aa9e9b138c13130841d7d6388793335f0 (diff)
UI: Very basic dynamic DPI support
-rw-r--r--premake5.lua1
-rw-r--r--src/xenia/ui/window.cc2
-rw-r--r--src/xenia/ui/window.h14
-rw-r--r--src/xenia/ui/window_win.cc67
-rw-r--r--src/xenia/ui/window_win.h2
5 files changed, 73 insertions, 13 deletions
diff --git a/premake5.lua b/premake5.lua
index 8626ec7fb..593f0503d 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -145,6 +145,7 @@ filter("platforms:Windows")
"glu32",
"opengl32",
"comctl32",
+ "shcore",
"shlwapi",
})
diff --git a/src/xenia/ui/window.cc b/src/xenia/ui/window.cc
index 91f4a8f67..cf300a4b5 100644
--- a/src/xenia/ui/window.cc
+++ b/src/xenia/ui/window.cc
@@ -154,6 +154,8 @@ void Window::Layout() {
void Window::Invalidate() {}
+void Window::OnDpiChanged(UIEvent* e) {}
+
void Window::OnResize(UIEvent* e) {
ForEachListener([e](auto listener) { listener->OnResize(e); });
}
diff --git a/src/xenia/ui/window.h b/src/xenia/ui/window.h
index 107078be1..1fd53fe10 100644
--- a/src/xenia/ui/window.h
+++ b/src/xenia/ui/window.h
@@ -62,6 +62,9 @@ class Window {
virtual bool is_bordered() const { return false; }
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_; }
virtual void set_focus(bool value) { has_focus_ = value; }
@@ -70,9 +73,15 @@ class Window {
int32_t width() const { return width_; }
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,
- int32_t bottom) = 0;
+ int32_t bottom) {
+ width_ = right - left;
+ height_ = bottom - top;
+ }
GraphicsContext* context() const { return context_.get(); }
ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); }
@@ -126,6 +135,7 @@ class Window {
virtual void OnClose();
virtual void OnDestroy();
+ virtual void OnDpiChanged(UIEvent* e);
virtual void OnResize(UIEvent* e);
virtual void OnLayout(UIEvent* e);
virtual void OnPaint(UIEvent* e);
diff --git a/src/xenia/ui/window_win.cc b/src/xenia/ui/window_win.cc
index ba1ff0556..97cf76e5c 100644
--- a/src/xenia/ui/window_win.cc
+++ b/src/xenia/ui/window_win.cc
@@ -7,6 +7,7 @@
******************************************************************************
*/
+#include <ShellScalingApi.h>
#include <string>
#include "xenia/base/assert.h"
@@ -48,6 +49,16 @@ bool Win32Window::OnCreate() {
static bool has_registered_class = false;
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;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
@@ -207,22 +218,22 @@ void Win32Window::ToggleFullscreen(bool fullscreen) {
return;
}
- fullscreen_ = fullscreen;
-
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
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
MONITORINFO mi = {sizeof(mi)};
if (GetWindowPlacement(hwnd_, &windowed_pos_) &&
GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY),
&mi)) {
+ // Remove the menubar and borders.
SetWindowLong(hwnd_, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);
::SetMenu(hwnd_, NULL);
- // Call into parent class to get around menu resizing code.
- Resize(mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right,
- mi.rcMonitor.bottom);
+ // Resize the window to fullscreen.
+ auto& rc = mi.rcMonitor;
+ AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), false);
+ MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
+ TRUE);
}
} else {
// Reinstate borders, resize to 1280x720
@@ -234,6 +245,8 @@ void Win32Window::ToggleFullscreen(bool fullscreen) {
::SetMenu(hwnd_, main_menu->handle());
}
}
+
+ fullscreen_ = fullscreen;
}
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) {
if (is_cursor_visible_ == value) {
return;
@@ -284,6 +306,11 @@ void Win32Window::set_focus(bool value) {
}
void Win32Window::Resize(int32_t width, int32_t height) {
+ if (is_fullscreen()) {
+ // Cannot resize while in fullscreen.
+ return;
+ }
+
RECT rc = {0, 0, width, height};
bool has_menu = !is_fullscreen() && (main_menu_ ? true : false);
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,
TRUE);
+
+ super::Resize(width, height);
}
void Win32Window::Resize(int32_t left, int32_t top, int32_t right,
int32_t bottom) {
+ if (is_fullscreen()) {
+ // Cannot resize while in fullscreen.
+ return;
+ }
+
RECT rc = {left, top, right, bottom};
bool has_menu = !is_fullscreen() && (main_menu_ ? true : false);
AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu);
MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
TRUE);
+
+ super::Resize(left, top, right, bottom);
}
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,
LPARAM lParam) {
- if (hWnd != hwnd_) {
+ if (hwnd_ != nullptr && hWnd != hwnd_) {
return DefWindowProc(hWnd, message, wParam, lParam);
}
@@ -396,8 +432,14 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
DragFinish(hDrop);
} break;
- case WM_NCCREATE:
- break;
+ case WM_NCCREATE: {
+ // 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:
break;
case WM_DESTROY:
@@ -418,8 +460,7 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
case WM_SIZE: {
auto e = UIEvent(this);
OnResize(&e);
- break;
- }
+ } break;
case WM_PAINT: {
ValidateRect(hwnd_, nullptr);
@@ -436,6 +477,10 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
return 0; // Ignored because of custom paint.
case WM_DISPLAYCHANGE:
break;
+ case WM_DPICHANGED: {
+ auto e = UIEvent(this);
+ OnDpiChanged(&e);
+ } break;
case WM_ACTIVATEAPP:
case WM_SHOWWINDOW: {
diff --git a/src/xenia/ui/window_win.h b/src/xenia/ui/window_win.h
index eae68b2ce..530aa3e7e 100644
--- a/src/xenia/ui/window_win.h
+++ b/src/xenia/ui/window_win.h
@@ -40,6 +40,8 @@ class Win32Window : public Window {
bool is_bordered() const override;
void set_bordered(bool enabled) override;
+ int get_dpi() const override;
+
void set_cursor_visible(bool value) override;
void set_focus(bool value) override;