src/gui/kernel/qwidget_mac.mm
changeset 30 5dc02b23752f
parent 19 fcece45ef507
child 33 3e2da88830cd
--- a/src/gui/kernel/qwidget_mac.mm	Wed Jun 23 19:07:03 2010 +0300
+++ b/src/gui/kernel/qwidget_mac.mm	Tue Jul 06 15:10:48 2010 +0300
@@ -460,7 +460,13 @@
 
 bool qt_isGenuineQWidget(const QWidget *window)
 {
-    return window && qt_isGenuineQWidget(OSViewRef(window->winId()));
+    if (!window)
+        return false;
+
+    if (!window->internalWinId())
+        return true;  //alien
+
+    return qt_isGenuineQWidget(OSViewRef(window->internalWinId()));
 }
 
 Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget *w)
@@ -1912,13 +1918,15 @@
         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;
 
@@ -2022,8 +2030,6 @@
         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)
@@ -2218,6 +2224,41 @@
     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);
@@ -2259,6 +2300,12 @@
         if (q->testAttribute(Qt::WA_DropSiteRegistered))
             registerDropSite(true);
         transferChildren();
+
+        // Tell Cocoa explicit that we wan't the view to receive key events
+        // (regardless of focus policy) because this is how it works on other
+        // platforms (and in the carbon port):
+        if (!qApp->focusWidget())
+            [windowRef makeFirstResponder:nsview];
     }
 
     if (topExtra->posFromMove) {
@@ -2290,6 +2337,10 @@
         q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
     }
 
+    if (qApp->overrideCursor())
+        [windowRef disableCursorRects];
+
+    setWindowLevel();
     macUpdateHideOnSuspend();
     macUpdateOpaqueSizeGrip();
     macUpdateIgnoreMouseEvents();
@@ -2564,7 +2615,16 @@
         }
     } else {
         data.fstrut_dirty = false; // non-toplevel widgets don't have a frame, so no need to update the strut
-        if(OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) {
+
+#ifdef QT_MAC_USE_COCOA
+        if (q->testAttribute(Qt::WA_NativeWindow) == false ||
+            q->internalWinId() != 0) {
+#ifdef ALIEN_DEBUG
+            qDebug() << "Skipping native widget creation for" << this;
+#endif
+        } else
+#endif
+        if (OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) {
 #ifndef QT_MAC_USE_COCOA
             HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height());
             HIViewSetFrame(osview, &bounds);
@@ -2720,6 +2780,35 @@
     }
 }
 
+#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);
@@ -2780,13 +2869,14 @@
 
     //recreate and setup flags
     QObjectPrivate::setParent_helper(parent);
-    QPoint pt = q->pos();
     bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
     if (wasCreated && !qt_isGenuineQWidget(q))
         return;
 
-    if ((data.window_flags & Qt::Sheet) && topData && topData->opacity == 242)
+    if (!q->testAttribute(Qt::WA_WState_WindowOpacitySet)) {
         q->setWindowOpacity(1.0f);
+        q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
+    }
 
     setWinId(0); //do after the above because they may want the id
 
@@ -2795,9 +2885,12 @@
     q->setAttribute(Qt::WA_WState_Visible, false);
     q->setAttribute(Qt::WA_WState_Hidden, false);
     adjustFlags(data.window_flags, q);
-    // keep compatibility with previous versions, we need to preserve the created state
-    // (but we recreate the winId for the widget being reparented, again for compatibility)
-    if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created))) {
+    // keep compatibility with previous versions, we need to preserve the created state.
+    // (but we recreate the winId for the widget being reparented, again for compatibility,
+    // unless this is an alien widget. )
+    const bool nonWindowWithCreatedParent = !q->isWindow() && parent->testAttribute(Qt::WA_WState_Created);
+    const bool nativeWidget = q->internalWinId() != 0;
+    if (wasCreated || nativeWidget && nonWindowWithCreatedParent) {
         createWinId();
         if (q->isWindow()) {
 #ifndef QT_MAC_USE_COCOA
@@ -2874,7 +2967,6 @@
             current = current->parentWidget();
         }
     }
-
     invalidateBuffer(q->rect());
     qt_event_request_window_change(q);
 }
