diff options
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 5 | ||||
-rw-r--r-- | intern/ghost/GHOST_IWindow.h | 6 | ||||
-rw-r--r-- | intern/ghost/GHOST_Types.h | 1 | ||||
-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 | 43 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.h | 2 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_userpref.py | 6 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_defaults.c | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_userdef.c | 36 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 71 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_window.h | 2 |
18 files changed, 267 insertions, 57 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index ff1922af4f3..6887063eae9 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 688ebecf557..4a4d6be5ced 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 9ee4599a4a6..02b5063e515 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 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..429c9af0e3e 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,42 @@ endFullScreen() const return GHOST_kSuccess; } + +GHOST_TUns16 +GHOST_WindowX11:: +getDPIHint() +{ + /* Try to read DPI setting set using xrdb */ + char* resMan = XResourceManagerString(m_display); + 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. diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index f4e2cf006b2..e50beba50d8 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -217,6 +217,7 @@ class USERPREF_PT_interface(Panel): col = row.column() col.label(text="Display:") + col.prop(view, "ui_scale", text="Scale") col.prop(view, "show_tooltips") col.prop(view, "show_tooltips_python") col.prop(view, "show_object_info", text="Object Info") @@ -467,11 +468,6 @@ class USERPREF_PT_system(Panel): col = colsplit.column() col.label(text="General:") - col.prop(system, "dpi") - col.label("Virtual Pixel Mode:") - col.prop(system, "virtual_pixel_mode", text="") - - col.separator() col.prop(system, "frame_server_port") col.prop(system, "scrollback", text="Console Scrollback") diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 99d9e140481..6145b90b406 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -68,6 +68,10 @@ void BLO_update_defaults_userpref_blend(void) * but take care since some hardware has driver bugs here (T46962). * Further hardware workarounds should be made in gpu_extensions.c */ U.glalphaclip = (1.0f / 255); + + /* default so DPI is detected automatically */ + U.dpi = 0; + U.ui_scale = 1.0f; } /** diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index d76452edb83..5e7e7366e35 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -467,9 +467,11 @@ typedef struct UserDef { int audioformat; int audiochannels; - int scrollback; /* console scrollback limit */ - int dpi; /* range 48-128? */ - char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */ + int scrollback; /* console scrollback limit */ + int dpi; /* range 48-128? */ + float ui_scale; /* interface scale */ + int pad1; + char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */ char pad2; short transopts; short menuthreshold1, menuthreshold2; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 7b6eb5fef47..4d70b87843a 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -138,23 +138,11 @@ static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe } /* also used by buffer swap switching */ -static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) +static void rna_userdef_dpi_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ BLF_cache_clear(); - BKE_blender_userdef_refresh(); - WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ - WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ -} - -static void rna_userdef_virtual_pixel_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) -{ - /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ - BLF_cache_clear(); - - BKE_blender_userdef_refresh(); - /* force setting drawable again */ wmWindowManager *wm = bmain->wm.first; if (wm) { @@ -3325,6 +3313,12 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "View & Controls", "Preferences related to viewing data"); /* View */ + prop = RNA_def_property(srna, "ui_scale", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_ui_text(prop, "UI Scale", "Changes the size of the fonts and buttons in the interface"); + RNA_def_property_range(prop, 0.25f, 4.0f); + RNA_def_property_ui_range(prop, 0.5f, 2.0f, 1, 1); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); /* display */ prop = RNA_def_property(srna, "show_tooltips", PROP_BOOLEAN, PROP_NONE); @@ -3916,12 +3910,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem virtual_pixel_mode_items[] = { - {VIRTUAL_PIXEL_NATIVE, "NATIVE", 0, "Native", "Use native pixel size of the display"}, - {VIRTUAL_PIXEL_DOUBLE, "DOUBLE", 0, "Double", "Use double the native pixel size of the display"}, - {0, NULL, 0, NULL, NULL} - }; - srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); @@ -3936,16 +3924,8 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update"); prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "dpi"); - RNA_def_property_range(prop, 48, 144); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); - RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); - - prop = RNA_def_property(srna, "virtual_pixel_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "virtual_pixel"); - RNA_def_property_enum_items(prop, virtual_pixel_mode_items); - RNA_def_property_ui_text(prop, "Virtual Pixel Mode", "Modify the pixel size for hi-res devices"); - RNA_def_property_update(prop, 0, "rna_userdef_virtual_pixel_update"); prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 2d43c47679d..40baab8809c 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -77,6 +77,7 @@ #include "GPU_extensions.h" #include "GPU_init_exit.h" #include "GPU_glew.h" +#include "BLF_api.h" /* for assert */ #ifndef NDEBUG @@ -374,14 +375,39 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) } } -static float wm_window_get_virtual_pixelsize(void) +static void wm_window_set_dpi(wmWindow *win) { - return ((U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1.0f : 2.0f); -} + int auto_dpi = GHOST_GetDPIHint(win->ghostwin); -float wm_window_pixelsize(wmWindow *win) -{ - return (GHOST_GetNativePixelSize(win->ghostwin) * wm_window_get_virtual_pixelsize()); + /* Lazily init UI scale size, preserving backwards compatibility by + * computing UI scale from ratio of previous DPI and auto DPI */ + if (U.ui_scale == 0) { + int virtual_pixel = (U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1 : 2; + + if (U.dpi == 0) { + U.ui_scale = virtual_pixel; + } + else { + U.ui_scale = (virtual_pixel * U.dpi * 96.0f) / (auto_dpi * 72.0f); + } + + CLAMP(U.ui_scale, 0.25f, 4.0f); + } + + /* Blender's UI drawing assumes DPI 72 as a good default following macOS + * while Windows and Linux use DPI 96. GHOST assumes a default 96 so we + * remap the DPI to Blender's convention. */ + int dpi = auto_dpi * U.ui_scale * (72.0/96.0f); + + /* Automatically set larger pixel size for high DPI. */ + int pixelsize = MAX2(1, dpi / 54); + + /* Set user preferences globals for drawing, and for forward compatibility. */ + U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin) * pixelsize; + U.dpi = dpi / pixelsize; + U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE; + + BKE_blender_userdef_refresh(); } /* belongs to below */ @@ -456,10 +482,8 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm glClear(GL_COLOR_BUFFER_BIT); } - /* displays with larger native pixels, like Macbook. Used to scale dpi with */ /* needed here, because it's used before it reads userdef */ - U.pixelsize = wm_window_pixelsize(win); - BKE_blender_userdef_refresh(); + wm_window_set_dpi(win); wm_window_swap_buffers(win); @@ -626,7 +650,6 @@ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type) Scene *scene = CTX_data_scene(C); const char *title; rcti rect = *rect_init; - const short px_virtual = (short)wm_window_get_virtual_pixelsize(); /* changes rect to fit within desktop */ wm_window_check_position(&rect); @@ -644,9 +667,8 @@ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type) win->posy = rect.ymin; } - /* multiply with virtual pixelsize, ghost handles native one (e.g. for retina) */ - win->sizex = BLI_rcti_size_x(&rect) * px_virtual; - win->sizey = BLI_rcti_size_y(&rect) * px_virtual; + win->sizex = BLI_rcti_size_x(&rect); + win->sizey = BLI_rcti_size_y(&rect); if (win->ghostwin) { wm_window_set_size(win, win->sizex, win->sizey); @@ -835,8 +857,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) GHOST_ActivateWindowDrawingContext(win->ghostwin); /* this can change per window */ - U.pixelsize = wm_window_pixelsize(win); - BKE_blender_userdef_refresh(); + wm_window_set_dpi(win); } } @@ -1035,6 +1056,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr if (type == GHOST_kEventWindowSize) { WM_jobs_stop(wm, win->screen, NULL); } + + wm_window_set_dpi(win); /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { @@ -1118,7 +1141,19 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr } break; } - + + case GHOST_kEventWindowDPIHintChanged: + { + wm_window_set_dpi(win); + /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ + BLF_cache_clear(); + + BKE_blender_userdef_refresh(); + WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ + WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ + break; + } + case GHOST_kEventOpenMainFile: { PointerRNA props_ptr; @@ -1199,11 +1234,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr { // only update if the actual pixel size changes float prev_pixelsize = U.pixelsize; - U.pixelsize = wm_window_pixelsize(win); + wm_window_set_dpi(win); if (U.pixelsize != prev_pixelsize) { - BKE_blender_userdef_refresh(); - // close all popups since they are positioned with the pixel // size baked in and it's difficult to correct them wmWindow *oldWindow = CTX_wm_window(C); diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index c106f9d7851..f70ec6b47f6 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -63,8 +63,6 @@ void wm_window_swap_buffers (wmWindow *win); void wm_window_set_swap_interval(wmWindow *win, int interval); bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut); -float wm_window_pixelsize(wmWindow *win); - void wm_get_cursor_position (wmWindow *win, int *x, int *y); void wm_cursor_position_from_ghost (wmWindow *win, int *x, int *y); void wm_cursor_position_to_ghost (wmWindow *win, int *x, int *y); |