Index: Source/core/page/FocusController.cpp |
diff --git a/Source/core/page/FocusController.cpp b/Source/core/page/FocusController.cpp |
index a75d57d3133212b33f5bc2a06b9c2ae0bed5029f..85ad369a4533d5ea01f7072a977000ae3b85c451 100644 |
--- a/Source/core/page/FocusController.cpp |
+++ b/Source/core/page/FocusController.cpp |
@@ -1,6 +1,7 @@ |
/* |
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved. |
* Copyright (C) 2008 Nuanti Ltd. |
+ * Copyright (C) 2013, 2014 Opera Software ASA. All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
@@ -57,6 +58,8 @@ |
#include "core/page/SpatialNavigation.h" |
#include "core/rendering/HitTestResult.h" |
#include "core/rendering/RenderLayer.h" |
+#include "core/rendering/RenderObject.h" |
+#include "core/rendering/style/StyleNavigationValue.h" |
namespace WebCore { |
@@ -923,4 +926,79 @@ bool FocusController::advanceFocusDirectionally(FocusType type) |
return consumed; |
} |
+bool FocusController::handleCSSFocusNavigation(FocusType type) |
+{ |
+ DEFINE_STATIC_LOCAL(AtomicString, frameTargetCurrent, ("current")); |
+ DEFINE_STATIC_LOCAL(AtomicString, frameTargetRoot, ("root")); |
+ |
+ ASSERT(focusedOrMainFrame()); |
+ if (!focusedOrMainFrame()->isLocalFrame()) |
+ return false; |
+ |
+ LocalFrame* currentFrame = toLocalFrame(focusedOrMainFrame()); |
+ Document* focusedDocument = currentFrame->document(); |
+ if (!focusedDocument) |
+ return false; |
+ |
+ Element* focused = focusedDocument->focusedElement(); |
+ RenderObject* renderer = focused ? focused->renderer() : 0; |
+ if (!renderer) |
+ return false; |
+ |
+ StyleNavigationValue value; |
+ |
+ switch (type) { |
+ case FocusTypeForward: |
+ case FocusTypeBackward: |
+ return false; |
+ case FocusTypeUp: |
+ value = renderer->style()->navUp(); |
+ break; |
+ case FocusTypeDown: |
+ value = renderer->style()->navDown(); |
+ break; |
+ case FocusTypeLeft: |
+ value = renderer->style()->navLeft(); |
+ break; |
+ case FocusTypeRight: |
+ value = renderer->style()->navRight(); |
+ break; |
+ case FocusTypeNone: |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ break; |
+ } |
+ |
+ if (value.isAuto()) |
+ return false; |
+ |
+ const AtomicString& target = value.target(); |
+ LocalFrame* targetFrame = 0; |
+ |
+ // If we were in the autoscroll/panScroll mode we want to stop it. |
+ currentFrame->eventHandler().stopAutoscroll(); |
+ |
+ if (target == frameTargetCurrent) |
+ targetFrame = currentFrame; |
+ else if (target == frameTargetRoot) |
+ targetFrame = currentFrame->tree().top(); |
+ else |
+ targetFrame = currentFrame->tree().find(target); |
+ |
+ if (!targetFrame) |
+ return false; |
+ |
+ Element* targetElement = targetFrame->document()->getElementById(value.id()); |
+ |
+ if (!targetElement) |
+ return false; |
+ |
+ // If it's the same as the current focused, it should be considered a valid navigation, |
+ // but there is no need to change focus. |
+ if (focused == targetElement) |
+ return true; |
+ |
+ return setFocusedElement(targetElement, targetFrame); |
+} |
+ |
} // namespace WebCore |