Index: Source/core/page/FocusController.cpp |
diff --git a/Source/core/page/FocusController.cpp b/Source/core/page/FocusController.cpp |
index f9cb3d95a7062afb608644e7ab992efb0939656f..52af0c4a5a9d4639c67d3e32fc70e1bc6ff0106e 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" |
#include <limits> |
namespace blink { |
@@ -931,4 +934,75 @@ void FocusController::trace(Visitor* visitor) |
visitor->trace(m_focusedFrame); |
} |
+bool FocusController::handleCSSFocusNavigation(FocusType type) |
+{ |
+ 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; |
+ |
+ // If we were in the autoscroll/panScroll mode we want to stop it. |
+ currentFrame->eventHandler().stopAutoscroll(); |
+ |
+ ENavigationTarget navigationTarget = value.navigationTarget(); |
+ Frame* targetFrame = 0; |
+ if (navigationTarget == Current) |
+ targetFrame = currentFrame; |
+ else if (navigationTarget == Root) |
+ targetFrame = currentFrame->tree().top(); |
+ else |
+ targetFrame = currentFrame->tree().find(value.targetName()); |
+ |
+ if (!targetFrame || !targetFrame->isLocalFrame()) |
+ return false; |
+ |
+ Element* targetElement = toLocalFrame(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 blink |