Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/ghost/GHOST_C-api.h5
-rw-r--r--intern/ghost/GHOST_IWindow.h6
-rw-r--r--intern/ghost/GHOST_Types.h1
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp6
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp78
-rw-r--r--intern/ghost/intern/GHOST_Window.h9
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp16
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp18
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h11
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp43
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h2
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py6
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c4
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h8
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c36
-rw-r--r--source/blender/windowmanager/intern/wm_window.c71
-rw-r--r--source/blender/windowmanager/wm_window.h2
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);