FatFingers.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #ifndef FatFingers_h
  19. #define FatFingers_h
  20. #include "HitTestResult.h"
  21. #include "RenderLayer.h"
  22. #include <BlackBerryPlatformIntRectRegion.h>
  23. #include <utility>
  24. #include <wtf/HashSet.h>
  25. #include <wtf/ListHashSet.h>
  26. #include <wtf/Vector.h>
  27. namespace WebCore {
  28. class Document;
  29. class Element;
  30. class IntPoint;
  31. class IntRect;
  32. class IntSize;
  33. class Node;
  34. }
  35. #define DEBUG_FAT_FINGERS 0
  36. namespace BlackBerry {
  37. namespace WebKit {
  38. class WebPagePrivate;
  39. class FatFingersResult;
  40. class TouchEventHandler;
  41. class FatFingers {
  42. public:
  43. enum TargetType { ClickableElement, Text };
  44. FatFingers(WebPagePrivate* webpage, const WebCore::IntPoint& contentPos, TargetType);
  45. ~FatFingers();
  46. const FatFingersResult findBestPoint();
  47. #if DEBUG_FAT_FINGERS
  48. // These debug vars are all in content coordinates. They are public so
  49. // they can be read from BackingStore, which will draw a visible rect
  50. // around the fat fingers area.
  51. static WebCore::IntRect m_debugFatFingerRect;
  52. static WebCore::IntPoint m_debugFatFingerClickPosition;
  53. static WebCore::IntPoint m_debugFatFingerAdjustedPosition;
  54. #endif
  55. private:
  56. enum MatchingApproachForClickable { ClickableByDefault = 0, MadeClickableByTheWebpage, Done };
  57. typedef std::pair<WebCore::Node*, Platform::IntRectRegion> IntersectingRegion;
  58. bool checkFingerIntersection(const Platform::IntRectRegion&,
  59. const Platform::IntRectRegion& remainingFingerRegion,
  60. WebCore::Node*,
  61. Vector<IntersectingRegion>& intersectingRegions);
  62. bool findIntersectingRegions(WebCore::Document*,
  63. Vector<IntersectingRegion>& intersectingRegions,
  64. Platform::IntRectRegion& remainingFingerRegion);
  65. bool checkForClickableElement(WebCore::Element*,
  66. Vector<IntersectingRegion>& intersectingRegions,
  67. Platform::IntRectRegion& remainingFingerRegion,
  68. WebCore::RenderLayer*& lowestPositionedEnclosingLayerSoFar);
  69. bool checkForText(WebCore::Node*,
  70. Vector<IntersectingRegion>& intersectingRegions,
  71. Platform::IntRectRegion& fingerRegion);
  72. void setSuccessfulFatFingersResult(FatFingersResult&, WebCore::Node*, const WebCore::IntPoint&);
  73. void getNodesFromRect(WebCore::Document*, const WebCore::IntPoint&, ListHashSet<RefPtr<WebCore::Node> >&);
  74. bool isElementClickable(WebCore::Element*) const;
  75. inline WebCore::IntRect fingerRectForPoint(const WebCore::IntPoint&) const;
  76. void getAdjustedPaddings(const WebCore::IntPoint&, unsigned& top, unsigned& right, unsigned& bottom, unsigned& left) const;
  77. WebPagePrivate* m_webPage;
  78. WebCore::IntPoint m_contentPos;
  79. TargetType m_targetType;
  80. };
  81. class FatFingersResult {
  82. public:
  83. FatFingersResult(const WebCore::IntPoint& p = WebCore::IntPoint::zero(), const FatFingers::TargetType targetType = FatFingers::ClickableElement)
  84. : m_originalPosition(p)
  85. , m_adjustedPosition(p)
  86. , m_targetType(targetType)
  87. , m_positionWasAdjusted(false)
  88. , m_isTextInput(false)
  89. , m_isValid(false)
  90. , m_nodeUnderFatFinger(0)
  91. {
  92. }
  93. void reset()
  94. {
  95. m_originalPosition = m_adjustedPosition = WebCore::IntPoint::zero();
  96. m_positionWasAdjusted = false;
  97. m_isTextInput = false;
  98. m_isValid = false;
  99. m_nodeUnderFatFinger = 0;
  100. }
  101. bool resultMatches(const WebCore::IntPoint& p, const FatFingers::TargetType targetType) const
  102. {
  103. return m_isValid && p == m_originalPosition && targetType == m_targetType;
  104. }
  105. WebCore::IntPoint originPosition() const { return m_originalPosition; }
  106. WebCore::IntPoint adjustedPosition() const { return m_adjustedPosition; }
  107. bool positionWasAdjusted() const { return m_isValid && m_positionWasAdjusted; }
  108. bool isTextInput() const { return m_isValid && !!m_nodeUnderFatFinger && m_isTextInput; }
  109. bool isValid() const { return m_isValid; }
  110. enum ContentType { ShadowContentAllowed, ShadowContentNotAllowed };
  111. WebCore::Node* node(ContentType type = ShadowContentAllowed, bool shouldUseRootEditableElement = false) const
  112. {
  113. if (!m_nodeUnderFatFinger || !m_nodeUnderFatFinger->inDocument())
  114. return 0;
  115. WebCore::Node* result = m_nodeUnderFatFinger.get();
  116. if (type == ShadowContentAllowed)
  117. return result;
  118. // Shadow trees can be nested.
  119. while (result->isInShadowTree())
  120. result = toElement(result->deprecatedShadowAncestorNode());
  121. if (!shouldUseRootEditableElement || !result->isElementNode())
  122. return result;
  123. // Retrieve the top level editable node
  124. while (!result->isRootEditableElement()) {
  125. WebCore::Element* parentElement = result->parentElement();
  126. if (!parentElement)
  127. break;
  128. result = parentElement;
  129. }
  130. return result;
  131. }
  132. WebCore::Element* nodeAsElementIfApplicable(ContentType type = ShadowContentAllowed, bool shouldUseRootEditableElement = false) const
  133. {
  134. WebCore::Node* result = node(type, shouldUseRootEditableElement);
  135. if (!result || !result->isElementNode())
  136. return 0;
  137. return static_cast<WebCore::Element*>(result);
  138. }
  139. private:
  140. friend class WebKit::FatFingers;
  141. friend class WebKit::TouchEventHandler;
  142. WebCore::IntPoint m_originalPosition; // Main frame contents coordinates.
  143. WebCore::IntPoint m_adjustedPosition; // Main frame contents coordinates.
  144. FatFingers::TargetType m_targetType;
  145. bool m_positionWasAdjusted;
  146. bool m_isTextInput; // Check if the element under the touch point will require a VKB be displayed so that the touch down can be suppressed.
  147. bool m_isValid;
  148. RefPtr<WebCore::Node> m_nodeUnderFatFinger;
  149. };
  150. }
  151. }
  152. #endif // FatFingers_h