Safari does not emit composition end if blurred for dead key / Japanese IME
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Nov 2016 23:55:00 +0000 (23:55 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Nov 2016 23:55:00 +0000 (23:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164369
<rdar://problem/29050439>

Reviewed by Ryosuke Niwa.

Source/WebCore:

On Mac, _before_ changing selection, try to finalize the composition by calling Editor::cancelComposition early.
This is because the focused element may have changed after performing the selection change, so we would
otherwise be dispatching the `compositionend` to the new focused element (or no compositionend at all) instead
of the element with the composition.

Doing this allows us to match Chrome and Firefox behavior. After canceling the composition, we then need to also
clear the system IME state. We do this on Mac WK1/WK2 through the cancelComposition() codepath, which ends up
calling into -discardMarkedText, which resets the marked text state. Some minor refactoring was performed to
accomplish this -- currently, discardedComposition sends a CompositionWasCanceled message over to the UI process
that discards the marked text, and then updates the editor state. This patch splits this into two separate
steps -- see the WebKit2 ChangeLog for more details.

Test: fast/events/ime-compositionend-on-selection-change.html

* editing/Editor.cpp:
(WebCore::Editor::selectionWillChange):
* editing/Editor.h:
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelectionWithoutUpdatingAppearance):
* editing/mac/EditorMac.mm:
(WebCore::Editor::selectionWillChange):
* loader/EmptyClients.h:
* page/EditorClient.h:

Source/WebKit/mac:

When canceling a composition, make sure that we clear the system IME state.

* WebCoreSupport/WebEditorClient.h:
* WebCoreSupport/WebEditorClient.mm:
(WebEditorClient::canceledComposition):

Source/WebKit/win:

Add a stub implementation of canceledComposition.

* WebCoreSupport/WebEditorClient.cpp:
(WebEditorClient::canceledComposition):
* WebCoreSupport/WebEditorClient.h:

Source/WebKit2:

Split WebPage::discardedComposition into two steps, where we first discard marked text and then update the
editor state. This allows the codepath where we cancel the composition early (before setting the selection) to
discard marked text without also forcing an editor state update at the same time. The editor state is later
updated in WebPage::didChangeSelection.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::compositionWasCanceled):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::canceledComposition):
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
* WebProcess/WebPage/WebPage.h:

LayoutTests:

Adds a new test verifying that we dispatch `compositionend` events in various circumstances:
    1. After composing in an editable area and then focusing another editable area.
    2. After composing in an editable area and then blur()-ing.
    3. After composing in an editable area and then changing the selection.

There should be no behavior change for other platforms, so no new tests are needed there with this change.

* fast/events/ime-compositionend-on-selection-change-expected.txt: Added.
* fast/events/ime-compositionend-on-selection-change.html: Added.
* platform/ios-simulator/TestExpectations:

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

25 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/events/ime-compositionend-on-selection-change-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/ime-compositionend-on-selection-change.html [new file with mode: 0644]
LayoutTests/platform/ios-simulator/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/editing/mac/EditorMac.mm
Source/WebCore/loader/EmptyClients.h
Source/WebCore/page/EditorClient.h
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebCoreSupport/WebEditorClient.h
Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp
Source/WebKit/win/WebCoreSupport/WebEditorClient.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h

index 05d3e55..897fa89 100644 (file)
@@ -1,3 +1,22 @@
+2016-11-04  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Safari does not emit composition end if blurred for dead key / Japanese IME
+        https://bugs.webkit.org/show_bug.cgi?id=164369
+        <rdar://problem/29050439>
+
+        Reviewed by Ryosuke Niwa.
+
+        Adds a new test verifying that we dispatch `compositionend` events in various circumstances:
+            1. After composing in an editable area and then focusing another editable area.
+            2. After composing in an editable area and then blur()-ing.
+            3. After composing in an editable area and then changing the selection.
+
+        There should be no behavior change for other platforms, so no new tests are needed there with this change.
+
+        * fast/events/ime-compositionend-on-selection-change-expected.txt: Added.
+        * fast/events/ime-compositionend-on-selection-change.html: Added.
+        * platform/ios-simulator/TestExpectations:
+
 2016-11-04  Brady Eidson  <beidson@apple.com>
 
         IndexedDB 2.0: Clean up more transaction abort and exception throwing behavior from IDBObjectStore.
