2011-03-23 Jia Pu <jpu@apple.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 24 Mar 2011 02:53:04 +0000 (02:53 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 24 Mar 2011 02:53:04 +0000 (02:53 +0000)
        Reviewed by Darin Adler.

        Hook up new AppKit autocorrection UI with WK2.
        https://bugs.webkit.org/show_bug.cgi?id=56055
        <rdar://problem/8947463>

        Please see WebCore/ChangeLog for detail.

        * platform/mac-wk2/Skipped: Enable autocorrection tests for WK2.
2011-03-23  Jia Pu  <jpu@apple.com>

        Reviewed by Darin Adler.

        Hook up new AppKit autocorrection UI with WK2.
        https://bugs.webkit.org/show_bug.cgi?id=56055
        <rdar://problem/8947463>

        This patch is to enable WK2 to utilize autocorrection UI on Mac OS X. It contains following
        major changes:

        1. All but one autocorrection related message is synchronous. Since dismissing autocorrection
        panel can potentially cause editing to occur, a synchronous dismissCorrectionPanelSoon() function
        is introduced to ensure all editing commands occur in correct order.

        2. Additional condition variable is needed to implement dismissCorrectionPanelSoon().
        To improve maintainability, CorrectionPanel class is introduced to manage the
        internal state related to correction panel. This change is applied to both WK1 and WK2.

        3. EditorClient::isShowingCorrectionPanel() has been removed. The original purpose is to allow
        editor to know when to handle ESC key event. Now this is handled internally in AppKit, so
        EditorClient::isShowingCorrectionPanel() isn't necessary anymore.

        4. The Editor* argument in EditorClient::showCorrectionPanel() has been removed, since we can
        access object via WebView or WKView.

        * editing/Editor.cpp:
        (WebCore::Editor::markMisspellingsAfterTypingToWord):
        (WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
        (WebCore::Editor::correctionPanelTimerFired):
        (WebCore::Editor::dismissCorrectionPanel):
        (WebCore::Editor::dismissCorrectionPanelSoon):
        (WebCore::Editor::applyAutocorrectionBeforeTypingIfAppropriate):
        * editing/Editor.h:
        * editing/EditorCommand.cpp:
        (WebCore::createCommandMap):
        * loader/EmptyClients.h:
        (WebCore::EmptyEditorClient::showCorrectionPanel):
        (WebCore::EmptyEditorClient::dismissCorrectionPanelSoon):
        * manual-tests/autocorrection/close-window-when-correction-is-shown.html: Added.
        * page/EditorClient.h:
2011-03-23  Jia Pu  <jpu@apple.com>

        Reviewed by Darin Adler.

        Hook up new AppKit autocorrection UI with WK2.
        https://bugs.webkit.org/show_bug.cgi?id=56055
        <rdar://problem/8947463>

        Please see WebCore/ChangeLog for detail.

        * WebKit.xcodeproj/project.pbxproj:
2011-03-23  Jia Pu  <jpu@apple.com>

        Reviewed by Darin Adler.

        Hook up new AppKit autocorrection UI with WK2.
        https://bugs.webkit.org/show_bug.cgi?id=56055
        <rdar://problem/8947463>

        Please see WebCore/ChangeLog for detail.

        * WebCoreSupport/CorrectionPanel.h: Added.
        (CorrectionPanel::isShowing):
        * WebCoreSupport/CorrectionPanel.mm: Added.
        (correctionBubbleType):
        (CorrectionPanel::CorrectionPanel):
        (CorrectionPanel::~CorrectionPanel):
        (CorrectionPanel::show):
        (CorrectionPanel::dismiss):
        (CorrectionPanel::dismissSoon):
        (CorrectionPanel::dismissInternal):
        (CorrectionPanel::recordAutocorrectionResponse):
        * WebCoreSupport/WebEditorClient.h:
        * WebCoreSupport/WebEditorClient.mm:
        (WebEditorClient::WebEditorClient):
        (WebEditorClient::showCorrectionPanel):
        (WebEditorClient::dismissCorrectionPanel):
        (WebEditorClient::dismissCorrectionPanelSoon):
        (WebEditorClient::recordAutocorrectionResponse):
        * WebView/WebView.mm:
        (-[WebView handleCorrectionPanelResult:]):
        * WebView/WebViewPrivate.h:
2011-03-23  Jia Pu  <jpu@apple.com>

        Reviewed by Darin Adler.

        Hook up new AppKit autocorrection UI with WK2.
        https://bugs.webkit.org/show_bug.cgi?id=56055
        <rdar://problem/8947463>

        Please see WebCore/ChangeLog for detail.

        The calls to AppKit are implemented in PageClientImpl. Other changes are necessary for the
        plumbing work.

        * UIProcess/API/mac/PageClientImpl.h:
        * UIProcess/API/mac/PageClientImpl.mm:
        (WebKit::PageClientImpl::showCorrectionPanel):
        (WebKit::PageClientImpl::dismissCorrectionPanel):
        (WebKit::PageClientImpl::dismissCorrectionPanelSoon):
        (WebKit::PageClientImpl::recordAutocorrectionResponse):
        * UIProcess/API/mac/WKView.mm:
        (-[WKView spellCheckerDocumentTag]):
        (-[WKView handleCorrectionPanelResult:]):
        * UIProcess/API/mac/WKViewPrivate.h:
        * UIProcess/PageClient.h:
        * UIProcess/WebPageProxy.cpp:
        (WebKit::WebPageProxy::didCommitLoadForFrame):
        (WebKit::WebPageProxy::showCorrectionPanel):
        (WebKit::WebPageProxy::dismissCorrectionPanel):
        (WebKit::WebPageProxy::dismissCorrectionPanelSoon):
        (WebKit::WebPageProxy::recordAutocorrectionResponse):
        (WebKit::WebPageProxy::handleCorrectionPanelResult):
        * UIProcess/WebPageProxy.h:
        * UIProcess/WebPageProxy.messages.in:
        * UIProcess/mac/CorrectionPanel.h: Added.
        (WebKit::CorrectionPanel::isShowing):
        * UIProcess/mac/CorrectionPanel.mm: Added.
        (correctionBubbleType):
        (WebKit::CorrectionPanel::CorrectionPanel):
        (WebKit::CorrectionPanel::~CorrectionPanel):
        (WebKit::CorrectionPanel::show):
        (WebKit::CorrectionPanel::dismiss):
        (WebKit::CorrectionPanel::dismissSoon):
        (WebKit::CorrectionPanel::dismissInternal):
        (WebKit::CorrectionPanel::recordAutocorrectionResponse):
        * WebKit2.xcodeproj/project.pbxproj:
        * WebProcess/WebCoreSupport/WebEditorClient.h:
        * WebProcess/WebCoreSupport/mac/WebEditorClientMac.mm:
        (WebKit::WebEditorClient::showCorrectionPanel):
        (WebKit::WebEditorClient::dismissCorrectionPanel):
        (WebKit::WebEditorClient::dismissCorrectionPanelSoon):
        (WebKit::WebEditorClient::recordAutocorrectionResponse):
        * WebProcess/WebPage/WebPage.cpp:
        (WebKit::WebPage::handleCorrectionPanelResult):
        * WebProcess/WebPage/WebPage.h:
        * WebProcess/WebPage/WebPage.messages.in:

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

35 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac-wk2/Skipped
Source/WebCore/ChangeLog
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/editing/EditorCommand.cpp
Source/WebCore/loader/EmptyClients.h
Source/WebCore/manual-tests/autocorrection/close-window-when-correction-is-shown.html [new file with mode: 0644]
Source/WebCore/page/EditorClient.h
Source/WebKit/ChangeLog
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebCoreSupport/CorrectionPanel.h [new file with mode: 0644]
Source/WebKit/mac/WebCoreSupport/CorrectionPanel.mm [new file with mode: 0644]
Source/WebKit/mac/WebCoreSupport/WebEditorClient.h
Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm
Source/WebKit/mac/WebView/WebView.mm
Source/WebKit/mac/WebView/WebViewPrivate.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/mac/PageClientImpl.h
Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm
Source/WebKit2/UIProcess/API/mac/WKView.mm
Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h
Source/WebKit2/UIProcess/PageClient.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/mac/CorrectionPanel.h [new file with mode: 0644]
Source/WebKit2/UIProcess/mac/CorrectionPanel.mm [new file with mode: 0644]
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h
Source/WebKit2/WebProcess/WebCoreSupport/mac/WebEditorClientMac.mm
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in

index 6b4bd0d..66aff1d 100644 (file)
@@ -1,3 +1,15 @@
+2011-03-23  Jia Pu  <jpu@apple.com>
+
+        Reviewed by Darin Adler.
+
+        Hook up new AppKit autocorrection UI with WK2.
+        https://bugs.webkit.org/show_bug.cgi?id=56055
+        <rdar://problem/8947463>
+
+        Please see WebCore/ChangeLog for detail.
+
+        * platform/mac-wk2/Skipped: Enable autocorrection tests for WK2.
+
 2011-03-23  Carol Szabo  <carol.szabo@nokia.com>
 
         Reviewed by David Hyatt.
index 1eb4eaf..67c8379 100644 (file)
@@ -569,23 +569,6 @@ platform/mac/editing/deleting/backward-delete.html
 platform/mac/editing/pasteboard/dataTransfer-set-data-file-url.html
 platform/mac/editing/selection/doubleclick-should-not-expand-across-lines.html
 platform/mac/editing/selection/word-thai.html
-platform/mac/editing/spelling/autocorrection-contraction.html
-platform/mac/editing/spelling/autocorrection-delete.html
-platform/mac/editing/spelling/autocorrection-removing-underline-after-paste.html
-platform/mac/editing/spelling/autocorrection-removing-underline.html
-platform/mac/editing/spelling/autocorrection-simple.html
-platform/mac/editing/spelling/click-autocorrected-word.html
-platform/mac/editing/spelling/delete-autocorrected-word-1.html
-platform/mac/editing/spelling/delete-into-autocorrected-word.html
-platform/mac/editing/spelling/delete-into-misspelled-word.html
-platform/mac/editing/spelling/editing-multiple-words-with-markers.html
-platform/mac/editing/spelling/editing-word-with-marker-1.html
-platform/mac/editing/spelling/editing-word-with-marker-2.html
-platform/mac/editing/spelling/forward-delete-into-autocorrected-word.html
-platform/mac/editing/spelling/move-cursor-around-misspelled-word.html
-platform/mac/editing/spelling/move-cursor-to-autocorrected-word.html
-platform/mac/editing/spelling/move-cursor-to-beginning-of-autocorrected-word.html
-platform/mac/editing/spelling/removing-underline-after-accepting-autocorrection-using-punctuation.html
 platform/mac/fast/forms/input-appearance-spinbutton-up.html
 platform/mac/fast/forms/input-number-click.html
 platform/mac/fast/forms/listbox-scrollbar-hit-test.html
index 863a910..cb6f65f 100644 (file)
@@ -1,3 +1,45 @@
+2011-03-23  Jia Pu  <jpu@apple.com>
+
+        Reviewed by Darin Adler.
+
+        Hook up new AppKit autocorrection UI with WK2.
+        https://bugs.webkit.org/show_bug.cgi?id=56055
+        <rdar://problem/8947463>
+
+        This patch is to enable WK2 to utilize autocorrection UI on Mac OS X. It contains following
+        major changes:
+
+        1. All but one autocorrection related message is synchronous. Since dismissing autocorrection
+        panel can potentially cause editing to occur, a synchronous dismissCorrectionPanelSoon() function
+        is introduced to ensure all editing commands occur in correct order.
+
+        2. Additional condition variable is needed to implement dismissCorrectionPanelSoon().
+        To improve maintainability, CorrectionPanel class is introduced to manage the
+        internal state related to correction panel. This change is applied to both WK1 and WK2.
+
+        3. EditorClient::isShowingCorrectionPanel() has been removed. The original purpose is to allow
+        editor to know when to handle ESC key event. Now this is handled internally in AppKit, so
+        EditorClient::isShowingCorrectionPanel() isn't necessary anymore.
+
+        4. The Editor* argument in EditorClient::showCorrectionPanel() has been removed, since we can
+        access object via WebView or WKView.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::markMisspellingsAfterTypingToWord):
+        (WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
+        (WebCore::Editor::correctionPanelTimerFired):
+        (WebCore::Editor::dismissCorrectionPanel):
+        (WebCore::Editor::dismissCorrectionPanelSoon):
+        (WebCore::Editor::applyAutocorrectionBeforeTypingIfAppropriate):
+        * editing/Editor.h:
+        * editing/EditorCommand.cpp:
+        (WebCore::createCommandMap):
+        * loader/EmptyClients.h:
+        (WebCore::EmptyEditorClient::showCorrectionPanel):
+        (WebCore::EmptyEditorClient::dismissCorrectionPanelSoon):
+        * manual-tests/autocorrection/close-window-when-correction-is-shown.html: Added.
+        * page/EditorClient.h:
+
 2011-03-22  Ojan Vafai  <ojan@chromium.org>
 
         Reviewed by Antti Koivisto.
index 8807965..b8c95cc 100644 (file)
@@ -2072,7 +2072,7 @@ void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart,
             doApplyCorrection = false;
     }
     if (doApplyCorrection)
-        dismissCorrectionPanel(ReasonForDismissingCorrectionPanelAccepted);
+        handleCorrectionPanelResult(dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanelAccepted));
     else
         m_correctionPanelInfo.rangeToBeReplaced.clear();
 #else
