2011-04-07 Jia Pu <jpu@apple.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 Apr 2011 03:59:34 +0000 (03:59 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 Apr 2011 03:59:34 +0000 (03:59 +0000)
        Reviewed by Darin Adler.

        [Mac] Editor::setComposition() should not trigger correction panel timer.
        https://bugs.webkit.org/show_bug.cgi?id=58049
         <rdar://problem/9226305>

        On Mac OS X that supports autocorrection panel, typing unconfirmed composition (i.e. unconfirmed Japanese or Chinese input)
        should not start autocorrection timer. We added a member variable, m_shouldPreventSpellChecking, to TypingCommand.
        When this value is true, markMisspellingsAfterTyping() will not be called in TypingCommand::typingAddedToOpenCommand().
        m_shouldPreventSpellChecking is set to true in the TypingCommand objects created by Editor::setComposition().

        No new tests. No deterministically reproducible test case. Patch is based on static code analysis. Testing this also requires firing
        autocorrection panel timer, which can not be easily done in automated fashion.

        * editing/Editor.cpp:
        (WebCore::Editor::deleteWithDirection):
        (WebCore::Editor::insertTextWithoutSendingTextEvent):
        (WebCore::Editor::confirmComposition):
        (WebCore::Editor::setComposition):
        * editing/EditorCommand.cpp:
        (WebCore::executeDelete):
        * editing/TypingCommand.cpp:
        (WebCore::TypingCommand::TypingCommand):
        (WebCore::TypingCommand::deleteSelection):
        (WebCore::TypingCommand::deleteKeyPressed):
        (WebCore::TypingCommand::forwardDeleteKeyPressed):
        (WebCore::TypingCommand::insertText):
        (WebCore::TypingCommand::insertLineBreak):
        (WebCore::TypingCommand::insertParagraphSeparator):
        (WebCore::TypingCommand::typingAddedToOpenCommand):
        * editing/TypingCommand.h:
        (WebCore::TypingCommand::create):
        (WebCore::TypingCommand::setShouldPreventSpellChecking):

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

Source/WebCore/ChangeLog
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/EditorCommand.cpp
Source/WebCore/editing/TypingCommand.cpp
Source/WebCore/editing/TypingCommand.h

index 389984a..d8daaac 100644 (file)
@@ -1,3 +1,39 @@
+2011-04-07  Jia Pu  <jpu@apple.com>
+
+        Reviewed by Darin Adler.
+
+        [Mac] Editor::setComposition() should not trigger correction panel timer.
+        https://bugs.webkit.org/show_bug.cgi?id=58049
+         <rdar://problem/9226305>
+
+        On Mac OS X that supports autocorrection panel, typing unconfirmed composition (i.e. unconfirmed Japanese or Chinese input)
+        should not start autocorrection timer. We added a member variable, m_shouldPreventSpellChecking, to TypingCommand. 
+        When this value is true, markMisspellingsAfterTyping() will not be called in TypingCommand::typingAddedToOpenCommand().
+        m_shouldPreventSpellChecking is set to true in the TypingCommand objects created by Editor::setComposition().
+
+        No new tests. No deterministically reproducible test case. Patch is based on static code analysis. Testing this also requires firing
+        autocorrection panel timer, which can not be easily done in automated fashion.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::deleteWithDirection):
+        (WebCore::Editor::insertTextWithoutSendingTextEvent):
+        (WebCore::Editor::confirmComposition):
+        (WebCore::Editor::setComposition):
+        * editing/EditorCommand.cpp:
+        (WebCore::executeDelete):
+        * editing/TypingCommand.cpp:
+        (WebCore::TypingCommand::TypingCommand):
+        (WebCore::TypingCommand::deleteSelection):
+        (WebCore::TypingCommand::deleteKeyPressed):
+        (WebCore::TypingCommand::forwardDeleteKeyPressed):
+        (WebCore::TypingCommand::insertText):
+        (WebCore::TypingCommand::insertLineBreak):
+        (WebCore::TypingCommand::insertParagraphSeparator):
+        (WebCore::TypingCommand::typingAddedToOpenCommand):
+        * editing/TypingCommand.h:
+        (WebCore::TypingCommand::create):
+        (WebCore::TypingCommand::setShouldPreventSpellChecking):
+
 2011-04-07  John Bauman  <jbauman@chromium.org>
 
         Reviewed by Kenneth Russell.