diff --git a/LayoutTests/fast/events/ime-compositionend-on-selection-change-expected.txt b/LayoutTests/fast/events/ime-compositionend-on-selection-change-expected.txt
new file mode 100644 (file)
index 0000000..0e6b18a
--- /dev/null
@@ -0,0 +1,21 @@
+To manually test, start editing a composition in the input field and focus the contenteditable without committing the composition. A compositionend event should be logged, with the event target being the input field. Next, insert a pending composition in the contenteditable and focus the input. A compositionend should be logged, with the event target being the contenteditable. Then insert a pending composition in the input field and focus the document. A compositionend event should be logged with the target being the input field. Lastly, insert a pending composition in the rich contenteditable and click and drag to select all the text in the contenteditable. A compositionend event should be fired on the contenteditable.
+
+
+defb
+
+1. Editing the plain input field
+Focusing the rich contenteditable
+PASS: Dispatched compositionend on <INPUT id="plain">
+
+2. Editing the rich contenteditable
+Focusing the plain input field
+PASS: Dispatched compositionend on <DIV id="rich">
+
+3. Editing the plain input field again
+Blurring the plain input field
+PASS: Dispatched compositionend on <INPUT id="plain">
+
+4. Editing the rich contenteditable again
+Changing selection within the rich contenteditable
+PASS: Dispatched compositionend on <DIV id="rich">
+
diff --git a/LayoutTests/fast/events/ime-compositionend-on-selection-change.html b/LayoutTests/fast/events/ime-compositionend-on-selection-change.html
new file mode 100644 (file)
index 0000000..b325273
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <p>To manually test, start editing a composition in the input field and focus the contenteditable without committing
+    the composition. A compositionend event should be logged, with the event target being the input field. Next, insert
+    a pending composition in the contenteditable and focus the input. A compositionend should be logged, with the event
+    target being the contenteditable. Then insert a pending composition in the input field and focus the document. A
+    compositionend event should be logged with the target being the input field. Lastly, insert a pending composition in
+    the rich contenteditable and click and drag to select all the text in the contenteditable. A compositionend event
+    should be fired on the contenteditable.</p>
+    <input id="plain"></input>
+    <div id="rich" contenteditable style="border: 1px dashed"></div>
+    <div id="output"></div>
+    <script type="text/javascript">
+        let write = s => output.innerHTML += `${s}<br>`;
+        plain.addEventListener("compositionend", logCompositionEnd);
+        rich.addEventListener("compositionend", logCompositionEnd);
+        plain.focus();
+
+        if (window.testRunner && window.textInputController) {
+            testRunner.dumpAsText();
+
+            write("");
+            write("1. Editing the plain input field");
+            textInputController.setMarkedText("a", 1, 0);
+            write("   Focusing the rich contenteditable");
+            rich.focus();
+
+            write("");
+            write("2. Editing the rich contenteditable");
+            textInputController.setMarkedText("b", 1, 0);
+            write("   Focusing the plain input field");
+            plain.focus();
+
+            write("");
+            write("3. Editing the plain input field again");
+            textInputController.setMarkedText("c", 1, 0);
+            write("   Blurring the plain input field");
+            plain.blur();
+
+            write("");
+            write("4. Editing the rich contenteditable again");
+            rich.focus();
+            textInputController.setMarkedText("d", 1, 0);
+            textInputController.setMarkedText("de", 2, 0);
+            textInputController.setMarkedText("def", 3, 0);
+            write("   Changing selection within the rich contenteditable");
+            document.execCommand("SelectAll");
+        }
+
+        function logCompositionEnd(event)
+        {
+            write(`PASS: Dispatched compositionend on &lt;${event.target.tagName} id="${event.target.id}"&gt;`);
+        }
+    </script>
+</body>
+</html>
index adbf131..4f2a15c 100644 (file)
@@ -1200,6 +1200,7 @@ fast/events/focus-change-crash2.html [ Failure ]
 fast/events/frame-scroll-fake-mouse-move.html [ Failure ]
 fast/events/frame-tab-focus.html [ Failure ]
 fast/events/ime-composition-events-001.html [ Failure ]
+fast/events/ime-compositionend-on-selection-change.html [ Failure ]
 fast/events/inputText-never-fired-on-keydown-cancel.html [ Failure ]
 fast/events/input-events-drag-and-drop.html [ Failure ]
 fast/events/input-events-insert-by-drop.html [ Failure ]