@@ -2387,7 +2387,7 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
                     m_correctionPanelInfo.replacedString = plainText(rangeToReplace.get());
                     m_correctionPanelInfo.replacementString = result->replacement;
                     m_correctionPanelInfo.isActive = true;
-                    client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, result->replacement, Vector<String>(), this);
+                    client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, result->replacement, Vector<String>());
                     break;
                 }
                 // If this function is called for showing correction panel, we ignore other correction or replacement.
@@ -2517,7 +2517,7 @@ void Editor::correctionPanelTimerFired(Timer<Editor>*)
         m_correctionPanelInfo.replacedString = plainText(m_correctionPanelInfo.rangeToBeReplaced.get());
         FloatRect boundingBox = windowRectForRange(m_correctionPanelInfo.rangeToBeReplaced.get());
         if (!boundingBox.isEmpty())
-            client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, m_correctionPanelInfo.replacementString, Vector<String>(), this);
+            client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, m_correctionPanelInfo.replacementString, Vector<String>());
     }
         break;
     case CorrectionPanelInfo::PanelTypeSpellingSuggestions: {
@@ -2535,7 +2535,7 @@ void Editor::correctionPanelTimerFired(Timer<Editor>*)
         m_correctionPanelInfo.isActive = true;
         FloatRect boundingBox = windowRectForRange(m_correctionPanelInfo.rangeToBeReplaced.get());
         if (!boundingBox.isEmpty())
-            client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, topSuggestion, suggestions, this);
+            client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, topSuggestion, suggestions);
     }
         break;
     }
@@ -2601,39 +2601,36 @@ void Editor::stopCorrectionPanelTimer()
 #endif
 }
 
-void Editor::handleCancelOperation()
+void Editor::dismissCorrectionPanel(ReasonForDismissingCorrectionPanel reasonForDismissing)
 {
 #if SUPPORT_AUTOCORRECTION_PANEL
     if (!m_correctionPanelInfo.isActive)
         return;
     m_correctionPanelInfo.isActive = false;
+    m_correctionPanelIsDismissedByEditor = true;
     if (client())
-        client()->dismissCorrectionPanel(ReasonForDismissingCorrectionPanelCancelled);
-#endif
-}
-
-bool Editor::isShowingCorrectionPanel()
-{
-#if SUPPORT_AUTOCORRECTION_PANEL
-    if (client())
-        return client()->isShowingCorrectionPanel();
+        client()->dismissCorrectionPanel(reasonForDismissing);
+#else
+    UNUSED_PARAM(reasonForDismissing);
 #endif
-    return false;
 }
 
-void Editor::dismissCorrectionPanel(ReasonForDismissingCorrectionPanel reasonForDismissing)
+String Editor::dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel reasonForDismissing)
 {
 #if SUPPORT_AUTOCORRECTION_PANEL
     if (!m_correctionPanelInfo.isActive)
-        return;
+        return String();
     m_correctionPanelInfo.isActive = false;
     m_correctionPanelIsDismissedByEditor = true;
-    if (client())
-        client()->dismissCorrectionPanel(reasonForDismissing);
+    if (!client())
+        return String();
+    return client()->dismissCorrectionPanelSoon(reasonForDismissing);
 #else
     UNUSED_PARAM(reasonForDismissing);
+    return String();
 #endif
 }
+
 void Editor::removeSpellAndCorrectionMarkersFromWordsToBeEdited(bool doNotRemoveIfSelectionAtWordBoundary)
 {
     // We want to remove the markers from a word if an editing command will change the word. This can happen in one of
@@ -2768,7 +2765,7 @@ bool Editor::applyAutocorrectionBeforeTypingIfAppropriate()
     Position caretPosition = m_frame->selection()->selection().start();
 
     if (m_correctionPanelInfo.rangeToBeReplaced->endPosition() == caretPosition) {
-        dismissCorrectionPanel(ReasonForDismissingCorrectionPanelAccepted);
+        handleCorrectionPanelResult(dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanelAccepted));
         return true;
     } 
     
index e1a7119..5fb48c5 100644 (file)
@@ -320,11 +320,9 @@ public:
 
     void addToKillRing(Range*, bool prepend);
 
-    void handleCancelOperation();
     void startCorrectionPanelTimer(CorrectionPanelInfo::PanelType);
     // If user confirmed a correction in the correction panel, correction has non-zero length, otherwise it means that user has dismissed the panel.
     void handleCorrectionPanelResult(const String& correction);
