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 WebCore {
     31 
     32 class Element;
     33 class LocalFrame;
     34 class HTMLAreaElement;
     35 class HTMLFrameOwnerElement;
     36 class IntRect;
     37 class RenderObject;
     38 
     39 inline long long maxDistance()
     40 {
     41     return std::numeric_limits<long long>::max();
     42 }
     43 
     44 inline int fudgeFactor()
     45 {
     46     return 2;
     47 }
     48 
     49 bool isSpatialNavigationEnabled(const LocalFrame*);
     50 
     51 // Spatially speaking, two given elements in a web page can be:
     52 // 1) Fully aligned: There is a full intersection between the rects, either
     53 //    vertically or horizontally.
     54 //
     55 // * Horizontally       * Vertically
     56 //    _
     57 //   |_|                   _ _ _ _ _ _
     58 //   |_|...... _          |_|_|_|_|_|_|
     59 //   |_|      |_|         .       .
     60 //   |_|......|_|   OR    .       .
     61 //   |_|      |_|         .       .
     62 //   |_|......|_|          _ _ _ _
     63 //   |_|                  |_|_|_|_|
     64 //
     65 //
     66 // 2) Partially aligned: There is a partial intersection between the rects, either
     67 //    vertically or horizontally.
     68 //
     69 // * Horizontally       * Vertically
     70 //    _                   _ _ _ _ _
     71 //   |_|                 |_|_|_|_|_|
     72 //   |_|.... _      OR           . .
     73 //   |_|    |_|                  . .
     74 //   |_|....|_|                  ._._ _
     75 //          |_|                  |_|_|_|
     76 //          |_|
     77 //
     78 // 3) Or, otherwise, not aligned at all.
     79 //
     80 // * Horizontally       * Vertically
     81 //         _              _ _ _ _
     82 //        |_|            |_|_|_|_|
     83 //        |_|                    .
     84 //        |_|                     .
     85 //       .          OR             .
     86 //    _ .                           ._ _ _ _ _
     87 //   |_|                            |_|_|_|_|_|
     88 //   |_|
     89 //   |_|
     90 //
     91 // "Totally Aligned" elements are preferable candidates to move
     92 // focus to over "Partially Aligned" ones, that on its turns are
     93 // more preferable than "Not Aligned".
     94 enum RectsAlignment {
     95     None = 0,
     96     Partial,
     97     Full
     98 };
     99 
    100 struct FocusCandidate {
    101     FocusCandidate()
    102         : visibleNode(0)
    103         , focusableNode(0)
    104         , enclosingScrollableBox(0)
    105         , distance(maxDistance())
    106         , parentDistance(maxDistance())
    107         , alignment(None)
    108         , parentAlignment(None)
    109         , isOffscreen(true)
    110         , isOffscreenAfterScrolling(true)
    111     {
    112     }
    113 
    114     FocusCandidate(Node*, FocusType);
    115     explicit FocusCandidate(HTMLAreaElement*, FocusType);
    116     bool isNull() const { return !visibleNode; }
    117     bool inScrollableContainer() const { return visibleNode && enclosingScrollableBox; }
    118     bool isFrameOwnerElement() const { return visibleNode && visibleNode->isFrameOwnerElement(); }
    119     Document* document() const { return visibleNode ? &visibleNode->document() : 0; }
    120 
    121     // We handle differently visibleNode and FocusableNode to properly handle the areas of imagemaps,
    122     // where visibleNode would represent the image element and focusableNode would represent the area element.
    123     // In all other cases, visibleNode and focusableNode are one and the same.
    124     Node* visibleNode;
    125     Node* focusableNode;
    126     Node* enclosingScrollableBox;
    127     long long distance;
    128     long long parentDistance;
    129     RectsAlignment alignment;
    130     RectsAlignment parentAlignment;
    131     LayoutRect rect;
    132     bool isOffscreen;
    133     bool isOffscreenAfterScrolling;
    134 };
    135 
    136 bool hasOffscreenRect(Node*, FocusType = FocusTypeNone);
    137 bool scrollInDirection(LocalFrame*, FocusType);
    138 bool scrollInDirection(Node* container, FocusType);
    139 bool canScrollInDirection(const Node* container, FocusType);
    140 bool canScrollInDirection(const LocalFrame*, FocusType);
    141 bool canBeScrolledIntoView(FocusType, const FocusCandidate&);
    142 bool areElementsOnSameLine(const FocusCandidate& firstCandidate, const FocusCandidate& secondCandidate);
    143 void distanceDataForNode(FocusType, const FocusCandidate& current, FocusCandidate&);
    144 Node* scrollableEnclosingBoxOrParentFrameForNodeInDirection(FocusType, Node*);
    145 LayoutRect nodeRectInAbsoluteCoordinates(Node*, bool ignoreBorder = false);
    146 LayoutRect frameRectInAbsoluteCoordinates(LocalFrame*);
    147 LayoutRect virtualRectForDirection(FocusType, const LayoutRect& startingRect, LayoutUnit width = 0);
    148 LayoutRect virtualRectForAreaElementAndDirection(HTMLAreaElement&, FocusType);
    149 HTMLFrameOwnerElement* frameOwnerElement(FocusCandidate&);
    150 
    151 } // namspace WebCore
    152 
    153 #endif // SpatialNavigation_h
    154