Implement Focus UI
authorSangYong Park <sy302.park@samsung.com>
Fri, 10 May 2013 10:14:22 +0000 (19:14 +0900)
committerGerrit Code Review <gerrit@gerrit.vlan144.tizendev.org>
Fri, 2 Aug 2013 07:23:54 +0000 (07:23 +0000)
[Title] Implement Focus UI
[Issue#] N/A
[Problem] Focus UI is not supported.
[Cause] N/A
[Solution] N/A

Change-Id: I9845408e0a104f7777db5271f1c55e412dfbcede

20 files changed:
Source/WebCore/page/FocusController.cpp
Source/WebCore/page/SpatialNavigation.cpp [changed mode: 0644->0755]
Source/WebKit2/PlatformTizen.cmake
Source/WebKit2/UIProcess/API/efl/EwkViewImpl.cpp
Source/WebKit2/UIProcess/API/efl/EwkViewImpl.h
Source/WebKit2/UIProcess/API/efl/ewk_view.cpp
Source/WebKit2/UIProcess/API/efl/tizen/images/focusUIFocusRing.png [new file with mode: 0755]
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/efl/InputMethodContextEfl.cpp
Source/WebKit2/UIProcess/efl/InputMethodContextEfl.h
Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp
Source/WebKit2/WebProcess/WebPage/efl/tizen/ScreenReader.cpp
Source/WebKit2/WebProcess/WebPage/efl/tizen/ScreenReader.h
Source/cmake/OptionsTizen.cmake [changed mode: 0644->0755]

index 8b4b414..d3ff2a6 100755 (executable)
 #include "htmlediting.h" // For firstPositionInOrBeforeNode
 #include <limits>
 
+#if ENABLE(TIZEN_FOCUS_UI)
+#include "RenderLayer.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
 using namespace std;
 
+#if ENABLE(TIZEN_FOCUS_UI)
+HashSet<Node*> m_excludedCandidateSet;
+#endif
+
 static inline ComposedShadowTreeWalker walkerFrom(const Node* node)
 {
     return ComposedShadowTreeWalker(node, ComposedShadowTreeWalker::DoNotCrossUpperBoundary);
@@ -731,6 +739,96 @@ void FocusController::setContainingWindowIsVisible(bool containingWindowIsVisibl
     }
 }
 
+#if ENABLE(TIZEN_FOCUS_UI)
+static IntSize frameOffset(Frame* initialFrame)
+{
+    IntSize offset;
+    for (Frame* frame = initialFrame; frame; frame = frame->tree()->parent()) {
+        RenderBoxModelObject* renderer;
+        if (frame->ownerElement() && (renderer = frame->ownerElement()->renderBoxModelObject())) {
+            do {
+                offset.expand(renderer->offsetLeft(), renderer->offsetTop());
+            } while ((renderer = renderer->offsetParent()));
+            offset -= frame->view()->scrollOffset();
+        }
+    }
+    return offset;
+}
+
+static bool isTopmostNode(const FocusCandidate& candidate)
+{
+    Node* candidateNode = candidate.visibleNode;
+    if (candidateNode->isFrameOwnerElement())
+        return true;
+
+    Frame* frame = candidateNode->document()->frame();
+    EventHandler* eventHandler = frame->eventHandler();
+    IntSize offset(frameOffset(frame));
+
+    Node* childNode;
+    if (candidateNode->hasTagName(HTMLNames::aTag))
+        childNode = candidateNode->firstChild();
+    else
+        childNode = 0;
+
+    Region region(pixelSnappedIntRect(candidate.rect));
+
+    while (!region.isEmpty()) {
+        Vector<IntRect> rects = region.rects();
+        HitTestResult result = eventHandler->hitTestResultAtPoint(IntPoint(rects[0].x(), rects[0].y()) - offset, false);
+
+        Node* node = result.innerNode();
+        if (!node || !node->parentNode() || node->parentNode()->isDocumentNode() || candidateNode->contains(node))
+            return true;
+
+        if (node->hasTagName(HTMLNames::areaTag))
+            node = static_cast<HTMLAreaElement*>(node)->imageElement();
+
+        ASSERT(node && node->renderer() && node->renderer()->enclosingLayer());
+        IntRect layerRect(node->renderer()->enclosingLayer()->absoluteBoundingBox());
+        layerRect.move(frameOffset(node->document()->frame()));
+        if (!layerRect.intersects(rects[0]))
+            return true;
+
+        region.subtract(layerRect);
+
+        while (childNode && region.isEmpty()) {
+            if (childNode->renderer())
+                region.intersect(pixelSnappedIntRect(nodeRectInAbsoluteCoordinates(childNode)));
+            childNode = childNode->nextSibling();
+        }
+    }
+
+    return false;
+}
+
+static bool isSuitableCandidate(FocusDirection direction, const FocusCandidate& candidate, const FocusCandidate& closest)
+{
+    ASSERT(candidate.alignment != closest.alignment);
+    if (candidate.alignment == None)
+        return false;
+    if (closest.alignment == None)
+        return true;
+
+    long long candidateDistance = candidate.distance;
+    long long closestDistance = closest.distance;
+
+    if (candidate.alignment < closest.alignment) {
+        if (direction == FocusDirectionLeft || direction == FocusDirectionRight)
+            candidateDistance += candidate.rect.width().toInt();
+        else
+            candidateDistance += candidate.rect.height().toInt();
+    } else {
+        if (direction == FocusDirectionLeft || direction == FocusDirectionRight)
+            closestDistance += closest.rect.width().toInt();
+        else
+            closestDistance += closest.rect.height().toInt();
+    }
+
+    return candidateDistance < closestDistance;
+}
+#endif
+
 static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCandidate& current, FocusCandidate& candidate, FocusCandidate& closest)
 {
     ASSERT(candidate.visibleNode->isElementNode());
@@ -751,6 +849,11 @@ static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCa
     if (candidate.isOffscreenAfterScrolling && candidate.alignment < Full)
         return;
 
+#if ENABLE(TIZEN_FOCUS_UI)
+    if (!isTopmostNode(candidate))
+        return;
+#endif
+
     if (closest.isNull()) {
         closest = candidate;
         return;
@@ -776,8 +879,13 @@ static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCa
         return;
     }
 
+#if ENABLE(TIZEN_FOCUS_UI)
+    if (isSuitableCandidate(direction, candidate, closest))
+        closest = candidate;
+#else
     if (candidate.alignment > closest.alignment)
         closest = candidate;
+#endif
 }
 
 void FocusController::findFocusCandidateInContainer(Node* container, const LayoutRect& startingRect, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closest)
