|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "GWebTouchNavigation.h" |
|
20 #include "qwebpage.h" |
|
21 #include "qwebframe.h" |
|
22 #include "qapplication.h" |
|
23 #include "qwebelement.h" |
|
24 #include "GWebContentViewWidget.h" |
|
25 #include "GWebContentView.h" |
|
26 #include <QGraphicsSceneMouseEvent> |
|
27 #include <QTimer> |
|
28 #include <qmath.h> |
|
29 #include <QDebug> |
|
30 #include <QGraphicsView> |
|
31 |
|
32 #include "webcontentview.h" |
|
33 #include "wrtBrowserUtils.h" |
|
34 #include "ChromeWidget.h" |
|
35 #include <qdebug.h> |
|
36 |
|
37 |
|
38 #define LONG_PRESS_DURATION 500 |
|
39 |
|
40 const int KFlickSpeed = 400; |
|
41 const qreal PI = 3.1415926535897932; |
|
42 const qreal KAngleTolerance = 30; |
|
43 const int KAnimationTimeout = 40; |
|
44 const qreal KDecelerationFactor = 0.8; |
|
45 const int KMilliSecond = 1000; |
|
46 const int KThresholdForRightToLeftMotion = 100; // 100 pixels |
|
47 const int KThresholdForLeftToRightMotion = -100; // 100 pixels |
|
48 const int XAlignVal = 10; |
|
49 const int KDecelerationTimer = 125; //Decelerate only if flicked/swiped after KDecelerationTimer milli seconds after last drag event |
|
50 |
|
51 const int KDoubleClickTimeOut = 400; |
|
52 const QPoint KFocussPoint(5, 50); |
|
53 const int KTouchThresholdX = 20; |
|
54 const int KTouchThresholdY = 20; |
|
55 const int KPanThreshold = 2; |
|
56 const int KThreshHoldValForLink = 10; |
|
57 const qreal KDeccelaration = 1000.00; |
|
58 const int KDefaultViewportWidth = 980; |
|
59 const int KDefaultPortraitScaleWidth = 540; |
|
60 |
|
61 const int KKineticTimeout = 60; |
|
62 |
|
63 static const int KStartPanDistance = 50; |
|
64 static const int KWaitForClickTimeoutMS = 200; |
|
65 //The amount of pixels to try to pan before pan mode unlocks |
|
66 static const int KPanModeChangeDelta = 100; |
|
67 |
|
68 |
|
69 namespace GVA { |
|
70 |
|
71 /*! |
|
72 \class WebTouchNavigation |
|
73 \since cwrt 1.0 |
|
74 \brief cwrt navigation. |
|
75 |
|
76 \sa WebNavigation, WebHtmlTabIndexedNavigation, WebCursorNavigation, WebDirectionalNavigation |
|
77 */ |
|
78 GWebTouchNavigation::GWebTouchNavigation(QWebPage* webPage,GWebContentViewWidget* view) |
|
79 : m_webPage(webPage) |
|
80 , m_view(view) |
|
81 , m_frame(0) |
|
82 , m_doubleClickTimer(0) |
|
83 , m_pressEvent(0) |
|
84 , m_scrollTimer(0) |
|
85 , m_releaseEvent(0) |
|
86 , m_focusedBlockPt(-1, -1) |
|
87 , m_ishighlighted(false) |
|
88 , m_offset(0) |
|
89 , m_longPressTimer(0) |
|
90 , m_finalzoomfactor(0) |
|
91 , m_kineticTimer(0) |
|
92 , m_isPanning(false) |
|
93 , m_enabled(true) |
|
94 , m_isLoading(false) |
|
95 { |
|
96 install(); |
|
97 connect(m_view, SIGNAL(BlockFocusChanged(QPoint)), this, SLOT(BlockFocusChanged(QPoint))); |
|
98 connect(m_webPage, SIGNAL(loadStarted()), this, SLOT(onLoadStarted())); |
|
99 connect(m_webPage, SIGNAL(loadFinished(bool)), this, SLOT(onLoadFinished(bool))); |
|
100 } |
|
101 |
|
102 /*! |
|
103 */ |
|
104 GWebTouchNavigation::~GWebTouchNavigation() |
|
105 { |
|
106 disconnect(m_doubleClickTimer, SIGNAL(timeout()), this, SLOT(doubleClickTimerExpired())); |
|
107 if (m_doubleClickTimer) { |
|
108 m_doubleClickTimer->stop(); |
|
109 delete m_doubleClickTimer; |
|
110 } |
|
111 disconnect(m_scrollTimer, SIGNAL(timeout()),this,SLOT(pan())); |
|
112 delete m_scrollTimer; |
|
113 |
|
114 disconnect(m_kineticTimer, SIGNAL(timeout()),this,SLOT(kineticScroll())); |
|
115 delete m_kineticTimer; |
|
116 uninstall(); |
|
117 } |
|
118 |
|
119 void GWebTouchNavigation::install() |
|
120 { |
|
121 m_view->installEventFilter(this); |
|
122 } |
|
123 |
|
124 void GWebTouchNavigation::BlockFocusChanged(QPoint pt) |
|
125 { |
|
126 m_focusedBlockPt = pt; |
|
127 } |
|
128 |
|
129 void GWebTouchNavigation::uninstall() |
|
130 { |
|
131 if (m_view) |
|
132 m_view->removeEventFilter(this); |
|
133 } |
|
134 |
|
135 bool GWebTouchNavigation::eventFilter(QObject *object, QEvent *event) |
|
136 { |
|
137 if (object != m_view || !enabled()) |
|
138 return false; |
|
139 |
|
140 switch (event->type()) { |
|
141 case QEvent::MouseButtonPress: |
|
142 if (static_cast<QMouseEvent *>(event)->buttons() & Qt::LeftButton) { |
|
143 mousePressEvent(static_cast<QMouseEvent *>(event)->pos()); |
|
144 return true; |
|
145 } |
|
146 break; |
|
147 case QEvent::MouseMove: |
|
148 if (static_cast<QMouseEvent *>(event)->buttons() & Qt::LeftButton) { |
|
149 QPoint diff = m_touchPosition - static_cast<QMouseEvent*>(event)->globalPos(); |
|
150 mouseMoveEvent(static_cast<QMouseEvent*>(event)->pos(), diff); |
|
151 return true; |
|
152 } |
|
153 break; |
|
154 case QEvent::MouseButtonRelease: |
|
155 mouseReleaseEvent(static_cast<QMouseEvent*>(event)->pos()); |
|
156 return true; |
|
157 case QEvent::MouseButtonDblClick: |
|
158 mouseDoubleClickEvent(static_cast<QMouseEvent*>(event)->pos()); |
|
159 return true; |
|
160 case QEvent::GraphicsSceneMousePress: |
|
161 if (static_cast<QGraphicsSceneMouseEvent*>(event)->buttons() & Qt::LeftButton) { |
|
162 mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(event)->pos().toPoint()); |
|
163 emit mouseEvent(QEvent::GraphicsSceneMousePress); |
|
164 return true; |
|
165 } |
|
166 break; |
|
167 case QEvent::GraphicsSceneMouseMove: |
|
168 if (static_cast<QGraphicsSceneMouseEvent *>(event)->buttons() & Qt::LeftButton) { |
|
169 QPoint diff = static_cast<QGraphicsSceneMouseEvent*>(event)->lastScenePos().toPoint() - static_cast<QGraphicsSceneMouseEvent*>(event)->scenePos().toPoint(); |
|
170 mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event)->pos().toPoint(), diff); |
|
171 return true; |
|
172 } |
|
173 break; |
|
174 case QEvent::GraphicsSceneMouseRelease: |
|
175 mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event)->pos().toPoint()); |
|
176 emit mouseEvent(QEvent::GraphicsSceneMouseRelease); |
|
177 return true; |
|
178 break; |
|
179 case QEvent::GraphicsSceneMouseDoubleClick: |
|
180 mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(event)->pos().toPoint()); |
|
181 emit mouseEvent(QEvent::GraphicsSceneMouseDoubleClick); |
|
182 return true; |
|
183 break; |
|
184 default: |
|
185 break; |
|
186 } |
|
187 return false; |
|
188 } |
|
189 |
|
190 void GWebTouchNavigation::stopScrolling() |
|
191 { |
|
192 if (m_scrollTimer && m_scrollTimer->isActive()) { |
|
193 m_scrollTimer->stop(); |
|
194 m_scrollDelta = QPoint(0,0); |
|
195 } |
|
196 |
|
197 if (m_kineticTimer && m_kineticTimer->isActive()) { |
|
198 m_kineticTimer->stop(); |
|
199 m_kineticSpeed.setX(0.0); |
|
200 m_kineticSpeed.setY(0.0); |
|
201 } |
|
202 } |
|
203 |
|
204 |
|
205 void GWebTouchNavigation::pan() |
|
206 { |
|
207 if (m_scrollDelta.x() != 0 || m_scrollDelta.y() != 0) { |
|
208 scrollCurrentFrame(-m_scrollDelta.x(), m_scrollDelta.y()); |
|
209 m_scrollDelta = QPoint(0,0); |
|
210 } |
|
211 } |
|
212 |
|
213 #define DECELERATION 0.0002 |
|
214 |
|
215 void GWebTouchNavigation::kineticScroll() |
|
216 { |
|
217 qreal decelX = m_kineticSpeed.x() > 0 ? -DECELERATION : DECELERATION; |
|
218 qreal decelY = m_kineticSpeed.y() > 0 ? -DECELERATION : DECELERATION; |
|
219 qreal dx = 0; |
|
220 qreal dy = 0; |
|
221 qreal vx = 0; |
|
222 qreal vy = 0; |
|
223 |
|
224 m_kineticScrollTime += m_actualTime.elapsed(); |
|
225 |
|
226 if (m_kineticSpeed.x()) { |
|
227 vx = m_kineticSpeed.x() + decelX * m_kineticScrollTime; |
|
228 if (vx * m_kineticSpeed.x() < 0) { |
|
229 dx = 0; |
|
230 vx = 0; |
|
231 } |
|
232 else { |
|
233 dx = m_kineticScrollTime * m_kineticSpeed.x() + |
|
234 0.5 * decelX * m_kineticScrollTime * m_kineticScrollTime; |
|
235 } |
|
236 } |
|
237 |
|
238 if (m_kineticSpeed.y()) { |
|
239 vy = m_kineticSpeed.y() + decelY * m_kineticScrollTime; |
|
240 if (vy * m_kineticSpeed.y() < 0) { |
|
241 dy = 0; |
|
242 vy = 0; |
|
243 } |
|
244 else { |
|
245 dy = m_kineticScrollTime * m_kineticSpeed.y() + |
|
246 0.5 * decelY * m_kineticScrollTime * m_kineticScrollTime; |
|
247 } |
|
248 } |
|
249 |
|
250 QPoint scrollPos = m_frame->scrollPosition(); |
|
251 QPoint distPos = m_initialScrollPos + QPointF(dx, dy).toPoint(); |
|
252 |
|
253 if (vx != 0 || vy != 0) { |
|
254 setCurrentFrameScrollPosition(distPos); |
|
255 } |
|
256 |
|
257 if ((vx == 0 && vy == 0) || scrollPos == m_frame->scrollPosition()) { |
|
258 stopScrolling(); |
|
259 } |
|
260 |
|
261 } |
|
262 |
|
263 |
|
264 |
|
265 /*! |
|
266 Scrolls QWebFrame to the given position |
|
267 \sa QWebFrame::scroll() |
|
268 */ |
|
269 void GWebTouchNavigation::scrollFrame(const QPoint& diff) |
|
270 { |
|
271 if (qAbs(diff.x()) < KPanThreshold && qAbs(diff.y()) < KPanThreshold) |
|
272 return; |
|
273 else if(m_dragPoints.size() == 1) { |
|
274 //WebContentWidget* view = qobject_cast<WebContentWidget*>(m_view); |
|
275 m_view->setBlockElement(QWebElement()); |
|
276 } |
|
277 |
|
278 if(!m_isPanning) { |
|
279 qreal dy = qAbs(diff.y()); |
|
280 qreal dx = qAbs(diff.x()); |
|
281 if (dy > KStartPanDistance || dx > KStartPanDistance |
|
282 || m_delayedPressMoment.elapsed() > KWaitForClickTimeoutMS) { |
|
283 //get the scroll direction |
|
284 Direction scrollDir = findDirectionWithAngle(diff); |
|
285 if(scrollDir == UP || scrollDir == DOWN) |
|
286 startPanGesture(VerticalPan); |
|
287 else if(scrollDir == LEFT || scrollDir == RIGHT) |
|
288 startPanGesture(HorizontalPan); |
|
289 else |
|
290 startPanGesture(RandomPan); |
|
291 m_isPanning = true; |
|
292 } |
|
293 } |
|
294 |
|
295 if (m_isPanning) { |
|
296 m_scrolled= false; |
|
297 m_frame = getNextScrollableFrame(diff); |
|
298 QPoint scrollPosition = m_frame->scrollPosition(); |
|
299 if (diff.manhattanLength()) |
|
300 panBy(diff); |
|
301 |
|
302 m_scrolled = (scrollPosition != m_frame->scrollPosition()); |
|
303 } |
|
304 } |
|
305 |
|
306 void GWebTouchNavigation::startPanGesture(PanDirection directionHint) { |
|
307 emit startingPanGesture((int)directionHint); |
|
308 m_panDirection = directionHint; |
|
309 m_panModeResidue = QPointF(0., 0.); |
|
310 } |
|
311 |
|
312 void GWebTouchNavigation::panBy(const QPointF& delta) { |
|
313 |
|
314 m_panModeResidue += delta; |
|
315 |
|
316 if (qAbs(m_panModeResidue.x()) > KPanModeChangeDelta) |
|
317 m_panDirection = HorizontalPan; |
|
318 |
|
319 if (qAbs(m_panModeResidue.y()) > KPanModeChangeDelta) |
|
320 m_panDirection = VerticalPan; |
|
321 |
|
322 if(qAbs(m_panModeResidue.x()) > KPanModeChangeDelta |
|
323 && qAbs(m_panModeResidue.y()) > KPanModeChangeDelta) |
|
324 m_panDirection = RandomPan; |
|
325 |
|
326 QPointF p; |
|
327 if(m_panDirection == HorizontalPan) |
|
328 p.setX(delta.x()); |
|
329 if(m_panDirection == VerticalPan) |
|
330 p.setY(delta.y()); |
|
331 if(m_panDirection == RandomPan) { |
|
332 p.setX(delta.x()); |
|
333 p.setY(delta.y()); |
|
334 } |
|
335 |
|
336 scrollCurrentFrame(p.x(),p.y()); |
|
337 } |
|
338 |
|
339 void GWebTouchNavigation::highlightableElement(QMouseEvent* ev) { |
|
340 m_anchorElement = getClosestAnchorElement(ev); |
|
341 } |
|
342 |
|
343 inline int xInRect(const QRect& r, int x) |
|
344 { |
|
345 return std::min(std::max(x, r.x()), r.x() + r.width()); |
|
346 } |
|
347 |
|
348 inline int yInRect(const QRect& r, int y) |
|
349 { |
|
350 return std::min(std::max(y, r.y()), r.y() + r.height()); |
|
351 } |
|
352 |
|
353 bool GWebTouchNavigation::traverseNextNode(QWebElement parentNode,QWebElement& nextNode) |
|
354 { |
|
355 if (!parentNode.firstChild().isNull()) { |
|
356 nextNode = parentNode.firstChild(); |
|
357 return true; |
|
358 } |
|
359 |
|
360 if (!parentNode.nextSibling().isNull()) { |
|
361 nextNode = parentNode.nextSibling(); |
|
362 return true; |
|
363 } |
|
364 |
|
365 QWebElement n = parentNode; |
|
366 while (!n.isNull() && n.nextSibling().isNull()) |
|
367 n = n.parent (); |
|
368 |
|
369 if (!n.isNull()) { |
|
370 nextNode = n.nextSibling(); |
|
371 return true; |
|
372 } |
|
373 |
|
374 return false; |
|
375 } |
|
376 |
|
377 |
|
378 QWebElement GWebTouchNavigation::getClosestAnchorElement(QMouseEvent* ev) |
|
379 { |
|
380 QWebElement webElement; |
|
381 QWebHitTestResult htRes = getHitTestResult(ev); |
|
382 QWebElement hitElement = htRes.element(); |
|
383 //check whether hit test returns a link element |
|
384 if(!htRes.linkElement().isNull()) { |
|
385 webElement = htRes.linkElement(); |
|
386 m_higlightedPos = ev->pos(); |
|
387 m_ishighlighted = true; |
|
388 } |
|
389 //get the closet anchor element |
|
390 else { |
|
391 QPoint docPoint = (m_touchPosition + m_frame->scrollPosition()); |
|
392 int dist = 99999999; |
|
393 QWebElement result; |
|
394 QWebElement ele = m_webPage->currentFrame()->documentElement(); |
|
395 do { |
|
396 if(ele.tagName().compare("a",Qt::CaseInsensitive) == 0 ) { |
|
397 QRect r = ele.geometry(); |
|
398 if(r.contains(docPoint)) { |
|
399 dist = 0; |
|
400 result = ele; |
|
401 break; |
|
402 } |
|
403 |
|
404 int x = xInRect(r, docPoint.x()); |
|
405 int y = yInRect(r, docPoint.y()); |
|
406 int d = (docPoint.x() - x) * (docPoint.x() - x) + (docPoint.y() - y) * (docPoint.y() - y); |
|
407 if (dist > d) { |
|
408 dist = d; |
|
409 result = ele; |
|
410 } |
|
411 } |
|
412 }while(traverseNextNode(ele,ele)); |
|
413 |
|
414 // WebContentWidget* view = qobject_cast<WebContentWidget*>(m_view); |
|
415 // check if we are close enough and calcualte with zoom factor. |
|
416 if (dist< (KThreshHoldValForLink/m_view->zoomFactor())) { |
|
417 QRect r = result.geometry(); |
|
418 r.translate(2,2); |
|
419 r.setWidth(2+2); |
|
420 r.setHeight(2+2); |
|
421 webElement = result; |
|
422 m_higlightedPos = QPoint(xInRect(r, docPoint.x()), yInRect(r, docPoint.y())) - m_frame->scrollPosition(); |
|
423 m_ishighlighted = true; |
|
424 QPoint centerpt = webElement.geometry().center(); |
|
425 m_offset = (docPoint.x()- centerpt.x())*(docPoint.x()- centerpt.x()) + (docPoint.y()- centerpt.y())*(docPoint.y()- centerpt.y()); |
|
426 |
|
427 } |
|
428 } |
|
429 return webElement; |
|
430 } |
|
431 |
|
432 /*! |
|
433 Sends a mouse press event to QWebPage |
|
434 */ |
|
435 void GWebTouchNavigation::mousePressEvent(const QPoint& pos) |
|
436 { |
|
437 m_delayedPressMoment.start(); |
|
438 // stop deceleration and don't send further events to engine if scroll timer is active |
|
439 if(m_scrollTimer && m_scrollTimer->isActive()) { |
|
440 m_prevPoint.setX(0); |
|
441 m_prevPoint.setY(0); |
|
442 m_scrollDistance.setX(0); |
|
443 m_scrollDistance.setY(0); |
|
444 |
|
445 m_lastMoveEventTime.setHMS(0,0,0,0); //H, M, S, mS |
|
446 m_scrolled = false; |
|
447 m_ishighlighted = false; |
|
448 m_higlightedPos = m_touchPosition = pos; |
|
449 m_frame = m_webPage->frameAt(pos); |
|
450 if (!m_frame) |
|
451 m_frame = m_webPage->currentFrame(); |
|
452 |
|
453 m_dragPoints.clear(); |
|
454 |
|
455 DragPoint dragPoint; |
|
456 dragPoint.iPoint = m_touchPosition; |
|
457 dragPoint.iTime = QTime::currentTime(); |
|
458 m_dragPoints.append(dragPoint); |
|
459 m_offset = 0; |
|
460 |
|
461 m_pressEvent = new QMouseEvent(QEvent::MouseButtonPress, m_touchPosition, Qt::LeftButton, Qt::LeftButton, getEventModifier(m_touchPosition)); |
|
462 m_scrollTimer->stop(); |
|
463 return; |
|
464 } |
|
465 |
|
466 if (m_doubleClickTimer) { |
|
467 // If there is another click event almost on the same region |
|
468 // as the previous click before doubleClick timeout |
|
469 // Consider it as double click. |
|
470 if (m_doubleClickTimer->isActive() && m_pressEvent) { |
|
471 QPoint diff = m_pressEvent->pos() - pos; |
|
472 if (qAbs(diff.x()) < KTouchThresholdX && qAbs(diff.y()) < KTouchThresholdY) { |
|
473 mouseDoubleClickEvent(pos); |
|
474 return; |
|
475 } |
|
476 } |
|
477 m_doubleClickTimer->stop(); |
|
478 } else { |
|
479 m_doubleClickTimer = new QTimer(this); |
|
480 connect(m_doubleClickTimer, SIGNAL(timeout()), this, SLOT(doubleClickTimerExpired())); |
|
481 } |
|
482 |
|
483 //Clear the previous press and release events. |
|
484 if (m_pressEvent) { |
|
485 delete m_pressEvent; |
|
486 m_pressEvent = NULL; |
|
487 } |
|
488 |
|
489 if (m_releaseEvent) { |
|
490 delete m_releaseEvent; |
|
491 m_releaseEvent = NULL; |
|
492 } |
|
493 |
|
494 m_doubleClickTimer->start(KDoubleClickTimeOut); |
|
495 m_pressEvent = new QMouseEvent(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, getEventModifier(pos)); |
|
496 } |
|
497 |
|
498 void GWebTouchNavigation::handleMousePressEvent(QMouseEvent* ev) |
|
499 { |
|
500 m_lastMoveEventTime.setHMS(0,0,0,0); //H, M, S, mS |
|
501 if(!m_longPressTimer){ |
|
502 delete m_longPressTimer; |
|
503 m_longPressTimer = 0; |
|
504 } |
|
505 startTimer(); |
|
506 m_scrolled = false; |
|
507 m_ishighlighted = false; |
|
508 m_higlightedPos = m_touchPosition = ev->pos(); |
|
509 m_frame = m_webPage->frameAt(ev->pos()); |
|
510 if (!m_frame) |
|
511 m_frame = m_webPage->currentFrame(); |
|
512 |
|
513 m_dragPoints.clear(); |
|
514 |
|
515 DragPoint dragPoint; |
|
516 dragPoint.iPoint = m_touchPosition; |
|
517 dragPoint.iTime = QTime::currentTime(); |
|
518 m_dragPoints.append(dragPoint); |
|
519 |
|
520 m_offset = 0; |
|
521 |
|
522 highlightableElement(ev); |
|
523 getFocusedElement(); |
|
524 |
|
525 //send a mouse press |
|
526 QMouseEvent iev(ev->type(), m_touchPosition, ev->button(), ev->buttons(), getEventModifier(m_higlightedPos)); |
|
527 m_webPage->event(&iev); |
|
528 } |
|
529 |
|
530 void GWebTouchNavigation::doubleClickTimerExpired() |
|
531 { |
|
532 handleMousePressEvent(m_pressEvent); |
|
533 |
|
534 delete m_pressEvent; |
|
535 m_pressEvent = NULL; |
|
536 |
|
537 if (m_releaseEvent) { |
|
538 handleMouseReleaseEvent(m_releaseEvent); |
|
539 |
|
540 //clear release event |
|
541 delete m_releaseEvent; |
|
542 m_releaseEvent = NULL; |
|
543 } |
|
544 if (m_doubleClickTimer && m_doubleClickTimer->isActive()) |
|
545 m_doubleClickTimer->stop(); |
|
546 } |
|
547 |
|
548 bool GWebTouchNavigation::canDehighlight(QMouseEvent* ev) |
|
549 { |
|
550 bool checkDehighlight = false; |
|
551 QPoint pt = ev->pos() + m_frame->scrollPosition(); |
|
552 |
|
553 if(m_scrolled && m_ishighlighted) { |
|
554 checkDehighlight = true; |
|
555 } |
|
556 else if(!m_scrolled && m_ishighlighted) { |
|
557 QRect rect = m_anchorElement.geometry(); |
|
558 |
|
559 if(m_anchorElement.geometry().contains(pt)) { |
|
560 checkDehighlight = false; |
|
561 } |
|
562 else if(m_offset){ |
|
563 QPoint centerpt = m_anchorElement.geometry().center(); |
|
564 int newoffset = (pt.x()- centerpt.x())*(pt.x()- centerpt.x()) + (pt.y()- centerpt.y())*(pt.y()- centerpt.y()); |
|
565 |
|
566 if(newoffset <= m_offset ) { |
|
567 m_offset = newoffset; |
|
568 checkDehighlight = false; |
|
569 } |
|
570 else { |
|
571 m_offset =0; |
|
572 checkDehighlight = true; |
|
573 } |
|
574 } |
|
575 else { |
|
576 checkDehighlight = true; |
|
577 } |
|
578 } |
|
579 return checkDehighlight; |
|
580 } |
|
581 void GWebTouchNavigation::dehighlight(QMouseEvent* ev) |
|
582 { |
|
583 m_higlightedPos = QPoint(0,0); |
|
584 m_ishighlighted = false; |
|
585 QMouseEvent iev(QEvent::MouseButtonPress,m_higlightedPos,ev->button(), ev->buttons(), ev->modifiers()); |
|
586 m_webPage->event(&iev); |
|
587 } |
|
588 |
|
589 void GWebTouchNavigation::handleHighlightChange(QMouseEvent* ev) |
|
590 { |
|
591 if (!canDehighlight(ev)) return; |
|
592 |
|
593 dehighlight(ev); |
|
594 } |
|
595 |
|
596 /*! |
|
597 Scrolls the frame |
|
598 \sa scrollFrame() |
|
599 */ |
|
600 void GWebTouchNavigation::mouseMoveEvent(const QPoint& pos, const QPoint& diff) |
|
601 { |
|
602 |
|
603 if (m_pressEvent){ |
|
604 QPoint diff2 = m_pressEvent->pos() - pos; |
|
605 if (qAbs(diff2.x()) < KTouchThresholdX && qAbs(diff2.y()) < KTouchThresholdY) |
|
606 return; |
|
607 } |
|
608 |
|
609 if (m_doubleClickTimer && m_doubleClickTimer->isActive()) { |
|
610 //send mousePressEvent |
|
611 m_doubleClickTimer->stop(); |
|
612 handleMousePressEvent(m_pressEvent); |
|
613 delete m_pressEvent; |
|
614 m_pressEvent = NULL; |
|
615 } |
|
616 |
|
617 stopTimer(); |
|
618 QMouseEvent tmpEv(QEvent::MouseMove, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
|
619 handleHighlightChange(&tmpEv); |
|
620 |
|
621 scrollFrame(diff); |
|
622 |
|
623 //m_touchPosition = pos; |
|
624 DragPoint dragPoint; |
|
625 dragPoint.iPoint = pos; |
|
626 dragPoint.iTime = QTime::currentTime(); |
|
627 m_dragPoints.append(dragPoint); |
|
628 |
|
629 QTime now(QTime::currentTime()); |
|
630 m_lastMoveEventTime.setHMS(now.hour(),now.minute(), now.second(), now.msec()); |
|
631 |
|
632 while (m_dragPoints.size() > 4) |
|
633 m_dragPoints.removeFirst(); |
|
634 |
|
635 } |
|
636 |
|
637 /*! |
|
638 If WebCanvas or QWebFrame were scrolled starts the deceleration alogrithm |
|
639 Otherwise sends the mouse release event to QWebPage |
|
640 \sa startDeceleration() |
|
641 */ |
|
642 void GWebTouchNavigation::mouseReleaseEvent(const QPoint& pos) |
|
643 { |
|
644 if(m_isPanning) |
|
645 m_isPanning = false; |
|
646 if (m_doubleClickTimer && m_doubleClickTimer->isActive()) { |
|
647 m_releaseEvent = new QMouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
|
648 return; |
|
649 } |
|
650 //mouseReleaseEvent is called in two cases. 1. Double click, 2. Mouse Drag |
|
651 //m_releaseEvent is not null only in Mouse double click |
|
652 //So delete m_releaseEvent only in double click case. |
|
653 //Send release event in mouse move case |
|
654 if (m_releaseEvent) { |
|
655 delete m_releaseEvent ; |
|
656 m_releaseEvent = NULL; |
|
657 } else { |
|
658 QMouseEvent tmpEv(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
|
659 handleMouseReleaseEvent(&tmpEv); |
|
660 } |
|
661 } |
|
662 Qt::KeyboardModifier GWebTouchNavigation::getEventModifier(const QPoint& pos) |
|
663 { |
|
664 QWebFrame *frame = m_webPage->frameAt(pos); |
|
665 if (!frame) |
|
666 frame = m_webPage->currentFrame(); |
|
667 QWebHitTestResult htr = frame->hitTestContent(pos); |
|
668 if (htr.element().tagName().toLower().compare("select")==0 && htr.element().hasAttribute("multiple")) |
|
669 return Qt::ControlModifier; |
|
670 return Qt::NoModifier; |
|
671 } |
|
672 |
|
673 void GWebTouchNavigation::handleMouseReleaseEvent(QMouseEvent* ev) |
|
674 { |
|
675 m_frame = m_webPage->frameAt(ev->pos()); |
|
676 if (!m_frame) |
|
677 m_frame = m_webPage->currentFrame(); |
|
678 assert(m_frame); |
|
679 |
|
680 stopTimer(); |
|
681 if (m_scrolled) { |
|
682 int msecs = 0; |
|
683 if (!m_lastMoveEventTime.isNull()) { |
|
684 //Start deceleration only if the delta since last drag event is less than threshold |
|
685 QTime now(QTime::currentTime()); |
|
686 msecs = m_lastMoveEventTime.msecsTo(now); |
|
687 m_lastMoveEventTime.setHMS(0,0,0,0); |
|
688 } |
|
689 if (msecs < KDecelerationTimer) { |
|
690 if( isFlick()) { |
|
691 updateFlickScrollDistance(); |
|
692 } |
|
693 else { |
|
694 QRect enclosingRect = findEnclosingBlock(ev); |
|
695 QPoint blockDocPt(enclosingRect.x(), enclosingRect.y()); |
|
696 QPoint blockCanvasPoint(blockDocPt - m_frame->scrollPosition()); |
|
697 calculateActualScrollDistance(); |
|
698 int thresholdCheckVal = blockCanvasPoint.x() - m_actualScrollDistance.x(); |
|
699 setNewScrollDistance(blockCanvasPoint, thresholdCheckVal); |
|
700 } |
|
701 startScrollTimer(); |
|
702 } |
|
703 } else { |
|
704 QMouseEvent iev = m_ishighlighted ? |
|
705 QMouseEvent(ev->type(), m_higlightedPos, ev->button(), ev->buttons(), getEventModifier(m_higlightedPos)) : |
|
706 QMouseEvent(QEvent::MouseButtonRelease, m_touchPosition, ev->button(), ev->buttons(), getEventModifier(m_touchPosition)); |
|
707 m_webPage->event(&iev); |
|
708 #if defined __SYMBIAN32__ |
|
709 // FIXME Remove this, it will be fixed Qt 4.6.3 ? |
|
710 if (ev->button() == Qt::LeftButton) { |
|
711 QWebHitTestResult htr = m_frame->hitTestContent(ev->pos()); |
|
712 if (htr.isContentEditable()) { |
|
713 QEvent vkbEvent(QEvent::RequestSoftwareInputPanel); |
|
714 QList<QGraphicsView*> views = m_view->scene()->views(); |
|
715 QWidget* view = qobject_cast<QWidget*>(views.value(0)); |
|
716 if (view) |
|
717 QApplication::sendEvent(view, &vkbEvent); |
|
718 } |
|
719 } |
|
720 #endif |
|
721 } |
|
722 } |
|
723 |
|
724 void GWebTouchNavigation::mouseDoubleClickEvent(const QPoint& pos) |
|
725 { |
|
726 |
|
727 if(m_doubleClickTimer && !m_doubleClickTimer->isActive()) |
|
728 return; |
|
729 else if(m_doubleClickTimer) |
|
730 m_doubleClickTimer->stop(); |
|
731 |
|
732 //If the page is already scrolling(because of a previous doubletap) |
|
733 //we need to stop the timer before we start scrolling the new block again. |
|
734 if (m_scrollTimer && m_scrollTimer->isActive()) |
|
735 m_scrollTimer->stop(); |
|
736 |
|
737 QMouseEvent tmpEv(QEvent::MouseButtonDblClick, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); |
|
738 handleDoubleClickEvent(&tmpEv); |
|
739 } |
|
740 |
|
741 void GWebTouchNavigation::handleDoubleClickEvent(QMouseEvent* ev) |
|
742 { |
|
743 QPoint imageFocusPoint; |
|
744 QWebHitTestResult hitTest = getHitTestResult(ev); |
|
745 |
|
746 QWebElement block = hitTest.element(); |
|
747 |
|
748 if (block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) |
|
749 block = hitTest.enclosingBlockElement(); |
|
750 |
|
751 QWebFrame* frame = m_webPage->frameAt(ev->pos()); |
|
752 m_frame = (frame) ? frame : m_webPage->mainFrame(); |
|
753 |
|
754 QRect enclosingRect = block.geometry(); |
|
755 |
|
756 QPoint blockCanvasPt = QPoint(enclosingRect.topLeft()) - m_frame->scrollPosition(); |
|
757 //WebContentWidget* view = qobject_cast<WebContentWidget*>(m_view); |
|
758 m_view->setBlockElement(QWebElement()); |
|
759 if(m_focusedBlockPt == blockCanvasPt) { |
|
760 m_focusedBlockPt.setX(-1); |
|
761 m_focusedBlockPt.setY(-1); |
|
762 qreal m_Ratiox = (qreal) blockCanvasPt.x() / block.geometry().width(); |
|
763 qreal m_Ratioy = (qreal) blockCanvasPt.y() / block.geometry().height(); |
|
764 m_view->setZoomFactor(m_view->initialScale()); |
|
765 QPoint m_InfocusBlockPt = QPoint(block.geometry().topLeft()) - m_webPage->mainFrame()->scrollPosition(); |
|
766 m_webPage->currentFrame()->scroll(m_InfocusBlockPt.x() - (m_Ratiox * block.geometry().width()), |
|
767 m_InfocusBlockPt.y() - (m_Ratioy * block.geometry().height())); |
|
768 m_finalzoomfactor = 0; |
|
769 }else { |
|
770 if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) { |
|
771 m_finalzoomfactor = (qreal) (m_webPage->viewportSize().width() - 10) * m_view->zoomFactor(); |
|
772 m_finalzoomfactor = (qreal) m_finalzoomfactor / (enclosingRect.width()); |
|
773 QString str; |
|
774 str.setNum(m_finalzoomfactor,'f',2); |
|
775 m_finalzoomfactor = str.toDouble(); |
|
776 }else { |
|
777 qreal factor; |
|
778 factor = 1/m_view->initialScale(); |
|
779 int boundW = block.geometry().width() * factor/m_view->zoomFactor(); |
|
780 int boundH = block.geometry().height() * factor/m_view->zoomFactor(); |
|
781 qreal factorw = 0.0,factorh = 0.0 ; |
|
782 |
|
783 if( boundW > m_webPage->viewportSize().width()) |
|
784 factorw = (qreal)(m_webPage->viewportSize().width()-5)/ block.geometry().width(); |
|
785 |
|
786 if(boundH > m_webPage->viewportSize().height()) |
|
787 factorh = (qreal)(m_webPage->viewportSize().height()-5)/ block.geometry().height(); |
|
788 |
|
789 if( (factorw == 0.0) && (factorh == 0.0)) |
|
790 ; |
|
791 else if(factorw == 0.0) |
|
792 factor = factorh * m_view->zoomFactor(); |
|
793 else if(factorh == 0.0) |
|
794 factor = factorw * m_view->zoomFactor(); |
|
795 else { |
|
796 factor = ((factorh < factorw) ? factorh : factorw) * m_view->zoomFactor(); |
|
797 } |
|
798 |
|
799 QString str; |
|
800 str.setNum(factor,'f',2); |
|
801 factor = str.toDouble(); |
|
802 |
|
803 if(m_finalzoomfactor != factor) |
|
804 m_finalzoomfactor = factor; |
|
805 } |
|
806 |
|
807 |
|
808 if (m_finalzoomfactor != m_view->zoomFactor()) { |
|
809 m_view->setZoomFactor(m_finalzoomfactor); |
|
810 m_focusedBlockPt = QPoint(block.geometry().topLeft()) - m_frame->scrollPosition(); |
|
811 |
|
812 if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) |
|
813 scrollCurrentFrame(m_focusedBlockPt.x() - KFocussPoint.x() , m_focusedBlockPt.y() - KFocussPoint.y()); |
|
814 else { |
|
815 if((m_webPage->viewportSize().width() - block.geometry().width()) > 0) |
|
816 imageFocusPoint.setX((m_webPage->viewportSize().width() - block.geometry().width())/2); |
|
817 else |
|
818 imageFocusPoint.setX(0); |
|
819 |
|
820 if((m_webPage->viewportSize().height() - block.geometry().height()) > 0) |
|
821 imageFocusPoint.setY((m_webPage->viewportSize().height() - block.geometry().height())/2); |
|
822 else |
|
823 imageFocusPoint.setY(0); |
|
824 |
|
825 scrollCurrentFrame(m_focusedBlockPt.x() - imageFocusPoint.x() , m_focusedBlockPt.y() - imageFocusPoint.y()); |
|
826 } |
|
827 |
|
828 m_focusedBlockPt = QPoint(block.geometry().topLeft()) - m_frame->scrollPosition(); |
|
829 } else { |
|
830 //Get doc size and current bottom right view corner point in document |
|
831 QSize viewSize = m_webPage->viewportSize(); |
|
832 QSize contentSize = m_frame->contentsSize(); |
|
833 QPoint documentViewPoint = QPoint(viewSize.width(),viewSize.height()) + m_frame->scrollPosition(); |
|
834 QPoint docFocusPoint; |
|
835 |
|
836 if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) |
|
837 docFocusPoint = KFocussPoint + m_frame->scrollPosition(); |
|
838 else { |
|
839 if((m_webPage->viewportSize().width() - block.geometry().width()) > 0) |
|
840 imageFocusPoint.setX((m_webPage->viewportSize().width() - block.geometry().width())/2); |
|
841 else |
|
842 imageFocusPoint.setX(0); |
|
843 |
|
844 if((m_webPage->viewportSize().height() - block.geometry().height()) > 0) |
|
845 imageFocusPoint.setY((m_webPage->viewportSize().height()- block.geometry().height())/2); |
|
846 else |
|
847 imageFocusPoint.setY(0); |
|
848 |
|
849 docFocusPoint = imageFocusPoint + m_frame->scrollPosition(); |
|
850 } |
|
851 |
|
852 m_focusedBlockPt = QPoint(block.geometry().x(), block.geometry().y()); |
|
853 m_scrollDistance.setX(m_focusedBlockPt.x() - docFocusPoint.x()); |
|
854 m_scrollDistance.setY(m_focusedBlockPt.y() - docFocusPoint.y()); |
|
855 |
|
856 QPoint scrollableDistance(0, 0); |
|
857 QPoint viewStartPoint = QPoint(0,0) + m_frame->scrollPosition(); |
|
858 |
|
859 if(m_scrollDistance.x() < 0) |
|
860 scrollableDistance.setX(viewStartPoint.x()); |
|
861 else |
|
862 scrollableDistance.setX(contentSize.width() - documentViewPoint.x()); |
|
863 |
|
864 |
|
865 if(m_scrollDistance.y() < 0) |
|
866 scrollableDistance.setY(viewStartPoint.y()); |
|
867 else |
|
868 scrollableDistance.setY(contentSize.height() - documentViewPoint.y()); |
|
869 |
|
870 if(abs(m_scrollDistance.x()) > abs(scrollableDistance.x())){ |
|
871 //m_scrollDistance.x() >= 0 means scroll from right to left |
|
872 if(m_scrollDistance.x() >= 0) |
|
873 m_focusedBlockPt.setX(m_focusedBlockPt.x() - abs(scrollableDistance.x())); |
|
874 //m_scrollDistance.x() < 0 means scroll from left to right |
|
875 else |
|
876 m_focusedBlockPt.setX(m_focusedBlockPt.x() + abs(scrollableDistance.x())); |
|
877 } else |
|
878 m_focusedBlockPt.setX(docFocusPoint.x()); |
|
879 |
|
880 if (abs(m_scrollDistance.y()) > abs(scrollableDistance.y())){ |
|
881 if(m_scrollDistance.y() >= 0) |
|
882 m_focusedBlockPt.setY(m_focusedBlockPt.y() - abs(scrollableDistance.y())); |
|
883 else |
|
884 m_focusedBlockPt.setY(m_focusedBlockPt.y() + abs(scrollableDistance.y())); |
|
885 } |
|
886 else |
|
887 m_focusedBlockPt.setY(docFocusPoint.y()); |
|
888 |
|
889 m_focusedBlockPt = m_focusedBlockPt - m_frame->scrollPosition(); |
|
890 startScrollTimer(); |
|
891 } |
|
892 m_view->setBlockElement(block); |
|
893 } |
|
894 } |
|
895 |
|
896 /*! |
|
897 Returns the next scrollable frame in the frame tree give the x,y position |
|
898 */ |
|
899 QWebFrame* GWebTouchNavigation::getNextScrollableFrame(const QPoint& pos) |
|
900 { |
|
901 QWebFrame* frame = m_frame; |
|
902 while (frame) { |
|
903 if (pos.x() > 0) { |
|
904 if (frame->scrollBarValue(Qt::Horizontal) < frame->scrollBarMaximum(Qt::Horizontal)) |
|
905 break; |
|
906 } |
|
907 else if (pos.x() < 0) { |
|
908 if (frame->scrollBarValue(Qt::Horizontal) > frame->scrollBarMinimum(Qt::Horizontal)) |
|
909 break; |
|
910 } |
|
911 |
|
912 if (pos.y() > 0) { |
|
913 if (frame->scrollBarValue(Qt::Vertical) < frame->scrollBarMaximum(Qt::Vertical)) |
|
914 break; |
|
915 } |
|
916 else if (pos.y() < 0) { |
|
917 if (frame->scrollBarValue(Qt::Vertical) > frame->scrollBarMinimum(Qt::Vertical)) |
|
918 break; |
|
919 } |
|
920 frame = frame->parentFrame(); |
|
921 } |
|
922 return (frame)?frame:m_webPage->mainFrame(); |
|
923 } |
|
924 |
|
925 /* |
|
926 Starts the timer for scrolling smoothly to the destination location . |
|
927 The timer will do the decelaration while scrolling |
|
928 */ |
|
929 void GWebTouchNavigation::startScrollTimer() |
|
930 { |
|
931 if(!m_scrollTimer) { |
|
932 m_scrollTimer = new QTimer(this); |
|
933 connect(m_scrollTimer,SIGNAL(timeout()),this,SLOT(scrollToEdge())); |
|
934 } |
|
935 m_scrollTimer->stop(); |
|
936 m_scrollTimer->start(KAnimationTimeout); |
|
937 } |
|
938 |
|
939 /* |
|
940 Update the scroll distance for flick gesture. Update the scroll distance upto the edge of the page |
|
941 */ |
|
942 void GWebTouchNavigation::updateFlickScrollDistance() |
|
943 { |
|
944 m_initialSpeed = speed(); |
|
945 m_initialSpeed.setX(qAbs(m_initialSpeed.x())); |
|
946 m_initialSpeed.setY(qAbs(m_initialSpeed.y())); |
|
947 m_flickDirection = findDirectionWithAngle(m_dragPoints.first().iPoint - m_dragPoints.last().iPoint); |
|
948 m_scrollDistance.setX((m_initialSpeed.x() * m_initialSpeed.x())/( 2 * KDeccelaration)); |
|
949 m_scrollDistance.setY((m_initialSpeed.y() * m_initialSpeed.y())/( 2 * KDeccelaration)); |
|
950 |
|
951 m_scrollDistance.setX(m_view->zoomFactor() * m_scrollDistance.x() / m_view->initialScale()); |
|
952 m_scrollDistance.setY(m_view->zoomFactor() * m_scrollDistance.y() / m_view->initialScale()); |
|
953 |
|
954 QSize viewSize = m_webPage->viewportSize(); |
|
955 QSize contentSize = m_frame->contentsSize(); |
|
956 QPoint documentViewPoint = QPoint(viewSize.width(),viewSize.height()) + m_frame->scrollPosition(); |
|
957 QPoint documentTouchPoint = m_touchPosition + m_frame->scrollPosition();; |
|
958 |
|
959 switch(m_flickDirection) |
|
960 { |
|
961 case DOWN : |
|
962 m_scrollDistance.setX(0); |
|
963 m_scrollDistance.setY(-(m_scrollDistance.y())); |
|
964 |
|
965 if(m_scrollDistance.y() < -(documentTouchPoint.y() - m_touchPosition.y())) |
|
966 m_scrollDistance.setY(-(documentTouchPoint.y() - m_touchPosition.y())); |
|
967 break; |
|
968 case UP : |
|
969 m_scrollDistance.setX(0); |
|
970 if(m_scrollDistance.y() > (contentSize.height() - documentViewPoint.y())) |
|
971 m_scrollDistance.setY(contentSize.height() - documentViewPoint.y()); |
|
972 break; |
|
973 case RIGHT: |
|
974 m_scrollDistance.setX(-(m_scrollDistance.x())); |
|
975 if(m_scrollDistance.x() < -(documentTouchPoint.x() - m_touchPosition.x())) |
|
976 m_scrollDistance.setX(-(documentTouchPoint.x() - m_touchPosition.x())); |
|
977 m_scrollDistance.setY(0); |
|
978 break; |
|
979 case LEFT: |
|
980 m_scrollDistance.setY(0); |
|
981 if(m_scrollDistance.x() > (contentSize.width() - documentViewPoint.x())) |
|
982 m_scrollDistance.setX(contentSize.width() - documentViewPoint.x()); |
|
983 break; |
|
984 case BOTTOMRIGHT: |
|
985 m_scrollDistance.setX(-(m_scrollDistance.x())); |
|
986 m_scrollDistance.setY(-(m_scrollDistance.y())); |
|
987 if(m_scrollDistance.x() < -(documentTouchPoint.x()-m_touchPosition.x())) |
|
988 m_scrollDistance.setX(-(documentTouchPoint.x()-m_touchPosition.x())); |
|
989 if(m_scrollDistance.y() < -((documentTouchPoint.y()-m_touchPosition.y())/2)) |
|
990 m_scrollDistance.setY(-((documentTouchPoint.y()-m_touchPosition.y())/2)); |
|
991 break; |
|
992 case BOTTOMLEFT: |
|
993 m_scrollDistance.setY(-(m_scrollDistance.y())); |
|
994 if(m_scrollDistance.x() > contentSize.width()-documentViewPoint.x()) |
|
995 m_scrollDistance.setX(contentSize.width()-documentViewPoint.x()); |
|
996 if(m_scrollDistance.y() < (-((documentTouchPoint.y()-m_touchPosition.y())/2))) |
|
997 m_scrollDistance.setY(-((documentTouchPoint.y()-m_touchPosition.y())/2)); |
|
998 break; |
|
999 case TOPLEFT: |
|
1000 if(m_scrollDistance.x() > (contentSize.width()-documentViewPoint.x())) |
|
1001 m_scrollDistance.setX(contentSize.width()-documentViewPoint.x()); |
|
1002 if(m_scrollDistance.y() > ((contentSize.height()-documentViewPoint.y())/2)) |
|
1003 m_scrollDistance.setY((contentSize.height()-documentViewPoint.y())/2); |
|
1004 break; |
|
1005 case TOPRIGHT: |
|
1006 m_scrollDistance.setX(-(m_scrollDistance.x())); |
|
1007 if(m_scrollDistance.x() < (-(documentTouchPoint.x()-m_touchPosition.x()))) |
|
1008 m_scrollDistance.setX(-(documentTouchPoint.x()-m_touchPosition.x())); |
|
1009 if(m_scrollDistance.y() > ((contentSize.height()-documentViewPoint.y())/2)) |
|
1010 m_scrollDistance.setY((contentSize.height()-documentViewPoint.y())/2); |
|
1011 break; |
|
1012 } |
|
1013 } |
|
1014 |
|
1015 /* |
|
1016 Distinguishes b/w swipe and flick |
|
1017 */ |
|
1018 bool GWebTouchNavigation::isFlick() |
|
1019 { |
|
1020 bool flick = false; |
|
1021 QPoint moveSpeed = speed(); |
|
1022 int xSpeed = moveSpeed.x(); |
|
1023 int ySpeed = moveSpeed.y(); |
|
1024 |
|
1025 flick = (qAbs(xSpeed) > KFlickSpeed || |
|
1026 qAbs(ySpeed) > KFlickSpeed); |
|
1027 |
|
1028 return flick; |
|
1029 } |
|
1030 |
|
1031 /* |
|
1032 Calculates the speed of te scroll along x-axis and y-axis |
|
1033 */ |
|
1034 QPoint GWebTouchNavigation::speed() |
|
1035 { |
|
1036 // Speed is only evaluated at the end of the swipe |
|
1037 QPoint dragSpeed(0,0); |
|
1038 qreal time = dragTime() / KMilliSecond; |
|
1039 if (time > 0) { |
|
1040 QPoint distance = currentPos() - previousPos(); |
|
1041 dragSpeed.setX((distance.x()) / time); |
|
1042 dragSpeed.setY((distance.y()) / time); |
|
1043 } |
|
1044 return dragSpeed; |
|
1045 } |
|
1046 |
|
1047 /* |
|
1048 Returns the last point in the m_dragPoints list |
|
1049 */ |
|
1050 QPoint GWebTouchNavigation::currentPos() |
|
1051 { |
|
1052 return m_dragPoints[m_dragPoints.size()-1].iPoint; |
|
1053 } |
|
1054 |
|
1055 /* |
|
1056 Returns the first point in the m_dragPoints list |
|
1057 */ |
|
1058 QPoint GWebTouchNavigation::previousPos() |
|
1059 { |
|
1060 return m_dragPoints[0].iPoint; |
|
1061 } |
|
1062 |
|
1063 /* |
|
1064 Finds the time difference b/w the first and last dragpoint |
|
1065 */ |
|
1066 qreal GWebTouchNavigation::dragTime() const |
|
1067 { |
|
1068 if(m_dragPoints.isEmpty()) |
|
1069 return 0.0; |
|
1070 else |
|
1071 return m_dragPoints[0].iTime.msecsTo(m_dragPoints[m_dragPoints.size()-1].iTime); |
|
1072 } |
|
1073 |
|
1074 /*! |
|
1075 Find the flick direction with respect to angle of flick |
|
1076 */ |
|
1077 Direction GWebTouchNavigation::findDirectionWithAngle(const QPoint& diff) |
|
1078 { |
|
1079 Direction direction; |
|
1080 int xDelta = -diff.x(); |
|
1081 int yDelta = -diff.y(); |
|
1082 |
|
1083 qreal angle = findAngle(xDelta, yDelta); |
|
1084 if(isNear(angle, 60.0, 120.0)) { |
|
1085 direction = DOWN; |
|
1086 } |
|
1087 else if(isNear(angle, 150.0, 210.0)) { |
|
1088 direction = LEFT; |
|
1089 } |
|
1090 else if(isNear(angle, 240.0, 300.0)) { |
|
1091 direction = UP; |
|
1092 } |
|
1093 else if(360.0 - KAngleTolerance <= angle || angle <= KAngleTolerance) { |
|
1094 direction = RIGHT; |
|
1095 } |
|
1096 else if(isNear(angle, 30.0, 60.0)) { |
|
1097 direction = BOTTOMRIGHT; |
|
1098 } |
|
1099 else if(isNear(angle, 120.0, 150.0)) { |
|
1100 direction = BOTTOMLEFT; |
|
1101 } |
|
1102 else if(isNear(angle, 210.0, 240.0)) { |
|
1103 direction = TOPLEFT; |
|
1104 } |
|
1105 else if(isNear(angle, 300.0, 330.0)) { |
|
1106 direction = TOPRIGHT; |
|
1107 } |
|
1108 |
|
1109 return direction; |
|
1110 } |
|
1111 |
|
1112 /* |
|
1113 Check the angle is in the range of aMinAngle and aMaxAngle |
|
1114 */ |
|
1115 bool GWebTouchNavigation::isNear(qreal angleUnderTest, qreal minAngle, qreal maxAngle) |
|
1116 { |
|
1117 return (minAngle < angleUnderTest) && (angleUnderTest <= maxAngle); |
|
1118 } |
|
1119 |
|
1120 /* |
|
1121 Find the angle from x and y displacement |
|
1122 */ |
|
1123 qreal GWebTouchNavigation::findAngle(const int& xDelta,const int& yDelta) |
|
1124 { |
|
1125 qreal angle = 0; |
|
1126 qreal hypotenuse = qSqrt(xDelta*xDelta + yDelta*yDelta); |
|
1127 |
|
1128 if(hypotenuse != 0) { |
|
1129 angle = qAcos(xDelta / hypotenuse); |
|
1130 |
|
1131 if(yDelta < 0) { |
|
1132 angle = (2 * PI) - angle; |
|
1133 } |
|
1134 } |
|
1135 |
|
1136 return (angle * 180) / PI; |
|
1137 } |
|
1138 |
|
1139 int GWebTouchNavigation::roundOff(qreal num) |
|
1140 { |
|
1141 return (num + 0.5); |
|
1142 } |
|
1143 |
|
1144 /* |
|
1145 Finds out the enclosing block |
|
1146 */ |
|
1147 QRect GWebTouchNavigation::findEnclosingBlock(QMouseEvent* ev) |
|
1148 { |
|
1149 QWebHitTestResult htr = getHitTestResult(ev); |
|
1150 QRect rect = htr.enclosingBlockElement().geometry(); |
|
1151 return rect; |
|
1152 } |
|
1153 |
|
1154 /* |
|
1155 Gets the hitTestResult for a particular event |
|
1156 */ |
|
1157 QWebHitTestResult GWebTouchNavigation::getHitTestResult(QMouseEvent* ev) |
|
1158 { |
|
1159 QPoint pt = ev->pos(); |
|
1160 QWebFrame* frame = m_webPage->frameAt(pt); |
|
1161 frame = (frame) ? frame : m_webPage->mainFrame(); |
|
1162 QWebHitTestResult htr = frame->hitTestContent(pt); |
|
1163 return htr; |
|
1164 } |
|
1165 |
|
1166 /* |
|
1167 Finds out the scroll distance associated with a swipe |
|
1168 */ |
|
1169 void GWebTouchNavigation::calculateActualScrollDistance() |
|
1170 { |
|
1171 m_actualScrollDistance.setX(0); |
|
1172 m_actualScrollDistance.setY(0); |
|
1173 if (!m_dragPoints.isEmpty()) { |
|
1174 QPoint distance = previousPos() - currentPos(); |
|
1175 if (qAbs(distance.x()) > 0 || qAbs(distance.y()) > 0) { |
|
1176 m_actualScrollDistance = distance / m_dragPoints.size() * 2; |
|
1177 } |
|
1178 } |
|
1179 } |
|
1180 |
|
1181 /* |
|
1182 In the case of slow swipe, if the destination location lies within the threshold area, then |
|
1183 we need to align the block to te left edge of the mobile screen. This method finds out the |
|
1184 new scroll distance |
|
1185 */ |
|
1186 void GWebTouchNavigation::setNewScrollDistance(QPoint blockCanvasPoint, int thresholdCheckVal) |
|
1187 { |
|
1188 m_scrollDistance.setX(m_actualScrollDistance.x()); |
|
1189 m_scrollDistance.setY(m_actualScrollDistance.y()); |
|
1190 if(blockCanvasPoint.x() > 0) { |
|
1191 //Checks whether the block falls within the threshold after right to left swipe |
|
1192 if( (thresholdCheckVal < KThresholdForRightToLeftMotion) && (thresholdCheckVal > 0)) { |
|
1193 //if the block is within the threshold range already and the user tries |
|
1194 //to swipe from left to right , then let it move to right. Dont try to |
|
1195 //snap to the left edge . |
|
1196 if(m_actualScrollDistance.x() > 0) { |
|
1197 m_scrollDistance.setX(blockCanvasPoint.x() - XAlignVal); |
|
1198 } |
|
1199 } |
|
1200 } |
|
1201 else { |
|
1202 //Checks whether the block falls within the threshold after left to right swipe |
|
1203 if( (thresholdCheckVal > KThresholdForLeftToRightMotion) && (thresholdCheckVal < 0)) { |
|
1204 //if the block is within the threshold range already and the user tries |
|
1205 //to swipe from right to left , then let it move to left. Dont try to |
|
1206 //snap to the left edge . |
|
1207 if (m_actualScrollDistance.x() < 0) { |
|
1208 m_scrollDistance.setX(blockCanvasPoint.x() - XAlignVal); |
|
1209 } |
|
1210 } |
|
1211 |
|
1212 } |
|
1213 } |
|
1214 |
|
1215 |
|
1216 /* |
|
1217 SLOT associated with the timer to adjust the scroll to the edge |
|
1218 */ |
|
1219 void GWebTouchNavigation::scrollToEdge() |
|
1220 { |
|
1221 m_prevPoint.setX(m_scrollDistance.x()); |
|
1222 m_prevPoint.setY(m_scrollDistance.y()); |
|
1223 |
|
1224 m_scrollDistance.setX(m_scrollDistance.x() * KDecelerationFactor); |
|
1225 m_scrollDistance.setY(m_scrollDistance.y() * KDecelerationFactor); |
|
1226 |
|
1227 //round off the values |
|
1228 m_scrollDistance.setX(roundOff(m_scrollDistance.x())); |
|
1229 m_scrollDistance.setY(roundOff(m_scrollDistance.y())); |
|
1230 |
|
1231 int diffX = m_prevPoint.x() - m_scrollDistance.x(); |
|
1232 int diffY = m_prevPoint.y() - m_scrollDistance.y(); |
|
1233 |
|
1234 if (((m_scrollDistance.x() == 0) && (m_scrollDistance.y() == 0)) |
|
1235 || ((diffX == 0) && (diffY == 0))) { |
|
1236 scrollCurrentFrame(m_prevPoint.x(), m_prevPoint.y()); |
|
1237 m_scrollTimer->stop(); |
|
1238 return; |
|
1239 } |
|
1240 scrollCurrentFrame(diffX, diffY); |
|
1241 } |
|
1242 void GWebTouchNavigation::timerControl() |
|
1243 { |
|
1244 stopTimer();// stop timer as soon as timeout |
|
1245 emit longPressEvent(); |
|
1246 } |
|
1247 void GWebTouchNavigation::startTimer() |
|
1248 { |
|
1249 m_longPressTimer = new QTimer(this); |
|
1250 connect(m_longPressTimer,SIGNAL(timeout()),this,SLOT(timerControl())); |
|
1251 m_longPressTimer->start(LONG_PRESS_DURATION); |
|
1252 } |
|
1253 void GWebTouchNavigation::stopTimer() |
|
1254 { |
|
1255 if(m_longPressTimer){ |
|
1256 m_longPressTimer->stop(); |
|
1257 delete m_longPressTimer; |
|
1258 m_longPressTimer = 0; |
|
1259 } |
|
1260 } |
|
1261 void GWebTouchNavigation::getFocusedElement() |
|
1262 { |
|
1263 QWebHitTestResult htRes = m_frame->hitTestContent(m_touchPosition); |
|
1264 wrtBrowserDefs::BrowserElementType elType = wrtBrowserUtils::getTypeFromElement(htRes); |
|
1265 emit focusElementChanged(elType); |
|
1266 } |
|
1267 |
|
1268 void GWebTouchNavigation::scrollCurrentFrame (int dx, int dy) |
|
1269 { |
|
1270 QPoint scrollPosition = m_frame->scrollPosition(); |
|
1271 if (m_frame == m_webPage->mainFrame() && |
|
1272 //scrollPosition.y() < m_chrome->getSnippetRect("UrlSearchChromeId").height()) { |
|
1273 scrollPosition.y() <=0 && |
|
1274 !m_isLoading && |
|
1275 !m_view->view()->currentPageIsSuperPage()) { |
|
1276 qreal slide = m_chrome->slideView(-dy); |
|
1277 dy+=slide; |
|
1278 } |
|
1279 |
|
1280 m_frame->scroll(dx, dy); |
|
1281 } |
|
1282 |
|
1283 void GWebTouchNavigation::setCurrentFrameScrollPosition (QPoint& pos) |
|
1284 { |
|
1285 QPoint scrollPosition = m_frame->scrollPosition(); |
|
1286 QPoint finalPos = pos; |
|
1287 |
|
1288 |
|
1289 /* emit pageScrollPositionZero singal if it's mainFrame scrolling or scroll to top*/ |
|
1290 if (m_frame == m_webPage->mainFrame() && |
|
1291 //scrollPosition.y() < m_chrome->getSnippetRect("UrlSearchChromeId").height()) { |
|
1292 scrollPosition.y() <=0 && |
|
1293 !m_isLoading && |
|
1294 !m_view->view()->currentPageIsSuperPage()) { |
|
1295 |
|
1296 int dy = scrollPosition.y() - pos.y(); |
|
1297 qreal slide = m_chrome->slideView(-dy); |
|
1298 dy+=slide; |
|
1299 finalPos.setY(scrollPosition.y() - dy); |
|
1300 } |
|
1301 |
|
1302 m_frame->setScrollPosition(finalPos); |
|
1303 } |
|
1304 |
|
1305 void GWebTouchNavigation::onLoadStarted() |
|
1306 { |
|
1307 m_isLoading = true; |
|
1308 } |
|
1309 void GWebTouchNavigation::onLoadFinished(bool ok) |
|
1310 { |
|
1311 m_isLoading = false; |
|
1312 } |
|
1313 void GWebTouchNavigation::setPage( QWebPage * page) |
|
1314 { |
|
1315 disconnect(m_webPage, SIGNAL(loadStarted()), this, SLOT(onLoadStarted())); |
|
1316 disconnect(m_webPage, SIGNAL(loadFinished(bool)), this, SLOT(onLoadFinished(bool))); |
|
1317 m_webPage = page ; |
|
1318 connect(m_webPage, SIGNAL(loadStarted()), this, SLOT(onLoadStarted())); |
|
1319 connect(m_webPage, SIGNAL(loadFinished(bool)), this, SLOT(onLoadFinished(bool))); |
|
1320 } |
|
1321 } |