MAINT-5992 Second Life unusable on Windows 10 with 4k monitor SL forcibly overrides DPI compatibility option

master
pavelkproductengine 2016-08-18 19:43:48 +03:00
parent 8db7540908
commit cf93c1c81d
7 changed files with 105 additions and 16 deletions

View File

@ -175,6 +175,11 @@ BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window)
return FALSE;
}
void LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
{
}
void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg)
{

View File

@ -65,6 +65,7 @@ public:
virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data);
virtual BOOL handleTimerEvent(LLWindow *window);
virtual BOOL handleDeviceChange(LLWindow *window);
virtual void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
enum DragNDropAction {
DNDA_START_TRACKING = 0,// Start tracking an incoming drag

View File

@ -71,6 +71,11 @@ const S32 MAX_MESSAGE_PER_UPDATE = 20;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
const F32 ICON_FLASH_TIME = 0.5f;
const F32 DEFAULT_DPI = 96.0f;
#ifndef WM_DPICHANGED
const S32 WM_DPICHANGED = 0x02E0;
#endif
extern BOOL gDebugWindowProc;
@ -97,6 +102,10 @@ typedef enum MONITOR_DPI_TYPE {
typedef HRESULT(STDAPICALLTYPE *SetProcessDpiAwarenessType)(_In_ PROCESS_DPI_AWARENESS value);
typedef HRESULT(STDAPICALLTYPE *GetProcessDpiAwarenessType)(
_In_ HANDLE hprocess,
_Out_ PROCESS_DPI_AWARENESS *value);
typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)(
_In_ HMONITOR hmonitor,
_In_ MONITOR_DPI_TYPE dpiType,
@ -2618,6 +2627,24 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
return 0;
}
case WM_DPICHANGED:
{
LPRECT lprc_new_scale;
F32 new_scale = LOWORD(w_param) / 96.0f;
lprc_new_scale = (LPRECT)l_param;
S32 new_width = lprc_new_scale->right - lprc_new_scale->left;
S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top;
window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height);
SetWindowPos(h_wnd,
HWND_TOP,
lprc_new_scale->left,
lprc_new_scale->top,
new_width,
new_height,
SWP_NOZORDER | SWP_NOACTIVATE);
return 0;
}
case WM_SETFOCUS:
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS");
@ -3903,40 +3930,86 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
return FALSE;
}
//static
void LLWindowWin32::setDPIAwareness()
{
HMODULE hShcore = LoadLibrary(L"shcore.dll");
if (hShcore != NULL)
{
SetProcessDpiAwarenessType pSPDA;
pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness");
if (pSPDA)
{
HRESULT hr = pSPDA(PROCESS_PER_MONITOR_DPI_AWARE);
if (hr != S_OK)
{
LL_WARNS() << "SetProcessDpiAwareness() function returned an error. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
}
}
FreeLibrary(hShcore);
}
else
{
LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
}
}
F32 LLWindowWin32::getSystemUISize()
{
float scale_value = 0;
HWND hWnd = (HWND)getPlatformWindow();
HDC hdc = GetDC(hWnd);
HMONITOR hMonitor;
HANDLE hProcess = GetCurrentProcess();
PROCESS_DPI_AWARENESS dpi_awareness;
HMODULE hShcore = LoadLibrary(L"shcore.dll");
if (hShcore != NULL)
{
SetProcessDpiAwarenessType pSPDA;
pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness");
GetProcessDpiAwarenessType pGPDA;
pGPDA = (GetProcessDpiAwarenessType)GetProcAddress(hShcore, "GetProcessDpiAwareness");
GetDpiForMonitorType pGDFM;
pGDFM = (GetDpiForMonitorType)GetProcAddress(hShcore, "GetDpiForMonitor");
if (pSPDA != NULL && pGDFM != NULL)
if (pGPDA != NULL && pGDFM != NULL)
{
pSPDA(PROCESS_PER_MONITOR_DPI_AWARE);
POINT pt;
UINT dpix = 0, dpiy = 0;
HRESULT hr = E_FAIL;
pGPDA(hProcess, &dpi_awareness);
if (dpi_awareness == PROCESS_PER_MONITOR_DPI_AWARE)
{
POINT pt;
UINT dpix = 0, dpiy = 0;
HRESULT hr = E_FAIL;
RECT rect;
// Get the DPI for the main monitor, and set the scaling factor
pt.x = 1;
pt.y = 1;
hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
scale_value = dpix / 96.0f;
GetWindowRect(hWnd, &rect);
// Get the DPI for the monitor, on which the center of window is displayed and set the scaling factor
pt.x = (rect.left + rect.right) / 2;
pt.y = (rect.top + rect.bottom) / 2;
hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
if (hr == S_OK)
{
scale_value = dpix / DEFAULT_DPI;
}
else
{
LL_WARNS() << "Could not determine DPI for monitor. Setting scale to default 100 %" << LL_ENDL;
scale_value = 1.0f;
}
}
else
{
LL_WARNS() << "Process is not per-monitor DPI-aware. Setting scale to default 100 %" << LL_ENDL;
scale_value = 1.0f;
}
}
FreeLibrary(hShcore);
}
else
{
LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK). Using legacy DPI awareness API of Win XP/7" << LL_ENDL;
scale_value = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f;
scale_value = GetDeviceCaps(hdc, LOGPIXELSX) / DEFAULT_DPI;
}
ReleaseDC(hWnd, hdc);

View File

@ -115,7 +115,7 @@ public:
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
static std::vector<std::string> getDynamicFallbackFontList();
static void setDPIAwareness();
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,

View File

@ -231,6 +231,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
DWORD heap_enable_lfh_error[MAX_HEAPS];
S32 num_heaps = 0;
LLWindowWin32::setDPIAwareness();
#if WINDOWS_CRT_MEM_CHECKS && !INCLUDE_VLD
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // dump memory leaks on exit
#elif 0
@ -569,7 +571,7 @@ bool LLAppViewerWin32::initHardwareTest()
// Do driver verification and initialization based on DirectX
// hardware polling and driver versions
//
if (FALSE == gSavedSettings.getBOOL("NoHardwareProbe"))
if (TRUE == gSavedSettings.getBOOL("ProbeHardwareOnStartup") && FALSE == gSavedSettings.getBOOL("NoHardwareProbe"))
{
// per DEV-11631 - disable hardware probing for everything
// but vram.

View File

@ -1593,6 +1593,13 @@ BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
return FALSE;
}
void LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
{
gSavedSettings.setF32("UIScaleFactor", ui_scale_factor);
LLViewerWindow::reshape(window_width, window_height);
mResDirty = true;
}
void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg)
{
LLAppViewer::instance()->pingMainloopTimeout(msg);

View File

@ -210,6 +210,7 @@ public:
/*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data);
/*virtual*/ BOOL handleTimerEvent(LLWindow *window);
/*virtual*/ BOOL handleDeviceChange(LLWindow *window);
/*virtual*/ void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
/*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg);
/*virtual*/ void handlePauseWatchdog(LLWindow *window);