Репозитории 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 |
Группа :: Система/Библиотеки
Пакет: 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;