Mac HiDPI ("retina") handling:
OK - so you have this nice crisp screen, and still you want to add extra monitors to the laptop! That means Blender should switch back and forth to HiDPI modes, when you move a window to another monitor. This code makes the pixelsize scale factor a window property, and handles an event when a window moves to another monitor. It then changes the native pixelsize nicely and refreshes entire UI. You can also have one Blender window on high, and other on low resolution. Stretching a Blender window from 1 monitor to the other works too, but that is Apple magic handling it.
This commit is contained in:
@@ -860,7 +860,7 @@ extern int GHOST_UseNativePixels(void);
|
||||
/**
|
||||
* If window was opened using native pixel size, it returns scaling factor.
|
||||
*/
|
||||
extern float GHOST_GetNativePixelSize(void);
|
||||
extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -297,10 +297,8 @@ public:
|
||||
|
||||
/**
|
||||
* Native pixel size support (MacBook 'retina').
|
||||
* \return The pixel size in float.
|
||||
*/
|
||||
virtual bool useNativePixel(void) = 0;
|
||||
virtual float getNativePixelSize(void) = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
* Event management functionality
|
||||
|
@@ -305,6 +305,10 @@ public:
|
||||
*/
|
||||
virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { return GHOST_kSuccess; }
|
||||
|
||||
|
||||
virtual float getNativePixelSize(void) = 0;
|
||||
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow")
|
||||
#endif
|
||||
|
@@ -183,6 +183,7 @@ typedef enum {
|
||||
GHOST_kEventDraggingDropDone,
|
||||
|
||||
GHOST_kEventOpenMainFile, // Needed for Cocoa to open double-clicked .blend file at startup
|
||||
GHOST_kEventNativeResolutionChange, // Needed for Cocoa when window moves to other display
|
||||
|
||||
GHOST_kEventTimer,
|
||||
|
||||
|
@@ -885,9 +885,11 @@ int GHOST_UseNativePixels(void)
|
||||
return system->useNativePixel();
|
||||
}
|
||||
|
||||
float GHOST_GetNativePixelSize(void)
|
||||
float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
return system->getNativePixelSize();
|
||||
GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
|
||||
if (window)
|
||||
return window->getNativePixelSize();
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
|
@@ -46,7 +46,6 @@
|
||||
|
||||
GHOST_System::GHOST_System()
|
||||
: m_nativePixel(false),
|
||||
m_nativePixelSize(1),
|
||||
m_displayManager(0),
|
||||
m_timerManager(0),
|
||||
m_windowManager(0),
|
||||
@@ -382,9 +381,3 @@ bool GHOST_System::useNativePixel(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
float GHOST_System::getNativePixelSize(void)
|
||||
{
|
||||
if (m_nativePixel)
|
||||
return m_nativePixelSize;
|
||||
return 1.0f;
|
||||
}
|
||||
|
@@ -175,9 +175,6 @@ public:
|
||||
virtual bool useNativePixel(void);
|
||||
bool m_nativePixel;
|
||||
|
||||
virtual float getNativePixelSize(void);
|
||||
float m_nativePixelSize;
|
||||
|
||||
/***************************************************************************************
|
||||
* Event management functionality
|
||||
***************************************************************************************/
|
||||
|
@@ -1054,6 +1054,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
|
||||
//m_ignoreWindowSizedMessages = true;
|
||||
}
|
||||
break;
|
||||
case GHOST_kEventNativeResolutionChange:
|
||||
|
||||
if (m_nativePixel) {
|
||||
window->setNativePixelSize();
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) );
|
||||
}
|
||||
|
||||
default:
|
||||
return GHOST_kFailure;
|
||||
break;
|
||||
|
@@ -61,6 +61,8 @@ GHOST_Window::GHOST_Window(
|
||||
|
||||
m_cursorGrabAccumPos[0] = 0;
|
||||
m_cursorGrabAccumPos[1] = 0;
|
||||
|
||||
m_nativePixelSize = 1.0f;
|
||||
|
||||
m_fullScreen = state == GHOST_kWindowStateFullScreen;
|
||||
if (m_fullScreen) {
|
||||
@@ -194,3 +196,4 @@ bool GHOST_Window::getModifiedState()
|
||||
{
|
||||
return m_isUnsavedChanges;
|
||||
}
|
||||
|
||||
|
@@ -257,6 +257,13 @@ public:
|
||||
{
|
||||
m_userData = userData;
|
||||
}
|
||||
|
||||
virtual float getNativePixelSize(void)
|
||||
{
|
||||
if (m_nativePixelSize > 0.0f)
|
||||
return m_nativePixelSize;
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -351,6 +358,9 @@ protected:
|
||||
GHOST_TUns32 m_fullScreenWidth;
|
||||
/** Full-screen height */
|
||||
GHOST_TUns32 m_fullScreenHeight;
|
||||
|
||||
/* OSX only, retina screens */
|
||||
float m_nativePixelSize;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -262,6 +262,11 @@ public:
|
||||
* Hides the progress bar icon
|
||||
*/
|
||||
virtual GHOST_TSuccess endProgressBar();
|
||||
|
||||
|
||||
virtual void setNativePixelSize(void);
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Tries to install a rendering context in this window.
|
||||
|
@@ -74,8 +74,10 @@ extern "C" {
|
||||
- (void)windowDidMove:(NSNotification *)notification;
|
||||
- (void)windowWillMove:(NSNotification *)notification;
|
||||
- (BOOL)windowShouldClose:(id)sender;
|
||||
- (void)windowDidChangeBackingProperties:(NSNotification *)notification;
|
||||
@end
|
||||
|
||||
|
||||
@implementation CocoaWindowDelegate : NSObject
|
||||
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
|
||||
{
|
||||
@@ -128,6 +130,11 @@ extern "C" {
|
||||
}*/
|
||||
}
|
||||
|
||||
- (void)windowDidChangeBackingProperties:(NSNotification *)notification
|
||||
{
|
||||
systemCocoa->handleWindowEvent(GHOST_kEventNativeResolutionChange, associatedWindow);
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(id)sender;
|
||||
{
|
||||
//Let Blender close the window rather than closing immediately
|
||||
@@ -593,7 +600,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
|
||||
[m_openGLView setWantsBestResolutionOpenGLSurface:YES];
|
||||
|
||||
NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]];
|
||||
m_systemCocoa->m_nativePixelSize = (float)backingBounds.size.width / (float)rect.size.width;
|
||||
m_nativePixelSize = (float)backingBounds.size.width / (float)rect.size.width;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -911,6 +918,17 @@ NSScreen* GHOST_WindowCocoa::getScreen()
|
||||
return [m_window screen];
|
||||
}
|
||||
|
||||
/* called for event, when window leaves monitor to another */
|
||||
void GHOST_WindowCocoa::setNativePixelSize(void)
|
||||
{
|
||||
NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]];
|
||||
|
||||
GHOST_Rect rect;
|
||||
getClientBounds(rect);
|
||||
|
||||
m_nativePixelSize = (float)backingBounds.size.width / (float)rect.getWidth();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Fullscreen switch is not actual fullscreen with display capture.
|
||||
|
@@ -426,6 +426,9 @@ void BKE_userdef_free(void)
|
||||
/* handle changes in settings that need recalc */
|
||||
void BKE_userdef_state(void)
|
||||
{
|
||||
/* prevent accidents */
|
||||
if (U.pixelsize == 0) U.pixelsize = 1;
|
||||
|
||||
BLF_default_dpi(U.pixelsize * U.dpi);
|
||||
U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72;
|
||||
|
||||
|
@@ -302,11 +302,6 @@ static void wm_init_userdef(bContext *C)
|
||||
|
||||
/* update tempdir from user preferences */
|
||||
BLI_init_temporary_dir(U.tempdir);
|
||||
|
||||
/* displays with larger native pixels, like Macbook. Used to scale dpi with */
|
||||
if (G.background == FALSE)
|
||||
U.pixelsize = GHOST_GetNativePixelSize();
|
||||
if (U.pixelsize == 0) U.pixelsize = 1;
|
||||
|
||||
BKE_userdef_state();
|
||||
}
|
||||
|
@@ -377,7 +377,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
|
||||
|
||||
/* displays with larger native pixels, like Macbook. Used to scale dpi with */
|
||||
/* needed here, because it's used before it reads userdef */
|
||||
U.pixelsize = GHOST_GetNativePixelSize();
|
||||
U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
|
||||
BKE_userdef_state();
|
||||
|
||||
/* store actual window size in blender window */
|
||||
@@ -595,12 +595,13 @@ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
|
||||
static void wm_convert_cursor_position(wmWindow *win, int *x, int *y)
|
||||
{
|
||||
|
||||
float fac = GHOST_GetNativePixelSize(win->ghostwin);
|
||||
|
||||
GHOST_ScreenToClient(win->ghostwin, *x, *y, x, y);
|
||||
*x *= GHOST_GetNativePixelSize();
|
||||
*x *= fac;
|
||||
|
||||
*y = (win->sizey - 1) - *y;
|
||||
*y *= GHOST_GetNativePixelSize();
|
||||
*y *= fac;
|
||||
}
|
||||
|
||||
|
||||
@@ -661,6 +662,10 @@ void wm_window_make_drawable(bContext *C, wmWindow *win)
|
||||
printf("%s: set drawable %d\n", __func__, win->winid);
|
||||
}
|
||||
GHOST_ActivateWindowDrawingContext(win->ghostwin);
|
||||
|
||||
/* this can change per window */
|
||||
U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
|
||||
BKE_userdef_state();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -947,6 +952,15 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
|
||||
|
||||
break;
|
||||
}
|
||||
case GHOST_kEventNativeResolutionChange:
|
||||
// printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin));
|
||||
|
||||
U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
|
||||
BKE_userdef_state();
|
||||
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
|
||||
WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL);
|
||||
|
||||
break;
|
||||
case GHOST_kEventTrackpad:
|
||||
{
|
||||
GHOST_TEventTrackpadData *pd = data;
|
||||
@@ -1289,7 +1303,7 @@ void WM_init_native_pixels(int do_it)
|
||||
void WM_cursor_warp(wmWindow *win, int x, int y)
|
||||
{
|
||||
if (win && win->ghostwin) {
|
||||
float f = GHOST_GetNativePixelSize();
|
||||
float f = GHOST_GetNativePixelSize(win->ghostwin);
|
||||
int oldx = x, oldy = y;
|
||||
|
||||
x = x / f;
|
||||
@@ -1308,14 +1322,14 @@ void WM_cursor_warp(wmWindow *win, int x, int y)
|
||||
/* mac retina opens window in size X, but it has up to 2 x more pixels */
|
||||
int WM_window_pixels_x(wmWindow *win)
|
||||
{
|
||||
float f = GHOST_GetNativePixelSize();
|
||||
float f = GHOST_GetNativePixelSize(win->ghostwin);
|
||||
|
||||
return (int)(f * (float)win->sizex);
|
||||
}
|
||||
|
||||
int WM_window_pixels_y(wmWindow *win)
|
||||
{
|
||||
float f = GHOST_GetNativePixelSize();
|
||||
float f = GHOST_GetNativePixelSize(win->ghostwin);
|
||||
|
||||
return (int)(f * (float)win->sizey);
|
||||
|
||||
|
Reference in New Issue
Block a user