Index: Source/core/page/FocusController.cpp |
diff --git a/Source/core/page/FocusController.cpp b/Source/core/page/FocusController.cpp |
index 4382f680fb5796be7026505d992dd3478f2ea719..0bf6cb92b6f7e06a875c44cdd0948c776481e67f 100644 |
--- a/Source/core/page/FocusController.cpp |
+++ b/Source/core/page/FocusController.cpp |
@@ -787,6 +787,43 @@ static void updateFocusCandidateIfNeeded(FocusType type, const FocusCandidate& c |
closest = candidate; |
} |
+static inline bool hasFocusEventHandler(const Element& element) |
+{ |
+ return element.hasEventListeners(EventTypeNames::focus) |
+ || element.hasEventListeners(EventTypeNames::blur) |
+ || element.hasEventListeners(EventTypeNames::focusin) |
+ || element.hasEventListeners(EventTypeNames::focusout); |
+} |
+ |
+static inline NavigationClass classifyNavigationCandidate(const Element& element, FocusType type) |
+{ |
+ if (element.isKeyboardFocusable()) |
+ return NavigationClassFocusable; |
+ |
+ if (element.isFrameOwnerElement()) |
+ return NavigationClassFrameOwner; |
+ |
+ if (canScrollInDirection(&element, type)) |
+ return NavigationClassScrollable; |
+ |
+ // If the element is not "keyboard focusable", apply an extended heuristic, |
+ // by checking for the presence of a click/keyboard/focus/blur event |
+ // handler. |
+ // This way it's possible to navigate to (focus) elements which the web |
+ // designer intended to be active (made them respond to mentioned events). |
+ |
+ if (element.hasEventListeners(EventTypeNames::click) |
+ || element.hasEventListeners(EventTypeNames::keydown) |
+ || element.hasEventListeners(EventTypeNames::keypress) |
+ || element.hasEventListeners(EventTypeNames::keyup)) |
+ return NavigationClassEventHandler; |
+ |
+ if (element.isSVGElement() && hasFocusEventHandler(element)) |
c.shu
2015/01/07 23:49:48
I would either expand the four focus event listene
|
+ return NavigationClassEventHandler; |
+ |
+ return NavigationClassNone; |
+} |
+ |
void FocusController::findFocusCandidateInContainer(Node& container, const LayoutRect& startingRect, FocusType type, FocusCandidate& closest) |
{ |
Element* focusedElement = (focusedFrame() && toLocalFrame(focusedFrame())->document()) ? toLocalFrame(focusedFrame())->document()->focusedElement() : nullptr; |
@@ -796,6 +833,10 @@ void FocusController::findFocusCandidateInContainer(Node& container, const Layou |
current.rect = startingRect; |
current.focusableNode = focusedElement; |
current.visibleNode = focusedElement; |
+ if (focusedElement) { |
+ // FIXME: Result the computed class depends on the focus type. |
+ current.targetClass = classifyNavigationCandidate(*focusedElement, type); |
+ } |
for (; element; element = (element->isFrameOwnerElement() || canScrollInDirection(element, type)) |
? ElementTraversal::nextSkippingChildren(*element, &container) |
@@ -803,10 +844,11 @@ void FocusController::findFocusCandidateInContainer(Node& container, const Layou |
if (element == focusedElement) |
continue; |
- if (!element->isKeyboardFocusable() && !element->isFrameOwnerElement() && !canScrollInDirection(element, type)) |
+ NavigationClass navigationClass = classifyNavigationCandidate(*element, type); |
+ if (navigationClass == NavigationClassNone) |
continue; |
- FocusCandidate candidate = FocusCandidate(element, type); |
+ FocusCandidate candidate(element, type, navigationClass); |
c.shu
2015/01/07 23:49:48
Can we do some additional code refactory here so t
|
if (candidate.isNull()) |
continue; |