のねのBlog

パソコンの問題や、ソフトウェアの開発で起きた問題など書いていきます。よろしくお願いします^^。

no rect-based-test nodes found

   1285 HTMLElement* WebViewCore::retrieveElement(int x, int y,
   1286     const QualifiedName& tagName)
   1287 {
   1288     HitTestResult hitTestResult = m_mainFrame->eventHandler()
   1289         ->hitTestResultAtPoint(IntPoint(x, y), false, false,
   1290         DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
   1291         IntSize(1, 1));
   1292     if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
   1293         ALOGE("Should not happen: no in document Node found");
   1294         return 0;
   1295     }
   1296     const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
   1297     if (list.isEmpty()) {
   1298         ALOGE("Should not happen: no rect-based-test nodes found");
   1299         return 0;
   1300     }
   1301     Node* node = hitTestResult.innerNode();
   1302     Node* element = node;
   1303     while (element && (!element->isElementNode()
   1304         || !element->hasTagName(tagName))) {
   1305         element = element->parentNode();
   1306     }
   1307     return static_cast<WebCore::HTMLElement*>(element);
   1308 }
  1836 // get the highlight rectangles for the touch point (x, y) with the slop
   1837 AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool doMoveMouse)
   1838 {
   1839     if (doMoveMouse)
   1840         moveMouse(x, y, 0, true);
   1841     HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
   1842             false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(slop, slop));
   1843     AndroidHitTestResult androidHitResult(this, hitTestResult);
   1844     if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
   1845         ALOGE("Should not happen: no in document Node found");
   1846         return androidHitResult;
   1847     }
   1848     const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
   1849     if (list.isEmpty()) {
   1850         ALOGE("Should not happen: no rect-based-test nodes found");
   1851         return androidHitResult;
   1852     }
   1853     Frame* frame = hitTestResult.innerNode()->document()->frame();
   1854     Vector<TouchNodeData> nodeDataList;
   1855     if (hitTestResult.innerNode() != hitTestResult.innerNonSharedNode()
   1856             && hitTestResult.innerNode()->hasTagName(WebCore::HTMLNames::areaTag)) {
   1857         HTMLAreaElement* area = static_cast<HTMLAreaElement*>(hitTestResult.innerNode());
   1858         androidHitResult.hitTestResult().setURLElement(area);
   1859         androidHitResult.highlightRects().append(area->computeRect(
   1860                 hitTestResult.innerNonSharedNode()->renderer()));
   1861         return androidHitResult;
   1862     }
   1863     ListHashSet<RefPtr<Node> >::const_iterator last = list.end();
   1864     for (ListHashSet<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) {
   1865         // TODO: it seems reasonable to not search across the frame. Isn't it?
   1866         // if the node is not in the same frame as the innerNode, skip it
   1867         if (it->get()->document()->frame() != frame)
   1868             continue;
   1869         // traverse up the tree to find the first node that needs highlight
   1870         bool found = false;
   1871         Node* eventNode = it->get();
   1872         Node* innerNode = eventNode;
   1873         while (eventNode) {
   1874             RenderObject* render = eventNode->renderer();
   1875             if (render && (render->isBody() || render->isRenderView()))
   1876                 break;
   1877             if (nodeIsClickableOrFocusable(eventNode)) {
   1878                 found = true;
   1879                 break;
   1880             }
   1881             // the nodes in the rectBasedTestResult() are ordered based on z-index during hit testing.
   1882             // so do not search for the eventNode across explicit z-index border.
   1883             // TODO: this is a hard one to call. z-index is quite complicated as its value only
   1884             // matters when you compare two RenderLayer in the same hierarchy level. e.g. in
   1885             // the following example, "b" is on the top as its z level is the highest. even "c"
   1886             // has 100 as z-index, it is still below "d" as its parent has the same z-index as
   1887             // "d" and logically before "d". Of course "a" is the lowest in the z level.
   1888             //
   1889             // z-index:auto "a"
   1890             //   z-index:2 "b"
   1891             //   z-index:1
   1892             //     z-index:100 "c"
   1893             //   z-index:1 "d"
   1894             //
   1895             // If the fat point touches everyone, the order in the list should be "b", "d", "c"
   1896             // and "a". When we search for the event node for "b", we really don't want "a" as
   1897             // in the z-order it is behind everything else.
   1898             if (render && !render->style()->hasAutoZIndex())
   1899                 break;
   1900             eventNode = eventNode->parentNode();
   1901         }
   1902         // didn't find any eventNode, skip it
   1903         if (!found)
   1904             continue;
   1905         // first quick check whether it is a duplicated node before computing bounding box
   1906         Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
   1907         for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
   1908             // found the same node, skip it
   1909             if (eventNode == n->mUrlNode) {
   1910                 found = false;
   1911                 break;
   1912             }
   1913         }
   1914         if (!found)
   1915             continue;
   1916         // next check whether the node is fully covered by or fully covering another node.
   1917         found = false;
   1918         IntRect rect = getAbsoluteBoundingBox(eventNode);
   1919         if (rect.isEmpty()) {
   1920             // if the node's bounds is empty and it is not a ContainerNode, skip it.
   1921             if (!eventNode->isContainerNode())
   1922                 continue;
   1923             // if the node's children are all positioned objects, its bounds can be empty.
   1924             // Walk through the children to find the bounding box.
   1925             Node* child = static_cast<const ContainerNode*>(eventNode)->firstChild();
   1926             while (child) {
   1927                 IntRect childrect;
   1928                 if (child->renderer())
   1929                     childrect = getAbsoluteBoundingBox(child);
   1930                 if (!childrect.isEmpty()) {
   1931                     rect.unite(childrect);
   1932                     child = child->traverseNextSibling(eventNode);
   1933                 } else
   1934                     child = child->traverseNextNode(eventNode);
   1935             }
   1936         }
   1937         for (int i = nodeDataList.size() - 1; i >= 0; i--) {
   1938             TouchNodeData n = nodeDataList.at(i);
   1939             // the new node is enclosing an existing node, skip it
   1940             if (rect.contains(n.mBounds)) {
   1941                 found = true;
   1942                 break;
   1943             }
   1944             // the new node is fully inside an existing node, remove the existing node
   1945             if (n.mBounds.contains(rect))
   1946                 nodeDataList.remove(i);
   1947         }
   1948         if (!found) {
   1949             TouchNodeData newNode;
   1950             newNode.mUrlNode = eventNode;
   1951             newNode.mBounds = rect;
   1952             newNode.mInnerNode = innerNode;
   1953             nodeDataList.append(newNode);
   1954         }
   1955     }
   1956     if (!nodeDataList.size()) {
   1957         androidHitResult.searchContentDetectors();
   1958         return androidHitResult;
   1959     }
   1960     // finally select the node with the largest overlap with the fat point
   1961     TouchNodeData final;
   1962     final.mUrlNode = 0;
   1963     IntPoint docPos = frame->view()->windowToContents(m_mousePos);
   1964     IntRect testRect(docPos.x() - slop, docPos.y() - slop, 2 * slop + 1, 2 * slop + 1);
   1965     int area = 0;
   1966     Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
   1967     for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
   1968         IntRect rect = n->mBounds;
   1969         rect.intersect(testRect);
   1970         int a = rect.width() * rect.height();
   1971         if (a > area || !final.mUrlNode) {
   1972             final = *n;
   1973             area = a;
   1974         }
   1975     }
   1976     // now get the node's highlight rectangles in the page coordinate system
   1977     if (final.mUrlNode) {
   1978         // Update innerNode and innerNonSharedNode
   1979         androidHitResult.hitTestResult().setInnerNode(final.mInnerNode);
   1980         androidHitResult.hitTestResult().setInnerNonSharedNode(final.mInnerNode);
   1981         if (final.mUrlNode->isElementNode()) {
   1982             // We found a URL element. Update the hitTestResult
   1983             androidHitResult.setURLElement(static_cast<Element*>(final.mUrlNode));
   1984         } else {
   1985             androidHitResult.setURLElement(0);
   1986         }
   1987         Vector<IntRect>& highlightRects = androidHitResult.highlightRects();
   1988         if (doMoveMouse && highlightRects.size() > 0) {
   1989             // adjust m_mousePos if it is not inside the returned highlight
   1990             // rectangles
   1991             IntRect foundIntersection;
   1992             IntRect inputRect = IntRect(x - slop, y - slop,
   1993                                         slop * 2 + 1, slop * 2 + 1);
   1994             for (size_t i = 0; i < highlightRects.size(); i++) {
   1995                 IntRect& hr = highlightRects[i];
   1996                 IntRect test = inputRect;
   1997                 test.intersect(hr);
   1998                 if (!test.isEmpty()) {
   1999                     foundIntersection = test;
   2000                     break;
   2001                 }
   2002             }
   2003             if (!foundIntersection.isEmpty() && !foundIntersection.contains(x, y)) {
   2004                 IntPoint pt = foundIntersection.center();
   2005                 moveMouse(pt.x(), pt.y(), 0, true);
   2006             }
   2007         }
   2008     } else {
   2009         androidHitResult.searchContentDetectors();
   2010     }
   2011     return androidHitResult;
   2012 }