Changeset 71393 in webkit
- Timestamp:
- Nov 4, 2010 10:08:02 PM (13 years ago)
- Location:
- trunk/WebKit/qt
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebKit/qt/Api/qwebpage.cpp
r70999 r71393 32 32 #include "qwebinspector_p.h" 33 33 #include "qwebsettings.h" 34 #include "qwebkitplatformplugin.h" 34 35 #include "qwebkitversion.h" 35 36 37 #include "CSSComputedStyleDeclaration.h" 38 #include "CSSParser.h" 36 39 #include "ApplicationCacheStorage.h" 37 40 #include "BackForwardListImpl.h" … … 39 42 #include "Chrome.h" 40 43 #include "ChromeClientQt.h" 44 #include "ClientRect.h" 41 45 #include "ContextMenu.h" 42 46 #include "ContextMenuClientQt.h" … … 61 65 #include "GeolocationPermissionClientQt.h" 62 66 #include "HTMLFormElement.h" 67 #include "HTMLFrameOwnerElement.h" 63 68 #include "HTMLInputElement.h" 64 69 #include "HTMLNames.h" … … 75 80 #include "NavigationAction.h" 76 81 #include "NetworkingContext.h" 82 #include "NodeList.h" 77 83 #include "NotificationPresenterClientQt.h" 84 #include "NotImplemented.h" 78 85 #include "Page.h" 79 86 #include "PageClientQt.h" … … 87 94 #include "PluginPackage.h" 88 95 #include "ProgressTracker.h" 96 #include "QtPlatformPlugin.h" 89 97 #include "RefPtr.h" 90 98 #include "RenderTextControl.h" … … 658 666 659 667 bool accepted = false; 668 adjustPointForClicking(ev); 660 669 PlatformMouseEvent mev(ev, 1); 661 670 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton … … 737 746 738 747 bool accepted = false; 748 adjustPointForClicking(ev); 739 749 PlatformMouseEvent mev(ev, 0); 740 750 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton … … 1262 1272 1263 1273 return frame->eventHandler()->scrollRecursively(direction, granularity); 1274 } 1275 1276 void QWebPagePrivate::adjustPointForClicking(QMouseEvent*) 1277 { 1278 notImplemented(); 1279 } 1280 1281 void QWebPagePrivate::adjustPointForClicking(QGraphicsSceneMouseEvent* ev) 1282 { 1283 QtPlatformPlugin platformPlugin; 1284 QWebTouchModifier* touchModifier = platformPlugin.createTouchModifier(); 1285 if (!touchModifier) 1286 return; 1287 1288 unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up); 1289 unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right); 1290 unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down); 1291 unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left); 1292 1293 delete touchModifier; 1294 touchModifier = 0; 1295 1296 if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) 1297 return; 1298 1299 Document* startingDocument = page->mainFrame()->document(); 1300 if (!startingDocument) 1301 return; 1302 1303 IntPoint originalPoint(QPointF(ev->pos()).toPoint()); 1304 TouchAdjuster touchAdjuster(topPadding, rightPadding, bottomPadding, leftPadding); 1305 IntPoint adjustedPoint = touchAdjuster.findCandidatePointForTouch(originalPoint, startingDocument); 1306 if (adjustedPoint == IntPoint::zero()) 1307 return; 1308 1309 ev->setPos(QPointF(adjustedPoint)); 1264 1310 } 1265 1311 … … 1428 1474 #endif 1429 1475 return 0; 1476 } 1477 1478 static bool hasMouseListener(Element* element) 1479 { 1480 ASSERT(element); 1481 return element->hasEventListeners(eventNames().clickEvent) 1482 || element->hasEventListeners(eventNames().mousedownEvent) 1483 || element->hasEventListeners(eventNames().mouseupEvent); 1484 } 1485 1486 static bool isClickableElement(Element* element, RefPtr<NodeList> list) 1487 { 1488 ASSERT(element); 1489 bool isClickable = hasMouseListener(element); 1490 if (!isClickable && list) { 1491 Element* parent = element->parentElement(); 1492 unsigned count = list->length(); 1493 for (unsigned i = 0; i < count && parent; i++) { 1494 if (list->item(i) != parent) 1495 continue; 1496 1497 isClickable = hasMouseListener(parent); 1498 if (isClickable) 1499 break; 1500 1501 parent = parent->parentElement(); 1502 } 1503 } 1504 1505 ExceptionCode ec = 0; 1506 return isClickable 1507 || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec) 1508 || computedStyle(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer"; 1509 } 1510 1511 static bool isValidFrameOwner(Element* element) 1512 { 1513 ASSERT(element); 1514 return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame(); 1515 } 1516 1517 static Element* nodeToElement(Node* node) 1518 { 1519 if (node && node->isElementNode()) 1520 return static_cast<Element*>(node); 1521 return 0; 1522 } 1523 1524 QWebPagePrivate::TouchAdjuster::TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding) 1525 : m_topPadding(topPadding) 1526 , m_rightPadding(rightPadding) 1527 , m_bottomPadding(bottomPadding) 1528 , m_leftPadding(leftPadding) 1529 { 1530 } 1531 1532 IntPoint QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch(const IntPoint& touchPoint, Document* document) const 1533 { 1534 if (!document) 1535 return IntPoint(); 1536 1537 int x = touchPoint.x(); 1538 int y = touchPoint.y(); 1539 1540 RefPtr<NodeList> intersectedNodes = document->nodesFromRect(x, y, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding, false); 1541 if (!intersectedNodes) 1542 return IntPoint(); 1543 1544 Element* closestClickableElement = 0; 1545 IntRect largestIntersectionRect; 1546 FrameView* view = document->frame()->view(); 1547 1548 // Touch rect in contents coordinates. 1549 IntRect touchRect(HitTestResult::rectForPoint(view->windowToContents(IntPoint(x, y)), m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding)); 1550 1551 // Iterate over the list of nodes hit looking for the one whose bounding area 1552 // has largest intersection with the touch area (point + padding). 1553 for (unsigned i = 0; i < intersectedNodes->length(); i++) { 1554 Node* currentNode = intersectedNodes->item(i); 1555 1556 Element* currentElement = nodeToElement(currentNode); 1557 if (!currentElement || (!isClickableElement(currentElement, 0) && !isValidFrameOwner(currentElement))) 1558 continue; 1559 1560 IntRect currentElementBoundingRect = currentElement->getRect(); 1561 currentElementBoundingRect.intersect(touchRect); 1562 1563 if (currentElementBoundingRect.isEmpty()) 1564 continue; 1565 1566 int currentIntersectionRectArea = currentElementBoundingRect.width() * currentElementBoundingRect.height(); 1567 int largestIntersectionRectArea = largestIntersectionRect.width() * largestIntersectionRect.height(); 1568 if (currentIntersectionRectArea > largestIntersectionRectArea) { 1569 closestClickableElement = currentElement; 1570 largestIntersectionRect = currentElementBoundingRect; 1571 } 1572 } 1573 1574 if (largestIntersectionRect.isEmpty()) 1575 return IntPoint(); 1576 1577 // Handle the case when user taps a inner frame. It is done in three steps: 1578 // 1) Transform the original touch point to the inner document coordinates; 1579 // 1) Call nodesFromRect for the inner document in case; 1580 // 3) Re-add the inner frame offset (location) before passing the new clicking 1581 // position to WebCore. 1582 if (closestClickableElement->isFrameOwnerElement()) { 1583 // Adjust client coordinates' origin to be top left of inner frame viewport. 1584 PassRefPtr<ClientRect> rect = closestClickableElement->getBoundingClientRect(); 1585 IntPoint newTouchPoint = touchPoint; 1586 IntSize offset = IntSize(rect->left(), rect->top()); 1587 newTouchPoint -= offset; 1588 1589 HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(closestClickableElement); 1590 Document* childDocument = owner->contentFrame()->document(); 1591 return findCandidatePointForTouch(newTouchPoint, childDocument); 1592 } 1593 return view->contentsToWindow(largestIntersectionRect).center(); 1430 1594 } 1431 1595 -
trunk/WebKit/qt/Api/qwebpage_p.h
r69331 r71393 32 32 #include "qwebframe.h" 33 33 34 #include "IntPoint.h" 34 35 #include "KURL.h" 35 36 #include "PlatformString.h" … … 44 45 class ContextMenuItem; 45 46 class ContextMenu; 47 class Document; 46 48 class EditorClientQt; 47 49 class Element; 48 50 class InspectorController; 51 class IntRect; 49 52 class Node; 53 class NodeList; 50 54 class Page; 51 55 class Frame; … … 127 131 bool touchEvent(QTouchEvent*); 128 132 133 class TouchAdjuster { 134 public: 135 TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding); 136 137 WebCore::IntPoint findCandidatePointForTouch(const WebCore::IntPoint&, WebCore::Document*) const; 138 139 private: 140 unsigned m_topPadding; 141 unsigned m_rightPadding; 142 unsigned m_bottomPadding; 143 unsigned m_leftPadding; 144 }; 145 146 void adjustPointForClicking(QMouseEvent*); 147 void adjustPointForClicking(QGraphicsSceneMouseEvent*); 148 129 149 void setInspector(QWebInspector*); 130 150 QWebInspector* getOrCreateInspector(); -
trunk/WebKit/qt/ChangeLog
r71388 r71393 1 2010-11-03 Antonio Gomes <tonikitoo@webkit.org>, Andre Pedralho <andre.pedralho@gmail.com> 2 3 Reviewed by Kenneth Rohde Christiansen and Antti Koivisto. 4 5 [Qt] Making effective use of nodesFromRect. 6 https://bugs.webkit.org/show_bug.cgi?id=44089 7 8 Patch adds a helper class (named TouchAdjuster) to improve tap actions 9 on mobile touch devices. TouchAdjuster makes use of the newly added rect 10 based hit test extension through the Document::nodesFromRect method. 11 Given a rectangle as input, nodesFromRect returns a z-index ordered list 12 of nodes whose boundaries intersect the rectangle. 13 14 Basically the TouchAdjuster class intercepts the QGraphicsSceneMouseEvent 15 passed to both QWebPagePrivate::mouse{Press,Release}Event methods before 16 they are passed down to WebCore. The goal is to infer the target click position. 17 For that, a rectangle is built up using the event position as a center point and 18 expanding it based on the values and directions set in the Platform Plugin 19 QWebTouchModifier::hitTestPadding. 20 21 TouchAdjuster iterates over the list of nodes returned by nodesFromRect and 22 picks the clickable one that has the largest intersection area with the hit 23 test rectangle. The target position is then the center point of this intersection 24 area. 25 26 In case of no clickable node intersects the hit test area, the click position 27 is not altered. 28 29 TouchAdjuster is *only* working for QGraphicsWebView based views. 30 31 * Api/qwebpage.cpp: 32 (QWebPagePrivate::mousePressEvent): 33 (QWebPagePrivate::mouseReleaseEvent): 34 (QWebPagePrivate::adjustPointForClicking): 35 (QWebPagePrivate::TouchAdjuster::TouchAdjuster): 36 (QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch): 37 (isClickableElement): 38 (hasMouseListener): 39 (isValidFrameOwner): 40 (nodeToElement): 41 * Api/qwebpage_p.h: 42 1 43 2010-10-20 Chang Shu <chang.shu@nokia.com>, Antonio Gomes <tonikitoo@webkit.org> 2 44
Note: See TracChangeset
for help on using the changeset viewer.