-    bool isShowingCorrectionPanel();
 
     void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle);
     void pasteAsPlainText(const String&, bool smartReplace);
@@ -425,6 +423,7 @@ private:
     Node* findEventTargetFromSelection() const;
     void stopCorrectionPanelTimer();
     void dismissCorrectionPanel(ReasonForDismissingCorrectionPanel);
+    String dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel);
     void applyCorrectionPanelInfo(const Vector<DocumentMarker::MarkerType>& markerTypesToAdd);
     // Return true if correction was applied, false otherwise.
     bool applyAutocorrectionBeforeTypingIfAppropriate();
index 6ea9954..9eafd18 100644 (file)
@@ -1091,14 +1091,6 @@ static bool executeYankAndSelect(Frame* frame, Event*, EditorCommandSource, cons
     return true;
 }
 
-#if SUPPORT_AUTOCORRECTION_PANEL
-static bool executeCancelOperation(Frame* frame, Event*, EditorCommandSource, const String&)
-{
-    frame->editor()->handleCancelOperation();
-    return true;
-}
-#endif
-
 // Supported functions
 
 static bool supported(Frame*)
@@ -1249,13 +1241,6 @@ static bool enabledUndo(Frame* frame, Event*, EditorCommandSource)
     return frame->editor()->canUndo();
 }
 
-#if SUPPORT_AUTOCORRECTION_PANEL
-static bool enabledDismissCorrectionPanel(Frame* frame, Event*, EditorCommandSource)
-{
-    return frame->editor()->isShowingCorrectionPanel();
-}
-#endif
-
 // State functions
 
 static TriState stateNone(Frame*, Event*)
@@ -1532,10 +1517,6 @@ static const CommandMap& createCommandMap()
 #if PLATFORM(MAC)
         { "TakeFindStringFromSelection", { executeTakeFindStringFromSelection, supportedFromMenuOrKeyBinding, enabledTakeFindStringFromSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
 #endif
-
-#if SUPPORT_AUTOCORRECTION_PANEL
-        { "CancelOperation", { executeCancelOperation, supportedFromMenuOrKeyBinding, enabledDismissCorrectionPanel, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
-#endif
     };
 
     // These unsupported commands are listed here since they appear in the Microsoft
index ed92f11..3b0ad2e 100644 (file)
@@ -511,9 +511,9 @@ public:
     TextCheckerClient* textChecker() { return &m_textCheckerClient; }
 
 #if SUPPORT_AUTOCORRECTION_PANEL
-    virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect&, const String&, const String&, const Vector<String>&, Editor*) { }
+    virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect&, const String&, const String&, const Vector<String>&) { }
     virtual void dismissCorrectionPanel(ReasonForDismissingCorrectionPanel) { }
-    virtual bool isShowingCorrectionPanel() { return false; }
+    virtual String dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel) { return String(); }
     virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const String&, const String&) { }
 #endif
     virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) { }
diff --git a/Source/WebCore/manual-tests/autocorrection/close-window-when-correction-is-shown.html b/Source/WebCore/manual-tests/autocorrection/close-window-when-correction-is-shown.html
new file mode 100644 (file)
index 0000000..5c82a20
--- /dev/null
@@ -0,0 +1,48 @@
+<html>
+<head>
+
+<style>
+.editing {
+    border: 2px solid red;
+    padding: 12px;
+    font-size: 24px;
+}
+</style>
+<script src=../../../../LayoutTests/editing/editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+function editingTest() {
+    typeCharacterCommand('t');
+    typeCharacterCommand('h');
+    typeCharacterCommand('e');
+    typeCharacterCommand(' ');
+    typeCharacterCommand('m');
+    typeCharacterCommand('e');
+    typeCharacterCommand('s');
+    typeCharacterCommand('a');
+    typeCharacterCommand('e');
+    typeCharacterCommand('g');
+    typeCharacterCommand('e');
+    typeCharacterCommand('e');
+    typeCharacterCommand(' ');
+    execMoveSelectionBackwardByCharacterCommand();
+}
+
+</script>
+
+<title>Testing closing window when correction suggestion is shown</title>
+</head>
+<body>
+<div><p>This test verifies that when correction suggestion is visible, closing window doesn't hang or crash.</p>
+<p>After seeing the panel with multiple candidates, close the window.</p>
+<div contenteditable id="root" class="editing">
+<span id="test"></span>
+</div>
+
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
index d5de6a4..aeda844 100644 (file)
@@ -158,14 +158,15 @@ public:
 
     virtual TextCheckerClient* textChecker() = 0;
 
-#if SUPPORT_AUTOCORRECTION_PANEL
     enum AutocorrectionResponseType {
         AutocorrectionEdited,
         AutocorrectionReverted
     };
-    virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacmentString, const Vector<String>& alternativeReplacementStrings, Editor*) = 0;
+
+#if SUPPORT_AUTOCORRECTION_PANEL
+    virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacmentString, const Vector<String>& alternativeReplacementStrings) = 0;
     virtual void dismissCorrectionPanel(ReasonForDismissingCorrectionPanel) = 0;
-    virtual bool isShowingCorrectionPanel() = 0;
+    virtual String dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel) = 0;
     virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const String& replacedString, const String& replacementString) = 0;
 #endif
 
index 03e1816..82d9e70 100644 (file)
@@ -1,3 +1,15 @@
+2011-03-23  Jia Pu  <jpu@apple.com>
+
+        Reviewed by Darin Adler.
+
+        Hook up new AppKit autocorrection UI with WK2.
+        https://bugs.webkit.org/show_bug.cgi?id=56055
+        <rdar://problem/8947463>
+
+        Please see WebCore/ChangeLog for detail.
+
+        * WebKit.xcodeproj/project.pbxproj:
+
 2011-03-17  Jeff Miller  <jeffm@apple.com>
 
         Use a consistent set of file patterns in the svn:ignore property for all .xcodeproj directories, specifically:
index 20c156f..06a5566 100644 (file)
                B6CE5C25100BC5F500219936 /* WebApplicationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B68049710FFBCEC1009F7F62 /* WebApplicationCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                B804176F1217A83100466BAE /* WebInspectorFrontend.h in Headers */ = {isa = PBXBuildFile; fileRef = B804176D1217A83100466BAE /* WebInspectorFrontend.h */; };
                B80417701217A83100466BAE /* WebInspectorFrontend.mm in Sources */ = {isa = PBXBuildFile; fileRef = B804176E1217A83100466BAE /* WebInspectorFrontend.mm */; };
