Skip to content

Commit

Permalink
macOS: Manually compute frame rect for zoomed/maximized state
Browse files Browse the repository at this point in the history
We cannot rely on AppKit to compute the zoomed frame for us, as it will
not allow borderless windows to be zoomed, and also has bugs in corner
cases with multiple screens, where the zoomed window jumps from the
current screen to a nearby screen.

The latter happens when the zoomed rect overlaps more with a nearby
screen than it does with the current screen. In this case AppKit zooms
the window on the nearby screen, but this is unexpected from the user's
perspective, who zoomed the window on the current screen, so we make
sure to always keep the window on the current screen by repositioning
the window correspondingly.

Task-number: QTBUG-67543
Change-Id: I8762c5cbf2e3b317a6caf11d820712596e15114a
Reviewed-by: Morten Johan Sørvig <[email protected]>
  • Loading branch information
torarnv committed Jun 5, 2018
1 parent 0a63d5f commit 8058380
Showing 1 changed file with 24 additions and 11 deletions.
35 changes: 24 additions & 11 deletions src/plugins/platforms/cocoa/qnswindowdelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -69,25 +69,38 @@ - (BOOL)windowShouldClose:(NSNotification *)notification
/*!
Overridden to ensure that the zoomed state always results in a maximized
window, which would otherwise not be the case for borderless windows.
We also keep the window on the same screen as before; something AppKit
sometimes fails to do using its built in logic.
*/
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)proposedFrame
{
Q_UNUSED(proposedFrame);
Q_ASSERT(window == m_cocoaWindow->nativeWindow());

// We compute the maximized state based on the maximum size, and
// the current position of the window. This may result in the window
// geometry falling outside of the current screen's available geometry,
// e.g. when there is not maximize size set, but this is okey, AppKit
// will then shift and possibly clip the geometry for us.
const QWindow *w = m_cocoaWindow->window();
QRect maximizedRect = QRect(w->framePosition(), w->maximumSize());

// QWindow::maximumSize() refers to the client size,
// but AppKit expects the full frame size.
maximizedRect.adjust(0, 0, 0, w->frameMargins().top());
// maximumSize() refers to the client size, but AppKit expects the full frame size
QSizeF maximumSize = w->maximumSize() + QSize(0, w->frameMargins().top());

// The window should never be larger than the current screen geometry
const QRectF screenGeometry = m_cocoaWindow->screen()->geometry();
maximumSize = maximumSize.boundedTo(screenGeometry.size());

// Use the current frame position for the initial maximized frame,
// so that the window stays put and just expand, in case its maximum
// size is within the screen bounds.
QRectF maximizedFrame = QRectF(w->framePosition(), maximumSize);

// But constrain the frame to the screen bounds in case the frame
// extends beyond the screen bounds as a result of starting out
// with the current frame position.
maximizedFrame.translate(QPoint(
qMax(screenGeometry.left() - maximizedFrame.left(), 0.0) +
qMin(screenGeometry.right() - maximizedFrame.right(), 0.0),
qMax(screenGeometry.top() - maximizedFrame.top(), 0.0) +
qMin(screenGeometry.bottom() - maximizedFrame.bottom(), 0.0)));

return QCocoaScreen::mapToNative(maximizedRect);
return QCocoaScreen::mapToNative(maximizedFrame);
}

- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
Expand Down

0 comments on commit 8058380

Please sign in to comment.