2010-10-20 Chang Shu <chang.shu@nokia.com>, Antonio Gomes <tonikitoo@webkit.org>
authortonikitoo@webkit.org <tonikitoo@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 5 Nov 2010 04:31:22 +0000 (04:31 +0000)
committertonikitoo@webkit.org <tonikitoo@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 5 Nov 2010 04:31:22 +0000 (04:31 +0000)
        Reviewed by Simon Fraser.

        Spatial Navigation: add support to <input type=text> and <textarea>
        https://bugs.webkit.org/show_bug.cgi?id=37153

        Before this patch, the focus cannot move away from input box once it is in. This patch allows focus
        move to neighbor nodes when the caret reaches the edge of the texts. This patch does not support yet
        cases where the focused <input> has a JS handler for the arrow keys.

        WebCore:

        Tests: fast/events/spatial-navigation/snav-input.html
        fast/events/spatial-navigation/snav-textarea.html

        * editing/EditorCommand.cpp:
        (WebCore::executeMoveDown):
        (WebCore::executeMoveLeft):
        (WebCore::executeMoveRight):
        (WebCore::executeMoveUp):
        * editing/SelectionController.cpp:
        (WebCore::SelectionController::modify):

        WebKit/qt:

        * WebCoreSupport/EditorClientQt.cpp:
        WebCore::EditorClientQt::handleKeyboardEvent):

        LayoutTests:

        * fast/events/spatial-navigation/snav-input-expected.txt: Added.
        * fast/events/spatial-navigation/snav-input.html: Added.
        * fast/events/spatial-navigation/snav-textarea-expected.txt: Added.
        * fast/events/spatial-navigation/snav-textarea.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@71388 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/events/spatial-navigation/snav-input-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/spatial-navigation/snav-input.html [new file with mode: 0644]
LayoutTests/fast/events/spatial-navigation/snav-textarea-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/spatial-navigation/snav-textarea.html [new file with mode: 0644]
LayoutTests/platform/gtk/Skipped
WebCore/ChangeLog
WebCore/editing/EditorCommand.cpp
WebCore/editing/SelectionController.cpp
WebKit/qt/ChangeLog
WebKit/qt/WebCoreSupport/EditorClientQt.cpp

index 0f5deb8..7190bb0 100644 (file)
@@ -1,3 +1,20 @@
+2010-10-20  Chang Shu  <chang.shu@nokia.com>, Antonio Gomes <tonikitoo@webkit.org>
+
+        Reviewed by Simon Fraser.
+
+        [Qt] Makes <input type=text> and <textarea> functional with
+        Spatial Navigation enabled. Before this patch, the focus cannot
+        move away from input box once it is in. This patch allows focus
+        move to neighbor nodes when the caret reaches the edge of the texts.
+        This patch does not support yet cases where the focused <input>
+        has a JS handler for the arrow keys.
+        https://bugs.webkit.org/show_bug.cgi?id=37153
+
+        * fast/events/spatial-navigation/snav-input-expected.txt: Added.
+        * fast/events/spatial-navigation/snav-input.html: Added.
+        * fast/events/spatial-navigation/snav-textarea-expected.txt: Added.
+        * fast/events/spatial-navigation/snav-textarea.html: Added.
+
 2010-11-04  Martin Robinson  <mrobinson@igalia.com>
 
         Skip two new tests. One of which is only failing on the