+               B82958D3132707D0000D0E79 /* CorrectionPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = B82958D1132707D0000D0E79 /* CorrectionPanel.h */; };
+               B82958D4132707D0000D0E79 /* CorrectionPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = B82958D2132707D0000D0E79 /* CorrectionPanel.mm */; };
                BC26C69E10B743F400B687ED /* WebSerializedJSValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC26C69D10B743F400B687ED /* WebSerializedJSValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC26C6A510B7447A00B687ED /* WebSerializedJSValue.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC26C6A410B7447A00B687ED /* WebSerializedJSValue.mm */; };
                BC2E464D0FD8A96800A9D9DE /* WebViewData.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2E464B0FD8A96800A9D9DE /* WebViewData.h */; };
                B68049720FFBCEC1009F7F62 /* WebApplicationCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebApplicationCache.mm; sourceTree = "<group>"; };
                B804176D1217A83100466BAE /* WebInspectorFrontend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebInspectorFrontend.h; sourceTree = "<group>"; };
                B804176E1217A83100466BAE /* WebInspectorFrontend.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebInspectorFrontend.mm; sourceTree = "<group>"; };
+               B82958D1132707D0000D0E79 /* CorrectionPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CorrectionPanel.h; sourceTree = "<group>"; };
+               B82958D2132707D0000D0E79 /* CorrectionPanel.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CorrectionPanel.mm; sourceTree = "<group>"; };
                BC26C69D10B743F400B687ED /* WebSerializedJSValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSerializedJSValue.h; sourceTree = "<group>"; };
                BC26C6A410B7447A00B687ED /* WebSerializedJSValue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebSerializedJSValue.mm; sourceTree = "<group>"; };
                BC2E464B0FD8A96800A9D9DE /* WebViewData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewData.h; sourceTree = "<group>"; };
                F5B36B400281DE87018635CB /* WebCoreSupport */ = {
                        isa = PBXGroup;
                        children = (
+                               B82958D1132707D0000D0E79 /* CorrectionPanel.h */,
+                               B82958D2132707D0000D0E79 /* CorrectionPanel.mm */,
                                598AD91D1201CECF00ABAE4E /* WebDeviceOrientationClient.mm */,
                                598AD9191201CEC900ABAE4E /* WebDeviceOrientationClient.h */,
                                B68049710FFBCEC1009F7F62 /* WebApplicationCache.h */,
                                3AE15D5012DBDED4009323C8 /* WebStorageManagerInternal.h in Headers */,
                                3ABB3C7A1309C3B500E93D94 /* WebStorageTrackerClient.h in Headers */,
                                BC42D324131ED1E00075FA4B /* WebLocalizableStringsInternal.h in Headers */,
+                               B82958D3132707D0000D0E79 /* CorrectionPanel.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                CDA62AE3125F87C2007FD118 /* WebFullScreenController.mm in Sources */,
                                3ABB3C7B1309C3B500E93D94 /* WebStorageTrackerClient.mm in Sources */,
                                BC42D34D131ED3880075FA4B /* WebLocalizableStringsInternal.mm in Sources */,
+                               B82958D4132707D0000D0E79 /* CorrectionPanel.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 8c70ffe..9398dec 100644 (file)
@@ -1,3 +1,35 @@
+2011-03-23  Jia Pu  <jpu@apple.com>
+
+        Reviewed by Darin Adler.
+
+        Hook up new AppKit autocorrection UI with WK2.
+        https://bugs.webkit.org/show_bug.cgi?id=56055
+        <rdar://problem/8947463>
+
+        Please see WebCore/ChangeLog for detail.
+
+        * WebCoreSupport/CorrectionPanel.h: Added.
+        (CorrectionPanel::isShowing):
+        * WebCoreSupport/CorrectionPanel.mm: Added.
+        (correctionBubbleType):
+        (CorrectionPanel::CorrectionPanel):
+        (CorrectionPanel::~CorrectionPanel):
+        (CorrectionPanel::show):
+        (CorrectionPanel::dismiss):
+        (CorrectionPanel::dismissSoon):
+        (CorrectionPanel::dismissInternal):
+        (CorrectionPanel::recordAutocorrectionResponse):
+        * WebCoreSupport/WebEditorClient.h:
+        * WebCoreSupport/WebEditorClient.mm:
+        (WebEditorClient::WebEditorClient):
+        (WebEditorClient::showCorrectionPanel):
+        (WebEditorClient::dismissCorrectionPanel):
+        (WebEditorClient::dismissCorrectionPanelSoon):
+        (WebEditorClient::recordAutocorrectionResponse):
+        * WebView/WebView.mm:
+        (-[WebView handleCorrectionPanelResult:]):
+        * WebView/WebViewPrivate.h:
+
 2011-03-23  Enrica Casucci  <enrica@apple.com>
 
         Reviewed by Alexey Proskuryakov.
diff --git a/Source/WebKit/mac/WebCoreSupport/CorrectionPanel.h b/Source/WebKit/mac/WebCoreSupport/CorrectionPanel.h
new file mode 100644 (file)
index 0000000..8adb79f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CorrectionPanel_h
+#define CorrectionPanel_h
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+#import <AppKit/NSTextChecker.h>
+#import <WebCore/CorrectionPanelInfo.h>
+#import <wtf/RetainPtr.h>
+
+@class WebView;
+
+class CorrectionPanel {
+    WTF_MAKE_NONCOPYABLE(CorrectionPanel);
+public:
+    CorrectionPanel();
+    ~CorrectionPanel();
+    void show(WebView*, WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings);
+    void dismiss(WebCore::ReasonForDismissingCorrectionPanel);
+    String dismissSoon(WebCore::ReasonForDismissingCorrectionPanel);
+    static void recordAutocorrectionResponse(WebView*, NSCorrectionResponse, const String& replacedString, const String& replacementString);
+
+private:
+    bool isShowing() const { return m_view; }
+    void dismissInternal(WebCore::ReasonForDismissingCorrectionPanel, bool dismissingExternally);
+    void handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement, NSCorrectionBubbleType);
+
+    bool m_wasDismissedExternally;
+    WebCore::ReasonForDismissingCorrectionPanel m_reasonForDismissing;
+    RetainPtr<WebView> m_view;
+    RetainPtr<NSString> m_resultForSynchronousDismissal;
+    RetainPtr<NSCondition> m_resultCondition;
+};
+
+#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+
+#endif // CorrectionPanel_h
diff --git a/Source/WebKit/mac/WebCoreSupport/CorrectionPanel.mm b/Source/WebKit/mac/WebCoreSupport/CorrectionPanel.mm
new file mode 100644 (file)
index 0000000..383b634
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#import "CorrectionPanel.h"
+
+#import "WebViewPrivate.h"
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+using namespace WebCore;
+
+static inline NSCorrectionBubbleType correctionBubbleType(CorrectionPanelInfo::PanelType panelType)
+{
+    switch (panelType) {
+    case CorrectionPanelInfo::PanelTypeCorrection:
+        return NSCorrectionBubbleTypeCorrection;
+    case CorrectionPanelInfo::PanelTypeReversion:
+        return NSCorrectionBubbleTypeReversion;
+    case CorrectionPanelInfo::PanelTypeSpellingSuggestions:
+        return NSCorrectionBubbleTypeGuesses;
+    }
+    ASSERT_NOT_REACHED();
+    return NSCorrectionBubbleTypeCorrection;
+}
+
+CorrectionPanel::CorrectionPanel()
+    : m_wasDismissedExternally(false)
+    , m_reasonForDismissing(ReasonForDismissingCorrectionPanelIgnored)
+    , m_resultCondition(AdoptNS, [[NSCondition alloc] init])
+{
+}
+
+CorrectionPanel::~CorrectionPanel()
+{
+    dismissInternal(ReasonForDismissingCorrectionPanelIgnored, false);
+}
+
+void CorrectionPanel::show(WebView* view, CorrectionPanelInfo::PanelType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
+{
+    dismissInternal(ReasonForDismissingCorrectionPanelIgnored, false);
+    
+    if (!view)
+        return;
+
+    NSString* replacedStringAsNSString = replacedString;
+    NSString* replacementStringAsNSString = replacementString;
+    m_view = view;
+    NSCorrectionBubbleType bubbleType = correctionBubbleType(type);
+    
+    NSMutableArray* alternativeStrings = 0;
+    if (!alternativeReplacementStrings.isEmpty()) {
+        size_t size = alternativeReplacementStrings.size();
+        alternativeStrings = [NSMutableArray arrayWithCapacity:size];
+        for (size_t i = 0; i < size; ++i)
+            [alternativeStrings addObject:(NSString*)alternativeReplacementStrings[i]];
+    }
+
+    [[NSSpellChecker sharedSpellChecker] showCorrectionBubbleOfType:bubbleType primaryString:replacementStringAsNSString alternativeStrings:alternativeStrings forStringInRect:boundingBoxOfReplacedString view:m_view.get() completionHandler:^(NSString* acceptedString) {
+        handleAcceptedReplacement(acceptedString, replacedStringAsNSString, replacementStringAsNSString, bubbleType);
+    }];
+}
+
+void CorrectionPanel::dismiss(ReasonForDismissingCorrectionPanel reason)
+{
+    dismissInternal(reason, true);
+}
+
+String CorrectionPanel::dismissSoon(ReasonForDismissingCorrectionPanel reason)
+{
+    if (!isShowing())
+        return String();
+
+    dismissInternal(reason, true);
+    [m_resultCondition.get() lock];
+    while (!m_resultForSynchronousDismissal)
+        [m_resultCondition.get() wait];
+    [m_resultCondition.get() unlock];
+    return m_resultForSynchronousDismissal.get();
+}
+
+void CorrectionPanel::dismissInternal(ReasonForDismissingCorrectionPanel reason, bool dismissingExternally)
+{
+    m_wasDismissedExternally = dismissingExternally;
+    if (!isShowing())
+        return;
+    
+    m_reasonForDismissing = reason;
+    m_resultForSynchronousDismissal.clear();
+    if (reason == ReasonForDismissingCorrectionPanelAccepted)
+        [[NSSpellChecker sharedSpellChecker] dismissCorrectionBubbleForView:m_view.get()];
+    else
+        [[NSSpellChecker sharedSpellChecker] cancelCorrectionBubbleForView:m_view.get()];
+    m_view.clear();
+}
+
+void CorrectionPanel::recordAutocorrectionResponse(WebView* view, NSCorrectionResponse response, const String& replacedString, const String& replacementString)
+{
+    [[NSSpellChecker sharedSpellChecker] recordResponse:response toCorrection:replacementString forWord:replacedString language:nil inSpellDocumentWithTag:[view spellCheckerDocumentTag]];
+}
+
+void CorrectionPanel::handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement,  NSCorrectionBubbleType correctionBubbleType)
+{
+    NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker];
+    NSInteger documentTag = [m_view.get() spellCheckerDocumentTag];
+
+    switch (correctionBubbleType) {
+    case NSCorrectionBubbleTypeCorrection:
+        if (acceptedReplacement)
+            [spellChecker recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag];
+        else {
+            if (!m_wasDismissedExternally || m_reasonForDismissing == ReasonForDismissingCorrectionPanelCancelled)
+                [spellChecker recordResponse:NSCorrectionResponseRejected toCorrection:proposedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag];
+            else
+                [spellChecker recordResponse:NSCorrectionResponseIgnored toCorrection:proposedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag];
+        }
+        break;
+    case NSCorrectionBubbleTypeReversion:
+        if (acceptedReplacement)
+            [spellChecker recordResponse:NSCorrectionResponseReverted toCorrection:replaced forWord:acceptedReplacement language:nil inSpellDocumentWithTag:documentTag];
+        break;
+    case NSCorrectionBubbleTypeGuesses:
+        if (acceptedReplacement)
+            [spellChecker recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag];
+        break;
+    }
+    
+    if (!m_wasDismissedExternally) {
+        [m_view.get() handleCorrectionPanelResult:acceptedReplacement];
+        return;
+    }
+    
+    [m_resultCondition.get() lock];
+    if (acceptedReplacement)
+        m_resultForSynchronousDismissal.adoptNS([acceptedReplacement copy]);
+    [m_resultCondition.get() signal];
+    [m_resultCondition.get() unlock];
+}
+
+#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+
index 1fa132a..412cb45 100644 (file)
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import <WebCore/Editor.h>
+#import "CorrectionPanel.h"
 #import <WebCore/EditorClient.h>
 #import <WebCore/TextCheckerClient.h>
-#import <wtf/RetainPtr.h>
 #import <wtf/Forward.h>
+#import <wtf/RetainPtr.h>
 #import <wtf/Vector.h>
 
 @class WebView;
@@ -140,10 +140,10 @@ public:
     virtual void setInputMethodState(bool enabled);
     virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&);
 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
-    virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const WTF::String& replacedString, const WTF::String& replacementString, const WTF::Vector<WTF::String>& alternativeReplacementStrings, WebCore::Editor*);
+    virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings);
     virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel);
-    virtual bool isShowingCorrectionPanel();
-    virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const WTF::String& replacedString, const WTF::String& replacementString);
+    virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel);
+    virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const String& replacedString, const String& replacementString);
 #endif
 private:
     void registerCommandForUndoOrRedo(PassRefPtr<WebCore::EditCommand>, bool isRedo);
@@ -154,8 +154,6 @@ private:
     bool m_haveUndoRedoOperations;
 
 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
-    BOOL m_correctionPanelIsShown;
-    BOOL m_correctionPanelIsDismissedExternally;
-    WebCore::ReasonForDismissingCorrectionPanel m_reasonForDismissingCorrectionPanel;
+    CorrectionPanel m_correctionPanel;
 #endif
 };
index 69dd574..df985ce 100644 (file)
@@ -74,7 +74,6 @@
 #endif
 
 using namespace WebCore;
-using namespace WTF;
 
 using namespace HTMLNames;
 
@@ -202,9 +201,6 @@ WebEditorClient::WebEditorClient(WebView *webView)
     : m_webView(webView)
     , m_undoTarget([[[WebEditorUndoTarget alloc] init] autorelease])
     , m_haveUndoRedoOperations(false)
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
-    , m_correctionPanelIsShown(false)
-#endif
 {
 }
 
@@ -891,73 +887,25 @@ void WebEditorClient::updateSpellingUIWithGrammarString(const String& badGrammar
 }
 
 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
-void WebEditorClient::showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType panelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings, Editor* editor) {
-    dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored);
-
-    // Need to explicitly use these local NSString objects, because the C++ references may be invalidated by the time the block below is executed.
-    NSString *replacedStringAsNSString = replacedString;
-    NSString *replacementStringAsNSString = replacementString;
-
-    m_correctionPanelIsShown = YES;
-    m_correctionPanelIsDismissedExternally = NO;
-    m_reasonForDismissingCorrectionPanel = ReasonForDismissingCorrectionPanelIgnored;
-
-    NSCorrectionBubbleType bubbleType = correctionBubbleType(panelType);
-    NSMutableArray *alternativeStrings = nil;
-    if (!alternativeReplacementStrings.isEmpty()) {
-        size_t size = alternativeReplacementStrings.size();
-        alternativeStrings = [NSMutableArray arrayWithCapacity:size];
-        for (size_t i = 0; i < size; ++i)
-            [alternativeStrings addObject:(NSString*)alternativeReplacementStrings[i]];
-    }
-    NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
-    [[NSSpellChecker sharedSpellChecker] showCorrectionBubbleOfType:bubbleType primaryString:replacementStringAsNSString alternativeStrings:alternativeStrings forStringInRect:boundingBoxOfReplacedString view:m_webView completionHandler:^(NSString *acceptedString) {
-        switch (bubbleType) {
-        case NSCorrectionBubbleTypeCorrection:
-            if (acceptedString)
-                [spellChecker recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedString forWord:replacedStringAsNSString language:nil inSpellDocumentWithTag:spellCheckerDocumentTag()];
-            else {
-                if (!m_correctionPanelIsDismissedExternally || m_reasonForDismissingCorrectionPanel == ReasonForDismissingCorrectionPanelCancelled)
-                    [spellChecker recordResponse:NSCorrectionResponseRejected toCorrection:replacementStringAsNSString forWord:replacedStringAsNSString language:nil inSpellDocumentWithTag:spellCheckerDocumentTag()];
-                else
-                    [spellChecker recordResponse:NSCorrectionResponseIgnored toCorrection:replacementStringAsNSString forWord:replacedStringAsNSString language:nil inSpellDocumentWithTag:spellCheckerDocumentTag()];
-            }
-            break;
-        case NSCorrectionBubbleTypeReversion:
-            if (acceptedString)
-                [spellChecker recordResponse:NSCorrectionResponseReverted toCorrection:replacedStringAsNSString forWord:acceptedString language:nil inSpellDocumentWithTag:spellCheckerDocumentTag()];
-            break;
-        case NSCorrectionBubbleTypeGuesses:
-            if (acceptedString)
-                [[NSSpellChecker sharedSpellChecker] recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedString forWord:replacedStringAsNSString language:nil inSpellDocumentWithTag:[m_webView spellCheckerDocumentTag]];
-            break;
-        }
-        editor->handleCorrectionPanelResult(String(acceptedString));
-    }];
+void WebEditorClient::showCorrectionPanel(CorrectionPanelInfo::PanelType panelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
+{
+    m_correctionPanel.show(m_webView, panelType, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
 }
 
 void WebEditorClient::dismissCorrectionPanel(ReasonForDismissingCorrectionPanel reasonForDismissing)
 {
-    if (isShowingCorrectionPanel()) {
-        m_correctionPanelIsDismissedExternally = YES;
-        m_reasonForDismissingCorrectionPanel = reasonForDismissing;
-        if (reasonForDismissing == ReasonForDismissingCorrectionPanelAccepted)
-            [[NSSpellChecker sharedSpellChecker] dismissCorrectionBubbleForView:m_webView];
-        else
-            [[NSSpellChecker sharedSpellChecker] cancelCorrectionBubbleForView:m_webView];
-        m_correctionPanelIsShown = NO;
-    }
+    m_correctionPanel.dismiss(reasonForDismissing);
 }
 
-bool WebEditorClient::isShowingCorrectionPanel()
+String WebEditorClient::dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel reasonForDismissing)
 {
-    return m_correctionPanelIsShown;
+    return m_correctionPanel.dismissSoon(reasonForDismissing);
 }
 
 void WebEditorClient::recordAutocorrectionResponse(EditorClient::AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
 {
-    NSCorrectionResponse spellCheckerResponse = responseType == EditorClient::AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited;
-    [[NSSpellChecker sharedSpellChecker] recordResponse:spellCheckerResponse toCorrection:replacementString forWord:replacedString language:nil inSpellDocumentWithTag:[m_webView spellCheckerDocumentTag]];
+    NSCorrectionResponse response = responseType == EditorClient::AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited;
+    CorrectionPanel::recordAutocorrectionResponse(m_webView, response, replacedString, replacementString);
 }
 #endif
 
index 84748e5..59eb80c 100644 (file)
@@ -5311,6 +5311,16 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue jsValu
 
 #endif
 
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+- (void)handleCorrectionPanelResult:(NSString*)result
+{
+    WebFrame *webFrame = [self _selectedOrMainFrame];
+    Frame* coreFrame = core(webFrame);
+    if (coreFrame)
+        coreFrame->editor()->handleCorrectionPanelResult(result);
+}
+#endif
+
 @end
 
 @implementation WebView (WebViewUndoableEditing)
index a4ea809..cb94851 100644 (file)
@@ -644,7 +644,9 @@ Could be worth adding to the API.
 - (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag;
 - (void)toggleAutomaticSpellingCorrection:(id)sender;
 #endif
-
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+- (void)handleCorrectionPanelResult:(NSString*)result;
+#endif
 @end
 
 @interface WebView (WebViewEditingInMail)
index 834d842..9f29f06 100644 (file)
@@ -1,3 +1,59 @@
+2011-03-23  Jia Pu  <jpu@apple.com>
+
+        Reviewed by Darin Adler.
+
+        Hook up new AppKit autocorrection UI with WK2.
+        https://bugs.webkit.org/show_bug.cgi?id=56055
+        <rdar://problem/8947463>
+
+        Please see WebCore/ChangeLog for detail.
+
+        The calls to AppKit are implemented in PageClientImpl. Other changes are necessary for the
+        plumbing work.
+
+        * UIProcess/API/mac/PageClientImpl.h:
+        * UIProcess/API/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::showCorrectionPanel):
+        (WebKit::PageClientImpl::dismissCorrectionPanel):
+        (WebKit::PageClientImpl::dismissCorrectionPanelSoon):
+        (WebKit::PageClientImpl::recordAutocorrectionResponse):
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView spellCheckerDocumentTag]):
+        (-[WKView handleCorrectionPanelResult:]):
+        * UIProcess/API/mac/WKViewPrivate.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didCommitLoadForFrame):
+        (WebKit::WebPageProxy::showCorrectionPanel):
+        (WebKit::WebPageProxy::dismissCorrectionPanel):
+        (WebKit::WebPageProxy::dismissCorrectionPanelSoon):
+        (WebKit::WebPageProxy::recordAutocorrectionResponse):
+        (WebKit::WebPageProxy::handleCorrectionPanelResult):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/mac/CorrectionPanel.h: Added.
+        (WebKit::CorrectionPanel::isShowing):
+        * UIProcess/mac/CorrectionPanel.mm: Added.
+        (correctionBubbleType):
+        (WebKit::CorrectionPanel::CorrectionPanel):
+        (WebKit::CorrectionPanel::~CorrectionPanel):
+        (WebKit::CorrectionPanel::show):
+        (WebKit::CorrectionPanel::dismiss):
+        (WebKit::CorrectionPanel::dismissSoon):
+        (WebKit::CorrectionPanel::dismissInternal):
+        (WebKit::CorrectionPanel::recordAutocorrectionResponse):
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+        * WebProcess/WebCoreSupport/mac/WebEditorClientMac.mm:
+        (WebKit::WebEditorClient::showCorrectionPanel):
+        (WebKit::WebEditorClient::dismissCorrectionPanel):
+        (WebKit::WebEditorClient::dismissCorrectionPanelSoon):
+        (WebKit::WebEditorClient::recordAutocorrectionResponse):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::handleCorrectionPanelResult):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2011-03-23  Brian Weinstein  <bweinstein@apple.com>
 
         Reviewed by Maciej Stachowiak.
index 338f776..e2ad17f 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef PageClientImpl_h
 #define PageClientImpl_h
 
+#include "CorrectionPanel.h"
 #include "PageClient.h"
 #include <wtf/RetainPtr.h>
 
@@ -104,8 +105,16 @@ private:
 
     virtual void didPerformDictionaryLookup(const String&, double scaleFactor, const DictionaryPopupInfo&);
 
+    virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings);
+    virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel);
+    virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel);
+    virtual void recordAutocorrectionResponse(WebCore::EditorClient::AutocorrectionResponseType, const String& replacedString, const String& replacementString);
+
     WKView* m_wkView;
     RetainPtr<WebEditorUndoTargetObjC> m_undoTarget;
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+    CorrectionPanel m_correctionPanel;
+#endif
 };
 
 } // namespace WebKit
index e3503de..c62445b 100644 (file)
@@ -427,4 +427,37 @@ void PageClientImpl::didPerformDictionaryLookup(const String& text, double scale
     [m_wkView showDefinitionForAttributedString:attributedString.get() range:NSMakeRange(0, [attributedString.get() length]) options:options baselineOriginProvider:^(NSRange adjustedRange) { return (NSPoint)textBaselineOrigin; }];
 }
 
+void PageClientImpl::showCorrectionPanel(CorrectionPanelInfo::PanelType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
+{
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+    if (!isViewVisible() || !isViewInWindow())
+        return;
+    m_correctionPanel.show(m_wkView, type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
+#endif
+}
+
+void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingCorrectionPanel reason)
+{
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+    m_correctionPanel.dismiss(reason);
+#endif
+}
+
+String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel reason)
+{
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+    return m_correctionPanel.dismissSoon(reason);
+#else
+    return String();
+#endif
+}
+
+void PageClientImpl::recordAutocorrectionResponse(EditorClient::AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
+{
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+    NSCorrectionResponse response = responseType == EditorClient::AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited;
+    CorrectionPanel::recordAutocorrectionResponse(m_wkView, response, replacedString, replacementString);
+#endif
+}
+
 } // namespace WebKit
index 95fba8a..7a1fdf8 100644 (file)
@@ -149,6 +149,9 @@ typedef HashMap<String, ValidationVector> ValidationMap;
 #if ENABLE(FULLSCREEN_API)
     RetainPtr<WKFullScreenWindowController> _fullScreenWindowController;
 #endif
+
+    BOOL _hasSpellCheckerDocumentTag;
+    NSInteger _spellCheckerDocumentTag;
 }
 @end
 
@@ -2070,5 +2073,19 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I
     _data->_page->performDictionaryLookupAtLocation(FloatPoint(thePoint.x, thePoint.y));
 }
 
+- (NSInteger)spellCheckerDocumentTag
+{
+    if (!_data->_hasSpellCheckerDocumentTag) {
+        _data->_spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
+        _data->_hasSpellCheckerDocumentTag = YES;
+    }
+    return _data->_spellCheckerDocumentTag;
+}
+
+- (void)handleCorrectionPanelResult:(NSString*)result
+{
+    _data->_page->handleCorrectionPanelResult(result);
+}
+
 @end
 
index cece1c7..37c2d8d 100644 (file)
@@ -35,4 +35,6 @@
 
 - (void)performDictionaryLookupAtCurrentMouseLocation;
 
+- (NSInteger)spellCheckerDocumentTag;
+- (void)handleCorrectionPanelResult:(NSString*)result;
 @end
index 10bd078..85576f9 100644 (file)
@@ -130,6 +130,10 @@ public:
     virtual void setComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled) = 0;
     virtual CGContextRef containingWindowGraphicsContext() = 0;
     virtual void didPerformDictionaryLookup(const String&, double scaleFactor, const DictionaryPopupInfo&) = 0;
+    virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) = 0;
+    virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel) = 0;
+    virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel) = 0;
+    virtual void recordAutocorrectionResponse(WebCore::EditorClient::AutocorrectionResponseType, const String& replacedString, const String& replacementString) = 0;
 #endif
 
     virtual void didChangeScrollbarsForMainFrame() const = 0;
index daa26c1..c99f05e 100644 (file)
@@ -1394,6 +1394,10 @@ void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, const String& mimeTyp
     if (!arguments->decode(messageDecoder))
         return;
 
+#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
+    dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored);
+#endif
+
     WebFrameProxy* frame = process()->webFrame(frameID);
     MESSAGE_CHECK(frame);
 
@@ -2759,4 +2763,36 @@ void WebPageProxy::saveDataToFileInDownloadsFolder(const String& suggestedFilena
     m_uiClient.saveDataToFileInDownloadsFolder(this, suggestedFilename, mimeType, originatingURLString, data);
 }
 
+#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
+void WebPageProxy::showCorrectionPanel(int32_t panelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
+{
+    m_pageClient->showCorrectionPanel((WebCore::CorrectionPanelInfo::PanelType)panelType, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
+}
+
+void WebPageProxy::dismissCorrectionPanel(int32_t reason)
+{
+    m_pageClient->dismissCorrectionPanel((WebCore::ReasonForDismissingCorrectionPanel)reason);
+}
+
+void WebPageProxy::dismissCorrectionPanelSoon(int32_t reason, String& result)
+{
+    result = m_pageClient->dismissCorrectionPanelSoon((WebCore::ReasonForDismissingCorrectionPanel)reason);
+}
+
+void WebPageProxy::recordAutocorrectionResponse(int32_t responseType, const String& replacedString, const String& replacementString)
+{
+    m_pageClient->recordAutocorrectionResponse((WebCore::EditorClient::AutocorrectionResponseType)responseType, replacedString, replacementString);
+}
+#endif
+
+#if PLATFORM(MAC)
+void WebPageProxy::handleCorrectionPanelResult(const String& result)
+{
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+    if (!isClosed())
+        process()->send(Messages::WebPage::HandleCorrectionPanelResult(result), m_pageID, 0);
+#endif
+}
+#endif
+
 } // namespace WebKit
index 85400f5..c3cc374 100644 (file)
@@ -448,6 +448,10 @@ public:
 
     void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects);
 
+#if PLATFORM(MAC)
+    void handleCorrectionPanelResult(const String& result);
+#endif
+
     static void setDebugPaintFlags(WKPageDebugPaintFlags flags) { s_debugPaintFlags = flags; }
     static WKPageDebugPaintFlags debugPaintFlags() { return s_debugPaintFlags; }
 
@@ -641,6 +645,13 @@ private:
 
     void initializeSandboxExtensionHandle(const WebCore::KURL&, SandboxExtension::Handle&);
 
+#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
+    void showCorrectionPanel(int32_t panelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings);
+    void dismissCorrectionPanel(int32_t reason);
+    void dismissCorrectionPanelSoon(int32_t reason, String& result);
+    void recordAutocorrectionResponse(int32_t responseType, const String& replacedString, const String& replacementString);
+#endif
+
     PageClient* m_pageClient;
     WebLoaderClient m_loaderClient;
     WebPolicyClient m_policyClient;
index c812ae1..55a6dc2 100644 (file)
@@ -208,4 +208,12 @@ messages -> WebPageProxy {
 #if PLATFORM(WIN)
     StartDragDrop(WebCore::IntPoint imagePoint, WebCore::IntPoint dragPoint, uint64_t okEffect, HashMap<UINT,Vector<String> > dataMap, WebCore::IntSize dragImageSize, WebKit::SharedMemory::Handle dragImage, bool linkDrag)
 #endif
+
+#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
+    # Autocorrection messages
+    ShowCorrectionPanel(int32_t panelType, WebCore::FloatRect boundingBoxOfReplacedString, String replacedString, String replacementString, Vector<String> alternativeReplacementStrings)
+    DismissCorrectionPanel(int32_t reason)
+    DismissCorrectionPanelSoon(int32_t reason) -> (String result)
+    RecordAutocorrectionResponse(int32_t responseType, String replacedString, String replacementString);
+#endif
 }
diff --git a/Source/WebKit2/UIProcess/mac/CorrectionPanel.h b/Source/WebKit2/UIProcess/mac/CorrectionPanel.h
new file mode 100644 (file)
index 0000000..d4bc353
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CorrectionPanel_h
+#define CorrectionPanel_h
+
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+#import <AppKit/NSTextChecker.h>
+#import <WebCore/CorrectionPanelInfo.h>
+#import <wtf/RetainPtr.h>
+
+@class WKView;
+
+namespace WebKit {
+
+class CorrectionPanel {
+public:
+    CorrectionPanel();
+    ~CorrectionPanel();
+    void show(WKView*, WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings);
+    void dismiss(WebCore::ReasonForDismissingCorrectionPanel);
+    String dismissSoon(WebCore::ReasonForDismissingCorrectionPanel);
+    static void recordAutocorrectionResponse(WKView*, NSCorrectionResponse, const String& replacedString, const String& replacementString);
+
+private:
+    bool isShowing() const { return m_view; }
+    void dismissInternal(WebCore::ReasonForDismissingCorrectionPanel, bool dismissingExternally);
+    void handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement, NSCorrectionBubbleType);
+
+    bool m_wasDismissedExternally;
+    WebCore::ReasonForDismissingCorrectionPanel m_reasonForDismissing;
+    RetainPtr<WKView> m_view;
+    RetainPtr<NSString> m_resultForSynchronousDismissal;
+    RetainPtr<NSCondition> m_resultCondition;
+};
+
+} // namespace WebKit
+
+#endif // !defined(BUILDING_ON_SNOW_LEOPARD)
+
+#endif // CorrectionPanel_h
diff --git a/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm b/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm
new file mode 100644 (file)
index 0000000..01ffcdf
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+#import "CorrectionPanel.h"
+
+#import "WebPageProxy.h"
+#import "WKView.h"
+#import "WKViewPrivate.h"
+
+using namespace WebCore;
+
+static inline NSCorrectionBubbleType correctionBubbleType(CorrectionPanelInfo::PanelType panelType)
+{
+    switch (panelType) {
+    case CorrectionPanelInfo::PanelTypeCorrection:
+        return NSCorrectionBubbleTypeCorrection;
+    case CorrectionPanelInfo::PanelTypeReversion:
+        return NSCorrectionBubbleTypeReversion;
+    case CorrectionPanelInfo::PanelTypeSpellingSuggestions:
+        return NSCorrectionBubbleTypeGuesses;
+    }
+    ASSERT_NOT_REACHED();
+    return NSCorrectionBubbleTypeCorrection;
+}
+
+namespace WebKit {
+
+CorrectionPanel::CorrectionPanel()
+    : m_wasDismissedExternally(false)
+    , m_reasonForDismissing(ReasonForDismissingCorrectionPanelIgnored)
+    , m_resultCondition(AdoptNS, [[NSCondition alloc] init])
+{
+}
+
+CorrectionPanel::~CorrectionPanel()
+{
+    dismissInternal(ReasonForDismissingCorrectionPanelIgnored, false);
+}
+
+void CorrectionPanel::show(WKView* view, CorrectionPanelInfo::PanelType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
+{
+    dismissInternal(ReasonForDismissingCorrectionPanelIgnored, false);
+    
+    if (!view)
+        return;
+
+    NSString* replacedStringAsNSString = replacedString;
+    NSString* replacementStringAsNSString = replacementString;
+    m_view = view;
+    NSCorrectionBubbleType bubbleType = correctionBubbleType(type);
+    
+    NSMutableArray* alternativeStrings = 0;
+    if (!alternativeReplacementStrings.isEmpty()) {
+        size_t size = alternativeReplacementStrings.size();
+        alternativeStrings = [NSMutableArray arrayWithCapacity:size];
+        for (size_t i = 0; i < size; ++i)
+            [alternativeStrings addObject:(NSString*)alternativeReplacementStrings[i]];
+    }
+
+    NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker];
+    [spellChecker showCorrectionBubbleOfType:bubbleType primaryString:replacementStringAsNSString alternativeStrings:alternativeStrings forStringInRect:boundingBoxOfReplacedString view:m_view.get() completionHandler:^(NSString* acceptedString) {
+        handleAcceptedReplacement(acceptedString, replacedStringAsNSString, replacementStringAsNSString, bubbleType);
+    }];
+}
+
+void CorrectionPanel::dismiss(ReasonForDismissingCorrectionPanel reason)
+{
+    dismissInternal(reason, true);
+}
+
+String CorrectionPanel::dismissSoon(ReasonForDismissingCorrectionPanel reason)
+{
+    if (!isShowing())
+        return String();
+
+    dismissInternal(reason, true);
+    [m_resultCondition.get() lock];
+    while (!m_resultForSynchronousDismissal)
+        [m_resultCondition.get() wait];
+    [m_resultCondition.get() unlock];
+    return m_resultForSynchronousDismissal.get();
+}
+
+void CorrectionPanel::dismissInternal(ReasonForDismissingCorrectionPanel reason, bool dismissingExternally)
+{
+    m_wasDismissedExternally = dismissingExternally;
+    if (!isShowing())
+        return;
+    
+    m_reasonForDismissing = reason;
+    m_resultForSynchronousDismissal.clear();
+    if (reason == ReasonForDismissingCorrectionPanelAccepted)
+        [[NSSpellChecker sharedSpellChecker] dismissCorrectionBubbleForView:m_view.get()];
+    else
+        [[NSSpellChecker sharedSpellChecker] cancelCorrectionBubbleForView:m_view.get()];
+    m_view.clear();
+}
+
+void CorrectionPanel::recordAutocorrectionResponse(WKView* view, NSCorrectionResponse response, const String& replacedString, const String& replacementString)
+{
+    [[NSSpellChecker sharedSpellChecker] recordResponse:response toCorrection:replacementString forWord:replacedString language:nil inSpellDocumentWithTag:[view spellCheckerDocumentTag]];
+}
+
+void CorrectionPanel::handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement,  NSCorrectionBubbleType correctionBubbleType)
+{
+    NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker];
+    NSInteger documentTag = [m_view.get() spellCheckerDocumentTag];
+    
+    switch (correctionBubbleType) {
+    case NSCorrectionBubbleTypeCorrection:
+        if (acceptedReplacement)
+            [spellChecker recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag];
+        else {
+            if (!m_wasDismissedExternally || m_reasonForDismissing == ReasonForDismissingCorrectionPanelCancelled)
+                [spellChecker recordResponse:NSCorrectionResponseRejected toCorrection:proposedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag];
+            else
+                [spellChecker recordResponse:NSCorrectionResponseIgnored toCorrection:proposedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag];
+        }
+        break;
+    case NSCorrectionBubbleTypeReversion:
+        if (acceptedReplacement)
+            [spellChecker recordResponse:NSCorrectionResponseReverted toCorrection:replaced forWord:acceptedReplacement language:nil inSpellDocumentWithTag:documentTag];
+        break;
+    case NSCorrectionBubbleTypeGuesses:
+        if (acceptedReplacement)
+            [spellChecker recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag];
+        break;
+    }
+    
+    if (!m_wasDismissedExternally) {
+        [m_view.get() handleCorrectionPanelResult:acceptedReplacement];
+        return;
+    }
+    
+    [m_resultCondition.get() lock];
+    if (acceptedReplacement)
+        m_resultForSynchronousDismissal.adoptNS([acceptedReplacement copy]);
+    [m_resultCondition.get() signal];
+    [m_resultCondition.get() unlock];
+}
+
+} // namespace WebKit
+
+#endif //!defined(BUILDING_ON_SNOW_LEOPARD)
+
index 4f0b9f0..f3fe1e5 100644 (file)
                93FC67BE12D3CCF200A60610 /* DecoderAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 93FC679E12D3CC7400A60610 /* DecoderAdapter.h */; };
                93FC67BF12D3CCF200A60610 /* EncoderAdapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93FC679F12D3CC7400A60610 /* EncoderAdapter.cpp */; };
                93FC67C012D3CCF200A60610 /* EncoderAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 93FC67A012D3CC7400A60610 /* EncoderAdapter.h */; };