index 90eb825..8d5101c 100644 (file)
@@ -339,7 +339,7 @@ bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity g
 
     if (m_frame->selection()->isRange()) {
         if (isTypingAction) {
-            TypingCommand::deleteKeyPressed(m_frame->document(), canSmartCopyOrDelete(), granularity);
+            TypingCommand::deleteKeyPressed(m_frame->document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
             revealSelectionAfterEditingOperation();
         } else {
             if (killRing)
@@ -348,14 +348,19 @@ bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity g
             // Implicitly calls revealSelectionAfterEditingOperation().
         }
     } else {
+        TypingCommand::Options options = 0;
+        if (canSmartCopyOrDelete())
+            options |= TypingCommand::SmartDelete;
+        if (killRing)
+            options |= TypingCommand::KillRing;
         switch (direction) {
         case DirectionForward:
         case DirectionRight:
-            TypingCommand::forwardDeleteKeyPressed(m_frame->document(), canSmartCopyOrDelete(), granularity, killRing);
+            TypingCommand::forwardDeleteKeyPressed(m_frame->document(), options, granularity);
             break;
         case DirectionBackward:
         case DirectionLeft:
-            TypingCommand::deleteKeyPressed(m_frame->document(), canSmartCopyOrDelete(), granularity, killRing);
+            TypingCommand::deleteKeyPressed(m_frame->document(), options, granularity);
             break;
         }
         revealSelectionAfterEditingOperation();
@@ -1202,7 +1207,7 @@ bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectIn
             RefPtr<Document> document = selectionStart->document();
 
             // Insert the text
-            TypingCommand::TypingCommandOptions options = 0;
+            TypingCommand::Options options = 0;
             if (selectInsertedText)
                 options |= TypingCommand::SelectInsertedText;
             if (autocorrectionWasApplied)
@@ -1629,7 +1634,7 @@ void Editor::confirmComposition(const String& text, bool preserveSelection)
     // If text is empty, then delete the old composition here.  If text is non-empty, InsertTextCommand::input
     // will delete the old composition with an optimized replace operation.
     if (text.isEmpty())
-        TypingCommand::deleteSelection(m_frame->document(), false);
+        TypingCommand::deleteSelection(m_frame->document(), 0);
 
     m_compositionNode = 0;
     m_customCompositionUnderlines.clear();
@@ -1697,13 +1702,13 @@ void Editor::setComposition(const String& text, const Vector<CompositionUnderlin
     // If text is empty, then delete the old composition here.  If text is non-empty, InsertTextCommand::input
     // will delete the old composition with an optimized replace operation.
     if (text.isEmpty())
-        TypingCommand::deleteSelection(m_frame->document(), false);
+        TypingCommand::deleteSelection(m_frame->document(), TypingCommand::PreventSpellChecking);
 
     m_compositionNode = 0;
     m_customCompositionUnderlines.clear();
 
     if (!text.isEmpty()) {
-        TypingCommand::insertText(m_frame->document(), text, true, TypingCommand::TextCompositionUpdate);
+        TypingCommand::insertText(m_frame->document(), text, TypingCommand::SelectInsertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionUpdate);
 
         // Find out what node has the composition now.
         Position base = m_frame->selection()->base().downstream();
index 75a20d7..290ee47 100644 (file)
@@ -318,7 +318,7 @@ static bool executeDelete(Frame* frame, Event*, EditorCommandSource source, cons
     case CommandFromDOMWithUserInterface:
         // If the current selection is a caret, delete the preceding character. IE performs forwardDelete, but we currently side with Firefox.
         // Doesn't scroll to make the selection visible, or modify the kill ring (this time, siding with IE, not Firefox).
-        TypingCommand::deleteKeyPressed(frame->document(), frame->selection()->granularity() == WordGranularity);
+        TypingCommand::deleteKeyPressed(frame->document(), frame->selection()->granularity() == WordGranularity ? TypingCommand::SmartDelete : 0);
         return true;
     }
     ASSERT_NOT_REACHED();
index df150ee..1ff2524 100644 (file)
@@ -59,23 +59,24 @@ static bool canAppendNewLineFeed(const VisibleSelection& selection)
     return event->text().length();
 }
 
-TypingCommand::TypingCommand(Document *document, ETypingCommand commandType, const String &textToInsert, TypingCommandOptions options, TextGranularity granularity, TextCompositionType compositionType)
+TypingCommand::TypingCommand(Document *document, ETypingCommand commandType, const String &textToInsert, Options options, TextGranularity granularity, TextCompositionType compositionType)
     : CompositeEditCommand(document)
     , m_commandType(commandType)
     , m_textToInsert(textToInsert)
     , m_openForMoreTyping(true)
     , m_selectInsertedText(options & SelectInsertedText)
-    , m_smartDelete(false)
+    , m_smartDelete(options & SmartDelete)
     , m_granularity(granularity)
     , m_compositionType(compositionType)
     , m_killRing(options & KillRing)
     , m_openedByBackwardDelete(false)
     , m_shouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator)
+    , m_shouldPreventSpellChecking(options & PreventSpellChecking)
 {
     updatePreservesTypingStyle(m_commandType);
 }
 
-void TypingCommand::deleteSelection(Document* document, bool smartDelete)
+void TypingCommand::deleteSelection(Document* document, Options options)
 {
     ASSERT(document);
     
@@ -87,16 +88,16 @@ void TypingCommand::deleteSelection(Document* document, bool smartDelete)
     
     EditCommand* lastEditCommand = frame->editor()->lastEditCommand();
     if (isOpenForMoreTypingCommand(lastEditCommand)) {
-        static_cast<TypingCommand*>(lastEditCommand)->deleteSelection(smartDelete);
+        TypingCommand* lastTypingCommand = static_cast<TypingCommand*>(lastEditCommand);
+        lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
+        lastTypingCommand->deleteSelection(options & SmartDelete);
         return;
     }
 
-    RefPtr<TypingCommand> typingCommand = TypingCommand::create(document, DeleteSelection, "", 0);
-    typingCommand->setSmartDelete(smartDelete);
-    typingCommand->apply();
+    TypingCommand::create(document, DeleteSelection, "", options)->apply();
 }
 
-void TypingCommand::deleteKeyPressed(Document *document, bool smartDelete, TextGranularity granularity, bool killRing)
+void TypingCommand::deleteKeyPressed(Document *document, Options options, TextGranularity granularity)
 {
     ASSERT(document);
     
@@ -105,18 +106,17 @@ void TypingCommand::deleteKeyPressed(Document *document, bool smartDelete, TextG
     
     EditCommand* lastEditCommand = frame->editor()->lastEditCommand();
     if (granularity == CharacterGranularity && isOpenForMoreTypingCommand(lastEditCommand)) {
-        updateSelectionIfDifferentFromCurrentSelection(static_cast<TypingCommand*>(lastEditCommand), frame);
-        static_cast<TypingCommand*>(lastEditCommand)->deleteKeyPressed(granularity, killRing);
+        TypingCommand* lastTypingCommand = static_cast<TypingCommand*>(lastEditCommand);
+        updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand, frame);
+        lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
+        lastTypingCommand->deleteKeyPressed(granularity, options & KillRing);
         return;
     }
 
-    TypingCommandOptions options = killRing ? KillRing : 0;
-    RefPtr<TypingCommand> typingCommand = TypingCommand::create(document, DeleteKey, "", options, granularity);
-    typingCommand->setSmartDelete(smartDelete);
-    typingCommand->apply();
+    TypingCommand::create(document, DeleteKey, "", options, granularity)->apply();
 }
 
-void TypingCommand::forwardDeleteKeyPressed(Document *document, bool smartDelete, TextGranularity granularity, bool killRing)
+void TypingCommand::forwardDeleteKeyPressed(Document *document, Options options, TextGranularity granularity)
 {
     // FIXME: Forward delete in TextEdit appears to open and close a new typing command.
     ASSERT(document);
@@ -126,15 +126,14 @@ void TypingCommand::forwardDeleteKeyPressed(Document *document, bool smartDelete
     
     EditCommand* lastEditCommand = frame->editor()->lastEditCommand();
     if (granularity == CharacterGranularity && isOpenForMoreTypingCommand(lastEditCommand)) {
-        updateSelectionIfDifferentFromCurrentSelection(static_cast<TypingCommand*>(lastEditCommand), frame);
-        static_cast<TypingCommand*>(lastEditCommand)->forwardDeleteKeyPressed(granularity, killRing);
+        TypingCommand* lastTypingCommand = static_cast<TypingCommand*>(lastEditCommand);
+        updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand, frame);
+        lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
+        lastTypingCommand->forwardDeleteKeyPressed(granularity, options & KillRing);
         return;
     }
 
-    TypingCommandOptions options = killRing ? KillRing : 0;
-    RefPtr<TypingCommand> typingCommand = TypingCommand::create(document, ForwardDeleteKey, "", options, granularity);
-    typingCommand->setSmartDelete(smartDelete);
-    typingCommand->apply();
+    TypingCommand::create(document, ForwardDeleteKey, "", options, granularity)->apply();
 }
 
 void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand* typingCommand, Frame* frame)
@@ -148,7 +147,7 @@ void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand
     typingCommand->setEndingSelection(currentSelection);
 }
 