diff --git a/LayoutTests/fast/events/spatial-navigation/snav-input-expected.txt b/LayoutTests/fast/events/spatial-navigation/snav-input-expected.txt
new file mode 100644 (file)
index 0000000..5a33fb7
--- /dev/null
@@ -0,0 +1,26 @@
+This test ensures the correctness of Spatial Navigation (SNav) algorithm over input box.
+* Pre-conditions:
+1) DRT support for SNav enable/disable.
+* Navigation steps:
+1) Loads this page, focus goes to "start" automatically.
+2) Focus moves away from input box in 4 different directions to neighbor nodes and back.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+2      
+4              6
+8      
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "8"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "2"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "6"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "4"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+
diff --git a/LayoutTests/fast/events/spatial-navigation/snav-input.html b/LayoutTests/fast/events/spatial-navigation/snav-input.html
new file mode 100644 (file)
index 0000000..b07f9ea
--- /dev/null
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+  <head>
+    <script src="../../js/resources/js-test-pre.js"></script>
+    <script src="resources/spatial-navigation-utils.js"></script>
+    <script src="../js/resources/js-test-post.js"></script>
+  </head>
+  <body id="some-content" xmlns="http://www.w3.org/1999/xhtml">
+    <p id="description"></p>
+    <table style="text-align: left; width: 100%; margin-left: auto; margin-right: auto;" border="1" cellpadding="2" cellspacing="1">
+      <tbody>
+        <tr>
+          <td style="vertical-align: top; text-align: center;"></td>
+          <td style="vertical-align: top; text-align: center;"><a id="2" href="a">2</a></td>
+          <td style="vertical-align: top; text-align: center;"></td>
+        </tr>
+        <tr>
+          <td style="vertical-align: top; text-align: center;"><a id="4" href="a">4</a></td>
+          <td style="vertical-align: top; text-align: center;"><input id="start" type="text" value="text"></td>
+          <td style="vertical-align: top; text-align: center;"><a id="6" href="a">6</a></td>
+        </tr>
+        <tr>
+          <td style="vertical-align: top; text-align: center;"></td>
+          <td style="vertical-align: top; text-align: center;"><a id="8" href="a">8</a></td>
+          <td style="vertical-align: top; text-align: center;"></td>
+        </tr>
+      </tbody>
+    </table>
+    <div id="console"></div>
+    <script type="application/javascript">
+    description('This test ensures the correctness of Spatial Navigation (SNav) algorithm over input box.<br>\
+                * Pre-conditions:<br>\
+                1) DRT support for SNav enable/disable.<br>\
+                * Navigation steps:<br>\
+                1) Loads this page, focus goes to "start" automatically.<br>\
+                2) Focus moves away from input box in 4 different directions to neighbor nodes and back.<br>');
+
+    var resultMap = [
+      ["Down", "start"],
+      ["Down", "8"],
+      ["Up", "start"],
+      ["Up", "start"],
+      ["Up", "2"],
+      ["Down", "start"],
+      ["Right", "start"],
+      ["Right", "6"],
+      ["Left", "start"],
+      ["Left", "start"],
+      ["Left", "4"],
+      ["Right", "start"],
+      ["DONE", "DONE"]
+    ];
+
+    if (window.layoutTestController) {
+      layoutTestController.dumpAsText();
+      layoutTestController.setSpatialNavigationEnabled(true);
+      layoutTestController.overridePreference("WebKitTabToLinksPreferenceKey", 1);
+      layoutTestController.waitUntilDone();
+    }
+
+    function runTest()
+    {
+      // starting the test itself: get to a known place.
+      document.getElementById("start").focus();
+
+      initTest(resultMap, testCompleted);
+    }
+
+    function testCompleted()
+    {
+      if (window.layoutTestController)
+        layoutTestController.notifyDone();
+    }
+
+    window.onload = runTest;
+
+    </script>
+  </body>
+</html>
diff --git a/LayoutTests/fast/events/spatial-navigation/snav-textarea-expected.txt b/LayoutTests/fast/events/spatial-navigation/snav-textarea-expected.txt
new file mode 100644 (file)
index 0000000..730e35d
--- /dev/null
@@ -0,0 +1,29 @@
+This test ensures the correctness of Spatial Navigation (SNav) algorithm over textarea.
+* Pre-conditions:
+1) DRT support for SNav enable/disable.
+* Navigation steps:
+1) Loads this page, focus goes to "start" automatically.
+2) Focus moves away from textarea in 4 different directions to neighbor nodes and back.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+2      
+4              6
+8      
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "8"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "2"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "6"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "4"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+
diff --git a/LayoutTests/fast/events/spatial-navigation/snav-textarea.html b/LayoutTests/fast/events/spatial-navigation/snav-textarea.html
new file mode 100644 (file)
index 0000000..0d01396
--- /dev/null
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+  <head>
+    <script src="../../js/resources/js-test-pre.js"></script>
+    <script src="resources/spatial-navigation-utils.js"></script>
+    <script src="../js/resources/js-test-post.js"></script>
+  </head>
+  <body id="some-content" xmlns="http://www.w3.org/1999/xhtml">
+    <p id="description"></p>
+    <table style="text-align: left; width: 100%; margin-left: auto; margin-right: auto;" border="1" cellpadding="2" cellspacing="1">
+      <tbody>
+        <tr>
+          <td style="vertical-align: top; text-align: center;"></td>
+          <td style="vertical-align: top; text-align: center;"><a id="2" href="a">2</a></td>
+          <td style="vertical-align: top; text-align: center;"></td>
+        </tr>
+        <tr>
+          <td style="vertical-align: top; text-align: center;"><a id="4" href="a">4</a></td>
+          <td style="vertical-align: top; text-align: center;"><textarea id="start" rows="5" cols="2">abc d</textarea>
+          <td style="vertical-align: top; text-align: center;"><a id="6" href="a">6</a></td>
+        </tr>
+        <tr>
+          <td style="vertical-align: top; text-align: center;"></td>
+          <td style="vertical-align: top; text-align: center;"><a id="8" href="a">8</a></td>
+          <td style="vertical-align: top; text-align: center;"></td>
+        </tr>
+      </tbody>
+    </table>
+    <div id="console"></div>
+    <script type="application/javascript">
+    description('This test ensures the correctness of Spatial Navigation (SNav) algorithm over textarea.<br>\
+                * Pre-conditions:<br>\
+                1) DRT support for SNav enable/disable.<br>\
+                * Navigation steps:<br>\
+                1) Loads this page, focus goes to "start" automatically.<br>\
+                2) Focus moves away from textarea in 4 different directions to neighbor nodes and back.<br>');
+
+    var resultMap = [
+      ["Down", "start"],
+      ["Down", "start"],
+      ["Down", "8"],
+      ["Up", "start"],
+      ["Up", "2"],
+      ["Down", "start"],
+      ["Right", "start"],
+      ["Right", "start"],
+      ["Right", "start"],
+      ["Right", "start"],
+      ["Right", "start"],
+      ["Right", "6"],
+      ["Left", "start"],
+      ["Left", "4"],
+      ["Right", "start"],
+      ["DONE", "DONE"]
+    ];
+
+    if (window.layoutTestController) {
+      layoutTestController.dumpAsText();
+      layoutTestController.setSpatialNavigationEnabled(true);
+      layoutTestController.overridePreference("WebKitTabToLinksPreferenceKey", 1);
+      layoutTestController.waitUntilDone();
+    }
+
+    function runTest()
+    {
+      var textarea = document.getElementById("start");
+      textarea.value = "abc\nd";
+
+      // starting the test itself: get to a known place.
+      document.getElementById("start").focus();
+
+      initTest(resultMap, testCompleted);
+    }
+
+    function testCompleted()
+    {
+      if (window.layoutTestController)
+        layoutTestController.notifyDone();
+    }
+
+    window.onload = runTest;
+
+    </script>
+  </body>
+</html>
index fda14b3..59561c6 100644 (file)
@@ -4966,8 +4966,12 @@ scrollbars/scrollbar-middleclick-nopaste.html
 # Relies on WebKit API [WebView _loadBackForwardListFromOtherView:]
 fast/loader/crash-copying-backforwardlist.html
 
