diff options
Diffstat (limited to 'intern/ghost/intern')
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 6 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.cpp | 78 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_Window.h | 9 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowSDL.cpp | 16 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowSDL.h | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.cpp | 18 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.h | 11 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.cpp | 45 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.h | 2 |
9 files changed, 187 insertions, 0 deletions
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 41bc735e1e2..ce653188760 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -914,6 +914,12 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle) return 1.0f; } +GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + return window->getDPIHint(); +} + #ifdef WITH_INPUT_IME void GHOST_BeginIME(GHOST_WindowHandle windowhandle, diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 7d55a973f91..240d7ccd2fe 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -111,6 +111,11 @@ #define VK_MEDIA_PLAY_PAUSE 0xB3 #endif // VK_MEDIA_PLAY_PAUSE +// Window message newer than Windows 7 +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif // WM_DPICHANGED + /* Workaround for some laptop touchpads, some of which seems to * have driver issues which makes it so window function receives * the message, but PeekMessage doesn't pick those messages for @@ -152,6 +157,27 @@ static void initRawInput() #undef DEVICE_COUNT } +#ifndef DPI_ENUMS_DECLARED +typedef enum PROCESS_DPI_AWARENESS { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 +} PROCESS_DPI_AWARENESS; + +typedef enum MONITOR_DPI_TYPE { + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI +} MONITOR_DPI_TYPE; + +#define USER_DEFAULT_SCREEN_DPI 96 + +#define DPI_ENUMS_DECLARED +#endif +typedef HRESULT(API * GHOST_WIN32_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); +typedef BOOL(API * GHOST_WIN32_EnableNonClientDpiScaling)(HWND); + GHOST_SystemWin32::GHOST_SystemWin32() : m_hasPerformanceCounter(false), m_freq(0), m_start(0) { @@ -161,6 +187,18 @@ GHOST_SystemWin32::GHOST_SystemWin32() m_consoleStatus = 1; + // Tell Windows we are per monitor DPI aware. This disables the default + // blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI. + HMODULE m_shcore = ::LoadLibrary("Shcore.dll"); + if (m_shcore) { + GHOST_WIN32_SetProcessDpiAwareness fpSetProcessDpiAwareness = + (GHOST_WIN32_SetProcessDpiAwareness) ::GetProcAddress(m_shcore, "SetProcessDpiAwareness"); + + if (fpSetProcessDpiAwareness) { + fpSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); + } + } + // Check if current keyboard layout uses AltGr and save keylayout ID for // specialized handling if keys like VK_OEM_*. I.e. french keylayout // generates VK_OEM_8 for their exclamation key (key left of right shift) @@ -922,6 +960,20 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized"); if (hwnd) { + if(msg == WM_NCCREATE) { + // Tell Windows to automatically handle scaling of non-client areas + // such as the caption bar. EnableNonClientDpiScaling was introduced in Windows 10 + HMODULE m_user32 = ::LoadLibrary("User32.dll"); + if (m_user32) { + GHOST_WIN32_EnableNonClientDpiScaling fpEnableNonClientDpiScaling = + (GHOST_WIN32_EnableNonClientDpiScaling) ::GetProcAddress(m_user32, "EnableNonClientDpiScaling"); + + if (fpEnableNonClientDpiScaling) { + fpEnableNonClientDpiScaling(hwnd); + } + } + } + GHOST_WindowWin32 *window = (GHOST_WindowWin32 *)::GetWindowLongPtr(hwnd, GWLP_USERDATA); if (window) { switch (msg) { @@ -1294,6 +1346,32 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; + case WM_DPICHANGED: + /* The WM_DPICHANGED message is sent when the effective dots per inch (dpi) for a window has changed. + * The DPI is the scale factor for a window. There are multiple events that can cause the DPI to + * change such as when the window is moved to a monitor with a different DPI. + */ + { + WORD newYAxisDPI = HIWORD(wParam); + WORD newXAxisDPI = LOWORD(wParam); + // The suggested new size and position of the window. + RECT* const suggestedWindowRect = (RECT*)lParam; + + // Push DPI change event first + system->pushEvent(processWindowEvent(GHOST_kEventWindowDPIHintChanged, window)); + system->dispatchEvents(); + eventHandled = true; + + // Then move and resize window + SetWindowPos(hwnd, + NULL, + suggestedWindowRect->left, + suggestedWindowRect->top, + suggestedWindowRect->right - suggestedWindowRect->left, + suggestedWindowRect->bottom - suggestedWindowRect->top, + SWP_NOZORDER | SWP_NOACTIVATE); + } + break; //////////////////////////////////////////////////////////////////////// // Window events, ignored //////////////////////////////////////////////////////////////////////// diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index d778628ea37..2798bdf72f3 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -295,6 +295,15 @@ public: return 1.0f; } + /** + * Returns the recommended DPI for this window. + * \return The recommended DPI for this window. + */ + virtual inline GHOST_TUns16 getDPIHint() + { + return 96; + } + #ifdef WITH_INPUT_IME virtual void beginIME(GHOST_TInt32 x, GHOST_TInt32 y, diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp index 1335c38d977..aeb6188daef 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cpp +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -563,3 +563,19 @@ GHOST_WindowSDL::setWindowCursorVisibility(bool visible) SDL_ShowCursor(visible); return GHOST_kSuccess; } + +GHOST_TUns16 +GHOST_WindowSDL::getDPIHint() +{ + int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win); + if (displayIndex < 0) { + return 96; + } + + float ddpi; + if (SDL_GetDisplayDPI(displayIndex, &ddpi, NULL, NULL) != 0) { + return 96; + } + + return (int)ddpi; +} diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h index 5f658e8ad01..96104ec28b4 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.h +++ b/intern/ghost/intern/GHOST_WindowSDL.h @@ -168,6 +168,8 @@ protected: GHOST_TSuccess beginFullScreen() const { return GHOST_kFailure; } GHOST_TSuccess endFullScreen() const { return GHOST_kFailure; } + + GHOST_TUns16 getDPIHint(); }; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 7d80aa43a40..fc46164c135 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -92,6 +92,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_tablet(0), m_maxPressure(0), m_normal_state(GHOST_kWindowStateNormal), + m_user32(NULL), m_parentWindowHwnd(parentwindowhwnd), m_debug_context(is_debug) { @@ -965,6 +966,23 @@ void GHOST_WindowWin32::bringTabletContextToFront() } } +GHOST_TUns16 GHOST_WindowWin32::getDPIHint() +{ + if (!m_user32) { + m_user32 = ::LoadLibrary("user32.dll"); + } + + if (m_user32) { + GHOST_WIN32_GetDpiForWindow fpGetDpiForWindow = (GHOST_WIN32_GetDpiForWindow) ::GetProcAddress(m_user32, "GetDpiForWindow"); + + if (fpGetDpiForWindow) { + return fpGetDpiForWindow(this->m_hWnd); + } + } + + return USER_DEFAULT_SCREEN_DPI; +} + /** Reverse the bits in a GHOST_TUns8 */ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) { diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index a1cf58c9ceb..75a33951ff4 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -58,6 +58,12 @@ typedef BOOL (API * GHOST_WIN32_WTClose)(HCTX); typedef BOOL (API * GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID); typedef BOOL (API * GHOST_WIN32_WTOverlap)(HCTX, BOOL); +// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions +typedef UINT(API * GHOST_WIN32_GetDpiForWindow)(HWND); +#ifndef USER_DEFAULT_SCREEN_DPI +#define USER_DEFAULT_SCREEN_DPI 96 +#endif // USER_DEFAULT_SCREEN_DPI + /** * GHOST window on M$ Windows OSs. * \author Maarten Gribnau @@ -251,6 +257,8 @@ public: GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;} + GHOST_TUns16 getDPIHint() override; + /** if the window currently resizing */ bool m_inLiveResize; @@ -351,6 +359,9 @@ private: GHOST_TWindowState m_normal_state; + /** user32 dll handle*/ + HMODULE m_user32; + /** Hwnd to parent window */ GHOST_TEmbedderWindowID m_parentWindowHwnd; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 47fbe1256b1..2019f58251f 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -56,6 +56,9 @@ # include <X11/extensions/XInput2.h> #endif +//For DPI value +#include <X11/Xresource.h> + #if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX) # include <strings.h> #endif @@ -68,6 +71,7 @@ #include <algorithm> #include <string> +#include <math.h> /* For obscure full screen mode stuff * lifted verbatim from blut. */ @@ -1672,3 +1676,44 @@ endFullScreen() const return GHOST_kSuccess; } + +GHOST_TUns16 +GHOST_WindowX11:: +getDPIHint() +{ + /* Try to read DPI setting set using xrdb */ + char* resMan = XResourceManagerString(m_display); + if (resMan) { + XrmDatabase xrdb = XrmGetStringDatabase(resMan); + if (xrdb) { + char* type = NULL; + XrmValue val; + + int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val); + if (success && type) { + if (strcmp(type, "String") == 0) { + return atoi((char*)val.addr); + } + } + } + } + + /* Fallback to calculating DPI using X reported DPI, set using xrandr --dpi */ + XWindowAttributes attr; + if (!XGetWindowAttributes(m_display, m_window, &attr)) { + /* Failed to get window attributes, return X11 default DPI */ + return 96; + } + + Screen* screen = attr.screen; + int pixelWidth = WidthOfScreen(screen); + int pixelHeight = HeightOfScreen(screen); + int mmWidth = WidthMMOfScreen(screen); + int mmHeight = HeightMMOfScreen(screen); + + double pixelDiagonal = sqrt((pixelWidth * pixelWidth) + (pixelHeight * pixelHeight)); + double mmDiagonal = sqrt((mmWidth * mmWidth) + (mmHeight * mmHeight)); + float inchDiagonal = mmDiagonal * 0.039f; + int dpi = pixelDiagonal / inchDiagonal; + return dpi; +} diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 9380aa9d631..5c54c1e8162 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -235,6 +235,8 @@ public: GHOST_TSuccess endFullScreen() const; + GHOST_TUns16 getDPIHint(); + protected: /** * \param type The type of rendering context create. |