Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
      3  * Copyright (C) 2009 Antonio Gomes <tonikitoo (at) webkit.org>
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #ifndef SpatialNavigation_h
     22 #define SpatialNavigation_h
     23 
     24 #include "core/dom/Node.h"
     25 #include "core/page/FocusType.h"
     26 #include "platform/geometry/LayoutRect.h"
     27 
     28 #include <limits>
     29 
     30 namespace blink {
     31 
     32 class LocalFrame;
     33 class HTMLAreaElement;
     34 class HTMLFrameOwnerElement;
     35 
     36 inline long long maxDistance()
     37 {
     38     return std::numeric_limits<long long>::max();
     39 }
     40 
     41 inline int fudgeFactor()
     42 {
     43     return 2;
     44 }
     45 
     46 bool isSpatialNavigationEnabled(const LocalFrame*);
     47 
     48 // Spatially speaking, two given elements in a web page can be:
     49 // 1) Fully aligned: There is a full intersection between the rects, either
     50 //    vertically or horizontally.
     51 //
     52 // * Horizontally       * Vertically
     53 //    _
     54 //   |_|                   _ _ _ _ _ _
     55 //   |_|...... _          |_|_|_|_|_|_|
     56 //   |_|      |_|         .       .
     57 //   |_|......|_|   OR    .       .
     58 //   |_|      |_|         .       .
     59 //   |_|......|_|          _ _ _ _
     60 //   |_|                  |_|_|_|_|
     61 //
     62 //
     63 // 2) Partially aligned: There is a partial intersection between the rects, either
     64 //    vertically or horizontally.
     65 //
     66 // * Horizontally       * Vertically
     67 //    _                   _ _ _ _ _
     68 //   |_|                 |_|_|_|_|_|
     69 //   |_|.... _      OR           . .
     70 //   |_|    |_|                  . .
     71 //   |_|....|_|                  ._._ _
     72 //          |_|                  |_|_|_|
     73 //          |_|
     74 //
     75 // 3) Or, otherwise, not aligned at all.
     76 //
     77 // * Horizontally       * Vertically
     78 //         _              _ _ _ _
     79 //        |_|            |_|_|_|_|
     80 //        |_|                    .
     81 //        |_|                     .
     82 //       .          OR             .
     83 //    _ .                           ._ _ _ _ _
     84 //   |_|                            |_|_|_|_|_|
     85 //   |_|
     86 //   |_|
     87 //
     88 // "Totally Aligned" elements are preferable candidates to move
     89 // focus to over "Partially Aligned" ones, that on its turns are
     90 // more preferable than "Not Aligned".
     91 enum RectsAlignment {
     92     None = 0,
     93     Partial,
     94     Full
     95 };
     96 
     97 struct FocusCandidate {
     98     STACK_ALLOCATED();
     99 public:
    100     FocusCandidate()
    101         : visibleNode(nullptr)
    102         , focusableNode(nullptr)
    103         , enclosingScrollableBox(nullptr)
    104         , distance(maxDistance())
    105         , alignment(None)
    106         , isOffscreen(true)
    107         , isOffscreenAfterScrolling(true)
    108     {
    109     }
    110 
    111     FocusCandidate(Node*, FocusType);
    112     explicit FocusCandidate(HTMLAreaElement*, FocusType);
    113     bool isNull() const { return !visibleNode; }
    114     bool inScrollableContainer() const { return visibleNode && enclosingScrollableBox; }
    115     bool isFrameOwnerElement() const { return visibleNode && visibleNode->isFrameOwnerElement(); }
    116     Document* document() const { return visibleNode ? &visibleNode->document() : 0; }
    117 
    118     // We handle differently visibleNode and FocusableNode to properly handle the areas of imagemaps,
    119     // where visibleNode would represent the image element and focusableNode would represent the area element.
    120     // In all other cases, visibleNode and focusableNode are one and the same.
    121     RawPtrWillBeMember<Node> visibleNode;
    122     RawPtrWillBeMember<Node> focusableNode;
    123     RawPtrWillBeMember<Node> enclosingScrollableBox;
    124     long long distance;
    125     RectsAlignment alignment;
    126     LayoutRect rect;
    127     bool isOffscreen;
    128     bool isOffscreenAfterScrolling;
    129 };
    130 
    131 bool hasOffscreenRect(Node*, FocusType = FocusTypeNone);
    132 bool scrollInDirection(LocalFrame*, FocusType);
    133 bool scrollInDirection(Node* container, FocusType);
    134 bool canScrollInDirection(const Node* container, FocusType);
    135 bool canScrollInDirection(const LocalFrame*, FocusType);
    136 bool canBeScrolledIntoView(FocusType, const FocusCandidate&);
    137 bool areElementsOnSameLine(const FocusCandidate& firstCandidate, const FocusCandidate& secondCandidate);
    138 void distanceDataForNode(FocusType, const FocusCandidate& current, FocusCandidate&);
    139 Node* scrollableEnclosingBoxOrParentFrameForNodeInDirection(FocusType, Node*);
    140 LayoutRect nodeRectInAbsoluteCoordinates(Node*, bool ignoreBorder = false);
    141 LayoutRect frameRectInAbsoluteCoordinates(LocalFrame*);
    142 LayoutRect virtualRectForDirection(FocusType, const LayoutRect& startingRect, LayoutUnit width = 0);
    143 LayoutRect virtualRectForAreaElementAndDirection(HTMLAreaElement&, FocusType);
    144 HTMLFrameOwnerElement* frameOwnerElement(FocusCandidate&);
    145 
    146 } // namespace blink
    147 
    148 #endif // SpatialNavigation_h
    149