blob: 81c30f6b335bc32184fa3872a7ace6f165bfc92c [file] [log] [blame]
/*
* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2009 Antonio Gomes <tonikitoo@webkit.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef SpatialNavigation_h
#define SpatialNavigation_h
#include "core/dom/Node.h"
#include "platform/geometry/LayoutRect.h"
#include "public/platform/WebFocusType.h"
#include <limits>
namespace blink {
class LocalFrame;
class HTMLAreaElement;
class HTMLFrameOwnerElement;
inline double maxDistance() {
return std::numeric_limits<double>::max();
}
inline int fudgeFactor() {
return 2;
}
bool isSpatialNavigationEnabled(const LocalFrame*);
bool spatialNavigationIgnoresEventHandlers(const LocalFrame*);
// Spatially speaking, two given elements in a web page can be:
// 1) Fully aligned: There is a full intersection between the rects, either
// vertically or horizontally.
//
// * Horizontally * Vertically
// _
// |_| _ _ _ _ _ _
// |_|...... _ |_|_|_|_|_|_|
// |_| |_| . .
// |_|......|_| OR . .
// |_| |_| . .
// |_|......|_| _ _ _ _
// |_| |_|_|_|_|
//
//
// 2) Partially aligned: There is a partial intersection between the rects,
// either vertically or horizontally.
//
// * Horizontally * Vertically
// _ _ _ _ _ _
// |_| |_|_|_|_|_|
// |_|.... _ OR . .
// |_| |_| . .
// |_|....|_| ._._ _
// |_| |_|_|_|
// |_|
//
// 3) Or, otherwise, not aligned at all.
//
// * Horizontally * Vertically
// _ _ _ _ _
// |_| |_|_|_|_|
// |_| .
// |_| .
// . OR .
// _ . ._ _ _ _ _
// |_| |_|_|_|_|_|
// |_|
// |_|
//
// "Totally Aligned" elements are preferable candidates to move
// focus to over "Partially Aligned" ones, that on its turns are
// more preferable than "Not Aligned".
enum RectsAlignment { None = 0, Partial, Full };
struct FocusCandidate {
STACK_ALLOCATED();
public:
FocusCandidate()
: visibleNode(nullptr),
focusableNode(nullptr),
enclosingScrollableBox(nullptr),
distance(maxDistance()),
isOffscreen(true),
isOffscreenAfterScrolling(true) {}
FocusCandidate(Node*, WebFocusType);
explicit FocusCandidate(HTMLAreaElement*, WebFocusType);
bool isNull() const { return !visibleNode; }
bool inScrollableContainer() const {
return visibleNode && enclosingScrollableBox;
}
bool isFrameOwnerElement() const {
return visibleNode && visibleNode->isFrameOwnerElement();
}
Document* document() const {
return visibleNode ? &visibleNode->document() : nullptr;
}
// We handle differently visibleNode and FocusableNode to properly handle the
// areas of imagemaps, where visibleNode would represent the image element and
// focusableNode would represent the area element. In all other cases,
// visibleNode and focusableNode are one and the same.
Member<Node> visibleNode;
Member<Node> focusableNode;
Member<Node> enclosingScrollableBox;
double distance;
LayoutRect rect;
bool isOffscreen;
bool isOffscreenAfterScrolling;
};
bool hasOffscreenRect(Node*, WebFocusType = WebFocusTypeNone);
bool scrollInDirection(LocalFrame*, WebFocusType);
bool scrollInDirection(Node* container, WebFocusType);
bool canScrollInDirection(const Node* container, WebFocusType);
bool canScrollInDirection(const LocalFrame*, WebFocusType);
bool canBeScrolledIntoView(WebFocusType, const FocusCandidate&);
bool areElementsOnSameLine(const FocusCandidate& firstCandidate,
const FocusCandidate& secondCandidate);
void distanceDataForNode(WebFocusType,
const FocusCandidate& current,
FocusCandidate&);
Node* scrollableEnclosingBoxOrParentFrameForNodeInDirection(WebFocusType,
Node*);
LayoutRect nodeRectInAbsoluteCoordinates(Node*, bool ignoreBorder = false);
LayoutRect frameRectInAbsoluteCoordinates(LocalFrame*);
LayoutRect virtualRectForDirection(WebFocusType,
const LayoutRect& startingRect,
LayoutUnit width = LayoutUnit());
LayoutRect virtualRectForAreaElementAndDirection(HTMLAreaElement&,
WebFocusType);
HTMLFrameOwnerElement* frameOwnerElement(FocusCandidate&);
} // namespace blink
#endif // SpatialNavigation_h