Line 0
Link Here
|
|
|
1 |
From 52e0d9e23c3f7a1b0faf6649cf3dd825bcfd4f08 Mon Sep 17 00:00:00 2001 |
2 |
From: Christian Ehrlicher <ch.ehrlicher@gmx.de> |
3 |
Date: Thu, 3 Jan 2019 20:33:57 +0100 |
4 |
Subject: [PATCH] Drag'n'Drop: fix dnd when dragMoveEvent() is not implemented |
5 |
|
6 |
The refactoring of dnd with f8944a7f07112c85dc4f66848cabb490514cd28e |
7 |
added a regression which results in a need to reimplement |
8 |
dragMoveEvent() on the drop side. Before this change it was possible to |
9 |
accept the dnd in dragEnterEvent() without again accepting it in |
10 |
dragMoveEvent(). |
11 |
Fix it in a similar way it's done in |
12 |
QGuiApplicationPrivate::processDrag() by prefilling the first simulated |
13 |
QDragMoveEvent with the values from the previous QDragEnterEvent before |
14 |
it is sent to the drop receiver. |
15 |
|
16 |
Fixes: QTBUG-72844 |
17 |
Change-Id: I1300dd02b7f1d9dcd44ecefa8335f92ad6c6cafa |
18 |
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io> |
19 |
--- |
20 |
src/widgets/kernel/qwidgetwindow.cpp | 7 ++-- |
21 |
.../qwidget_window/tst_qwidget_window.cpp | 36 ++++++++++++++++--- |
22 |
2 files changed, 37 insertions(+), 6 deletions(-) |
23 |
|
24 |
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp |
25 |
index 279c6c0282..991a05fa02 100644 |
26 |
--- src/widgets/kernel/qwidgetwindow.cpp |
27 |
+++ src/widgets/kernel/qwidgetwindow.cpp |
28 |
@@ -899,10 +899,10 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event) |
29 |
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos())); |
30 |
QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(), |
31 |
event->mouseButtons(), event->keyboardModifiers()); |
32 |
- translated.setDropAction(event->dropAction()); |
33 |
- translated.setAccepted(event->isAccepted()); |
34 |
|
35 |
if (widget == m_dragTarget) { // Target widget unchanged: Send DragMove |
36 |
+ translated.setDropAction(event->dropAction()); |
37 |
+ translated.setAccepted(event->isAccepted()); |
38 |
QGuiApplication::forwardEvent(m_dragTarget, &translated, event); |
39 |
} else { |
40 |
if (m_dragTarget) { // Send DragLeave to previous |
41 |
@@ -912,6 +912,9 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event) |
42 |
} |
43 |
// Send DragEnter to new widget. |
44 |
handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget); |
45 |
+ // Handling 'DragEnter' should suffice for the application. |
46 |
+ translated.setDropAction(event->dropAction()); |
47 |
+ translated.setAccepted(event->isAccepted()); |
48 |
// The drag enter event is always immediately followed by a drag move event, |
49 |
// see QDragEnterEvent documentation. |
50 |
QGuiApplication::forwardEvent(m_dragTarget, &translated, event); |
51 |
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp |
52 |
index f4da4c3e5f..431d6ba960 100644 |
53 |
--- tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp |
54 |
+++ tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp |
55 |
@@ -470,6 +470,10 @@ static const char *expectedLogC[] = { |
56 |
"Event at 11,241 accepted", |
57 |
"acceptingDropsWidget2::dropEvent at 1,51 action=1 MIME_DATA_ADDRESS 'testmimetext'", |
58 |
"Event at 11,261 accepted", |
59 |
+ "acceptingDropsWidget3::dragEnterEvent at 1,21 action=1 MIME_DATA_ADDRESS 'testmimetext'", |
60 |
+ "Event at 11,281 accepted", |
61 |
+ "acceptingDropsWidget3::dragLeaveEvent QDragLeaveEvent", |
62 |
+ "Event at 11,301 ignored", |
63 |
"acceptingDropsWidget1::dragEnterEvent at 10,10 action=1 MIME_DATA_ADDRESS 'testmimetext'", |
64 |
"Event at 0,0 accepted", |
65 |
"acceptingDropsWidget1::dragMoveEvent at 11,11 action=1 MIME_DATA_ADDRESS 'testmimetext'", |
66 |
@@ -482,8 +486,9 @@ static const char *expectedLogC[] = { |
67 |
class DnDEventLoggerWidget : public QWidget |
68 |
{ |
69 |
public: |
70 |
- DnDEventLoggerWidget(QStringList *log, QWidget *w = 0) : QWidget(w), m_log(log) {} |
71 |
- |
72 |
+ DnDEventLoggerWidget(QStringList *log, QWidget *w = nullptr, bool ignoreDragMove = false) |
73 |
+ : QWidget(w), m_log(log), m_ignoreDragMove(ignoreDragMove) |
74 |
+ {} |
75 |
protected: |
76 |
void dragEnterEvent(QDragEnterEvent *); |
77 |
void dragMoveEvent(QDragMoveEvent *); |
78 |
@@ -493,6 +498,7 @@ protected: |
79 |
private: |
80 |
void formatDropEvent(const char *function, const QDropEvent *e, QTextStream &str) const; |
81 |
QStringList *m_log; |
82 |
+ bool m_ignoreDragMove; |
83 |
}; |
84 |
|
85 |
void DnDEventLoggerWidget::formatDropEvent(const char *function, const QDropEvent *e, QTextStream &str) const |
86 |
@@ -513,6 +519,8 @@ void DnDEventLoggerWidget::dragEnterEvent(QDragEnterEvent *e) |
87 |
|
88 |
void DnDEventLoggerWidget::dragMoveEvent(QDragMoveEvent *e) |
89 |
{ |
90 |
+ if (m_ignoreDragMove) |
91 |
+ return; |
92 |
e->accept(); |
93 |
QString message; |
94 |
QTextStream str(&message); |
95 |
@@ -580,7 +588,17 @@ void tst_QWidget_window::tst_dnd() |
96 |
dropsRefusingWidget2->resize(160, 60); |
97 |
dropsRefusingWidget2->move(10, 10); |
98 |
|
99 |
+ QWidget *dropsAcceptingWidget3 = new DnDEventLoggerWidget(&log, &dndTestWidget, true); |
100 |
+ dropsAcceptingWidget3->setAcceptDrops(true); |
101 |
+ dropsAcceptingWidget3->setObjectName(QLatin1String("acceptingDropsWidget3")); |
102 |
+ // 260 + 40 = 300 = widget size, must not be more than that. |
103 |
+ // otherwise it will break WinRT because there the tlw is maximized every time |
104 |
+ // and this window will receive one more event |
105 |
+ dropsAcceptingWidget3->resize(180, 40); |
106 |
+ dropsAcceptingWidget3->move(10, 260); |
107 |
+ |
108 |
dndTestWidget.show(); |
109 |
+ QVERIFY(QTest::qWaitForWindowExposed(&dndTestWidget)); |
110 |
qApp->setActiveWindow(&dndTestWidget); |
111 |
QVERIFY(QTest::qWaitForWindowActive(&dndTestWidget)); |
112 |
|
113 |
@@ -595,16 +613,17 @@ void tst_QWidget_window::tst_dnd() |
114 |
log.push_back(msgEventAccepted(e)); |
115 |
while (true) { |
116 |
position.ry() += 20; |
117 |
- if (position.y() >= 250) { |
118 |
+ if (position.y() >= 250 && position.y() < 270) { |
119 |
QDropEvent e(position, Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier); |
120 |
qApp->sendEvent(window, &e); |
121 |
log.push_back(msgEventAccepted(e)); |
122 |
- break; |
123 |
} else { |
124 |
QDragMoveEvent e(position, Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier); |
125 |
qApp->sendEvent(window, &e); |
126 |
log.push_back(msgEventAccepted(e)); |
127 |
} |
128 |
+ if (position.y() > 290) |
129 |
+ break; |
130 |
} |
131 |
|
132 |
window = nativeWidget->windowHandle(); |
133 |
@@ -628,6 +647,15 @@ void tst_QWidget_window::tst_dnd() |
134 |
for (int i= 0; i < expectedLogSize; ++i) |
135 |
expectedLog.push_back(QString::fromLatin1(expectedLogC[i]).replace(mimeDataAddressPlaceHolder, mimeDataAddress)); |
136 |
|
137 |
+ if (log.size() != expectedLog.size()) { |
138 |
+ for (int i = 0; i < log.size() && i < expectedLog.size(); ++i) |
139 |
+ QCOMPARE(log.at(i), expectedLog.at(i)); |
140 |
+ const int iMin = std::min(log.size(), expectedLog.size()); |
141 |
+ for (int i = iMin; i < log.size(); ++i) |
142 |
+ qDebug() << "log[" << i << "]:" << log.at(i); |
143 |
+ for (int i = iMin; i < expectedLog.size(); ++i) |
144 |
+ qDebug() << "exp[" << i << "]:" << log.at(i); |
145 |
+ } |
146 |
QCOMPARE(log, expectedLog); |
147 |
} |
148 |
|
149 |
-- |
150 |
2.20.1 |
151 |
|