diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoansmenu.mm | 15 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 24 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 48 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioswindow.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioswindow.mm | 13 | ||||
-rw-r--r-- | src/plugins/platforms/ios/quiview.mm | 35 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowscontext.cpp | 6 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.cpp | 6 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.h | 1 |
10 files changed, 110 insertions, 45 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.mm b/src/plugins/platforms/cocoa/qcocoansmenu.mm index 996a4ff194..6be2569dbc 100644 --- a/src/plugins/platforms/cocoa/qcocoansmenu.mm +++ b/src/plugins/platforms/cocoa/qcocoansmenu.mm @@ -40,6 +40,8 @@ #import "qcocoansmenu.h" #include "qcocoamenu.h" #include "qcocoamenuitem.h" +#include "qcocoamenubar.h" +#include "qcocoawindow.h" #import "qnsview.h" #include <QtCore/qmetaobject.h> @@ -291,6 +293,19 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string) return nil; } +// Cocoa will query the menu item's target for the worksWhenModal selector. +// So we need to implement this to allow the items to be handled correctly +// when a modal dialog is visible. +- (BOOL)worksWhenModal +{ + if (!QGuiApplication::modalWindow()) + return YES; + const auto &qpaMenu = static_cast<QCocoaNSMenu *>(self).qpaMenu; + if (auto *mb = qobject_cast<QCocoaMenuBar *>(qpaMenu->menuParent())) + return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO; + return YES; +} + @end #undef CHECK_MENU_CLASS diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 562872a300..ca580e7d17 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -503,9 +503,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) { const Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); const bool frameless = (flags & Qt::FramelessWindowHint) || windowIsPopupType(type); + const bool resizeable = type != Qt::Dialog; // Dialogs: remove zoom button by disabling resize - // Select base window type. - NSUInteger styleMask = frameless ? NSBorderlessWindowMask : NSResizableWindowMask; + // Select base window type. Note that the value of NSBorderlessWindowMask is 0. + NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask; if (frameless) { // No further customizations for frameless since there are no window decorations. @@ -1156,23 +1157,6 @@ void QCocoaWindow::handleExposeEvent(const QRegion ®ion) m_exposedRect = QRect(); } - QWindowPrivate *windowPrivate = qt_window_private(window()); - if (windowPrivate->updateRequestPending) { - // We can only deliver update request events when the window is exposed, - // and we also have to make sure we deliver any change to the exposed - // rect as a real expose event (including going from non-exposed to - // exposed). FIXME: Should this logic live in QGuiApplication? - if (isExposed() && m_exposedRect == previouslyExposedRect) { - qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "as update request"; - windowPrivate->deliverUpdateRequest(); - return; - } else { - // Since updateRequestPending is still set, we will issue a deferred setNeedsDisplay - // from drawRect and get back into this code on the next display cycle, delivering - // the pending update request. - } - } - qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed(); QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), region); } @@ -1347,7 +1331,7 @@ void QCocoaWindow::recreateWindowIfNeeded() void QCocoaWindow::requestUpdate() { qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::requestUpdate" << window(); - [m_view setNeedsDisplay:YES]; + [m_view requestUpdate]; } void QCocoaWindow::requestActivateWindow() diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index f8903725a6..e2ea862cd5 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -81,6 +81,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); NSEvent *m_currentlyInterpretedKeyEvent; bool m_isMenuView; QSet<quint32> m_acceptedKeyDowns; + bool m_updateRequested; } @property (nonatomic, retain) NSCursor *cursor; @@ -105,6 +106,8 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)resetMouseButtons; +- (void)requestUpdate; + - (void)handleMouseEvent:(NSEvent *)theEvent; - (bool)handleMouseDownEvent:(NSEvent *)theEvent withButton:(int)buttonNumber; - (bool)handleMouseDraggedEvent:(NSEvent *)theEvent withButton:(int)buttonNumber; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 216b2f1287..ec1d126ab9 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -148,6 +148,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") m_isMenuView = false; self.focusRingType = NSFocusRingTypeNone; self.cursor = nil; + m_updateRequested = false; } return self; } @@ -300,6 +301,25 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") return m_platformWindow->isOpaque(); } +- (void)requestUpdate +{ + if (self.needsDisplay) { + // If the view already has needsDisplay set it means that there may be code waiting for + // a real expose event, so we can't issue setNeedsDisplay now as a way to trigger an + // update request. We will re-trigger requestUpdate from drawRect. + return; + } + + [self setNeedsDisplay:YES]; + m_updateRequested = true; +} + +- (void)setNeedsDisplayInRect:(NSRect)rect +{ + [super setNeedsDisplayInRect:rect]; + m_updateRequested = false; +} + - (void)drawRect:(NSRect)dirtyRect { Q_UNUSED(dirtyRect); @@ -315,7 +335,11 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect(); qCDebug(lcQpaCocoaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion; + [self updateRegion:exposedRegion]; +} +- (void)updateRegion:(QRegion)dirtyRegion +{ #ifndef QT_NO_OPENGL if (m_glContext && m_shouldSetGLContextinDrawRect) { [m_glContext->nsOpenGLContext() setView:self]; @@ -323,18 +347,24 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") } #endif - m_platformWindow->handleExposeEvent(exposedRegion); + QWindowPrivate *windowPrivate = qt_window_private(m_platformWindow->window()); + + if (m_updateRequested) { + Q_ASSERT(windowPrivate->updateRequestPending); + qCDebug(lcQpaCocoaWindow) << "Delivering update request to" << m_platformWindow->window(); + windowPrivate->deliverUpdateRequest(); + m_updateRequested = false; + } else { + m_platformWindow->handleExposeEvent(dirtyRegion); + } - if (qt_window_private(m_platformWindow->window())->updateRequestPending) { - // A call to QWindow::requestUpdate was issued during the expose event, or we - // had to deliver a real expose event and still need to deliver the update. - // But AppKit will reset the needsDisplay state of the view after completing + if (windowPrivate->updateRequestPending) { + // A call to QWindow::requestUpdate was issued during event delivery above, + // but AppKit will reset the needsDisplay state of the view after completing // the current display cycle, so we need to defer the request to redisplay. // FIXME: Perhaps this should be a trigger to enable CADisplayLink? qCDebug(lcQpaCocoaDrawing) << "[QNSView drawRect:] issuing deferred setNeedsDisplay due to pending update request"; - dispatch_async(dispatch_get_main_queue (), ^{ - [self setNeedsDisplay:YES]; - }); + dispatch_async(dispatch_get_main_queue (), ^{ [self requestUpdate]; }); } } @@ -351,7 +381,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") qCDebug(lcQpaCocoaDrawing) << "[QNSView updateLayer]" << m_platformWindow->window(); // FIXME: Find out if there's a way to resolve the dirty rect like in drawRect: - m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect()); + [self updateRegion:QRectF::fromCGRect(self.bounds).toRect()]; } - (void)viewDidChangeBackingProperties diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index d5af31044d..2028fc2a42 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -110,6 +110,10 @@ private: friend class QIOSScreen; }; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QIOSWindow *window); +#endif + QT_END_NAMESPACE #endif // QIOSWINDOW_H diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 38136c05db..6ee258e363 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -381,6 +381,19 @@ CAEAGLLayer *QIOSWindow::eaglLayer() const return static_cast<CAEAGLLayer *>(m_view.layer); } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QIOSWindow *window) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QIOSWindow(" << (const void *)window; + if (window) + debug << ", window=" << window->window(); + debug << ')'; + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + #include "moc_qioswindow.cpp" QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 6960698bf1..584dfe9b41 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -149,6 +149,21 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") [super dealloc]; } +- (NSString *)description +{ + NSMutableString *description = [NSMutableString stringWithString:[super description]]; + +#ifndef QT_NO_DEBUG_STREAM + QString platformWindowDescription; + QDebug debug(&platformWindowDescription); + debug.nospace() << "; " << m_qioswindow << ">"; + NSRange lastCharacter = [description rangeOfComposedCharacterSequenceAtIndex:description.length - 1]; + [description replaceCharactersInRange:lastCharacter withString:platformWindowDescription.toNSString()]; +#endif + + return description; +} + - (void)willMoveToWindow:(UIWindow *)newWindow { // UIKIt will normally set the scale factor of a view to match the corresponding @@ -193,13 +208,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") // when the size is also changed. if (!CGAffineTransformIsIdentity(self.transform)) - qWarning() << m_qioswindow->window() - << "is backed by a UIView that has a transform set. This is not supported."; + qWarning() << self << "has a transform set. This is not supported."; QWindow *window = m_qioswindow->window(); QRect lastReportedGeometry = qt_window_private(window)->geometry; QRect currentGeometry = QRectF::fromCGRect(self.frame).toRect(); - qCDebug(lcQpaWindow) << m_qioswindow->window() << "new geometry is" << currentGeometry; + qCDebug(lcQpaWindow) << m_qioswindow << "new geometry is" << currentGeometry; QWindowSystemInterface::handleGeometryChange(window, currentGeometry); if (currentGeometry.size() != lastReportedGeometry.size()) { @@ -232,7 +246,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") region = QRect(QPoint(), bounds); } - qCDebug(lcQpaWindow) << m_qioswindow->window() << region << "isExposed" << m_qioswindow->isExposed(); + qCDebug(lcQpaWindow) << m_qioswindow << region << "isExposed" << m_qioswindow->isExposed(); QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region); } @@ -256,16 +270,14 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") // blocked by this guard. FirstResponderCandidate firstResponderCandidate(self); - qImDebug() << "win:" << m_qioswindow->window() << "self:" << self - << "first:" << [UIResponder currentFirstResponder]; + qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder]; if (![super becomeFirstResponder]) { - qImDebug() << m_qioswindow->window() - << "was not allowed to become first responder"; + qImDebug() << self << "was not allowed to become first responder"; return NO; } - qImDebug() << m_qioswindow->window() << "became first responder"; + qImDebug() << self << "became first responder"; } if (qGuiApp->focusWindow() != m_qioswindow->window()) @@ -297,13 +309,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") - (BOOL)resignFirstResponder { - qImDebug() << "win:" << m_qioswindow->window() << "self:" << self - << "first:" << [UIResponder currentFirstResponder]; + qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder]; if (![super resignFirstResponder]) return NO; - qImDebug() << m_qioswindow->window() << "resigned first responder"; + qImDebug() << self << "resigned first responder"; UIResponder *newResponder = FirstResponderCandidate::currentCandidate(); if ([self responderShouldTriggerWindowDeactivation:newResponder]) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index c146f8ec25..3d0dbd7b1a 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -980,8 +980,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::QuerySizeHints: d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam)); return true; - case QtWindows::ResizeEvent: - d->m_creationContext->obtainedGeometry.setSize(QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); + case QtWindows::ResizeEvent: { + const QSize size(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) - d->m_creationContext->menuHeight); + d->m_creationContext->obtainedGeometry.setSize(size); + } return true; case QtWindows::MoveEvent: d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 038ee5cd62..159e1250d0 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1034,8 +1034,10 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const QMargins effectiveMargins = margins + customMargins; frameWidth = effectiveMargins.left() + geometry.width() + effectiveMargins.right(); frameHeight = effectiveMargins.top() + geometry.height() + effectiveMargins.bottom(); - if (QWindowsMenuBar::menuBarOf(w) != nullptr) - frameHeight += GetSystemMetrics(SM_CYMENU); + if (QWindowsMenuBar::menuBarOf(w) != nullptr) { + menuHeight = GetSystemMetrics(SM_CYMENU); + frameHeight += menuHeight; + } const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel(); if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) { frameX -= effectiveMargins.left(); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 3732255738..8d29b871bf 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -101,6 +101,7 @@ struct QWindowCreationContext int frameY = CW_USEDEFAULT; int frameWidth = CW_USEDEFAULT; int frameHeight = CW_USEDEFAULT; + int menuHeight = 0; }; struct QWindowsWindowData |