+# Spatial Navigation
 # https://bugs.webkit.org/show_bug.cgi?id=47587
 fast/events/spatial-navigation/snav-iframe-flattening-simple.html
+# https://bugs.webkit.org/show_bug.cgi?id=49056
+fast/events/spatial-navigation/snav-input.html
+fast/events/spatial-navigation/snav-textarea.html
 
 # Implement LayoutTestController::callShouldCloseOnWebView()
 fast/events/onbeforeunload-focused-iframe.html
index 4788e4d..af4888c 100644 (file)
@@ -1,3 +1,26 @@
+2010-10-20  Chang Shu  <chang.shu@nokia.com>, Antonio Gomes <tonikitoo@webkit.org>
+
+        Reviewed by Simon Fraser.
+
+        [Qt] Makes <input type=text> and <textarea> functional with
+        Spatial Navigation enabled. Before this patch, the focus cannot
+        move away from input box once it is in. This patch allows focus
+        move to neighbor nodes when the caret reaches the edge of the texts.
+        This patch does not support yet cases where the focused <input>
+        has a JS handler for the arrow keys.
+        https://bugs.webkit.org/show_bug.cgi?id=37153
+
+        Tests: fast/events/spatial-navigation/snav-input.html
+               fast/events/spatial-navigation/snav-textarea.html
+
+        * editing/EditorCommand.cpp:
+        (WebCore::executeMoveDown):
+        (WebCore::executeMoveLeft):
+        (WebCore::executeMoveRight):
+        (WebCore::executeMoveUp):
+        * editing/SelectionController.cpp:
+        (WebCore::SelectionController::modify):
+
 2010-11-04  Dan Bernstein  <mitz@apple.com>
 
         Build fix.