+               B878B615133428DC006888E9 /* CorrectionPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = B878B613133428DC006888E9 /* CorrectionPanel.h */; };
+               B878B616133428DC006888E9 /* CorrectionPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = B878B614133428DC006888E9 /* CorrectionPanel.mm */; };
                BC0092F7115837A300E0AE2A /* RunLoopMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC0092F5115837A300E0AE2A /* RunLoopMac.mm */; };
                BC0092F8115837A300E0AE2A /* WorkQueueMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0092F6115837A300E0AE2A /* WorkQueueMac.cpp */; };
                BC032D7510F4378D0058C15A /* WebChromeClient.h in Headers */ = {isa = PBXBuildFile; fileRef = BC032D6010F4378D0058C15A /* WebChromeClient.h */; };
                93FC67A012D3CC7400A60610 /* EncoderAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncoderAdapter.h; sourceTree = "<group>"; };
                A72D5D7F1236CBA800A88B15 /* WebSerializedScriptValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSerializedScriptValue.h; sourceTree = "<group>"; };
                B396EA5512E0ED2D00F4FEB7 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
+               B878B613133428DC006888E9 /* CorrectionPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CorrectionPanel.h; sourceTree = "<group>"; };
+               B878B614133428DC006888E9 /* CorrectionPanel.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CorrectionPanel.mm; sourceTree = "<group>"; };
                BC0092F5115837A300E0AE2A /* RunLoopMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RunLoopMac.mm; sourceTree = "<group>"; };
                BC0092F6115837A300E0AE2A /* WorkQueueMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkQueueMac.cpp; sourceTree = "<group>"; };
                BC032D6010F4378D0058C15A /* WebChromeClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebChromeClient.h; sourceTree = "<group>"; };
                BCCF085C113F3B7500C650C5 /* mac */ = {
                        isa = PBXGroup;
                        children = (
-                               CDCA85DE132AD05300E961DF /* WebFullScreenManagerProxyMac.mm */,
-                               CDCA85C6132ABA4E00E961DF /* WKFullScreenWindowController.mm */,
-                               CDCA85C7132ABA4E00E961DF /* WKFullScreenWindowController.h */,
                                1A64292C12DE5F9800CAAE2C /* BackingStoreMac.mm */,
                                BC2651F511825EF800243E12 /* ChunkedUpdateDrawingAreaProxyMac.mm */,
+                               B878B613133428DC006888E9 /* CorrectionPanel.h */,
+                               B878B614133428DC006888E9 /* CorrectionPanel.mm */,
                                1AA417ED12C00D87002BE67B /* TextCheckerMac.mm */,
                                1A1C648611F415B700553C19 /* WebContextMac.mm */,
                                51ACBB9E127A8F2C00D203B9 /* WebContextMenuProxyMac.h */,
                                51ACBB9F127A8F2C00D203B9 /* WebContextMenuProxyMac.mm */,
+                               CDCA85DE132AD05300E961DF /* WebFullScreenManagerProxyMac.mm */,
                                1CA8B935127C774E00576C2B /* WebInspectorProxyMac.mm */,
                                BC857E8512B71EBB00EDEB2E /* WebPageProxyMac.mm */,
                                BC5750951268F3C6006F0F12 /* WebPopupMenuProxyMac.h */,
                                BC5750961268F3C6006F0F12 /* WebPopupMenuProxyMac.mm */,
                                BC84EB1712A7100C0083F2DA /* WebPreferencesMac.mm */,
+                               CDCA85C6132ABA4E00E961DF /* WKFullScreenWindowController.mm */,
+                               CDCA85C7132ABA4E00E961DF /* WKFullScreenWindowController.h */,
                        );
                        path = mac;
                        sourceTree = "<group>";
                                511B24AB132E097200065A0C /* WebIconDatabase.h in Headers */,
                                51D02F6A132EC73700BEAA96 /* WebIconDatabaseMessages.h in Headers */,
                                51D02F6C132EC73700BEAA96 /* WebIconDatabaseProxyMessages.h in Headers */,
+                               B878B615133428DC006888E9 /* CorrectionPanel.h in Headers */,
                                33D3A3B61339600B00709BE4 /* WKMediaCacheManager.h in Headers */,
                                33D3A3BB1339606200709BE4 /* WebMediaCacheManagerProxy.h in Headers */,
                                33D3A3C2133960B000709BE4 /* WebMediaCacheManager.h in Headers */,
                                511B24AA132E097200065A0C /* WebIconDatabase.cpp in Sources */,
                                51D02F64132EC5B900BEAA96 /* WebIconDatabaseMessageReceiver.cpp in Sources */,
                                51D02F6B132EC73700BEAA96 /* WebIconDatabaseProxyMessageReceiver.cpp in Sources */,
+                               B878B616133428DC006888E9 /* CorrectionPanel.mm in Sources */,
                                33D3A3B51339600B00709BE4 /* WKMediaCacheManager.cpp in Sources */,
                                33D3A3BA1339606200709BE4 /* WebMediaCacheManagerProxy.cpp in Sources */,
                                33D3A3C1133960B000709BE4 /* WebMediaCacheManager.cpp in Sources */,
index fa8426a..9200af0 100644 (file)
@@ -141,11 +141,11 @@ private:
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool enabled);
     virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&);
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
-    virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings, WebCore::Editor*);
+#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
+    virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings);
     virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel);
