On Linux, should be able to get spelling suggestions without selecting the misspelled...
authorg.czajkowski@samsung.com <g.czajkowski@samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 11 Jan 2013 07:54:11 +0000 (07:54 +0000)
committerg.czajkowski@samsung.com <g.czajkowski@samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 11 Jan 2013 07:54:11 +0000 (07:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=103520

Reviewed by Ryosuke Niwa.

Source/WebCore:

Allow to get/insert spelling suggestions without selecting the misspelled word for
Linux WebKit ports. WebCore assumes that the misspelled word has to be selected
to get its suggestions.

In compliance with native application behaviour a new editing policy is introduced,
to do not highlight the misspelled word to just get its guesses.

No new tests, covered by context-menu-suggestions.html.

* WebCore.exp.in:
Remove _ZN7WebCore6Editor21isSelectionMisspelledEv symbol as Mac port doesn't
need it any longer.

* editing/EditingBehavior.h:
(EditingBehavior):
(WebCore::EditingBehavior::shouldAllowSpellingSuggestionsWithoutSelection):
Add a new behavior for Linux, to allow spelling suggestions without selecting
the misspelled word.

* editing/Editor.cpp:
(WebCore::Editor::isContinuousSpellCheckingEnabled):
Add missing const modifier, to use this method in 'misspelledWordAtCaretOrRange() const'.

(WebCore::Editor::misspelledWordAtCaretOrRange):
Allow to check spelling under the caret or selected word.
Does nothing for selection made on the multiple words.

(WebCore::Editor::misspelledSelectionString):
Return the misspelled selection.

(WebCore::Editor::guessesForMisspelledWord):
Remove 'Selection' from method name as it may return guesses without selection.

(WebCore::Editor::guessesForMisspelledOrUngrammatical):
Ditto.

* page/ContextMenuController.cpp:
(WebCore::ContextMenuController::contextMenuItemSelected):
Select the word under caret to meet the conditions from misspelledWordAtCaretOrRange.

(WebCore::ContextMenuController::populate):
Update guessesForMisspelledOrUngrammatical call.

LayoutTests:

* platform/efl/TestExpectations:
Unskip context-menu-suggestions.html for WebKit-EFL as it passes now.

* platform/gtk/TestExpectations:
Update failing reason.

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

LayoutTests/ChangeLog
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/editing/EditingBehavior.h
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/page/ContextMenuController.cpp

index 5681ac2..06512e6 100644 (file)
@@ -1,3 +1,16 @@
+2013-01-10  Grzegorz Czajkowski  <g.czajkowski@samsung.com>
+
+        On Linux, should be able to get spelling suggestions without selecting the misspelled word
+        https://bugs.webkit.org/show_bug.cgi?id=103520
+
+        Reviewed by Ryosuke Niwa.
+
+        * platform/efl/TestExpectations:
+        Unskip context-menu-suggestions.html for WebKit-EFL as it passes now.
+
+        * platform/gtk/TestExpectations:
+        Update failing reason.
+
 2013-01-10  John J. Barton  <johnjbarton@chromium.org>
 
         Web Inspector: Pass the script url to the script-preprocessor script
index bb50000..5520754 100644 (file)
@@ -1684,9 +1684,6 @@ webkit.org/b/101670 media/video-controls-captions-trackmenu-localized.html [ Ski
 # Fails until we enable the Resource Timing API.
 webkit.org/b/61138 http/tests/w3c/webperf/submission/resource-timing [ Skip ]
 
-# No spellcheck suggestions in context menu
-Bug(EFL) editing/spelling/context-menu-suggestions.html [ Failure ]
-
 # No support for exposing in-band text tracks
 Bug(EFL) media/track/track-in-band.html [ Skip ]
 Bug(EFL) media/track/track-in-band-cues-added-once.html [ Skip ]
index ebe7896..84b1ec1 100644 (file)
@@ -968,7 +968,7 @@ webkit.org/b/73936 inspector/profiler/canvas2d/canvas-has-uninstrumented-canvase
 webkit.org/b/37613 webkit.org/b/20011 printing [ Skip ]
 webkit.org/b/37613 editing/execCommand/print.html [ Skip ]
 
-# Need to dump context menu items on eventSender.contextClick(true).
+# DRT doesn't dispatch an event for the second call eventSender.contextClick().
 webkit.org/b/39102 editing/spelling/context-menu-suggestions.html [ Failure ]
 
 # Some input type=range tests fail because of the size
index 7230bcb..edb4d52 100644 (file)
@@ -1,3 +1,53 @@
+2013-01-10  Grzegorz Czajkowski  <g.czajkowski@samsung.com>
+
+        On Linux, should be able to get spelling suggestions without selecting the misspelled word
+        https://bugs.webkit.org/show_bug.cgi?id=103520
+
+        Reviewed by Ryosuke Niwa.
+
+        Allow to get/insert spelling suggestions without selecting the misspelled word for
+        Linux WebKit ports. WebCore assumes that the misspelled word has to be selected
+        to get its suggestions.
+
+        In compliance with native application behaviour a new editing policy is introduced,
+        to do not highlight the misspelled word to just get its guesses.
+
+        No new tests, covered by context-menu-suggestions.html.
+
+        * WebCore.exp.in:
+        Remove _ZN7WebCore6Editor21isSelectionMisspelledEv symbol as Mac port doesn't
+        need it any longer.
+
+        * editing/EditingBehavior.h:
+        (EditingBehavior):
+        (WebCore::EditingBehavior::shouldAllowSpellingSuggestionsWithoutSelection):
+        Add a new behavior for Linux, to allow spelling suggestions without selecting
+        the misspelled word.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::isContinuousSpellCheckingEnabled):
+        Add missing const modifier, to use this method in 'misspelledWordAtCaretOrRange() const'.
+
+        (WebCore::Editor::misspelledWordAtCaretOrRange):
+        Allow to check spelling under the caret or selected word.
+        Does nothing for selection made on the multiple words.
+
+        (WebCore::Editor::misspelledSelectionString):
+        Return the misspelled selection.
+
+        (WebCore::Editor::guessesForMisspelledWord):
+        Remove 'Selection' from method name as it may return guesses without selection.
+
+        (WebCore::Editor::guessesForMisspelledOrUngrammatical):
+        Ditto.
+
+        * page/ContextMenuController.cpp:
+        (WebCore::ContextMenuController::contextMenuItemSelected):
+        Select the word under caret to meet the conditions from misspelledWordAtCaretOrRange.
+
+        (WebCore::ContextMenuController::populate):
+        Update guessesForMisspelledOrUngrammatical call.
+
 2013-01-10  Hajime Morrita  <morrita@google.com>
 
         https://bugs.webkit.org/show_bug.cgi?id=106283
index b48f6a2..797a7f1 100644 (file)
@@ -842,7 +842,6 @@ __ZN7WebCore6Editor19countMatchesForTextERKN3WTF6StringEPNS_5RangeEjjb
 __ZN7WebCore6Editor19deleteWithDirectionENS_18SelectionDirectionENS_15TextGranularityEbb
 __ZN7WebCore6Editor19insertUnorderedListEv
 __ZN7WebCore6Editor21applyStyleToSelectionEPNS_16StylePropertySetENS_10EditActionE
-__ZN7WebCore6Editor21isSelectionMisspelledEv
 __ZN7WebCore6Editor23setBaseWritingDirectionE16WritingDirection
 __ZN7WebCore6Editor24computeAndSetTypingStyleEPNS_16StylePropertySetENS_10EditActionE
 __ZN7WebCore6Editor24isSelectionUngrammaticalEv
index 941430f..538ee0e 100644 (file)
@@ -59,6 +59,17 @@ public:
 
     // On Mac, when processing a contextual click, the object being clicked upon should be selected.
     bool shouldSelectOnContextualMenuClick() const { return m_type == EditingMacBehavior; }
+
+    // On Linux, should be able to get and insert spelling suggestions without selecting the misspelled word.
+    // Skip this policy for Chromium, they require selection for the misspelled word.
+    bool shouldAllowSpellingSuggestionsWithoutSelection() const
+    {
+#if !PLATFORM(CHROMIUM)
+        return m_type == EditingUnixBehavior;
+#else
+        return false;
+#endif
+    }
     
     // On Mac and Windows, pressing backspace (when it isn't handled otherwise) should navigate back.
     bool shouldNavigateBackOnBackspace() const { return m_type != EditingUnixBehavior; }
index 5fc3976..228fd47 100644 (file)
@@ -1090,7 +1090,7 @@ void Editor::copyImage(const HitTestResult& result)
     Pasteboard::generalPasteboard()->writeImage(result.innerNonSharedNode(), url, result.altDisplayString());
 }
 
