Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37740013
en ru br
Репозитории ALT
S:4.8.7-alt25
5.1: 4.6.3-alt1.M51.1
4.1: 4.4.3-alt1.M41.1
4.0: 4.3.4-alt5.M40.1
3.0: 4.0.1-alt1
+updates:4.0.1-alt2
+backports:4.2.3-alt7.1.M30
www.altlinux.org/Changes

Группа :: Система/Библиотеки
Пакет: qt4

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: 0181-qdnd-x11-fix.diff
Скачать


qt-bugs@ issue : 166518
Trolltech task ID : 167509
bugs.kde.org number :
applied: no
author: Matthias Kretz <kretz@kde.org>
os: unix
Consider:
QWidget toplevel;
QWidget dropWidget(&toplevel);
dropWidget.setAcceptDrops(true);
QWidget visibleFooWidget(&toplevel);
find_child in qdnd_x11.cpp will find visibleFooWidget because it's the last
entry in toplevel.children() and the QPoint of the drop is contained in it.
But since it does not acceptDrops() handle_xdnd_position will now look at the
parent widget which is toplevel. That one isWindow() so the iteration stops
and no QDragEnterEvent will be sent.
But it never even looked at dropWidget even though it also contains the QPoint
of the drop!
This patch makes the algorithm look at _all_ widgets that contain the QPoint.
This bug effectively breaks all drops on QAbstractScrollArea subclasses with
the KDE4 Oxygen widget style.
Index: src/gui/kernel/qdnd_x11.cpp
===================================================================
--- src/gui/kernel/qdnd_x11.cpp	(revision 671753)
+++ src/gui/kernel/qdnd_x11.cpp	(working copy)
@@ -58,6 +58,7 @@
 #include "qimagewriter.h"
 #include "qbuffer.h"
 #include "qtextcodec.h"
+#include "qstack.h"
 
 #include "qdnd_p.h"
 #include "qt_x11_p.h"
@@ -715,7 +716,44 @@ void qt_xdnd_cleanup()
 }
 
 
-static QWidget *find_child(QWidget *tlw, QPoint & p)
+static QWidget *find_next_child(QWidget *child, QPoint &p, QStack<int> &chosenLine)
+{
+    p = child->mapToParent(p);
+    QWidget *widget = child->parentWidget();
+    if (!widget) {
+        return widget;
+    }
+
+    bool done = false;
+    bool backwards = true;
+    while (!done) {
+        done = true;
+        if (((QExtraWidget*)widget)->extraData() &&
+             ((QExtraWidget*)widget)->extraData()->xDndProxy != 0)
+            break; // stop searching for widgets under the mouse cursor if found widget is a proxy.
+        QObjectList children = widget->children();
+        if (!chosenLine.isEmpty() && !children.isEmpty()) {
+            for(int i = backwards ? chosenLine.pop() : children.size(); i > 0;) {
+                --i;
+                QWidget *w = qobject_cast<QWidget *>(children.at(i));
+                if (!w)
+                    continue;
+                if (w->isVisible() &&
+                     w->geometry().contains(p) &&
+                     !w->isWindow()) {
+                    widget = w;
+                    done = false;
+                    backwards = false;
+                    p = widget->mapFromParent(p);
+                    chosenLine << i;
+                    break;
+                }
+            }
+        }
+    }
+    return widget;
+}
+static QWidget *find_child(QWidget *tlw, QPoint & p, QStack<int> &chosenLine)
 {
     QWidget *widget = tlw;
 
@@ -739,6 +777,7 @@ static QWidget *find_child(QWidget *tlw,
                     widget = w;
                     done = false;
                     p = widget->mapFromParent(p);
+                    chosenLine.push(i);
                     break;
                 }
             }
@@ -827,7 +866,8 @@ static void handle_xdnd_position(QWidget
     const unsigned long *l = (const unsigned long *)xe->xclient.data.l;
 
     QPoint p((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff);
-    QWidget * c = find_child(w, p); // changes p to to c-local coordinates
+    QStack<int> chosenLine;
+    QWidget * c = find_child(w, p, chosenLine); // changes p to to c-local coordinates
 
     if (!passive && checkEmbedded(c, xe))
         return;
@@ -861,8 +901,7 @@ static void handle_xdnd_position(QWidget
 
     if (!passive) { // otherwise just reject
         while (c && !c->acceptDrops() && !c->isWindow()) {
-            p = c->mapToParent(p);
-            c = c->parentWidget();
+            c = find_next_child(c, p, chosenLine);
         }
         QWidget *target_widget = c && c->acceptDrops() ? c : 0;
 
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin