macOS: Move geometry reporting from QNSView to QCocoaWindow

There's no longer any reason to call out from QCocoaWindow to QNView for
this, as the geometry events from AppKit are delivered directly to the
QCocoaWindow. Most of the data used in the implementation are coming
from QCocoaWindow anyways, and this enables geometry events for foreign
windows in the future.

Change-Id: Idd724d078e9981304dcbe6742b9ddc71640a2350
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
bb10
Tor Arne Vestbø 2017-07-04 17:01:22 +02:00
parent 0d196b4268
commit 74fc88f638
4 changed files with 61 additions and 55 deletions

View File

@ -226,6 +226,8 @@ public: // for QNSView
bool alwaysShowToolWindow() const;
void removeMonitor();
void handleGeometryChange();
NSView *m_view;
QCocoaNSWindow *m_nsWindow;

View File

@ -558,7 +558,7 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
{
if (isContentView()) {
// While setting style mask we can have -updateGeometry calls on a content
// While setting style mask we can have handleGeometryChange calls on a content
// view with null geometry, reporting an invalid coordinates as a result.
m_inSetStyleMask = true;
m_view.window.styleMask = windowStyleMask(flags);
@ -837,7 +837,7 @@ void QCocoaWindow::windowWillMove()
void QCocoaWindow::windowDidMove()
{
[qnsview_cast(m_view) updateGeometry];
handleGeometryChange();
// Moving a window might bring it out of maximized state
reportCurrentWindowState();
@ -848,7 +848,7 @@ void QCocoaWindow::windowDidResize()
if (!isContentView())
return;
[qnsview_cast(m_view) updateGeometry];
handleGeometryChange();
if (!m_view.inLiveResize)
reportCurrentWindowState();
@ -856,7 +856,7 @@ void QCocoaWindow::windowDidResize()
void QCocoaWindow::viewDidChangeFrame()
{
[qnsview_cast(m_view) updateGeometry];
handleGeometryChange();
}
/*!
@ -1023,6 +1023,55 @@ bool QCocoaWindow::windowShouldClose()
return accepted;
}
// ----------------------------- QPA forwarding -----------------------------
void QCocoaWindow::handleGeometryChange()
{
// Don't send geometry change event to Qt unless it's ready to handle events
if (m_inConstructor)
return;
// Don't send the geometry change if the QWindow is designated to be
// embedded in a foreign view hierarchy but has not actually been
// embedded yet - it's too early.
if (m_viewIsToBeEmbedded && !m_viewIsEmbedded)
return;
// It can happen that the current NSWindow is nil (if we are changing styleMask
// from/to borderless, and the content view is being re-parented), which results
// in invalid coordinates.
if (m_inSetStyleMask && !m_view.window)
return;
QRect newGeometry;
if (isContentView()) {
// Top level window, get window rect and flip y
NSRect rect = m_view.frame;
NSRect windowRect = m_view.window.frame;
newGeometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
} else if (m_viewIsToBeEmbedded) {
// Embedded child window, use the frame rect ### merge with case below
newGeometry = QRectF::fromCGRect(NSRectToCGRect(m_view.bounds)).toRect();
} else {
// Child window, use the frame rect
newGeometry = QRectF::fromCGRect(NSRectToCGRect(m_view.frame)).toRect();
}
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleGeometryChange" << window()
<< "current" << geometry() << "new" << newGeometry;
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
updateExposedGeometry();
// Guard against processing window system events during QWindow::setGeometry
// calls, which Qt and Qt applications do not expect.
if (!m_inSetGeometry)
QWindowSystemInterface::flushWindowSystemEvents();
else if (newGeometry.size() != geometry().size())
[qnsview_cast(m_view) clearBackingStore];
}
// --------------------------------------------------------------------------
bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const

View File

@ -95,12 +95,12 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
#endif
- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
- (void)clearBackingStore;
- (void)clearBackingStore:(QCocoaBackingStore *)backingStore;
- (void)setMaskRegion:(const QRegion *)region;
- (void)invalidateWindowShadowIfNeeded;
- (void)drawRect:(NSRect)dirtyRect;
- (void)drawBackingStoreUsingCoreGraphics:(NSRect)dirtyRect;
- (void)updateGeometry;
- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification;
- (void)viewDidHide;
- (void)viewDidUnhide;

View File

@ -274,56 +274,6 @@ static QTouchDevice *touchDevice = 0;
return focusWindow;
}
- (void)updateGeometry
{
if (!m_platformWindow)
return;
QRect geometry;
if (m_platformWindow->isContentView()) {
// top level window, get window rect and flip y.
NSRect rect = [self frame];
NSRect windowRect = [[self window] frame];
geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
} else if (m_platformWindow->m_viewIsToBeEmbedded) {
// embedded child window, use the frame rect ### merge with case below
geometry = QRectF::fromCGRect(NSRectToCGRect([self bounds])).toRect();
} else {
// child window, use the frame rect
geometry = QRectF::fromCGRect(NSRectToCGRect([self frame])).toRect();
}
const bool isResize = geometry.size() != m_platformWindow->geometry().size();
// It can happen that self.window is nil (if we are changing
// styleMask from/to borderless and content view is being re-parented)
// - this results in an invalid coordinates.
if (m_platformWindow->m_inSetStyleMask && !self.window)
return;
qCDebug(lcQpaCocoaWindow) << "[QNSView udpateGeometry:]" << m_platformWindow->window()
<< "current" << m_platformWindow->geometry() << "new" << geometry;
// Don't send the geometry change if the QWindow is designated to be
// embedded in a foreign view hiearchy but has not actually been
// embedded yet - it's too early.
if (m_platformWindow->m_viewIsToBeEmbedded && !m_platformWindow->m_viewIsEmbedded)
return;
// Send a geometry change event to Qt, if it's ready to handle events
if (!m_platformWindow->m_inConstructor) {
QWindowSystemInterface::handleGeometryChange(m_platformWindow->window(), geometry);
m_platformWindow->updateExposedGeometry();
// Guard against processing window system events during QWindow::setGeometry
// calles, which Qt and Qt applications do not excpect.
if (!m_platformWindow->m_inSetGeometry)
QWindowSystemInterface::flushWindowSystemEvents();
else if (isResize)
m_backingStore = 0;
}
}
- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification
{
Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification)
@ -367,6 +317,11 @@ static QTouchDevice *touchDevice = 0;
[self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
}
- (void)clearBackingStore
{
m_backingStore = nullptr;
}
- (void)clearBackingStore:(QCocoaBackingStore *)backingStore
{
if (backingStore == m_backingStore)