-bool Editor::isContinuousSpellCheckingEnabled()
+bool Editor::isContinuousSpellCheckingEnabled() const
 {
     return client() && client()->isContinuousSpellCheckingEnabled();
 }
@@ -1681,23 +1681,50 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
     }
 }
 
-bool Editor::isSelectionMisspelled()
+String Editor::misspelledWordAtCaretOrRange(Node* clickedNode) const
+{
+    if (!isContinuousSpellCheckingEnabled() || !clickedNode || !isSpellCheckingEnabledFor(clickedNode))
+        return String();
+
+    VisibleSelection selection = m_frame->selection()->selection();
+    if (!selection.isContentEditable() || selection.isNone())
+        return String();
+
+    VisibleSelection wordSelection(selection.base());
+    wordSelection.expandUsingGranularity(WordGranularity);
+    RefPtr<Range> wordRange = wordSelection.toNormalizedRange();
+
+    // In compliance with GTK+ applications, additionally allow to provide suggestions when the current
+    // selection exactly match the word selection.
+    if (selection.isRange() && !areRangesEqual(wordRange.get(), selection.toNormalizedRange().get()))
+        return String();
+
+    String word = wordRange->text();
+    if (word.isEmpty() || !client())
+        return String();
+
+    int wordLength = word.length();
+    int misspellingLocation = -1;
+    int misspellingLength = 0;
+    textChecker()->checkSpellingOfString(word.characters(), wordLength, &misspellingLocation, &misspellingLength);
+
+    return misspellingLength == wordLength ? word : String();
+}
+
+String Editor::misspelledSelectionString() const
 {
     String selectedString = selectedText();
     int length = selectedString.length();
-    if (!length)
-        return false;
+    if (!length || !client())
+        return String();
 
-    if (!client())
-        return false;
-    
     int misspellingLocation = -1;
     int misspellingLength = 0;
     textChecker()->checkSpellingOfString(selectedString.characters(), length, &misspellingLocation, &misspellingLength);
     
     // The selection only counts as misspelled if the selected text is exactly one misspelled word
     if (misspellingLength != length)
-        return false;
+        return String();
     
     // Update the spelling panel to be displaying this error (whether or not the spelling panel is on screen).
     // This is necessary to make a subsequent call to [NSSpellChecker ignoreWord:inSpellDocumentWithTag:] work
@@ -1705,7 +1732,7 @@ bool Editor::isSelectionMisspelled()
     // or a grammar error.
     client()->updateSpellingUIWithMisspelledWord(selectedString);
     
-    return true;
+    return selectedString;
 }
 
 bool Editor::isSelectionUngrammatical()
@@ -1736,18 +1763,17 @@ Vector<String> Editor::guessesForUngrammaticalSelection()
 #endif
 }
 
-Vector<String> Editor::guessesForMisspelledSelection()
+Vector<String> Editor::guessesForMisspelledWord(const String& word) const
 {
-    String selectedString = selectedText();
-    ASSERT(selectedString.length());
+    ASSERT(word.length());
 
     Vector<String> guesses;
     if (client())
-        textChecker()->getGuessesForWord(selectedString, String(), guesses);
+        textChecker()->getGuessesForWord(word, String(), guesses);
     return guesses;
 }
 
-Vector<String> Editor::guessesForMisspelledOrUngrammaticalSelection(bool& misspelled, bool& ungrammatical)
+Vector<String> Editor::guessesForMisspelledOrUngrammatical(bool& misspelled, bool& ungrammatical)
 {
     if (unifiedTextCheckerEnabled()) {
         RefPtr<Range> range = frame()->selection()->toNormalizedRange();
@@ -1756,10 +1782,12 @@ Vector<String> Editor::guessesForMisspelledOrUngrammaticalSelection(bool& misspe
         return TextCheckingHelper(client(), range).guessesForMisspelledOrUngrammaticalRange(isGrammarCheckingEnabled(), misspelled, ungrammatical);
     }
 
-    misspelled = isSelectionMisspelled();
+    String misspelledWord = behavior().shouldAllowSpellingSuggestionsWithoutSelection() ? misspelledWordAtCaretOrRange(m_frame->document()->focusedNode()) : misspelledSelectionString();
+    misspelled = !misspelledWord.isEmpty();
+
     if (misspelled) {
         ungrammatical = false;
-        return guessesForMisspelledSelection();
+        return guessesForMisspelledWord(misspelledWord);
     }
     if (isGrammarCheckingEnabled() && isSelectionUngrammatical()) {
         ungrammatical = true;
index 15234db..4fa78ea 100644 (file)
@@ -213,7 +213,7 @@ public:
     bool insertParagraphSeparatorInQuotedContent();
 #endif
     
-    bool isContinuousSpellCheckingEnabled();
+    bool isContinuousSpellCheckingEnabled() const;
     void toggleContinuousSpellChecking();
     bool isGrammarCheckingEnabled();
     void toggleGrammarChecking();
@@ -221,10 +221,11 @@ public:
     void learnSpelling();
     int spellCheckerDocumentTag();
     bool isSelectionUngrammatical();
-    bool isSelectionMisspelled();
-    Vector<String> guessesForMisspelledSelection();
+    String misspelledSelectionString() const;
+    String misspelledWordAtCaretOrRange(Node* clickedNode) const;
+    Vector<String> guessesForMisspelledWord(const String&) const;
     Vector<String> guessesForUngrammaticalSelection();
-    Vector<String> guessesForMisspelledOrUngrammaticalSelection(bool& misspelled, bool& ungrammatical);
+    Vector<String> guessesForMisspelledOrUngrammatical(bool& misspelled, bool& ungrammatical);
     bool isSpellCheckingEnabledInFocusedNode() const;
     bool isSpellCheckingEnabledFor(Node*) const;
     void markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping, bool doReplacement);
index adf0a79..85e6bcf 100644 (file)
@@ -340,15 +340,28 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
         frame->editor()->command("SelectAll").execute();
         break;
 #endif
-    case ContextMenuItemTagSpellingGuess:
-        ASSERT(frame->editor()->selectedText().length());
-        if (frame->editor()->shouldInsertText(item->title(), frame->selection()->toNormalizedRange().get(), EditorInsertActionPasted)) {
+    case ContextMenuItemTagSpellingGuess: {
+        FrameSelection* frameSelection = frame->selection();
+        if (frame->editor()->shouldInsertText(item->title(), frameSelection->toNormalizedRange().get(), EditorInsertActionPasted)) {
             Document* document = frame->document();
-            RefPtr<ReplaceSelectionCommand> command = ReplaceSelectionCommand::create(document, createFragmentFromMarkup(document, item->title(), ""), ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting);
+            ReplaceSelectionCommand::CommandOptions replaceOptions = ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting;
+
+            if (frame->editor()->behavior().shouldAllowSpellingSuggestionsWithoutSelection()) {
+                ASSERT(frameSelection->isCaretOrRange());
+                VisibleSelection wordSelection(frameSelection->base());
+                wordSelection.expandUsingGranularity(WordGranularity);
+                frameSelection->setSelection(wordSelection);
+            } else {
+                ASSERT(frame->editor()->selectedText().length());
+                replaceOptions |= ReplaceSelectionCommand::SelectReplacement;
+            }
+
+            RefPtr<ReplaceSelectionCommand> command = ReplaceSelectionCommand::create(document, createFragmentFromMarkup(document, item->title(), ""), replaceOptions);
             applyCommand(command);
-            frame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
+            frameSelection->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
         }
         break;
+    }
     case ContextMenuItemTagIgnoreSpelling:
         frame->editor()->ignoreSpelling();
         break;
@@ -914,7 +927,7 @@ void ContextMenuController::populate()
                 // is never considered a misspelling and bad grammar at the same time)
                 bool misspelling;
                 bool badGrammar;
-                Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammaticalSelection(misspelling, badGrammar);
+                Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammatical(misspelling, badGrammar);
                 if (misspelling || badGrammar) {
                     size_t size = guesses.size();
                     if (!size) {