ProximityDetector.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright (C) 2012, 2013 Research In Motion Limited. All rights reserved.
  3. */
  4. #include "config.h"
  5. #include "ProximityDetector.h"
  6. #include "Document.h"
  7. #include "Element.h"
  8. #include "ExceptionCode.h"
  9. #include "HTMLNames.h"
  10. #include "HitTestResult.h"
  11. #include "RenderLayer.h"
  12. #include "RenderObject.h"
  13. #include "RenderView.h"
  14. #include "WebPage_p.h"
  15. using namespace WebCore;
  16. namespace BlackBerry {
  17. namespace WebKit {
  18. static int getPriorityLevel(Node* node)
  19. {
  20. // Priority level is ascending with zero being the lowest.
  21. if (node->isTextNode())
  22. return 1;
  23. if (!node->isElementNode())
  24. return 0;
  25. Element* element = toElement(node);
  26. ASSERT(element);
  27. ExceptionCode ec = 0;
  28. if (element->webkitMatchesSelector("img,obj", ec))
  29. return 1;
  30. if (element->hasTagName(HTMLNames::pTag))
  31. return 2;
  32. if (element->webkitMatchesSelector("h1,h2,h3,h4,h5,h6", ec))
  33. return 3;
  34. return 0;
  35. }
  36. ProximityDetector::ProximityDetector(WebPagePrivate* webPage)
  37. : m_webPage(webPage)
  38. {
  39. }
  40. ProximityDetector::~ProximityDetector()
  41. {
  42. }
  43. IntPoint ProximityDetector::findBestPoint(const IntPoint& documentPos, const IntRect& documentPaddingRect)
  44. {
  45. ASSERT(m_webPage);
  46. if (!m_webPage->m_mainFrame)
  47. return documentPos;
  48. Document* document = m_webPage->m_mainFrame->document();
  49. if (!document || !document->frame()->view())
  50. return documentPos;
  51. unsigned left = -documentPaddingRect.x();
  52. unsigned top = -documentPaddingRect.y();
  53. unsigned right = documentPaddingRect.maxX();
  54. unsigned bottom = documentPaddingRect.maxY();
  55. // Adjust hit point to frame
  56. IntPoint frameContentPos(document->frame()->view()->windowToContents(m_webPage->m_mainFrame->view()->contentsToWindow(documentPos)));
  57. HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
  58. HitTestResult result(frameContentPos, top, right, bottom, left);
  59. document->renderView()->layer()->hitTest(request, result);
  60. IntPoint bestPoint = documentPos;
  61. int bestPriority = 0;
  62. // Iterate over the list of nodes checking both priority and location
  63. ListHashSet<RefPtr<Node> > intersectedNodes = result.rectBasedTestResult();
  64. ListHashSet<RefPtr<Node> >::const_iterator it = intersectedNodes.begin();
  65. ListHashSet<RefPtr<Node> >::const_iterator end = intersectedNodes.end();
  66. for ( ; it != end; ++it) {
  67. Node* curNode = (*it).get();
  68. if (!curNode || !curNode->renderer())
  69. continue;
  70. IntRect curRect = curNode->renderer()->absoluteBoundingBoxRect(true /*use transforms*/);
  71. IntRect hitTestRect = HitTestLocation::rectForPoint(documentPos, top, right, bottom, left);
  72. // Check that top corner does not exceed padding
  73. if (!hitTestRect.contains(curRect.location()))
  74. continue;
  75. int priority = getPriorityLevel(curNode);
  76. if (!priority)
  77. continue;
  78. bool equalPriorityAndCloser = (priority == bestPriority) && (documentPos.distanceSquaredToPoint(bestPoint) > documentPos.distanceSquaredToPoint(curRect.location()));
  79. if (priority > bestPriority || equalPriorityAndCloser) {
  80. bestPoint = curRect.location(); // use top left
  81. bestPriority = priority;
  82. }
  83. }
  84. return bestPoint;
  85. }
  86. }
  87. }