2067 w->show(); |
2070 w->show(); |
2068 QTest::qWaitForWindowShown(w); |
2071 QTest::qWaitForWindowShown(w); |
2069 delete w; |
2072 delete w; |
2070 } |
2073 } |
2071 |
2074 |
|
2075 class ReuseCanceledGesturesRecognizer : public QGestureRecognizer |
|
2076 { |
|
2077 public: |
|
2078 enum Type { |
|
2079 RmbAndCancelAllType, |
|
2080 LmbType |
|
2081 }; |
|
2082 |
|
2083 ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {} |
|
2084 |
|
2085 QGesture *create(QObject *) { |
|
2086 QGesture *g = new QGesture; |
|
2087 return g; |
|
2088 } |
|
2089 |
|
2090 Result recognize(QGesture *gesture, QObject *, QEvent *event) { |
|
2091 QMouseEvent *me = static_cast<QMouseEvent *>(event); |
|
2092 Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton); |
|
2093 |
|
2094 switch(event->type()) { |
|
2095 case QEvent::MouseButtonPress: |
|
2096 if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) { |
|
2097 gesture->setHotSpot(QPointF(me->globalPos())); |
|
2098 if (m_type == RmbAndCancelAllType) |
|
2099 gesture->setGestureCancelPolicy(QGesture::CancelAllInContext); |
|
2100 return QGestureRecognizer::TriggerGesture; |
|
2101 } |
|
2102 break; |
|
2103 case QEvent::MouseButtonRelease: |
|
2104 if (me->button() == mouseButton && gesture->state() > Qt::NoGesture) |
|
2105 return QGestureRecognizer::FinishGesture; |
|
2106 default: |
|
2107 break; |
|
2108 } |
|
2109 return QGestureRecognizer::Ignore; |
|
2110 } |
|
2111 private: |
|
2112 Type m_type; |
|
2113 }; |
|
2114 |
|
2115 class ReuseCanceledGesturesWidget : public QGraphicsWidget |
|
2116 { |
|
2117 public: |
|
2118 ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0) |
|
2119 : QGraphicsWidget(parent), |
|
2120 m_gestureType(gestureType), |
|
2121 m_started(0), m_updated(0), m_canceled(0), m_finished(0) |
|
2122 { |
|
2123 } |
|
2124 |
|
2125 bool event(QEvent *event) { |
|
2126 if (event->type() == QEvent::Gesture) { |
|
2127 QGesture *gesture = static_cast<QGestureEvent*>(event)->gesture(m_gestureType); |
|
2128 if (gesture) { |
|
2129 switch(gesture->state()) { |
|
2130 case Qt::GestureStarted: m_started++; break; |
|
2131 case Qt::GestureUpdated: m_updated++; break; |
|
2132 case Qt::GestureFinished: m_finished++; break; |
|
2133 case Qt::GestureCanceled: m_canceled++; break; |
|
2134 default: break; |
|
2135 } |
|
2136 } |
|
2137 return true; |
|
2138 } |
|
2139 if (event->type() == QEvent::GraphicsSceneMousePress) { |
|
2140 return true; |
|
2141 } |
|
2142 return QGraphicsWidget::event(event); |
|
2143 } |
|
2144 |
|
2145 int started() { return m_started; } |
|
2146 int updated() { return m_updated; } |
|
2147 int finished() { return m_finished; } |
|
2148 int canceled() { return m_canceled; } |
|
2149 |
|
2150 private: |
|
2151 Qt::GestureType m_gestureType; |
|
2152 int m_started; |
|
2153 int m_updated; |
|
2154 int m_canceled; |
|
2155 int m_finished; |
|
2156 }; |
|
2157 |
|
2158 void tst_Gestures::testReuseCanceledGestures() |
|
2159 { |
|
2160 Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer( |
|
2161 new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType)); |
|
2162 Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer( |
|
2163 new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType)); |
|
2164 |
|
2165 QMainWindow mw; |
|
2166 mw.setWindowFlags(Qt::X11BypassWindowManagerHint); |
|
2167 QGraphicsView *gv = new QGraphicsView(&mw); |
|
2168 QGraphicsScene *scene = new QGraphicsScene; |
|
2169 |
|
2170 gv->setScene(scene); |
|
2171 scene->setSceneRect(0,0,100,100); |
|
2172 |
|
2173 // Create container and add to the scene |
|
2174 ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget; |
|
2175 container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture |
|
2176 |
|
2177 // Create widget and add to the scene |
|
2178 ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container); |
|
2179 target->grabGesture(tapGestureTypeId); |
|
2180 |
|
2181 container->setGeometry(scene->sceneRect()); |
|
2182 |
|
2183 scene->addItem(container); |
|
2184 |
|
2185 mw.setCentralWidget(gv); |
|
2186 |
|
2187 // Viewport needs to grab all gestures that widgets in scene grab |
|
2188 gv->viewport()->grabGesture(cancellingGestureTypeId); |
|
2189 gv->viewport()->grabGesture(tapGestureTypeId); |
|
2190 |
|
2191 mw.show(); |
|
2192 QTest::qWaitForWindowShown(&mw); |
|
2193 |
|
2194 QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center()))); |
|
2195 targetPos = gv->viewport()->mapFromParent(targetPos); |
|
2196 |
|
2197 // "Tap" starts on child widget |
|
2198 QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos); |
|
2199 QCOMPARE(target->started(), 1); |
|
2200 QCOMPARE(target->updated(), 0); |
|
2201 QCOMPARE(target->finished(), 0); |
|
2202 QCOMPARE(target->canceled(), 0); |
|
2203 |
|
2204 // Canceling gesture starts on parent |
|
2205 QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos); |
|
2206 QCOMPARE(target->started(), 1); |
|
2207 QCOMPARE(target->updated(), 0); |
|
2208 QCOMPARE(target->finished(), 0); |
|
2209 QCOMPARE(target->canceled(), 1); // <- child canceled |
|
2210 |
|
2211 // Canceling gesture ends |
|
2212 QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos); |
|
2213 QCOMPARE(target->started(), 1); |
|
2214 QCOMPARE(target->updated(), 0); |
|
2215 QCOMPARE(target->finished(), 0); |
|
2216 QCOMPARE(target->canceled(), 1); |
|
2217 |
|
2218 // Tap would end if not canceled |
|
2219 QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos); |
|
2220 QCOMPARE(target->started(), 1); |
|
2221 QCOMPARE(target->updated(), 0); |
|
2222 QCOMPARE(target->finished(), 0); |
|
2223 QCOMPARE(target->canceled(), 1); |
|
2224 |
|
2225 // New "Tap" starts |
|
2226 QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos); |
|
2227 QCOMPARE(target->started(), 2); |
|
2228 QCOMPARE(target->updated(), 0); |
|
2229 QCOMPARE(target->finished(), 0); |
|
2230 QCOMPARE(target->canceled(), 1); |
|
2231 |
|
2232 QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos); |
|
2233 QCOMPARE(target->started(), 2); |
|
2234 QCOMPARE(target->updated(), 0); |
|
2235 QCOMPARE(target->finished(), 1); |
|
2236 QCOMPARE(target->canceled(), 1); |
|
2237 } |
|
2238 |
|
2239 void tst_Gestures::conflictingGesturesInGraphicsView() |
|
2240 { |
|
2241 QGraphicsScene scene; |
|
2242 GraphicsView view(&scene); |
|
2243 view.setWindowFlags(Qt::X11BypassWindowManagerHint); |
|
2244 |
|
2245 GestureItem *item1 = new GestureItem("item1"); |
|
2246 item1->grabGesture(CustomGesture::GestureType); |
|
2247 item1->size = QRectF(0, 0, 100, 100); |
|
2248 item1->setZValue(2); |
|
2249 scene.addItem(item1); |
|
2250 |
|
2251 GestureItem *item2 = new GestureItem("item2"); |
|
2252 item2->grabGesture(CustomGesture::GestureType); |
|
2253 item2->size = QRectF(0, 0, 100, 100); |
|
2254 item2->setZValue(5); |
|
2255 scene.addItem(item2); |
|
2256 |
|
2257 view.show(); |
|
2258 QTest::qWaitForWindowShown(&view); |
|
2259 view.ensureVisible(scene.sceneRect()); |
|
2260 |
|
2261 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; |
|
2262 |
|
2263 CustomEvent event; |
|
2264 |
|
2265 // nobody accepts override |
|
2266 item1->acceptGestureOverride = false; |
|
2267 item2->acceptGestureOverride = false; |
|
2268 event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); |
|
2269 event.hasHotSpot = true; |
|
2270 sendCustomGesture(&event, item2, &scene); |
|
2271 QCOMPARE(item2->gestureOverrideEventsReceived, 1); |
|
2272 QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); |
|
2273 QCOMPARE(item1->gestureOverrideEventsReceived, 1); |
|
2274 QCOMPARE(item1->gestureEventsReceived, 0); |
|
2275 |
|
2276 item1->reset(); item2->reset(); |
|
2277 |
|
2278 // the original target accepts override |
|
2279 item1->acceptGestureOverride = false; |
|
2280 item2->acceptGestureOverride = true; |
|
2281 event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); |
|
2282 event.hasHotSpot = true; |
|
2283 sendCustomGesture(&event, item2, &scene); |
|
2284 QCOMPARE(item2->gestureOverrideEventsReceived, 1); |
|
2285 QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); |
|
2286 QCOMPARE(item1->gestureOverrideEventsReceived, 0); |
|
2287 QCOMPARE(item1->gestureEventsReceived, 0); |
|
2288 |
|
2289 item1->reset(); item2->reset(); |
|
2290 |
|
2291 // the item behind accepts override |
|
2292 item1->acceptGestureOverride = true; |
|
2293 item2->acceptGestureOverride = false; |
|
2294 event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view); |
|
2295 event.hasHotSpot = true; |
|
2296 sendCustomGesture(&event, item2, &scene); |
|
2297 |
|
2298 QCOMPARE(item2->gestureOverrideEventsReceived, 1); |
|
2299 QCOMPARE(item2->gestureEventsReceived, 0); |
|
2300 QCOMPARE(item1->gestureOverrideEventsReceived, 1); |
|
2301 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); |
|
2302 } |
|
2303 |
2072 QTEST_MAIN(tst_Gestures) |
2304 QTEST_MAIN(tst_Gestures) |
2073 #include "tst_gestures.moc" |
2305 #include "tst_gestures.moc" |