@@ -798,7 +906,11 @@ void FocusController::findFocusCandidateInContainer(Node* container, const Layou
         if (!node->isElementNode())
             continue;
 
+#if ENABLE(TIZEN_FOCUS_UI)
+        if ((!node->isFocusable() && !node->isFrameOwnerElement() && !canScrollInDirection(node, direction)) || m_excludedCandidateSet.contains(node))
+#else
         if (!node->isKeyboardFocusable(event) && !node->isFrameOwnerElement() && !canScrollInDirection(node, direction))
+#endif
             continue;
 
         FocusCandidate candidate = FocusCandidate(node, direction);
@@ -849,7 +961,12 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
         frameElement->contentFrame()->document()->updateLayoutIgnorePendingStylesheets();
         if (!advanceFocusDirectionallyInContainer(frameElement->contentFrame()->document(), rect, direction, event)) {
             // The new frame had nothing interesting, need to find another candidate.
+#if ENABLE(TIZEN_FOCUS_UI)
+            m_excludedCandidateSet.add(focusCandidate.visibleNode);
+            return advanceFocusDirectionallyInContainer(container, newStartingRect, direction, event);
+#else
             return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.visibleNode, true), direction, event);
+#endif
         }
         return true;
     }
@@ -872,6 +989,13 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
         return true;
     }
 
+#if ENABLE(TIZEN_FOCUS_UI)
+    if (focusCandidate.isOffscreen) {
+        Node* container = focusCandidate.enclosingScrollableBox;
+        scrollInDirection(container, direction);
+    }
+#endif
+
     // We found a new focus node, navigate to it.
     Element* element = toElement(focusCandidate.focusableNode);
     ASSERT(element);
@@ -917,6 +1041,9 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa
             static_cast<Document*>(container)->updateLayoutIgnorePendingStylesheets();
     } while (!consumed && container);
 
+#if ENABLE(TIZEN_FOCUS_UI)
+    m_excludedCandidateSet.clear();
+#endif
     return consumed;
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index 4150b64..614d169
@@ -84,6 +84,12 @@ FocusCandidate::FocusCandidate(Node* node, FocusDirection direction)
         visibleNode = node;
         rect = nodeRectInAbsoluteCoordinates(node, true /* ignore border */);
     }
+#if ENABLE(TIZEN_FOCUS_UI)
+    if (rect.isEmpty() || rect.maxX() < 0 || rect.maxY() < 0) {
+        visibleNode = 0;
+        return;
+    }
+#endif
 
     focusableNode = node;
     isOffscreen = hasOffscreenRect(visibleNode);
