diff options
Diffstat (limited to 'src/gui/kernel/qwidget_mac.mm')
-rw-r--r-- | src/gui/kernel/qwidget_mac.mm | 180 |
1 files changed, 113 insertions, 67 deletions
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 3dbc843..3ff46f5 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -1898,13 +1898,15 @@ void QWidgetPrivate::determineWindowClass() wclass = kDocumentWindowClass; else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen)) wclass = kModalWindowClass; - else if(q->testAttribute(Qt::WA_ShowModal) || type == Qt::Dialog) + else if(type == Qt::Dialog) wclass = kMovableModalWindowClass; else if(type == Qt::ToolTip) wclass = kHelpWindowClass; else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 && type == Qt::SplashScreen)) wclass = kFloatingWindowClass; + else if(q->testAttribute(Qt::WA_ShowModal)) + wclass = kMovableModalWindowClass; else wclass = kDocumentWindowClass; @@ -2008,8 +2010,6 @@ void QWidgetPrivate::determineWindowClass() for(int i = 0; tmp_wattr && known_attribs[i].name; i++) { if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) { tmp_wattr ^= known_attribs[i].tag; - qDebug("Qt: internal: * %s %s", known_attribs[i].name, - (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)"); } } if(tmp_wattr) @@ -2204,6 +2204,41 @@ void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef) applyMaxAndMinSizeOnWindow(); } #else // QT_MAC_USE_COCOA + +void QWidgetPrivate::setWindowLevel() +{ + Q_Q(QWidget); + const QWidget * const windowParent = q->window()->parentWidget(); + const QWidget * const primaryWindow = windowParent ? windowParent->window() : 0; + NSInteger winLevel = -1; + + if (q->windowType() == Qt::Popup) { + winLevel = NSPopUpMenuWindowLevel; + // Popup should be in at least the same level as its parent. + if (primaryWindow) { + OSWindowRef parentRef = qt_mac_window_for(primaryWindow); + winLevel = qMax([parentRef level], winLevel); + } + } else if (q->windowType() == Qt::Tool) { + winLevel = NSFloatingWindowLevel; + } else if (q->windowType() == Qt::Dialog) { + // Correct modality level (NSModalPanelWindowLevel) will be + // set by cocoa when creating a modal session later. + winLevel = NSNormalWindowLevel; + } + + // StayOnTop window should appear above Tool windows. + if (data.window_flags & Qt::WindowStaysOnTopHint) + winLevel = NSPopUpMenuWindowLevel; + // Tooltips should appear above StayOnTop windows. + if (q->windowType() == Qt::ToolTip) + winLevel = NSScreenSaverWindowLevel; + // All other types are Normal level. + if (winLevel == -1) + winLevel = NSNormalWindowLevel; + [qt_mac_window_for(q) setLevel:winLevel]; +} + void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWindowRef) { Q_Q(QWidget); @@ -2276,6 +2311,10 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); } + if (qApp->overrideCursor()) + [windowRef disableCursorRects]; + + setWindowLevel(); macUpdateHideOnSuspend(); macUpdateOpaqueSizeGrip(); macUpdateIgnoreMouseEvents(); @@ -2706,6 +2745,35 @@ void QWidgetPrivate::transferChildren() } } +#ifdef QT_MAC_USE_COCOA +void QWidgetPrivate::setSubWindowStacking(bool set) +{ + Q_Q(QWidget); + if (!q->isWindow() || !q->testAttribute(Qt::WA_WState_Created)) + return; + + if (QWidget *parent = q->parentWidget()) { + if (parent->testAttribute(Qt::WA_WState_Created)) { + if (set) + [qt_mac_window_for(parent) addChildWindow:qt_mac_window_for(q) ordered:NSWindowAbove]; + else + [qt_mac_window_for(parent) removeChildWindow:qt_mac_window_for(q)]; + } + } + + QList<QWidget *> widgets = q->findChildren<QWidget *>(); + for (int i=0; i<widgets.size(); ++i) { + QWidget *child = widgets.at(i); + if (child->isWindow() && child->testAttribute(Qt::WA_WState_Created)) { + if (set) + [qt_mac_window_for(q) addChildWindow:qt_mac_window_for(child) ordered:NSWindowAbove]; + else + [qt_mac_window_for(q) removeChildWindow:qt_mac_window_for(child)]; + } + } +} +#endif + void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) { Q_Q(QWidget); @@ -2860,7 +2928,6 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) current = current->parentWidget(); } } - invalidateBuffer(q->rect()); qt_event_request_window_change(q); } @@ -3322,13 +3389,23 @@ void QWidgetPrivate::show_sys() #else // sync the opacity value back (in case of a fade). [window setAlphaValue:q->windowOpacity()]; - [window makeKeyAndOrderFront:window]; - - // If this window is app modal, we need to start spinning - // a modal session for it. Interrupting - // the event dispatcher will make this happend: - if (data.window_modality == Qt::ApplicationModal) - QEventDispatcherMac::instance()->interrupt(); + setSubWindowStacking(true); + + QWidget *top = 0; + if (QApplicationPrivate::tryModalHelper(q, &top)) { + [window makeKeyAndOrderFront:window]; + // If this window is app modal, we need to start spinning + // a modal session for it. Interrupting + // the event dispatcher will make this happend: + if (data.window_modality == Qt::ApplicationModal) + QEventDispatcherMac::instance()->interrupt(); + } else { + // The window is modally shaddowed, so we need to make + // sure that we don't pop in front of the modal window: + [window orderFront:window]; + if (NSWindow *modalWin = qt_mac_window_for(top)) + [modalWin orderFront:window]; + } #endif if (q->windowType() == Qt::Popup) { if (q->focusWidget()) @@ -3347,8 +3424,6 @@ void QWidgetPrivate::show_sys() } else if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) { #ifndef QT_MAC_USE_COCOA qt_event_request_activate(q); -#else - [qt_mac_window_for(q) makeKeyWindow]; #endif } } else if(topData()->embedded || !q->parentWidget() || q->parentWidget()->isVisible()) { @@ -3391,6 +3466,9 @@ void QWidgetPrivate::hide_sys() QMacCocoaAutoReleasePool pool; if(q->isWindow()) { +#ifdef QT_MAC_USE_COCOA + setSubWindowStacking(false); +#endif OSWindowRef window = qt_mac_window_for(q); if(qt_mac_is_macsheet(q)) { #ifndef QT_MAC_USE_COCOA @@ -3456,12 +3534,15 @@ void QWidgetPrivate::hide_sys() } #endif } - if(q->isActiveWindow() && !(q->windowType() == Qt::Popup)) { +#ifndef QT_MAC_USE_COCOA + // If the window we now hide was the active window, we need + // to find, and activate another window on screen. NB: Cocoa takes care of this + // logic for us (and distinquishes between main windows and key windows) + if (q->isActiveWindow() && !(q->windowType() == Qt::Popup)) { QWidget *w = 0; if(q->parentWidget()) w = q->parentWidget()->window(); if(!w || (!w->isVisible() && !w->isMinimized())) { -#ifndef QT_MAC_USE_COCOA for (WindowPtr wp = GetFrontWindowOfClass(kMovableModalWindowClass, true); wp; wp = GetNextWindowOfClass(wp, kMovableModalWindowClass, true)) { if((w = qt_mac_find_window(wp))) @@ -3481,24 +3562,12 @@ void QWidgetPrivate::hide_sys() break; } } -#else - NSArray *windows = [NSApp windows]; - NSUInteger totalWindows = [windows count]; - for (NSUInteger i = 0; i < totalWindows; ++i) { - OSWindowRef wp = [windows objectAtIndex:i]; - if ((w = qt_mac_find_window(wp))) - break; - } -#endif } if(w && w->isVisible() && !w->isMinimized()) { -#ifndef QT_MAC_USE_COCOA - qt_event_request_activate(w); -#else - [qt_mac_window_for(w) makeKeyWindow]; -#endif + qt_event_request_activate(w); } } +#endif } else { invalidateBuffer(q->rect()); #ifndef QT_MAC_USE_COCOA @@ -3510,6 +3579,8 @@ void QWidgetPrivate::hide_sys() if (!QWidget::mouseGrabber()){ QWidget *enterWidget = QApplication::widgetAt(QCursor::pos()); + if (enterWidget && enterWidget->data->in_destructor) + enterWidget = 0; QApplicationPrivate::dispatchEnterLeave(enterWidget, qt_mouseover); qt_mouseover = enterWidget; } @@ -4584,9 +4655,12 @@ void QWidgetPrivate::registerDropSite(bool on) #ifndef QT_MAC_USE_COCOA SetControlDragTrackingEnabled(qt_mac_nativeview_for(q), on); #else - NSView *view = qt_mac_nativeview_for(q); - if (on && [view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) { - [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) registerDragTypes]; + NSWindow *win = qt_mac_window_for(q); + if (on) { + if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaWindow) class]]) + [static_cast<QT_MANGLE_NAMESPACE(QCocoaWindow) *>(win) registerDragTypes]; + else if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaPanel) class]]) + [static_cast<QT_MANGLE_NAMESPACE(QCocoaPanel) *>(win) registerDragTypes]; } #endif } @@ -4740,7 +4814,7 @@ void QWidgetPrivate::setModal_sys() bool alreadySheet = [windowRef styleMask] & NSDocModalWindowMask; if (windowParent && q->windowModality() == Qt::WindowModal){ - // Window should be window-modal, which implies a sheet. + // INVARIANT: Window should be window-modal (which implies a sheet). if (!alreadySheet) { // NB: the following call will call setModal_sys recursivly: recreateMacWindow(); @@ -4757,47 +4831,19 @@ void QWidgetPrivate::setModal_sys() [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES]; } } else { - // Window shold not be window-modal, and as such, not a sheet. + // INVARIANT: Window shold _not_ be window-modal (and as such, not a sheet). if (alreadySheet){ // NB: the following call will call setModal_sys recursivly: recreateMacWindow(); windowRef = qt_mac_window_for(q); } - if (q->windowModality() == Qt::ApplicationModal) { - [windowRef setLevel:NSModalPanelWindowLevel]; - } else if (primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) { - // INVARIANT: Our window is a dialog that has a dialog parent that is - // application modal, or . This means that q is supposed to be on top of this - // dialog and not be modally shaddowed: - [windowRef setLevel:NSModalPanelWindowLevel]; + if (q->windowModality() == Qt::NonModal + && primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) { + // INVARIANT: Our window has a parent that is application modal. + // This means that q is supposed to be on top of this window and + // not be modally shaddowed: if ([windowRef isKindOfClass:[NSPanel class]]) [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES]; - } else { - // INVARIANT: q should not be modal. - NSInteger winLevel = -1; - if (q->windowType() == Qt::Popup) { - winLevel = NSPopUpMenuWindowLevel; - // Popup should be in at least the same level as its parent. - if (primaryWindow) { - OSWindowRef parentRef = qt_mac_window_for(primaryWindow); - winLevel = qMax([parentRef level], winLevel); - } - } else if (q->windowType() == Qt::Tool) { - winLevel = NSFloatingWindowLevel; - } else if (q->windowType() == Qt::Dialog) { - winLevel = NSModalPanelWindowLevel; - } - - // StayOnTop window should appear above Tool windows. - if (data.window_flags & Qt::WindowStaysOnTopHint) - winLevel = NSPopUpMenuWindowLevel; - // Tooltips should appear above StayOnTop windows. - if (q->windowType() == Qt::ToolTip) - winLevel = NSScreenSaverWindowLevel; - // All other types are Normal level. - if (winLevel == -1) - winLevel = NSNormalWindowLevel; - [windowRef setLevel:winLevel]; } } |