index 7f1158e..b9ad351 100644 (file)
@@ -1,3 +1,35 @@
+2016-11-04  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Safari does not emit composition end if blurred for dead key / Japanese IME
+        https://bugs.webkit.org/show_bug.cgi?id=164369
+        <rdar://problem/29050439>
+
+        Reviewed by Ryosuke Niwa.
+
+        On Mac, _before_ changing selection, try to finalize the composition by calling Editor::cancelComposition early.
+        This is because the focused element may have changed after performing the selection change, so we would
+        otherwise be dispatching the `compositionend` to the new focused element (or no compositionend at all) instead
+        of the element with the composition.
+
+        Doing this allows us to match Chrome and Firefox behavior. After canceling the composition, we then need to also
+        clear the system IME state. We do this on Mac WK1/WK2 through the cancelComposition() codepath, which ends up
+        calling into -discardMarkedText, which resets the marked text state. Some minor refactoring was performed to
+        accomplish this -- currently, discardedComposition sends a CompositionWasCanceled message over to the UI process
+        that discards the marked text, and then updates the editor state. This patch splits this into two separate
+        steps -- see the WebKit2 ChangeLog for more details.
+
+        Test: fast/events/ime-compositionend-on-selection-change.html
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::selectionWillChange):
+        * editing/Editor.h:
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::setSelectionWithoutUpdatingAppearance):
+        * editing/mac/EditorMac.mm:
+        (WebCore::Editor::selectionWillChange):
+        * loader/EmptyClients.h:
+        * page/EditorClient.h:
+
 2016-11-04  Brady Eidson  <beidson@apple.com>
 
         IndexedDB 2.0: Clean up more transaction abort and exception throwing behavior from IDBObjectStore.
index c734caf..1589c47 100644 (file)
@@ -3244,6 +3244,12 @@ void Editor::setMarkedTextMatchesAreHighlighted(bool flag)
     document().markers().repaintMarkers(DocumentMarker::TextMatch);
 }
 
+#if !PLATFORM(MAC)
+void Editor::selectionWillChange()
+{
+}
+#endif
+
 void Editor::respondToChangedSelection(const VisibleSelection&, FrameSelection::SetSelectionOptions options)
 {
 #if PLATFORM(IOS)
index 8670ae3..e2bbc49 100644 (file)
@@ -390,6 +390,7 @@ public:
 
     WEBCORE_EXPORT IntRect firstRectForRange(Range*) const;
 
+    void selectionWillChange();
     void respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions);
     WEBCORE_EXPORT void updateEditorUINowIfScheduled();
     bool shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity, bool stillSelecting) const;
index b57be6a..1151129 100644 (file)
@@ -305,13 +305,17 @@ bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelectio
         clearTypingStyle();
 
     VisibleSelection oldSelection = m_selection;
+    bool didMutateSelection = oldSelection != newSelection;
+    if (didMutateSelection)
+        m_frame->editor().selectionWillChange();
+
     m_selection = newSelection;
 
     // Selection offsets should increase when LF is inserted before the caret in InsertLineBreakCommand. See <https://webkit.org/b/56061>.
     if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(newSelection.start()))
         textControl->selectionChanged(options & FireSelectEvent);
 
-    if (oldSelection == newSelection)
+    if (!didMutateSelection)
         return false;
 
     setCaretRectNeedsUpdate();
index e803dfc..5e7eaea 100644 (file)
@@ -428,6 +428,15 @@ void Editor::fillInUserVisibleForm(PasteboardURL& pasteboardURL)
     pasteboardURL.userVisibleForm = client()->userVisibleString(pasteboardURL.url);
 }
 