@@ -2882,7 +2974,7 @@
 QPoint QWidget::mapToGlobal(const QPoint &pos) const
 {
     Q_D(const QWidget);
-    if (!testAttribute(Qt::WA_WState_Created)) {
+    if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
         QPoint p = pos + data->crect.topLeft();
         return isWindow() ?  p : parentWidget()->mapToGlobal(p);
     }
@@ -2909,7 +3001,7 @@
 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
 {
     Q_D(const QWidget);
-    if (!testAttribute(Qt::WA_WState_Created)) {
+    if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
         QPoint p = isWindow() ?  pos : parentWidget()->mapFromGlobal(pos);
         return p - data->crect.topLeft();
     }
@@ -3180,10 +3272,10 @@
             || windowActive) {
 #ifndef QT_MAC_USE_COCOA
         ActivateWindow(win, true);
+        qApp->setActiveWindow(tlw);
 #else
         [win makeKeyWindow];
 #endif
-        qApp->setActiveWindow(tlw);
     } else if(!isMinimized()) {
 #ifndef QT_MAC_USE_COCOA
         SelectWindow(win);
@@ -3208,7 +3300,7 @@
 #ifndef QT_MAC_USE_COCOA
             HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true);
 #else
-            [qt_mac_nativeview_for(q) setNeedsDisplay:YES];
+	    qt_mac_set_needs_display(q, QRegion());
 #endif
         return;
     }
@@ -3246,11 +3338,24 @@
         HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow.
     }
 #else
-    // Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect.
-    const QRect &boundingRect = rgn.boundingRect();
-    [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(boundingRect.x(),
-                                                            boundingRect.y(), boundingRect.width(),
-                                                            boundingRect.height())];
+    // Alien support: get the first native ancestor widget (will be q itself in the non-alien case),
+    // map the coordinates from q space to NSView space and invalidate the rect.
+    QWidget *nativeParent = q->internalWinId() ? q : q->nativeParentWidget();
+    if (nativeParent == 0)
+	return;
+
+    QVector<QRect> rects = rgn.rects();
+    for (int i = 0; i < rects.count(); ++i) {
+        const QRect &rect = rects.at(i);
+
+	const QRect nativeBoundingRect = QRect(
+		QPoint(q->mapTo(nativeParent, rect.topLeft())),
+		QSize(rect.size()));
+
+	[qt_mac_nativeview_for(nativeParent) setNeedsDisplayInRect:NSMakeRect(nativeBoundingRect.x(),
+		nativeBoundingRect.y(), nativeBoundingRect.width(),
+		nativeBoundingRect.height())];
+    }
 #endif
 }
 
@@ -3274,38 +3379,20 @@
         return;
 
     bool realWindow = isRealWindow();
+#ifndef QT_MAC_USE_COCOA
     if (realWindow && !q->testAttribute(Qt::WA_Moved)) {
+        if (qt_mac_is_macsheet(q))
+            recreateMacWindow();
         q->createWinId();
         if (QWidget *p = q->parentWidget()) {
             p->createWinId();
-#ifndef QT_MAC_USE_COCOA
             RepositionWindow(qt_mac_window_for(q), qt_mac_window_for(p), kWindowCenterOnParentWindow);
-#else
-            CGRect parentFrame = NSRectToCGRect([qt_mac_window_for(p) frame]);
-            OSWindowRef windowRef = qt_mac_window_for(q);
-            NSRect windowFrame = [windowRef frame];
-            NSPoint parentCenter = NSMakePoint(CGRectGetMidX(parentFrame), CGRectGetMidY(parentFrame));
-            [windowRef setFrameTopLeftPoint:NSMakePoint(parentCenter.x - (windowFrame.size.width / 2),
-                                                        (parentCenter.y + (windowFrame.size.height / 2)))];
-#endif
         } else {
-#ifndef QT_MAC_USE_COCOA
             RepositionWindow(qt_mac_window_for(q), 0, kWindowCenterOnMainScreen);
-#else
-            // Ideally we would do a "center" here, but NSWindow's center is more equivalent to
-            // kWindowAlertPositionOnMainScreen instead of kWindowCenterOnMainScreen.
-            QRect availGeo = QApplication::desktop()->availableGeometry(q);
-            // Center the content only.
-            data.crect.moveCenter(availGeo.center());
-            QRect fStrut = frameStrut();
-            QRect frameRect(data.crect.x() - fStrut.left(), data.crect.y() - fStrut.top(),
-                            fStrut.left() + fStrut.right() + data.crect.width(),
-                            fStrut.top() + fStrut.bottom() + data.crect.height());
-            NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), frameRect.width(), frameRect.height());
-            [qt_mac_window_for(q) setFrame:cocoaFrameRect display:NO];
-#endif
         }
     }
