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