+void Editor::selectionWillChange()
+{
+    if (!hasComposition() || ignoreCompositionSelectionChange() || m_frame.selection().isNone())
+        return;
+
+    cancelComposition();
+    client()->canceledComposition();
+}
+
 String Editor::plainTextFromPasteboard(const PasteboardPlainText& text)
 {
     String string = text.text;
index 660b12f..8be77ab 100644 (file)
@@ -468,6 +468,7 @@ public:
     void didChangeSelectionAndUpdateLayout() override { }
     void updateEditorStateAfterLayoutIfEditabilityChanged() override { }
     void discardedComposition(Frame*) override { }
+    void canceledComposition() override { }
     void didEndEditing() override { }
     void willWriteSelectionToPasteboard(Range*) override { }
     void didWriteSelectionToPasteboard() override { }
index 4f6a985..eb1a42e 100644 (file)
@@ -102,6 +102,7 @@ public:
     // Notify an input method that a composition was voluntarily discarded by WebCore, so that it could clean up too.
     // This function is not called when a composition is closed per a request from an input method.
     virtual void discardedComposition(Frame*) = 0;
+    virtual void canceledComposition() = 0;
 
     virtual void registerUndoStep(PassRefPtr<UndoStep>) = 0;
     virtual void registerRedoStep(PassRefPtr<UndoStep>) = 0;
index e635556..faf07c1 100644 (file)
@@ -1,3 +1,17 @@
+2016-11-04  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Safari does not emit composition end if blurred for dead key / Japanese IME
+        https://bugs.webkit.org/show_bug.cgi?id=164369
+        <rdar://problem/29050439>
+
+        Reviewed by Ryosuke Niwa.
+
+        When canceling a composition, make sure that we clear the system IME state.
+
+        * WebCoreSupport/WebEditorClient.h:
+        * WebCoreSupport/WebEditorClient.mm:
+        (WebEditorClient::canceledComposition):
+
 2016-11-04  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         Add a setting and preferences to enable/disable async image decoding
index 07a5edc..12eee2b 100644 (file)
@@ -113,6 +113,7 @@ private:
     void didChangeSelectionAndUpdateLayout() final { }
     void updateEditorStateAfterLayoutIfEditabilityChanged() final;
     void discardedComposition(WebCore::Frame*) final;
+    void canceledComposition() final;
 
     void registerUndoStep(PassRefPtr<WebCore::UndoStep>) final;
     void registerRedoStep(PassRefPtr<WebCore::UndoStep>) final;
index da49da9..ce48436 100644 (file)
@@ -375,6 +375,13 @@ void WebEditorClient::discardedComposition(Frame*)
     // The effects of this function are currently achieved via -[WebHTMLView _updateSelectionForInputManager].
 }
 
+void WebEditorClient::canceledComposition()
+{
+#if !PLATFORM(IOS)
+    [[NSTextInputContext currentInputContext] discardMarkedText];
+#endif
+}
+
 void WebEditorClient::didEndEditing()
 {
 #if !PLATFORM(IOS)
index b10b671..d79add1 100644 (file)
@@ -1,3 +1,17 @@
+2016-11-04  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Safari does not emit composition end if blurred for dead key / Japanese IME
+        https://bugs.webkit.org/show_bug.cgi?id=164369
+        <rdar://problem/29050439>
+
+        Reviewed by Ryosuke Niwa.
+
+        Add a stub implementation of canceledComposition.
+
+        * WebCoreSupport/WebEditorClient.cpp:
+        (WebEditorClient::canceledComposition):
+        * WebCoreSupport/WebEditorClient.h:
+
 2016-11-04  Per Arne Vollan  <pvollan@apple.com>
 
         [Win] Page visibility tests are timing out.
index c374139..f8b908d 100644 (file)
@@ -242,6 +242,11 @@ void WebEditorClient::discardedComposition(Frame*)
     notImplemented();
 }
 
+void WebEditorClient::canceledComposition()
+{
+    notImplemented();
+}
+
 void WebEditorClient::didEndEditing()
 {
     static _bstr_t webViewDidEndEditingNotificationName(WebViewDidEndEditingNotification);
index 4ff0abf..594c48d 100644 (file)
@@ -58,6 +58,7 @@ public:
     virtual void respondToChangedSelection(WebCore::Frame*);
     void didChangeSelectionAndUpdateLayout() final { }
     void updateEditorStateAfterLayoutIfEditabilityChanged() final { } 
+    void canceledComposition() final;
     void discardedComposition(WebCore::Frame*) final;
 
     bool shouldDeleteRange(WebCore::Range*);
index 31c8e7b..d95d8c0 100644 (file)
@@ -1,3 +1,29 @@
+2016-11-04  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Safari does not emit composition end if blurred for dead key / Japanese IME
+        https://bugs.webkit.org/show_bug.cgi?id=164369
+        <rdar://problem/29050439>
+
+        Reviewed by Ryosuke Niwa.
+
+        Split WebPage::discardedComposition into two steps, where we first discard marked text and then update the
+        editor state. This allows the codepath where we cancel the composition early (before setting the selection) to
+        discard marked text without also forcing an editor state update at the same time. The editor state is later
+        updated in WebPage::didChangeSelection.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::compositionWasCanceled):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::canceledComposition):
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::didChangeSelection):
+        (WebKit::WebPage::discardedComposition):
+        (WebKit::WebPage::canceledComposition):
+        * WebProcess/WebPage/WebPage.h:
+
 2016-11-04  Alex Christensen  <achristensen@webkit.org>
 
         Unreviewed, rolling out r208293.