+#endif
+
     data.fstrut_dirty = true;
     if (realWindow) {
          // Delegates can change window state, so record some things earlier.
@@ -3336,13 +3423,25 @@
 #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 (!top->testAttribute(Qt::WA_DontShowOnScreen)) {
+                    if (NSWindow *modalWin = qt_mac_window_for(top))
+                        [modalWin orderFront:window];
+                }
+            }
 #endif
             if (q->windowType() == Qt::Popup) {
 			    if (q->focusWidget())
@@ -3361,8 +3460,6 @@
         } 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()) {
@@ -3404,6 +3501,9 @@
         return;
     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
@@ -3469,12 +3569,15 @@
             }
 #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)))
@@ -3494,24 +3597,12 @@
                             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
@@ -3733,9 +3824,35 @@
 #if QT_MAC_USE_COCOA
     QMacCocoaAutoReleasePool pool;
     if (isRealWindow()) {
-        // Calling orderFront shows the window on Cocoa too.
+        // With the introduction of spaces it is not as simple as just raising the window.
+        // First we need to check if we are in the right space. If we are, then we just continue
+        // as usual. The problem comes when we are not in the active space. There are two main cases:
+        // 1. Our parent was moved to a new space. In this case we want the window to be raised
+        // in the same space as its parent.
+        // 2. We don't have a parent. For this case we will just raise the window and let Cocoa
+        // switch to the corresponding space.
+        // NOTICE: There are a lot of corner cases here. We are keeping this simple for now, if
+        // required we will introduce special handling for some of them.
         if (!q->testAttribute(Qt::WA_DontShowOnScreen) && q->isVisible()) {
-            [qt_mac_window_for(q) orderFront:qt_mac_window_for(q)];
+            OSWindowRef window = qt_mac_window_for(q);
+            // isOnActiveSpace is available only from 10.6 onwards, so we need to check if it is
+            // available before calling it.
+            if([window respondsToSelector:@selector(isOnActiveSpace)]) {
+                if(![window performSelector:@selector(isOnActiveSpace)]) {
+                    QWidget *parentWidget = q->parentWidget();
+                    if(parentWidget) {
+                        OSWindowRef parentWindow = qt_mac_window_for(parentWidget);
+                        if(parentWindow && [parentWindow isOnActiveSpace]) {
+                            // The window was created in a different space. Therefore if we want
+                            // to show it in the current space we need to recreate it in the new
+                            // space.
+                            recreateMacWindow();
+                            window = qt_mac_window_for(q);
+                        }
+                    }
+                }
+            }
+            [window orderFront:window];
         }
         if (qt_mac_raise_process) { //we get to be the active process now
             ProcessSerialNumber psn;
@@ -3848,7 +3965,7 @@
     widget, either by scrolling its contents or repainting, depending on the WA_StaticContents
     flag
 */
-static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newRect)
+static void qt_mac_update_widget_position(QWidget *q, QRect oldRect, QRect newRect)
 {
 #ifndef QT_MAC_USE_COCOA
     HIRect bounds = CGRectMake(newRect.x(), newRect.y(),
@@ -3945,7 +4062,7 @@
 #else
     Q_UNUSED(oldRect);
     NSRect bounds = NSMakeRect(newRect.x(), newRect.y(),
-                               newRect.width(), newRect.height());
+	    newRect.width(), newRect.height());
     [qt_mac_nativeview_for(q) setFrame:bounds];
 #endif
 }
@@ -3982,7 +4099,8 @@
     QRect xrect = data.crect;
 
     QRect parentWRect;
-    if (q->isWindow() && topData()->embedded) {
+    bool isEmbeddedWindow = (q->isWindow() && topData()->embedded);
+    if (isEmbeddedWindow) {
 #ifndef QT_MAC_USE_COCOA
         HIViewRef parentView = HIViewGetSuperview(qt_mac_nativeview_for(q));
 #else
@@ -4007,7 +4125,7 @@
 
     if (parentWRect.isValid()) {
         // parent is clipped, and we have to clip to the same limit as parent
-        if (!parentWRect.contains(xrect)) {
+        if (!parentWRect.contains(xrect) && !isEmbeddedWindow) {
             xrect &= parentWRect;
             wrect = xrect;
             //translate from parent's to my Qt coord sys
@@ -4109,7 +4227,7 @@
         }
     }
 
-    qt_mac_update_widget_posisiton(q, oldRect, xrect);
+    qt_mac_update_widget_position(q, oldRect, xrect);
 
     if  (jump)
         q->update();
@@ -4181,6 +4299,7 @@
 
     QMacCocoaAutoReleasePool pool;
     bool realWindow = isRealWindow();
+    BOOL needDisplay = realWindow ? YES : NO;
 
     if (realWindow && !q->testAttribute(Qt::WA_DontShowOnScreen)){
         adjustWithinMaxAndMinSize(w, h);
@@ -4195,6 +4314,22 @@
             setGeometry_sys_helper(x, y, w, h, isMove);
         }
 #else
+        if (!isMove && !q->testAttribute(Qt::WA_Moved) && !q->isVisible()) {
+            // INVARIANT: The location of the window has not yet been set. The default will
+            // instead be to center it on the desktop, or over the parent, if any. Since we now
+            // resize the window, we need to adjust the top left position to keep the window
+            // centeralized. And we need to to this now (and before show) in case the positioning
+            // of other windows (e.g. sub-windows) depend on this position:
+            if (QWidget *p = q->parentWidget()) {
+                x = p->geometry().center().x() - (w / 2);
+                y = p->geometry().center().y() - (h / 2);
+            } else {
+                QRect availGeo = QApplication::desktop()->availableGeometry(q);
+                x = availGeo.center().x() - (w / 2);
+                y = availGeo.center().y() - (h / 2);
+            }
+        }
+
         QSize  olds = q->size();
         const bool isResize = (olds != QSize(w, h));
         NSWindow *window = qt_mac_window_for(q);
@@ -4212,7 +4347,7 @@
         if (currTopLeft.x() == x && currTopLeft.y() == y
                 && cocoaFrameRect.size.width != 0
                 && cocoaFrameRect.size.height != 0) {
-            [window setFrame:cocoaFrameRect display:NO];
+            [window setFrame:cocoaFrameRect display:needDisplay];
         } else {
             // The window is moved and resized (or resized to zero).
             // Since Cocoa usually only sends us a resize callback after
@@ -4221,7 +4356,7 @@
             // would have the same origin as the setFrame call) we shift the
             // window back and forth inbetween.
             cocoaFrameRect.origin.y += 1;
-            [window setFrame:cocoaFrameRect display:NO];
+            [window setFrame:cocoaFrameRect display:needDisplay];
             cocoaFrameRect.origin.y -= 1;
             [window setFrameOrigin:cocoaFrameRect.origin];
         }
@@ -4611,9 +4746,12 @@
 #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
 }
@@ -4729,7 +4867,7 @@
         [window setOpaque:(extra->imageMask == 0)];
         [window invalidateShadow];
     }
-    [qt_mac_nativeview_for(q) setNeedsDisplay:YES];
+    qt_mac_set_needs_display(q, QRegion());
 }
 #endif
 
@@ -4769,7 +4907,7 @@
     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();
@@ -4786,47 +4924,19 @@
                 [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];
         }
     }