-void TypingCommand::insertText(Document* document, const String& text, TypingCommandOptions options, TextCompositionType composition)
+void TypingCommand::insertText(Document* document, const String& text, Options options, TextCompositionType composition)
 {
     ASSERT(document);
 
@@ -164,7 +163,7 @@ void TypingCommand::insertText(Document* document, const String& text, TypingCom
 }
 
 // FIXME: We shouldn't need to take selectionForInsertion. It should be identical to SelectionController's current selection.
-void TypingCommand::insertText(Document* document, const String& text, const VisibleSelection& selectionForInsertion, TypingCommandOptions options, TextCompositionType compositionType)
+void TypingCommand::insertText(Document* document, const String& text, const VisibleSelection& selectionForInsertion, Options options, TextCompositionType compositionType)
 {
     ASSERT(document);
 
@@ -200,6 +199,7 @@ void TypingCommand::insertText(Document* document, const String& text, const Vis
 
         lastTypingCommand->setCompositionType(compositionType);
         lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
+        lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
         lastTypingCommand->insertText(newText, options & SelectInsertedText);
         return;
     }
@@ -216,7 +216,7 @@ void TypingCommand::insertText(Document* document, const String& text, const Vis
     }
 }
 
-void TypingCommand::insertLineBreak(Document *document, TypingCommandOptions options)
+void TypingCommand::insertLineBreak(Document *document, Options options)
 {
     ASSERT(document);
 
@@ -250,7 +250,7 @@ void TypingCommand::insertParagraphSeparatorInQuotedContent(Document *document)
     applyCommand(TypingCommand::create(document, InsertParagraphSeparatorInQuotedContent));
 }
 
-void TypingCommand::insertParagraphSeparator(Document *document, TypingCommandOptions options)
+void TypingCommand::insertParagraphSeparator(Document *document, Options options)
 {
     ASSERT(document);
 
@@ -360,7 +360,8 @@ void TypingCommand::typingAddedToOpenCommand(ETypingCommand commandTypeForAddedT
 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
     document()->frame()->editor()->appliedEditing(this);
     // Since the spellchecking code may also perform corrections and other replacements, it should happen after the typing changes.
-    markMisspellingsAfterTyping(commandTypeForAddedTyping);
+    if (!m_shouldPreventSpellChecking)
+        markMisspellingsAfterTyping(commandTypeForAddedTyping);
 #else
     // The old spellchecking code requires that checking be done first, to prevent issues like that in 6864072, where <doesn't> is marked as misspelled.
     markMisspellingsAfterTyping(commandTypeForAddedTyping);
index beb4d02..a10634f 100644 (file)
@@ -48,20 +48,22 @@ public:
         TextCompositionConfirm
     };
 
-    enum TypingCommandOption {
+    enum Option {
         SelectInsertedText = 1 << 0,
         KillRing = 1 << 1,
-        RetainAutocorrectionIndicator = 1 << 2
+        RetainAutocorrectionIndicator = 1 << 2,
+        PreventSpellChecking = 1 << 3,
+        SmartDelete = 1 << 4
     };
-    typedef unsigned TypingCommandOptions;
-
-    static void deleteSelection(Document*, bool smartDelete = false);
-    static void deleteKeyPressed(Document*, bool smartDelete = false, TextGranularity = CharacterGranularity, bool killRing = false);
-    static void forwardDeleteKeyPressed(Document*, bool smartDelete = false, TextGranularity = CharacterGranularity, bool killRing = false);
-    static void insertText(Document*, const String&, TypingCommandOptions, TextCompositionType = TextCompositionNone);
-    static void insertText(Document*, const String&, const VisibleSelection&, TypingCommandOptions, TextCompositionType = TextCompositionNone);
-    static void insertLineBreak(Document*, TypingCommandOptions);
-    static void insertParagraphSeparator(Document*, TypingCommandOptions);
+    typedef unsigned Options;
+
+    static void deleteSelection(Document*, Options = 0);
+    static void deleteKeyPressed(Document*, Options = 0, TextGranularity = CharacterGranularity);
+    static void forwardDeleteKeyPressed(Document*, Options = 0, TextGranularity = CharacterGranularity);
+    static void insertText(Document*, const String&, Options, TextCompositionType = TextCompositionNone);
+    static void insertText(Document*, const String&, const VisibleSelection&, Options, TextCompositionType = TextCompositionNone);
+    static void insertLineBreak(Document*, Options);
+    static void insertParagraphSeparator(Document*, Options);
     static void insertParagraphSeparatorInQuotedContent(Document*);
     static bool isOpenForMoreTypingCommand(const EditCommand*);
     static void closeTyping(EditCommand*);
@@ -80,17 +82,17 @@ public:
     void setCompositionType(TextCompositionType type) { m_compositionType = type; }
 
 private:
-    static PassRefPtr<TypingCommand> create(Document* document, ETypingCommand command, const String& text = "", TypingCommandOptions options = 0, TextGranularity granularity = CharacterGranularity)
+    static PassRefPtr<TypingCommand> create(Document* document, ETypingCommand command, const String& text = "", Options options = 0, TextGranularity granularity = CharacterGranularity)
     {
         return adoptRef(new TypingCommand(document, command, text, options, granularity, TextCompositionNone));
     }
 
-    static PassRefPtr<TypingCommand> create(Document* document, ETypingCommand command, const String& text, TypingCommandOptions options, TextCompositionType compositionType)
+    static PassRefPtr<TypingCommand> create(Document* document, ETypingCommand command, const String& text, Options options, TextCompositionType compositionType)
     {
         return adoptRef(new TypingCommand(document, command, text, options, CharacterGranularity, compositionType));
     }
 
-    TypingCommand(Document*, ETypingCommand, const String& text, TypingCommandOptions, TextGranularity, TextCompositionType);
+    TypingCommand(Document*, ETypingCommand, const String& text, Options, TextGranularity, TextCompositionType);
 
     bool smartDelete() const { return m_smartDelete; }
     void setSmartDelete(bool smartDelete) { m_smartDelete = smartDelete; }
@@ -101,6 +103,7 @@ private:
     virtual bool preservesTypingStyle() const { return m_preservesTypingStyle; }
     virtual bool shouldRetainAutocorrectionIndicator() const { return m_shouldRetainAutocorrectionIndicator; }
     virtual void setShouldRetainAutocorrectionIndicator(bool retain) { m_shouldRetainAutocorrectionIndicator = retain; }
+    void setShouldPreventSpellChecking(bool prevent) { m_shouldPreventSpellChecking = prevent; }
 
     static void updateSelectionIfDifferentFromCurrentSelection(TypingCommand*, Frame*);
 
@@ -125,6 +128,7 @@ private:
     bool m_openedByBackwardDelete;
 
     bool m_shouldRetainAutocorrectionIndicator;
+    bool m_shouldPreventSpellChecking;
 };
 
 } // namespace WebCore