-    virtual bool isShowingCorrectionPanel();
-    virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const WTF::String& replacedString, const WTF::String& replacementString);
+    virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel);
+    virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const String& replacedString, const String& replacementString);
 #endif
     WebPage* m_page;
 };
index 8af0438..7a95a72 100644 (file)
@@ -46,7 +46,7 @@
 #import <WebCore/Page.h>
 #import <WebKit/WebResource.h>
 #import <WebKit/WebNSURLExtras.h>
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
 #import <AppKit/NSTextChecker.h>
 #endif
 
@@ -246,26 +246,27 @@ void WebEditorClient::checkTextOfParagraph(const UChar* text, int length, uint64
     m_page->sendSync(Messages::WebPageProxy::CheckTextOfParagraph(String(text, length), checkingTypes), Messages::WebPageProxy::CheckTextOfParagraph::Reply(results));
 }
 
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
-void WebEditorClient::showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType type, const WebCore::FloatRect& boundingBoxOfReplacedString, const WTF::String& replacedString, const WTF::String& replacementString, const Vector<String>& alternativeReplacementStrings, WebCore::Editor*)
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
+void WebEditorClient::showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType type, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
 {
-    notImplemented();
+    m_page->send(Messages::WebPageProxy::ShowCorrectionPanel(type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings));
 }
 
