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