Sophie

Sophie

distrib > Mandriva > 2008.1 > x86_64 > by-pkgid > c6df48aa6f24f13ac83670ff4f6d6ea9 > files > 5

qt4-4.3.4-6mdv2008.1.src.rpm

qt-bugs@ issue : none yet
Trolltech task ID : none
bugs.kde.org number : none
applied: no
author: Lubos Lunak <l.lunak@kde.org>

This patch adds Qt support for new window types used for compositing.


--- src/gui/kernel/qwidget.h
+++ src/gui/kernel/qwidget.h
@@ -352,6 +352,19 @@ public:
 
     void setWindowOpacity(qreal level);
     qreal windowOpacity() const;
+#if defined(Q_WS_X11)
+    enum X11WindowType {
+        X11WindowTypeSelect,
+        X11WindowTypeCombo,
+        X11WindowTypeDND,
+        X11WindowTypeTooltip,
+        X11WindowTypeMenu, // torn-off
+        X11WindowTypeDropdown,
+        X11WindowTypePopup
+    };
+    void x11SetWindowType( X11WindowType type = X11WindowTypeSelect );
+    void x11SetWindowTransient( QWidget* parent );
+#endif
 
     bool isWindowModified() const;
 #ifndef QT_NO_TOOLTIP
--- src/gui/kernel/qdnd_x11.cpp
+++ src/gui/kernel/qdnd_x11.cpp
@@ -268,6 +268,7 @@ public:
         QWidget(QApplication::desktop()->screen(screen),
                 Qt::Tool | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint)
     {
+    x11SetWindowType( X11WindowTypeDND );
     }
 
     void setPixmap(const QPixmap &pm)
