diff --git a/xbmc/platform/win32/app.manifest b/xbmc/platform/win32/app.manifest
index b11f40223f2e6..13e10b4faf693 100644
--- a/xbmc/platform/win32/app.manifest
+++ b/xbmc/platform/win32/app.manifest
@@ -1,22 +1,24 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
-
-
+
+
+
+
+
+
+
+
+
+ True/PM
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xbmc/windowing/windows/WinEventsWin32.cpp b/xbmc/windowing/windows/WinEventsWin32.cpp
index d5199f40ceb6a..f005ef0c0cc4c 100644
--- a/xbmc/windowing/windows/WinEventsWin32.cpp
+++ b/xbmc/windowing/windows/WinEventsWin32.cpp
@@ -402,6 +402,16 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L
ZeroMemory(&newEvent, sizeof(newEvent));
static HDEVNOTIFY hDeviceNotify;
+ if (uMsg == WM_NCCREATE)
+ {
+ // if available, enable DPI scaling of non-client portion of window (title bar, etc.)
+ if (g_Windowing.PtrEnableNonClientDpiScaling != NULL)
+ {
+ g_Windowing.PtrEnableNonClientDpiScaling(hWnd);
+ }
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+ }
+
if (uMsg == WM_CREATE)
{
g_hWnd = hWnd;
@@ -668,6 +678,19 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L
m_pEventFunc(newEvent);
}
return(0);
+ case WM_DPICHANGED:
+ // This message tells the program that most of its window is on a
+ // monitor with a new DPI. The wParam contains the new DPI, and the
+ // lParam contains a rect which defines the window rectangle scaled
+ // the new DPI.
+ if (g_application.GetRenderGUI() && !g_Windowing.IsAlteringWindow())
+ {
+ // get the suggested size of the window on the new display with a different DPI
+ unsigned short dpi = LOWORD(wParam);
+ RECT resizeRect = *((RECT*)lParam);
+ g_Windowing.DPIChanged(dpi, resizeRect);
+ }
+ return(0);
case WM_DISPLAYCHANGE:
CLog::Log(LOGDEBUG, __FUNCTION__": display change event");
if (g_application.GetRenderGUI() && !g_Windowing.IsAlteringWindow() && GET_X_LPARAM(lParam) > 0 && GET_Y_LPARAM(lParam) > 0)
@@ -684,9 +707,9 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L
newEvent.type = XBMC_VIDEORESIZE;
newEvent.resize.w = GET_X_LPARAM(lParam);
newEvent.resize.h = GET_Y_LPARAM(lParam);
- }
- m_pEventFunc(newEvent);
- }
+ }
+ m_pEventFunc(newEvent);
+ }
return(0);
case WM_SIZE:
newEvent.type = XBMC_VIDEORESIZE;
diff --git a/xbmc/windowing/windows/WinSystemWin32.cpp b/xbmc/windowing/windows/WinSystemWin32.cpp
index 58431efc5786f..7bfa54c4247b0 100644
--- a/xbmc/windowing/windows/WinSystemWin32.cpp
+++ b/xbmc/windowing/windows/WinSystemWin32.cpp
@@ -47,6 +47,7 @@ CWinSystemWin32::CWinSystemWin32()
PtrCloseGestureInfoHandle = NULL;
PtrSetGestureConfig = NULL;
PtrGetGestureInfo = NULL;
+ PtrEnableNonClientDpiScaling = NULL;
m_ValidWindowedPosition = false;
m_IsAlteringWindow = false;
}
@@ -87,6 +88,18 @@ bool CWinSystemWin32::CreateNewWindow(const std::string& name, bool fullScreen,
if(m_hInstance == NULL)
CLog::Log(LOGDEBUG, "%s : GetModuleHandle failed with %d", __FUNCTION__, GetLastError());
+ // Load Win32 procs if available
+ HMODULE hUser32 = GetModuleHandleA("user32");
+ if (hUser32)
+ {
+ PtrGetGestureInfo = (pGetGestureInfo)GetProcAddress(hUser32, "GetGestureInfo");
+ PtrSetGestureConfig = (pSetGestureConfig)GetProcAddress(hUser32, "SetGestureConfig");
+ PtrCloseGestureInfoHandle = (pCloseGestureInfoHandle)GetProcAddress(hUser32, "CloseGestureInfoHandle");
+
+ // if available, enable automatic DPI scaling of the non-client area portions of the window.
+ PtrEnableNonClientDpiScaling = (pEnableNonClientDpiScaling)GetProcAddress(hUser32, "EnableNonClientDpiScaling");
+ }
+
m_nWidth = res.iWidth;
m_nHeight = res.iHeight;
m_bFullScreen = fullScreen;
@@ -128,14 +141,7 @@ bool CWinSystemWin32::CreateNewWindow(const std::string& name, bool fullScreen,
SetProp(hWnd, MICROSOFT_TABLETPENSERVICE_PROPERTY, reinterpret_cast(dwHwndTabletProperty));
- // setup our touch pointers
- HMODULE hUser32 = GetModuleHandleA( "user32" );
- if (hUser32)
- {
- PtrGetGestureInfo = (pGetGestureInfo) GetProcAddress( hUser32, "GetGestureInfo" );
- PtrSetGestureConfig = (pSetGestureConfig) GetProcAddress( hUser32, "SetGestureConfig" );
- PtrCloseGestureInfoHandle = (pCloseGestureInfoHandle) GetProcAddress( hUser32, "CloseGestureInfoHandle" );
- }
+
m_hWnd = hWnd;
m_hDC = GetDC(m_hWnd);
@@ -330,6 +336,52 @@ bool CWinSystemWin32::SetFullScreenEx(bool fullScreen, RESOLUTION_INFO& res, boo
return true;
}
+bool CWinSystemWin32::DPIChanged(WORD dpi, RECT windowRect)
+{
+ (void)dpi;
+ RECT resizeRect = windowRect;
+ HMONITOR hMon = MonitorFromRect(&resizeRect, MONITOR_DEFAULTTONULL);
+ if (hMon == NULL)
+ {
+ hMon = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTOPRIMARY);
+ }
+
+ if (hMon)
+ {
+ MONITORINFOEX monitorInfo;
+ monitorInfo.cbSize = sizeof(MONITORINFOEX);
+ GetMonitorInfo(hMon, &monitorInfo);
+ RECT wr = monitorInfo.rcWork;
+ long wrWidth = wr.right - wr.left;
+ long wrHeight = wr.bottom - wr.top;
+ long resizeWidth = resizeRect.right - resizeRect.left;
+ long resizeHeight = resizeRect.bottom - resizeRect.top;
+
+ if (resizeWidth > wrWidth)
+ {
+ resizeRect.right = resizeRect.left + wrWidth;
+ }
+
+ // make sure suggested windows size is not taller or wider than working area of new monitor (considers the toolbar)
+ if (resizeHeight > wrHeight)
+ {
+ resizeRect.bottom = resizeRect.top + wrHeight;
+ }
+ }
+
+ // resize the window to the suggested size. Will generate a WM_SIZE event
+ SetWindowPos(m_hWnd,
+ NULL,
+ resizeRect.left,
+ resizeRect.top,
+ resizeRect.right - resizeRect.left,
+ resizeRect.bottom - resizeRect.top,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+
+ return true;
+}
+
+
void CWinSystemWin32::RestoreDesktopResolution(int screen)
{
int resIdx = RES_DESKTOP;
@@ -434,6 +486,7 @@ bool CWinSystemWin32::ResizeInternal(bool forceRefresh)
rc.top = m_nTop = newScreenRect.top + ((newScreenRect.bottom - newScreenRect.top) / 2) - (m_nHeight / 2);
rc.right = m_nLeft + m_nWidth;
rc.bottom = m_nTop + m_nHeight;
+ m_ValidWindowedPosition = true;
}
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, false );
@@ -458,7 +511,7 @@ bool CWinSystemWin32::ResizeInternal(bool forceRefresh)
// The SWP_DRAWFRAME is here because, perversely, without it win7 draws a
// white frame plus titlebar around the xbmc splash
- SetWindowPos(m_hWnd, windowAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_SHOWWINDOW|SWP_DRAWFRAME);
+ SetWindowPos(m_hWnd, windowAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_DRAWFRAME);
//! @todo Probably only need this if switching screens
ValidateRect(NULL, NULL);
diff --git a/xbmc/windowing/windows/WinSystemWin32.h b/xbmc/windowing/windows/WinSystemWin32.h
index 4de378cb4bd00..f220cefcd0d9e 100644
--- a/xbmc/windowing/windows/WinSystemWin32.h
+++ b/xbmc/windowing/windows/WinSystemWin32.h
@@ -157,14 +157,17 @@ class CWinSystemWin32 : public CWinSystemBase
// CWinSystemWin32
HWND GetHwnd() { return m_hWnd; }
bool IsAlteringWindow() { return m_IsAlteringWindow; }
+ bool DPIChanged(WORD dpi, RECT windowRect);
// touchscreen support
typedef BOOL (WINAPI *pGetGestureInfo)(HGESTUREINFO, PGESTUREINFO);
typedef BOOL (WINAPI *pSetGestureConfig)(HWND, DWORD, UINT, PGESTURECONFIG, UINT);
typedef BOOL (WINAPI *pCloseGestureInfoHandle)(HGESTUREINFO);
+ typedef BOOL(WINAPI *pEnableNonClientDpiScaling)(HWND);
pGetGestureInfo PtrGetGestureInfo;
pSetGestureConfig PtrSetGestureConfig;
pCloseGestureInfoHandle PtrCloseGestureInfoHandle;
+ pEnableNonClientDpiScaling PtrEnableNonClientDpiScaling;
protected:
bool ChangeResolution(const RESOLUTION_INFO& res, bool forceChange = false);