@@ -170,8 +176,10 @@ static bool areRectsFullyAligned(FocusDirection direction, const LayoutRect& a,
     aStart = start(direction, a);
     bStart = start(direction, b);
 
+#if !ENABLE(TIZEN_FOCUS_UI)
     LayoutUnit aMiddle = middle(direction, a);
     LayoutUnit bMiddle = middle(direction, b);
+#endif
 
     aEnd = end(direction, a);
     bEnd = end(direction, b);
@@ -200,10 +208,14 @@ static bool areRectsFullyAligned(FocusDirection direction, const LayoutRect& a,
     //  *             *            *  *             *             *
     //  ****************************  *****************************
 
+#if ENABLE(TIZEN_FOCUS_UI)
+    return (aStart <= bStart && aEnd >= bEnd) || (bStart <= aStart && bEnd >= aEnd);
+#else
     return ((bMiddle >= aStart && bMiddle <= aEnd) // (1)
             || (aMiddle >= bStart && aMiddle <= bEnd) // (2)
             || (bStart == aStart) // (3)
             || (bEnd == aEnd)); // (4)
+#endif
 }
 
 // This method checks if |start| and |dest| have a partial intersection, either
@@ -506,12 +518,22 @@ static LayoutRect rectToAbsoluteCoordinates(Frame* initialFrame, const LayoutRec
 {
     LayoutRect rect = initialRect;
     for (Frame* frame = initialFrame; frame; frame = frame->tree()->parent()) {
+#if ENABLE(TIZEN_FOCUS_UI)
+        RenderBoxModelObject* renderer;
+        if (frame->ownerElement() && (renderer = frame->ownerElement()->renderBoxModelObject())) {
+            do {
+                rect.move(renderer->offsetLeft(), renderer->offsetTop());
+            } while ((renderer = renderer->offsetParent()));
+            rect.move(-frame->view()->scrollOffset());
+        }
+#else
         if (Element* element = static_cast<Element*>(frame->ownerElement())) {
             do {
                 rect.move(element->offsetLeft(), element->offsetTop());
             } while ((element = element->offsetParent()));
             rect.move((-frame->view()->scrollOffset()));
         }
+#endif
     }
     return rect;
 }
@@ -522,7 +544,13 @@ LayoutRect nodeRectInAbsoluteCoordinates(Node* node, bool ignoreBorder)
 
     if (node->isDocumentNode())
         return frameRectInAbsoluteCoordinates(static_cast<Document*>(node)->frame());
+#if ENABLE(TIZEN_FOCUS_UI)
+    LayoutRect rect = node->getRect();
+    rect.intersect(node->renderer()->absoluteClippedOverflowRect());
+    rect = rectToAbsoluteCoordinates(node->document()->frame(), rect);
+#else
     LayoutRect rect = rectToAbsoluteCoordinates(node->document()->frame(), node->getRect());
+#endif
 
     // For authors that use border instead of outline in their CSS, we compensate by ignoring the border when calculating
     // the rect of the focused element.
index b876450..433b9c6 100755 (executable)
@@ -295,3 +295,9 @@ IF (ENABLE_TIZEN_SCREEN_READER)
     ADD_DEFINITIONS(-DSCREEN_READER_FOCUS_RING_IMAGE_PATH="${SCREEN_READER_FOCUS_RING_IMAGE_PATH}/screenReaderFocusRing.png")
     INSTALL(FILES ${WEBKIT2_DIR}/UIProcess/API/efl/tizen/images/screenReaderFocusRing.png DESTINATION ${SCREEN_READER_FOCUS_RING_IMAGE_PATH})
 ENDIF ()
+
+IF (ENABLE_TIZEN_FOCUS_UI)
+    SET(FOCUS_UI_FOCUS_RING_IMAGE_PATH ${CMAKE_INSTALL_PREFIX}/share/${WebKit2_LIBRARY_NAME}-${PROJECT_VERSION_MAJOR}/images)
+    ADD_DEFINITIONS(-DFOCUS_UI_FOCUS_RING_IMAGE_PATH="${FOCUS_UI_FOCUS_RING_IMAGE_PATH}/focusUIFocusRing.png")
+    INSTALL(FILES ${WEBKIT2_DIR}/UIProcess/API/efl/tizen/images/focusUIFocusRing.png DESTINATION ${FOCUS_UI_FOCUS_RING_IMAGE_PATH})
+ENDIF ()
index 371af74..24da214 100755 (executable)
@@ -1259,6 +1259,11 @@ void EwkViewImpl::feedTouchEvents(Ewk_Touch_Event_Type type)
     if (!count)
         return;
 
+#if ENABLE(TIZEN_FOCUS_UI)
+    if (type == EWK_TOUCH_START)
+        pageProxy->setSpatialNavigationEnabled(false);
+#endif
+
     Eina_List* points = 0;
     for (unsigned i = 0; i < count; ++i) {
         Ewk_Touch_Point* point = new Ewk_Touch_Point;
@@ -1415,4 +1420,16 @@ void EwkViewImpl::didChangeScrollAndScale(const WebCore::IntPoint& previousScrol
         focusRing->updateScrollAndScale(previousScrollPosition, previousScale);
 #endif
 }
+
+#if ENABLE(TIZEN_FOCUS_UI)
+void EwkViewImpl::pages(Vector<RefPtr<WebPageProxy> >& pages)
+{
+    pages.resize(pageViewMap.size());
+
+    PageViewMap::const_iterator::Keys it = pageViewMap.begin().keys();
+    PageViewMap::const_iterator::Keys end = pageViewMap.end().keys();
+    for (unsigned i = 0; it != end; ++it, ++i)
+        pages[i] = toImpl(*it);
+}
+#endif
 #endif //#if OS(TIZEN)
index 2b1e9bf..dfe660f 100755 (executable)
@@ -324,6 +324,10 @@ public:
 #endif
 
     void didChangeScrollAndScale(const WebCore::IntPoint&, float);
+
+#if ENABLE(TIZEN_FOCUS_UI)
+    static void pages(Vector<RefPtr<WebKit::WebPageProxy> >&);
+#endif
 #endif // #if OS(TIZEN)
 
     // FIXME: Make members private for encapsulation.
index 82f34e6..2ca3aee 100755 (executable)
@@ -2501,17 +2501,6 @@ bool ewk_view_focused_node_adjust(Evas_Object* ewkView, Eina_Bool adjustForExter
 #endif
 
 #if ENABLE(TIZEN_ISF_PORT)
-    Ecore_X_Window rootWin = ecore_x_window_root_first_get();
-    ecore_x_event_mask_set(rootWin, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
-    Ecore_X_Atom xAtom = ecore_x_atom_get("X External Keyboard Exist");
-    unsigned int connectedKeyboardNum = 0;
-    bool isExternalKeyboardConnected = false;
-
-    // get connected keyboard number
-    if (ecore_x_window_prop_card32_get(rootWin, xAtom, &connectedKeyboardNum, 1)
-        && connectedKeyboardNum)
-        isExternalKeyboardConnected = true;
-
     // We should treat both of ECORE_IMF_INPUT_PANEL_STATE_SHOW and ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW
     // as IME is shown. ECORE_IMF_INPUT_PANEL_STATE_HIDE is ignored at here.
     // input field zoom should not work with below conditions
@@ -2520,7 +2509,7 @@ bool ewk_view_focused_node_adjust(Evas_Object* ewkView, Eina_Bool adjustForExter
     // 3. imfContext is null(if adjustForExternalKeyboard is false)
     // 4. input panel state is hidden(if adjustForExternalKeyboard is false)
     if ((!(static_cast<PageClient*>(impl->pageClient.get()))->isViewFocused()
-        || (adjustForExternalKeyboard && !isExternalKeyboardConnected)
+        || (adjustForExternalKeyboard && !InputMethodContextEfl::shouldUseExternalKeyboard())
         || (!adjustForExternalKeyboard && !impl->inputMethodContext())
         || (!adjustForExternalKeyboard && !impl->inputMethodContext()->isShow()))
 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
diff --git a/Source/WebKit2/UIProcess/API/efl/tizen/images/focusUIFocusRing.png b/Source/WebKit2/UIProcess/API/efl/tizen/images/focusUIFocusRing.png
new file mode 100755 (executable)
index 0000000..4029269
Binary files /dev/null and b/Source/WebKit2/UIProcess/API/efl/tizen/images/focusUIFocusRing.png differ
index cbc652a..1b39b9c 100755 (executable)
@@ -260,6 +260,9 @@ WebPageProxy::WebPageProxy(PageClient* pageClient, PassRefPtr<WebProcessProxy> p
 #if ENABLE(TIZEN_WEBKIT2_NOTIFY_SUSPEND_BY_REMOTE_WEB_INSPECTOR)
     , m_contentSuspendedByInspector(false)
 #endif
+#if ENABLE(TIZEN_FOCUS_UI)
+    , m_spatialNavigationEnabled(false)
+#endif
 {
 #ifndef NDEBUG
     webPageProxyCounter.increment();
index 28e8fed..0625414 100755 (executable)
@@ -1030,10 +1030,13 @@ public:
     void recalcScreenReaderFocusRect();
     void clearScreenReader();
 
-    void didScreenReaderFocusRectChanged(const WebCore::IntRect&);
     void didScreenReaderTextChanged(const String&);
 #endif
 
+#if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI)
+    void didChangeFocusedRect(const WebCore::IntRect&);
+#endif
+
 #if ENABLE(TIZEN_CSP)
     void setContentSecurityPolicy(const String& policy, WebCore::ContentSecurityPolicy::HeaderType type);
 #endif
@@ -1058,6 +1061,10 @@ public:
     void useSettingsFont();
 #endif
 
+#if ENABLE(TIZEN_FOCUS_UI)
+    void setSpatialNavigationEnabled(bool);
+#endif
+
 private:
     WebPageProxy(PageClient*, PassRefPtr<WebProcessProxy>, WebPageGroup*, uint64_t pageID);
 
@@ -1703,6 +1710,10 @@ private:
 #if ENABLE(TIZEN_FILE_SYSTEM)
     RefPtr<Messages::WebPageProxy::ExceededLocalFileSystemQuota::DelayedReply> m_exceededLocalFileSystemQuotaReply;
 #endif
+
+#if ENABLE(TIZEN_FOCUS_UI)
+    bool m_spatialNavigationEnabled;
+#endif
 };
 
 } // namespace WebKit
index 3eb8354..7665ffc 100755 (executable)
@@ -458,10 +458,13 @@ messages -> WebPageProxy {
 #endif
 
 #if ENABLE(TIZEN_SCREEN_READER)
-    DidScreenReaderFocusRectChanged(WebCore::IntRect rect)
     DidScreenReaderTextChanged(WTF::String text)
 #endif
 
+#if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI)
+    DidChangeFocusedRect(WebCore::IntRect rect)
+#endif
+
 #if ENABLE(TIZEN_INDEXED_DATABASE)
     ExceededIndexedDatabaseQuota(uint64_t frameID, WTF::String originIdentifier, int64_t currentUsage) -> (bool returnValue) Delayed
 #endif
index 15b8b5a..8506a91 100755 (executable)
@@ -32,6 +32,52 @@ namespace WebKit {
 
 #if ENABLE(TIZEN_ISF_PORT)
 const unsigned InputMethodContextEfl::maxContextSize = 10;
+Ecore_X_Atom InputMethodContextEfl::s_externalKeyboardProperty = 0;
+bool InputMethodContextEfl::s_shouldUseExternalKeyboard = false;
+
+void InputMethodContextEfl::initializeExternalKeyboard()
+{
+    s_externalKeyboardProperty = ecore_x_atom_get("X External Keyboard Exist");
+    if (!s_externalKeyboardProperty)
+        return;
+
+    Ecore_X_Window rootWin = ecore_x_window_root_first_get();
+    ecore_x_event_mask_set(rootWin, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
+
+    ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, windowPropertyChanged, 0);
+
+    unsigned int value;
+    if (ecore_x_window_prop_card32_get(rootWin, s_externalKeyboardProperty, &value, 1) <= 0)
+        return;
+
+    s_shouldUseExternalKeyboard = value;
+}
+
+Eina_Bool InputMethodContextEfl::windowPropertyChanged(void*, int, void* event)
+{
+    Ecore_X_Event_Window_Property* propertyEvent = static_cast<Ecore_X_Event_Window_Property*>(event);
+
+    if (propertyEvent->atom != s_externalKeyboardProperty)
+        return ECORE_CALLBACK_PASS_ON;
+
+    unsigned int value;
+    if (ecore_x_window_prop_card32_get(propertyEvent->win, s_externalKeyboardProperty, &value, 1) <= 0 || s_shouldUseExternalKeyboard == value)
+        return ECORE_CALLBACK_PASS_ON;
+
+    s_shouldUseExternalKeyboard = value;
+
+#if ENABLE(TIZEN_FOCUS_UI)
+    if (!s_shouldUseExternalKeyboard) {
+        Vector<RefPtr<WebPageProxy> > pages;
+        EwkViewImpl::pages(pages);
+
+        for (size_t i = 0; i < pages.size(); ++i)
+            pages[i]->setSpatialNavigationEnabled(false);
+    }
+#endif
+
+    return ECORE_CALLBACK_PASS_ON;
+}
 #endif
 
 InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<Ecore_IMF_Context> context)
@@ -46,7 +92,10 @@ InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<E
     , m_fakeKeyEventTimer(this, &InputMethodContextEfl::fakeKeyEventTimerFired)
 #endif
 {
-#if !ENABLE(TIZEN_ISF_PORT)
+#if ENABLE(TIZEN_ISF_PORT)
+    if (!s_externalKeyboardProperty)
+        initializeExternalKeyboard();
+#else
     ASSERT(context);
     ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
     ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
@@ -336,6 +385,11 @@ void InputMethodContextEfl::handleMouseUpEvent(const Evas_Event_Mouse_Up*)
 
 void InputMethodContextEfl::handleKeyDownEvent(const Evas_Event_Key_Down* downEvent, bool* isFiltered)
 {
+#if ENABLE(TIZEN_FOCUS_UI)
+    if (s_shouldUseExternalKeyboard)
+        m_viewImpl->page()->setSpatialNavigationEnabled(true);
+#endif
+
 #if ENABLE(TIZEN_ISF_PORT)
     if (!m_context)
         return;
index 114707c..f26f4d9 100755 (executable)
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
 
+#if ENABLE(TIZEN_ISF_PORT)
+#include <Ecore_X.h>
+#endif
+
 class EwkViewImpl;
 
 namespace WebKit {
@@ -53,6 +57,8 @@ public:
     void updateTextInputState();
 
 #if ENABLE(TIZEN_ISF_PORT)
+    static bool shouldUseExternalKeyboard() { return s_shouldUseExternalKeyboard; }
+
     bool isShow();
     Ecore_IMF_Autocapital_Type autoCapitalType();
     void onFocusIn();
@@ -73,7 +79,8 @@ private:
     static void onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context*, void* eventInfo);
 
 #if ENABLE(TIZEN_ISF_PORT)
-    void initializeIMFContext(Ecore_IMF_Context*, Ecore_IMF_Input_Panel_Layout, int, Ecore_IMF_Input_Panel_Return_Key_Type);
+    static void initializeExternalKeyboard();
+    static Eina_Bool windowPropertyChanged(void*, int, void*);
 
     static void onIMFInputPanelStateChanged(void*, Ecore_IMF_Context*, int);
     static void onIMFInputPanelGeometryChanged(void*, Ecore_IMF_Context*, int);
@@ -82,6 +89,8 @@ private:
     static Eina_Bool onIMFRetrieveSurrounding(void*, Ecore_IMF_Context*, char**, int*);
     static void onIMFDeleteSurrounding(void*, Ecore_IMF_Context*, void*);
 
+    void initializeIMFContext(Ecore_IMF_Context*, Ecore_IMF_Input_Panel_Layout, int, Ecore_IMF_Input_Panel_Return_Key_Type);
+
     PassOwnPtr<Ecore_IMF_Context> takeContext(uintptr_t);
     void setIMFContext(const EditorState&);
     void revertIMFContext();
@@ -107,6 +116,9 @@ private:
 #if ENABLE(TIZEN_ISF_PORT)
     static const unsigned maxContextSize;
 
+    static Ecore_X_Atom s_externalKeyboardProperty;
+    static bool s_shouldUseExternalKeyboard;
+
     Vector<std::pair<uintptr_t, OwnPtr<Ecore_IMF_Context> > > m_contextList;
     uintptr_t m_contextID;
     int m_state;
index 720a9a8..3d7b14d 100755 (executable)
@@ -1037,7 +1037,14 @@ void WebPageProxy::clearScreenReader()
     process()->send(Messages::WebPage::ClearScreenReader(), m_pageID);
 }
 
-void WebPageProxy::didScreenReaderFocusRectChanged(const IntRect& rect)
+void WebPageProxy::didScreenReaderTextChanged(const String& text)
+{
+    ScreenReaderProxy::screenReader().setText(text);
+}
+#endif
+
+#if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI)
+void WebPageProxy::didChangeFocusedRect(const IntRect& rect)
 {
 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
     FocusRing* focusRing = ewkViewGetFocusRing(viewWidget());
@@ -1051,11 +1058,7 @@ void WebPageProxy::didScreenReaderFocusRectChanged(const IntRect& rect)
 #else
     UNUSED_PARAM(rect);
 #endif
-}
 
-void WebPageProxy::didScreenReaderTextChanged(const String& text)
-{
-    ScreenReaderProxy::screenReader().setText(text);
 }
 #endif
 
@@ -1241,4 +1244,20 @@ void WebPageProxy::setContentSuspendedByInspector(bool isSuspended)
 }
 #endif
 
+#if ENABLE(TIZEN_FOCUS_UI)
+void WebPageProxy::setSpatialNavigationEnabled(bool enabled)
+{
+    if (m_spatialNavigationEnabled == enabled)
+        return;
+
+    m_spatialNavigationEnabled = enabled;
+
+    if (enabled)
+        static_cast<PageClientImpl*>(m_pageClient)->viewImpl()->focusRing->setImage(FOCUS_UI_FOCUS_RING_IMAGE_PATH, 4, 2);
+    else
+        static_cast<PageClientImpl*>(m_pageClient)->viewImpl()->focusRing->setImage(String(), 0, 0);
+
+    process()->send(Messages::WebPage::SetSpatialNavigationEnabled(enabled), m_pageID);
+}
+#endif
 } // namespace WebKit
index 166b8b5..734b39d 100755 (executable)
@@ -172,6 +172,11 @@ void WebChromeClient::focusedNodeChanged(Node* node)
         nodeRect.setY(nodeRect.y() / m_page->pageScaleFactor());
     }
     m_page->send(Messages::WebPageProxy::FocusedNodeChanged(nodeRect));
+
+#if ENABLE(TIZEN_FOCUS_UI)
+    if (m_page->corePage()->settings()->isSpatialNavigationEnabled())
+        m_page->didChangeFocusedRect(m_page->corePage()->focusController()->focusedOrMainFrame()->document()->focusedNode());
+#endif
 #else
     notImplemented();
 #endif
@@ -486,6 +491,10 @@ void WebChromeClient::scroll(const IntSize& scrollOffset, const IntRect& scrollR
 void WebChromeClient::delegatedScrollRequested(const IntPoint& scrollOffset)
 {
     m_page->pageDidRequestScroll(scrollOffset);
+
+#if OS(TIZEN)
+    m_page->didChangeContents(m_page->bounds());
+#endif
 }
 #endif
 
index 6257029..d90c3df 100755 (executable)
@@ -815,6 +815,10 @@ public:
     WebCore::IntRect nodeRect(WebCore::Node*) const;
 #endif
 
+#if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI)
+    void didChangeFocusedRect(WebCore::Node*);
+#endif
+
 #if ENABLE(TIZEN_WEBKIT2_POPUP_INTERNAL)
     void notifyTransitionToCommitted(bool);
 #endif
@@ -839,6 +843,10 @@ public:
     void didChangeContents(const WebCore::IntRect&);
 #endif
 
+#if ENABLE(TIZEN_FOCUS_UI)
+    void setSpatialNavigationEnabled(bool);
+#endif
+
 private:
     WebPage(uint64_t pageID, const WebPageCreationParameters&);
 
@@ -1193,6 +1201,10 @@ private:
     OwnPtr<ScreenReader> m_screenReader;
 #endif
 
+#if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI)
+    WebCore::IntRect m_focusedRect;
+#endif
+
 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
     EditorState m_editorState;
 #endif
index 4e204a2..11b2b47 100755 (executable)
@@ -459,4 +459,8 @@ messages -> WebPage {
 #if ENABLE(TIZEN_USE_SETTINGS_FONT)
     UseSettingsFont()
 #endif
+
+#if ENABLE(TIZEN_FOCUS_UI)
+    SetSpatialNavigationEnabled(bool enabled)
+#endif
 }
index 1111865..785697b 100755 (executable)
@@ -1723,31 +1723,13 @@ void WebPage::getLinkMagnifierRect(const IntPoint& position, const IntSize& size
 #endif
 
 #if ENABLE(TIZEN_SCREEN_READER)
-static void sendScreenReaderFocusRect(WebPage* page, ScreenReader* screenReader)
-{
-    Node* node = screenReader->getFocusedNode();
-    IntRect rect;
-
-    if (node) {
-        bool isImage = false;
-        if (node->isElementNode()) {
-            Element* element = static_cast<Element*>(node);
-            isImage = !element->getAttribute(element->imageSourceAttributeName()).isEmpty();
-        }
-        rect = getNodeRect(node, node, isImage);
-    }
-
-    screenReader->setFocusedRect(rect);
-    page->send(Messages::WebPageProxy::DidScreenReaderFocusRectChanged(rect));
-}
-
 void WebPage::moveScreenReaderFocus(bool forward, bool& result)
 {
     if (!m_screenReader)
         m_screenReader = ScreenReader::create(this);
 
     result = m_screenReader->moveFocus(forward);
-    sendScreenReaderFocusRect(this, m_screenReader.get());
+    didChangeFocusedRect(m_screenReader->getFocusedNode());
 }
 
 void WebPage::moveScreenReaderFocusByPoint(const IntPoint& point)
@@ -1758,7 +1740,7 @@ void WebPage::moveScreenReaderFocusByPoint(const IntPoint& point)
     if (!m_screenReader->moveFocus(point))
         return;
 
-    sendScreenReaderFocusRect(this, m_screenReader.get());
+    didChangeFocusedRect(m_screenReader->getFocusedNode());
 }
 
 void WebPage::clearScreenReaderFocus()
@@ -1814,7 +1796,7 @@ void WebPage::recalcScreenReaderFocusRect()
     if (!m_screenReader || !m_screenReader->getFocusedNode())
         return;
 
-    sendScreenReaderFocusRect(this, m_screenReader.get());
+    didChangeFocusedRect(m_screenReader->getFocusedNode());
 }
 
 void WebPage::updateScreenReaderFocus(RenderObject* object)
@@ -1827,7 +1809,8 @@ void WebPage::updateScreenReaderFocus(RenderObject* object)
     else if (!m_screenReader->rendererWillBeDestroyed(object))
         return;
 
-    sendScreenReaderFocusRect(this, m_screenReader.get());
+    m_focusedRect = IntRect();
+    didChangeFocusedRect(m_screenReader->getFocusedNode());
 }
 
 void WebPage::clearScreenReader()
@@ -1883,6 +1866,14 @@ IntRect WebPage::nodeRect(Node* node) const
 }
 #endif
 
+#if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI)
+void WebPage::didChangeFocusedRect(WebCore::Node* node)
+{
+    m_focusedRect = nodeRect(node);
+    send(Messages::WebPageProxy::DidChangeFocusedRect(m_focusedRect));
+}
+#endif
+
 #if ENABLE(TIZEN_WEBKIT2_POPUP_INTERNAL)
 // FIXME: Currently with cached pages, hiding Popup list menu is not working correctly.
 // This patch is a fix allowing any popup list menu to get close for any page navigation.
@@ -1962,11 +1953,22 @@ void WebPage::didChangeContents(const IntRect& rect)
     }
 #endif
 
-#if ENABLE(TIZEN_SCREEN_READER)
-    if (m_screenReader && rect.intersects(m_screenReader->focusedRect()))
-        recalcScreenReaderFocusRect();
+#if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI)
+    if (rect.intersects(m_focusedRect)) {
+        if (m_screenReader)
+            didChangeFocusedRect(m_screenReader->getFocusedNode());
+        else if (m_page->settings()->isSpatialNavigationEnabled())
+            didChangeFocusedRect(frame->document()->focusedNode());
+    }
 #endif
 }
+
+#if ENABLE(TIZEN_FOCUS_UI)
+void WebPage::setSpatialNavigationEnabled(bool enabled)
+{
+    m_page->settings()->setSpatialNavigationEnabled(enabled);
+}
+#endif
 #endif // #if OS(TIZEN)
 
 } // namespace WebKit
index d168974..ac1ba95 100755 (executable)
@@ -579,7 +579,6 @@ bool ScreenReader::rendererWillBeDestroyed(RenderObject* object)
 void ScreenReader::clearFocus()
 {
     m_focusedObject = 0;
-    m_focusedRect = IntRect();
     m_hasFocus = false;
     m_page->send(Messages::WebPageProxy::DidScreenReaderTextChanged(emptyString()));
 }
index c6d45ed..41bf628 100755 (executable)
@@ -57,9 +57,6 @@ public:
     bool rendererWillBeDestroyed(WebCore::RenderObject*);
     void clearFocus();
 
-    const WebCore::IntRect& focusedRect() const { return m_focusedRect; }
-    void setFocusedRect(const WebCore::IntRect& rect) { m_focusedRect = rect; }
-
 private:
     ScreenReader(WebPage*);
 
@@ -73,7 +70,6 @@ private:
 
     WebPage* m_page;
     WebCore::RenderObject* m_focusedObject;
-    WebCore::IntRect m_focusedRect;
     bool m_hasFocus;
     bool m_isForward;
 
old mode 100644 (file)
new mode 100755 (executable)
index 1275fc5..8719beb
@@ -383,6 +383,9 @@ IF (ENABLE_TIZEN_SCREEN_READER)
     ADD_DEFINITIONS(-DHAVE_ACCESSIBILITY=1)
 ENDIF()
 
+SET(ENABLE_TIZEN_FOCUS_UI 1)
+ADD_DEFINITIONS(-DENABLE_TIZEN_FOCUS_UI=1)
+
 INCLUDE_IF_EXISTS(${CMAKE_CURRENT_SOURCE_DIR}/Source/cmake/OptionsExperimental.cmake)
 
 MESSAGE("Finish to check Tizen dependencies")