-void WebEditorClient::dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel)
+void WebEditorClient::dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel reason)
 {
-    notImplemented();
+    m_page->send(Messages::WebPageProxy::DismissCorrectionPanel(reason));
 }
 
-bool WebEditorClient::isShowingCorrectionPanel()
+String WebEditorClient::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel reason)
 {
-    notImplemented();
-    return false;
+    String result;
+    m_page->sendSync(Messages::WebPageProxy::DismissCorrectionPanelSoon(reason), Messages::WebPageProxy::DismissCorrectionPanelSoon::Reply(result));
+    return result;
 }
 
 void WebEditorClient::recordAutocorrectionResponse(EditorClient::AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
 {
-    notImplemented();
+    m_page->send(Messages::WebPageProxy::RecordAutocorrectionResponse(responseType, replacedString, replacementString));
 }
 #endif
 
index a0a6796..6f16456 100644 (file)
@@ -2131,4 +2131,14 @@ bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request)
     return platformCanHandleRequest(request);
 }
 
+#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
+void WebPage::handleCorrectionPanelResult(const String& result)
+{
+    Frame* frame = m_page->focusController()->focusedOrMainFrame();
+    if (!frame)
+        return;
+    frame->editor()->handleCorrectionPanelResult(result);
+}
+#endif
+
 } // namespace WebKit
index a573de2..f7b99d2 100644 (file)
@@ -361,6 +361,10 @@ public:
     void setDragSource(NSObject *);
 #endif
 
+#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
+    void handleCorrectionPanelResult(const String&);
+#endif
+
 private:
     WebPage(uint64_t pageID, const WebPageCreationParameters&);
 
index 64f7daf..865cd98 100644 (file)
@@ -192,4 +192,8 @@ messages -> WebPage {
 #if PLATFORM(QT)
     FindZoomableAreaForPoint(WebCore::IntPoint point)
 #endif
+
+#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
+    HandleCorrectionPanelResult(String result)
+#endif
 }