index d3ae222..e3ea37e 100644 (file)
@@ -618,8 +618,7 @@ static bool executeMoveBackwardAndModifySelection(Frame* frame, Event*, EditorCo
 
 static bool executeMoveDown(Frame* frame, Event*, EditorCommandSource, const String&)
 {
-    frame->selection()->modify(SelectionController::AlterationMove, SelectionController::DirectionForward, LineGranularity, true);
-    return true;
+    return frame->selection()->modify(SelectionController::AlterationMove, SelectionController::DirectionForward, LineGranularity, true);
 }
 
 static bool executeMoveDownAndModifySelection(Frame* frame, Event*, EditorCommandSource, const String&)
@@ -642,8 +641,7 @@ static bool executeMoveForwardAndModifySelection(Frame* frame, Event*, EditorCom
 
 static bool executeMoveLeft(Frame* frame, Event*, EditorCommandSource, const String&)
 {
-    frame->selection()->modify(SelectionController::AlterationMove, SelectionController::DirectionLeft, CharacterGranularity, true);
-    return true;
+    return frame->selection()->modify(SelectionController::AlterationMove, SelectionController::DirectionLeft, CharacterGranularity, true);
 }
 
 static bool executeMoveLeftAndModifySelection(Frame* frame, Event*, EditorCommandSource, const String&)
@@ -686,8 +684,7 @@ static bool executeMovePageUpAndModifySelection(Frame* frame, Event*, EditorComm
 
 static bool executeMoveRight(Frame* frame, Event*, EditorCommandSource, const String&)
 {
-    frame->selection()->modify(SelectionController::AlterationMove, SelectionController::DirectionRight, CharacterGranularity, true);
-    return true;
+    return frame->selection()->modify(SelectionController::AlterationMove, SelectionController::DirectionRight, CharacterGranularity, true);
 }
 
 static bool executeMoveRightAndModifySelection(Frame* frame, Event*, EditorCommandSource, const String&)
@@ -806,8 +803,7 @@ static bool executeMoveParagraphForwardAndModifySelection(Frame* frame, Event*,
 
 static bool executeMoveUp(Frame* frame, Event*, EditorCommandSource, const String&)
 {
-    frame->selection()->modify(SelectionController::AlterationMove, SelectionController::DirectionBackward, LineGranularity, true);
-    return true;
+    return frame->selection()->modify(SelectionController::AlterationMove, SelectionController::DirectionBackward, LineGranularity, true);
 }
 
 static bool executeMoveUpAndModifySelection(Frame* frame, Event*, EditorCommandSource, const String&)
index 6f25c86..0098d37 100644 (file)
@@ -642,6 +642,8 @@ bool SelectionController::modify(EAlteration alter, EDirection direction, TextGr
 
     willBeModified(alter, direction);
 
+    bool wasRange = m_selection.isRange();
+    Position originalStartPosition = m_selection.start();
     VisiblePosition position;
     switch (direction) {
     case DirectionRight:
@@ -673,6 +675,10 @@ bool SelectionController::modify(EAlteration alter, EDirection direction, TextGr
     if (position.isNull())
         return false;
 
+    if (m_frame && m_frame->settings() && m_frame->settings()->isSpatialNavigationEnabled())
+        if (!wasRange && alter == AlterationMove && position == originalStartPosition)
+            return false;
+
     // Some of the above operations set an xPosForVerticalArrowNavigation.
     // Setting a selection will clear it, so save it to possibly restore later.
     // Note: the START position type is arbitrary because it is unused, it would be
index 7a09d6c..8827c0b 100644 (file)
@@ -1,3 +1,18 @@
+2010-10-20  Chang Shu  <chang.shu@nokia.com>, Antonio Gomes <tonikitoo@webkit.org>
+
+        Reviewed by Simon Fraser.
+
+        [Qt] Makes <input type=text> and <textarea> functional with
+        Spatial Navigation enabled. Before this patch, the focus cannot
+        move away from input box once it is in. This patch allows focus
+        move to neighbor nodes when the caret reaches the edge of the texts.
+        This patch does not support yet cases where the focused <input>
+        has a JS handler for the arrow keys.
+        https://bugs.webkit.org/show_bug.cgi?id=37153
+
+        * WebCoreSupport/EditorClientQt.cpp:
+        (WebCore::EditorClientQt::handleKeyboardEvent):
+
 2010-11-04  Kenneth Rohde Christiansen  <kenneth@webkit.org>
 
         Reviewed by David Hyatt.
index 2dd3b37..3338065 100644 (file)
@@ -46,6 +46,7 @@
 #include "PlatformKeyboardEvent.h"
 #include "QWebPageClient.h"
 #include "Range.h"
+#include "Settings.h"
 #include "WindowsKeyboardCodes.h"
 #include "qwebpage.h"
 #include "qwebpage_p.h"
@@ -360,9 +361,21 @@ void EditorClientQt::handleKeyboardEvent(KeyboardEvent* event)
 
     // FIXME: refactor all of this to use Actions or something like them
     if (start->isContentEditable()) {
+        bool doSpatialNavigation = false;
+        if (frame->settings() && frame->settings()->isSpatialNavigationEnabled()) {
+            if (!kevent->modifiers()) {
+                switch (kevent->windowsVirtualKeyCode()) {
+                case VK_LEFT:
+                case VK_RIGHT:
+                case VK_UP:
+                case VK_DOWN:
+                    doSpatialNavigation = true;
+                }
+            }
+        }
 #ifndef QT_NO_SHORTCUT
         QWebPage::WebAction action = QWebPagePrivate::editorActionForKeyEvent(kevent->qtEvent());
-        if (action != QWebPage::NoWebAction) {
+        if (action != QWebPage::NoWebAction && !doSpatialNavigation) {
             const char* cmd = QWebPagePrivate::editorCommandForWebActions(action);
             // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
             // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
@@ -386,26 +399,26 @@ void EditorClientQt::handleKeyboardEvent(KeyboardEvent* event)
         case VK_LEFT:
             if (kevent->shiftKey())
                 frame->editor()->command("MoveLeftAndModifySelection").execute();
-            else
-                frame->editor()->command("MoveLeft").execute();
+            else if (!frame->editor()->command("MoveLeft").execute())
+                return;
             break;
         case VK_RIGHT:
             if (kevent->shiftKey())
                 frame->editor()->command("MoveRightAndModifySelection").execute();
-            else
-                frame->editor()->command("MoveRight").execute();
+            else if (!frame->editor()->command("MoveRight").execute())
+                return;
             break;
         case VK_UP:
             if (kevent->shiftKey())
                 frame->editor()->command("MoveUpAndModifySelection").execute();
-            else
-                frame->editor()->command("MoveUp").execute();
+            else if (!frame->editor()->command("MoveUp").execute())
+                return;
             break;
         case VK_DOWN:
             if (kevent->shiftKey())
                 frame->editor()->command("MoveDownAndModifySelection").execute();
-            else
-                frame->editor()->command("MoveDown").execute();
+            else if (!frame->editor()->command("MoveDown").execute())
+                return;
             break;
         case VK_PRIOR: // PageUp
             if (kevent->shiftKey())