@@ -1436,6 +1437,7 @@ void QDragManager::move(const QPoint & g
         // recreate the pixmap on the new screen...
         delete xdnd_data.deco;
         xdnd_data.deco = new QShapedPixmapWidget(screen);
+        xdnd_data.deco->x11SetWindowTransient( object->source()->topLevelWidget());
         if (!QWidget::mouseGrabber()) {
             updatePixmap();
             xdnd_data.deco->grabMouse();
@@ -1897,6 +1899,7 @@ Qt::DropAction QDragManager::drag(QDrag 
     object = o;
     object->d_func()->target = 0;
     xdnd_data.deco = new QShapedPixmapWidget();
+    xdnd_data.deco->x11SetWindowTransient( object->source()->topLevelWidget());
 
     willDrop = false;
 
--- src/gui/kernel/qt_x11_p.h
+++ src/gui/kernel/qt_x11_p.h
@@ -528,6 +528,11 @@ struct QX11Data
         _NET_WM_WINDOW_TYPE_SPLASH,
         _NET_WM_WINDOW_TYPE_TOOLBAR,
         _NET_WM_WINDOW_TYPE_UTILITY,
+        _NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
+        _NET_WM_WINDOW_TYPE_POPUP_MENU,
+        _NET_WM_WINDOW_TYPE_COMBO,
+        _NET_WM_WINDOW_TYPE_DND,
+        _NET_WM_WINDOW_TYPE_TOOLTIP,
 
         _KDE_NET_WM_FRAME_STRUT,
 
--- src/gui/kernel/qtooltip.cpp
+++ src/gui/kernel/qtooltip.cpp
@@ -147,6 +147,9 @@ QTipLabel::QTipLabel(const QPoint &pos, 
     setMouseTracking(true);
     fadingOut = false;
     reuseTip(text);
+#ifdef Q_WS_X11
+    x11SetWindowType( X11WindowTypeTooltip );
+#endif
 }
 
 void QTipLabel::restartHideTimer()
@@ -367,6 +370,10 @@ void QToolTip::showText(const QPoint &po
             // that is showing (removes flickering)
             if (QTipLabel::instance->tipChanged(pos, text, w)){
                 QTipLabel::instance->reuseTip(text);
+#ifdef Q_WS_X11
+                if (w)
+                    QTipLabel::instance->x11SetWindowTransient( w->topLevelWidget());
+#endif
                 QTipLabel::instance->setTipRect(w, rect);
                 QTipLabel::instance->placeTip(pos, w);
             }
@@ -376,6 +383,10 @@ void QToolTip::showText(const QPoint &po
 
     if (!text.isEmpty()){ // no tip can be reused, create new tip:
         new QTipLabel(pos, text, w); // sets QTipLabel::instance to itself
+#ifdef Q_WS_X11
+        if (w)
+            QTipLabel::instance->x11SetWindowTransient( w->topLevelWidget());
+#endif
         QTipLabel::instance->setTipRect(w, rect);
         QTipLabel::instance->placeTip(pos, w);
         QTipLabel::instance->setObjectName(QLatin1String("qtooltip_label"));
--- src/gui/kernel/qapplication_x11.cpp
+++ src/gui/kernel/qapplication_x11.cpp
@@ -212,6 +212,11 @@ static const char * x11_atomnames = {
     "_NET_WM_WINDOW_TYPE_SPLASH\0"
     "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
     "_NET_WM_WINDOW_TYPE_UTILITY\0"
+    "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
+    "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
+    "_NET_WM_WINDOW_TYPE_COMBO\0"
+    "_NET_WM_WINDOW_TYPE_DND\0"
+    "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
 
     "_KDE_NET_WM_FRAME_STRUT\0"
 
--- src/gui/kernel/qwidget_x11.cpp
+++ src/gui/kernel/qwidget_x11.cpp
@@ -560,10 +560,6 @@ void QWidgetPrivate::create_sys(WId wind
     }
 #endif // QT_NO_XRENDER
 
-    // NET window types
-    long net_wintypes[7] = { 0, 0, 0, 0, 0, 0, 0 };
-    int curr_wintype = 0;
-
     QtMWMHints mwmhints;
     mwmhints.flags = 0L;
     mwmhints.functions = MWM_FUNC_ALL;
@@ -574,15 +570,11 @@ void QWidgetPrivate::create_sys(WId wind
     if (topLevel) {
         ulong wsa_mask = 0;
         if (type == Qt::SplashScreen) {
-            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
         } else { //       if (customize) {
             mwmhints.decorations = 0L;
             mwmhints.flags |= MWM_HINTS_DECORATIONS;
 
-            if (flags & Qt::FramelessWindowHint) {
-                // override netwm type - quick and easy for KDE noborder
-                net_wintypes[curr_wintype++] = ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE);
-            } else {
+            if ((flags & Qt::FramelessWindowHint) == 0 ) {
                 mwmhints.decorations |= MWM_DECOR_BORDER;
                 mwmhints.decorations |= MWM_DECOR_RESIZEH;
 
@@ -604,22 +596,6 @@ void QWidgetPrivate::create_sys(WId wind
             wsa.save_under = True;
             wsa_mask |= CWSaveUnder;
         }
-        // ### need a better way to do this
-        if (q->inherits("QMenu")) {
-            // menu netwm type
-            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_MENU);
-        } else if (q->inherits("QToolBar")) {
-            // toolbar netwm type
-            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
-        } else if (type == Qt::Tool || type == Qt::Drawer) {
-            // utility netwm type
-            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
-        }
-
-        if (dialog) // dialog netwm type
-            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
-        // normal netwm type - default
-        net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
 
         if (flags & Qt::X11BypassWindowManagerHint) {
             wsa.override_redirect = True;
@@ -638,6 +614,7 @@ void QWidgetPrivate::create_sys(WId wind
         wsa.save_under = True;
         XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
                                 &wsa);
+        q->x11SetWindowType();
     } else if (topLevel && !desktop) {        // top-level widget
         if (!X11->wm_client_leader)
             create_wm_client_leader();
@@ -682,12 +659,7 @@ void QWidgetPrivate::create_sys(WId wind
         // set mwm hints
         SetMWMHints(dpy, id, mwmhints);
 
-        // set _NET_WM_WINDOW_TYPE
-        if (curr_wintype > 0)
-            XChangeProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32, PropModeReplace,
-                            (unsigned char *) net_wintypes, curr_wintype);
-        else
-            XDeleteProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE));
+        q->x11SetWindowType(); // set _NET_WM_WINDOW_TYPE
 
         // set _NET_WM_PID
         long curr_pid = getpid();
@@ -783,6 +755,63 @@ void QWidgetPrivate::create_sys(WId wind
         q->setAttribute(Qt::WA_OutsideWSRange, true);
 }
 
+// Sets the EWMH (netwm) window type. Needed as a separate function
+// because create() may be too soon in some cases.
+void QWidget::x11SetWindowType( X11WindowType type )
+{
+    Display* dpy = X11->display;
+    // NET window types
+    long net_wintypes[7] = { 0, 0, 0, 0, 0, 0, 0 };
+    int curr_wintype = 0;
+    if( type == X11WindowTypeSelect ) {
+        if ( windowType() == Qt::SplashScreen ) {
+            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
+        } else if (inherits("QToolBar")) {
+	    // toolbar netwm type
+	    net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
+        } else if (windowType() == Qt::Tool || windowType() == Qt::Drawer) {
+	    // utility netwm type
+	    net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
+        } else if (windowType() == Qt::Dialog || windowType() == Qt::Sheet
+            || (windowFlags() & Qt::MSWindowsFixedSizeDialogHint)) {
+            // dialog netwm type
+            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
+        }
+    } else if( type == X11WindowTypeCombo ) {
+        // combo netwm type
+	net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_COMBO);
+    } else if( type == X11WindowTypeDND ) {
+        // dnd netwm type
+    	net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_DND);
+    } else if( type == X11WindowTypeDropdown ) {
+        // dropdown netwm type
+    	net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU);
+    } else if( type == X11WindowTypePopup ) {
+        // popup netwm type
+    	net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU);
+    } else if( type == X11WindowTypeMenu ) {
+        // menu netwm type
+	net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_MENU);
+    } else if( type == X11WindowTypeTooltip ) {
+        // tooltip netwm type
+    	net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP);
+    }
+
+    // normal netwm type - default
+    net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
+    // set _NET_WM_WINDOW_TYPE
+    if (curr_wintype > 0)
+        XChangeProperty(dpy, winId(), ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32, PropModeReplace,
+			(unsigned char *) net_wintypes, curr_wintype);
+    else
+        XDeleteProperty(dpy, winId(), ATOM(_NET_WM_WINDOW_TYPE));
+}
+
+void QWidget::x11SetWindowTransient( QWidget* parent )
+{
+    XSetTransientForHint( X11->display, winId(), parent->window()->winId());
+}
+
 /*!
     Frees up window system resources. Destroys the widget window if \a
     destroyWindow is true.
--- src/gui/widgets/qcombobox.cpp
+++ src/gui/widgets/qcombobox.cpp
@@ -332,6 +332,10 @@ void QComboBoxPrivateContainer::timerEve
             combo->update();
         }
     }
+#ifdef Q_WS_X11
+    x11SetWindowType( X11WindowTypeCombo );
+    x11SetWindowTransient( combo->topLevelWidget());
+#endif
 }
 
 void QComboBoxPrivateContainer::resizeEvent(QResizeEvent *e)
--- src/gui/widgets/qmenu.cpp
+++ src/gui/widgets/qmenu.cpp
@@ -97,6 +97,9 @@ public:
     QTornOffMenu(QMenu *p) : QMenu(*(new QTornOffMenuPrivate(p)))
     {
         setParent(p, Qt::Window | Qt::Tool);
+#ifdef Q_WS_X11
+        x11SetWindowType( X11WindowTypeMenu );
+#endif
 	setAttribute(Qt::WA_DeleteOnClose, true);
         setWindowTitle(p->windowTitle());
         setEnabled(p->isEnabled());
@@ -143,6 +146,9 @@ void QMenuPrivate::init()
     }
     defaultMenuAction = menuAction = new QAction(q);
     menuAction->d_func()->menu = q;
+#ifdef Q_WS_X11
+    q->x11SetWindowType( QWidget::X11WindowTypePopup );
+#endif
 }
 
 //Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't
@@ -1678,6 +1684,33 @@ void QMenu::popup(const QPoint &p, QActi
         }
     }
     setGeometry(QRect(pos, size));
+
+#ifdef Q_WS_X11
+    QWidget* top = this;
+    for(;;) {
+        if( QMenu* m = qobject_cast< QMenu* >( top )) {
+            if( m->d_func()->causedPopup.widget == NULL )
+                break; // --->
+            top = m->d_func()->causedPopup.widget;
+        } else
+            break; // -->
+    }
+    if( QMenu* m = qobject_cast< QMenu* >( top ))
+        x11SetWindowType( X11WindowTypePopup );
+    else
+        x11SetWindowType( X11WindowTypeDropdown );
+    // hackish ... try to find the main window related to this popup
+    QWidget* parent = d_func()->causedPopup.widget;
+    if( parent == NULL )
+        parent = parentWidget() ? parentWidget()->topLevelWidget() : NULL;
+    if( parent == NULL )
+        parent = QApplication::widgetAt( pos );
+    if( parent == NULL )
+        parent = qApp->activeWindow();
+    if( parent != NULL )
+        x11SetWindowTransient( parent );
+#endif
+
 #ifndef QT_NO_EFFECTS
     int hGuess = qApp->layoutDirection() == Qt::RightToLeft ? QEffects::LeftScroll : QEffects::RightScroll;
     int vGuess = QEffects::DownScroll;
@@ -1874,6 +1907,9 @@ void QMenu::hideEvent(QHideEvent *)
     if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget))
         mb->d_func()->setCurrentAction(0);
 #endif
+#ifdef Q_WS_X11
+    x11SetWindowType( X11WindowTypePopup ); // reset
+#endif
     d->mouseDown = 0;
     d->hasHadMouse = false;
     d->causedPopup.widget = 0;