[Bf-blender-cvs] [fe3fb23697] master: Automatic DPI for all platforms, per monitor DPI for Windows.

Wouter noreply at git.blender.org
Sat Mar 25 11:30:29 CET 2017


Commit: fe3fb236970ce30733381ad1ae8b89c55266c517
Author: Wouter
Date:   Sat Mar 11 03:27:08 2017 +0100
Branches: master
https://developer.blender.org/rBfe3fb236970ce30733381ad1ae8b89c55266c517

Automatic DPI for all platforms, per monitor DPI for Windows.

For Windows 8.1 and X11 (Linux, BSD) now use the DPI specified by the operating
system, which previously only worked on macOS. For Windows this is handled per
monitor, for X11 this is based on Xft.dpi or xrandr --dpi. This should result
in appropriate font and button sizes by default in most cases.

The UI has been simplified to a single UI Scale factor relative to the automatic
DPI, instead of two DPI and Virtual Pixel Size settings. There is forward and
backwards compatibility for existing user preferences.

Reviewed By: brecht, LazyDodo

Differential Revision: https://developer.blender.org/D2539

===================================================================

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_IWindow.h
M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_SystemWin32.cpp
M	intern/ghost/intern/GHOST_Window.h
M	intern/ghost/intern/GHOST_WindowSDL.cpp
M	intern/ghost/intern/GHOST_WindowSDL.h
M	intern/ghost/intern/GHOST_WindowWin32.cpp
M	intern/ghost/intern/GHOST_WindowWin32.h
M	intern/ghost/intern/GHOST_WindowX11.cpp
M	intern/ghost/intern/GHOST_WindowX11.h
M	release/scripts/startup/bl_ui/space_userpref.py
M	source/blender/blenloader/intern/versioning_defaults.c
M	source/blender/makesdna/DNA_userdef_types.h
M	source/blender/makesrna/intern/rna_userdef.c
M	source/blender/windowmanager/intern/wm_window.c
M	source/blender/windowmanager/wm_window.h

===================================================================

diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index ff1922af4f..6887063eae 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -908,6 +908,11 @@ extern int GHOST_UseNativePixels(void);
 extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
 
 /**
+ * Returns the suggested DPI for this window.
+ */
+extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle);
+
+/**
  * Enable IME attached to the given window, i.e. allows user-input
  * events to be dispatched to the IME.
  * \param windowhandle Window handle of the caller
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 688ebecf55..4a4d6be5ce 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -332,6 +332,12 @@ public:
 
 	virtual float getNativePixelSize(void) = 0;
 
+	/**
+	 * Returns the recommended DPI for this window.
+	 * \return The recommended DPI for this window.
+	 */
+	virtual GHOST_TUns16 getDPIHint() = 0;
+
 #ifdef WITH_INPUT_IME
 	/**
 	 * Enable IME attached to the given window, i.e. allows user-input
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 9ee4599a4a..02b5063e51 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -189,6 +189,7 @@ typedef enum {
 	GHOST_kEventWindowUpdate,
 	GHOST_kEventWindowSize,
 	GHOST_kEventWindowMove,
+	GHOST_kEventWindowDPIHintChanged,
 	
 	GHOST_kEventDraggingEntered,
 	GHOST_kEventDraggingUpdated,
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 41bc735e1e..ce65318876 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 7d55a973f9..240d7ccd2f 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 d778628ea3..2798bdf72f 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 1335c38d97..aeb6188dae 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 5f658e8ad0..96104ec28b 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 7d80aa43a4..fc46164c13 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 a1cf58c9ce..75a33951ff 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_TEmb

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list