index 3e799a6..e021b03 100644 (file)
@@ -4379,12 +4379,11 @@ void WebPageProxy::backForwardForwardListCount(int32_t& count)
     count = m_backForwardList->forwardListCount();
 }
 
-void WebPageProxy::compositionWasCanceled(const EditorState& editorState)
+void WebPageProxy::compositionWasCanceled()
 {
 #if PLATFORM(COCOA)
     m_pageClient.notifyInputContextAboutDiscardedComposition();
 #endif
-    editorStateChanged(editorState);
 }
 
 // Undo management
index 32659d1..1f99aaf 100644 (file)
@@ -1320,7 +1320,7 @@ private:
 #endif
 
     void editorStateChanged(const EditorState&);
-    void compositionWasCanceled(const EditorState&);
+    void compositionWasCanceled();
     void setHasHadSelectionChangesFromUserInteraction(bool);
     void setNeedsHiddenContentEditableQuirk(bool);
     void setNeedsPlainTextQuirk(bool);
index ff250bf..7dcb92c 100644 (file)
@@ -240,7 +240,7 @@ messages -> WebPageProxy {
 
     # Editor notifications
     EditorStateChanged(struct WebKit::EditorState editorState)
-    CompositionWasCanceled(struct WebKit::EditorState editorState)
+    CompositionWasCanceled()
     SetHasHadSelectionChangesFromUserInteraction(bool hasHadUserSelectionChanges)
     SetNeedsHiddenContentEditableQuirk(bool needsHiddenContentEditableQuirk)
     SetNeedsPlainTextQuirk(bool needsPlainTextQuirk)
index 4c95e9f..c9c96be 100644 (file)
@@ -211,6 +211,11 @@ void WebEditorClient::discardedComposition(Frame*)
     m_page->discardedComposition();
 }
 
+void WebEditorClient::canceledComposition()
+{
+    m_page->canceledComposition();
+}
+
 void WebEditorClient::didEndEditing()
 {
     static NeverDestroyed<String> WebViewDidEndEditingNotification(ASCIILiteral("WebViewDidEndEditingNotification"));
index 0f1a852..6b3a20f 100644 (file)
@@ -65,6 +65,7 @@ private:
     void didChangeSelectionAndUpdateLayout() final;
     void updateEditorStateAfterLayoutIfEditabilityChanged() final;
     void discardedComposition(WebCore::Frame*) final;
+    void canceledComposition() final;
     void didEndEditing() final;
     void willWriteSelectionToPasteboard(WebCore::Range*) final;
     void didWriteSelectionToPasteboard() final;
index 4b490f4..d1530b1 100644 (file)
@@ -4898,7 +4898,7 @@ void WebPage::didChangeSelection()
     // FIXME: We can't cancel composition when selection changes to NoSelection, but we probably should.
     if (frame.editor().hasComposition() && !frame.editor().ignoreCompositionSelectionChange() && !frame.selection().isNone()) {
         frame.editor().cancelComposition();
-        send(Messages::WebPageProxy::CompositionWasCanceled(editorState));
+        discardedComposition();
     } else
         send(Messages::WebPageProxy::EditorStateChanged(editorState));
 #else
@@ -4983,7 +4983,13 @@ void WebPage::sendPostLayoutEditorStateIfNeeded()
 
 void WebPage::discardedComposition()
 {
-    send(Messages::WebPageProxy::CompositionWasCanceled(editorState()));
+    send(Messages::WebPageProxy::CompositionWasCanceled());
+    send(Messages::WebPageProxy::EditorStateChanged(editorState()));
+}
+
+void WebPage::canceledComposition()
+{
+    send(Messages::WebPageProxy::CompositionWasCanceled());
 }
 
 void WebPage::setMinimumLayoutSize(const IntSize& minimumLayoutSize)
index e36ab5f..091d8ea 100644 (file)
@@ -659,6 +659,7 @@ public:
     void didApplyStyle();
     void didChangeSelection();
     void discardedComposition();
+    void canceledComposition();
 
 #if PLATFORM(COCOA)
     void registerUIProcessAccessibilityTokens(const IPC::DataReference& elemenToken, const IPC::DataReference& windowToken);