Merge branch 'blender-v4.5-release'

This commit is contained in:
Jonas Holzman
2025-07-03 00:07:52 +02:00
3 changed files with 62 additions and 33 deletions

View File

@@ -686,10 +686,8 @@ uint64_t GHOST_SystemCocoa::getMilliSeconds() const
uint8_t GHOST_SystemCocoa::getNumDisplays() const
{
/* Note that OS X supports monitor hot plug.
* We do not support multiple monitors at the moment. */
@autoreleasepool {
return NSScreen.screens.count;
return [[NSScreen screens] count];
}
}
@@ -697,7 +695,7 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(uint32_t &width, uint32_t &heig
{
@autoreleasepool {
/* Get visible frame, that is frame excluding dock and top menu bar. */
const NSRect frame = [[NSScreen mainScreen] visibleFrame];
const NSRect frame = [GHOST_WindowCocoa::getPrimaryScreen() visibleFrame];
/* Returns max window contents (excluding title bar...). */
const NSRect contentRect = [NSWindow
@@ -730,18 +728,13 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
GHOST_IWindow *window = nullptr;
@autoreleasepool {
/* Get the available rect for including window contents. */
const NSRect frame = [[NSScreen mainScreen] visibleFrame];
const NSRect contentRect = [NSWindow
contentRectForFrameRect:frame
const NSRect primaryScreenFrame = [GHOST_WindowCocoa::getPrimaryScreen() visibleFrame];
const NSRect primaryScreenContentRect = [NSWindow
contentRectForFrameRect:primaryScreenFrame
styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
NSWindowStyleMaskMiniaturizable)];
int32_t bottom = (contentRect.size.height - 1) - height - top;
/* Ensures window top left is inside this available rect. */
left = left > contentRect.origin.x ? left : contentRect.origin.x;
/* Add `contentRect.origin.y` to respect dock-size. */
bottom = bottom > contentRect.origin.y ? bottom + contentRect.origin.y : contentRect.origin.y;
const int32_t bottom = primaryScreenContentRect.size.height - top - height;
window = new GHOST_WindowCocoa(this,
title,

View File

@@ -184,10 +184,18 @@ class GHOST_WindowCocoa : public GHOST_Window {
void screenToClientIntern(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
/**
* Gets the screen the window is displayed in
* \return The NSScreen object
* Return the screen the window is displayed in.
* \return The current screen NSScreen object
*/
NSScreen *getScreen();
NSScreen *getScreen() const;
/**
* Return the primary screen, the screen defined as "Main Display" in macOS Settings, source of
* all screen coordinates.
* \note This function is placed in WindowCocoa since SystemCocoa cannot include Obj-C types.
* \return The primary screen NSScreen object
*/
static NSScreen *getPrimaryScreen();
/**
* Sets the state of the window (normal, minimized, maximized).

View File

@@ -365,6 +365,11 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
styleMask:styleMask
backing:NSBackingStoreBuffered
defer:NO];
/* By default, AppKit repositions the window in the context of the current "mainMonitor"
* (the monitor which has focus), bypass this by forcing the window back into its correct
* position. Since we use global screen coordinate indexed on the first, primary screen.
*/
[m_window setFrameOrigin:NSMakePoint(left, bottom)];
/* Forbid to resize the window below the blender defined minimum one. */
const NSSize minSize = {320, 240};
@@ -600,13 +605,24 @@ void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect &bounds) const
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid");
@autoreleasepool {
const NSRect screenSize = m_window.screen.visibleFrame;
const NSRect rect = m_window.frame;
/* All coordinates are based off the primary screen. */
const NSRect screenFrame = [getPrimaryScreen() visibleFrame];
const NSRect windowFrame = m_window.frame;
bounds.m_b = screenSize.size.height - (rect.origin.y - screenSize.origin.y);
bounds.m_l = rect.origin.x - screenSize.origin.x;
bounds.m_r = rect.origin.x - screenSize.origin.x + rect.size.width;
bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height - screenSize.origin.y);
/* Flip the Y axis, from bottom left coordinate to top left, which is the expected coordinate
* return format for GHOST, even though the Window Manager later reflips it to bottom-left
* this is the expected coordinate system for all GHOST backends
*/
const int32_t screenMaxY = screenFrame.origin.y + screenFrame.size.height;
/* Flip the coordinates vertically from a bottom-left origin to a top-left origin,
* as expected by GHOST. */
bounds.m_b = screenMaxY - windowFrame.origin.y;
bounds.m_t = screenMaxY - windowFrame.origin.y - windowFrame.size.height;
bounds.m_l = windowFrame.origin.x;
bounds.m_r = windowFrame.origin.x + windowFrame.size.width;
}
}
@@ -615,19 +631,25 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect &bounds) const
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid");
@autoreleasepool {
const NSRect screenSize = m_window.screen.visibleFrame;
/* All coordinates are based off the primary screen. */
const NSRect screenFrame = [getPrimaryScreen() visibleFrame];
/* Screen Content Rectangle (excluding Menu Bar and Dock). */
const NSRect screenContentRect = [NSWindow contentRectForFrameRect:screenFrame
styleMask:[m_window styleMask]];
/* Max window contents as screen size (excluding title bar...). */
const NSRect contentRect = [BlenderWindow contentRectForFrameRect:screenSize
styleMask:[m_window styleMask]];
const NSRect windowFrame = m_window.frame;
/* Window Content Rectangle (excluding Titlebar and borders) */
const NSRect windowContentRect = [m_window contentRectForFrameRect:windowFrame];
const NSRect rect = [m_window contentRectForFrameRect:[m_window frame]];
const int32_t screenMaxY = screenContentRect.origin.y + screenContentRect.size.height;
bounds.m_b = contentRect.size.height - (rect.origin.y - contentRect.origin.y);
bounds.m_l = rect.origin.x - contentRect.origin.x;
bounds.m_r = rect.origin.x - contentRect.origin.x + rect.size.width;
bounds.m_t = contentRect.size.height -
(rect.origin.y + rect.size.height - contentRect.origin.y);
/* Flip the coordinates vertically from a bottom-left origin to a top-left origin,
* as expected by GHOST. */
bounds.m_b = screenMaxY - windowContentRect.origin.y;
bounds.m_t = screenMaxY - windowContentRect.origin.y - windowContentRect.size.height;
bounds.m_l = windowContentRect.origin.x;
bounds.m_r = windowContentRect.origin.x + windowContentRect.size.width;
}
}
@@ -763,11 +785,17 @@ void GHOST_WindowCocoa::clientToScreenIntern(int32_t inX,
outY = screenCoord.origin.y;
}
NSScreen *GHOST_WindowCocoa::getScreen()
NSScreen *GHOST_WindowCocoa::getScreen() const
{
return m_window.screen;
}
NSScreen *GHOST_WindowCocoa::getPrimaryScreen()
{
/* The first element of the screens array is guaranted to be the primary screen by AppKit. */
return [[NSScreen screens] firstObject];
}
/* called for event, when window leaves monitor to another */
void GHOST_WindowCocoa::setNativePixelSize()
{