[webkit-changes] [WebKit/WebKit] 90ab26: [iOS 18] Undo voice command in Mail compose view d...

Wenson Hsieh noreply at github.com
Mon Jul 8 09:16:12 PDT 2024


  Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 90ab262c20a7ad6601d72961b4fd7a2d745b8f41
      https://github.com/WebKit/WebKit/commit/90ab262c20a7ad6601d72961b4fd7a2d745b8f41
  Author: Wenson Hsieh <wenson_hsieh at apple.com>
  Date:   2024-07-08 (Mon, 08 Jul 2024)

  Changed paths:
    M Source/WebCore/editing/Editor.cpp
    M Source/WebCore/editing/Editor.h
    M Source/WebKit/UIProcess/WebPageProxy.cpp
    M Source/WebKit/UIProcess/WebPageProxy.h
    M Source/WebKit/UIProcess/ios/WKContentView.mm
    M Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
    M Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
    M Source/WebKit/WebProcess/WebPage/WebPage.cpp
    M Source/WebKit/WebProcess/WebPage/WebPage.h
    M Source/WebKit/WebProcess/WebPage/WebPage.messages.in
    M Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm

  Log Message:
  -----------
  [iOS 18] Undo voice command in Mail compose view does not fully undo dictated text
https://bugs.webkit.org/show_bug.cgi?id=276300
rdar://126653644

Reviewed by Abrar Rahman Protyasha.

In iOS 18, dictation recognizes the phrase "Undo" while dictating text, and reverts the most
recently inserted dictation phrase. However, in the following scenario:

1. Type "Hello"
2. Begin dictation and say "world"
3. Say "Undo"

...the resulting text will sometimes end up being `"Hello wo"` or `"Hello wor"`. To understand why,
we first need to understand how dictation-triggered undo works — when phrases are dictated,
`UIDictationController` begins a new undo group by calling `-[NSUndoManager beginUndoGrouping]` on
the editing responder (`WKContentView`). As the user continues speaking, the "hypothesis text" is
updated, which repeatedly uses `-insertText:` and `-adjustSelectionByRange:completionHandler:` to
replace the dictated text. When the user says "Undo", the dictation controller then undoes this
entire group.

The issue is that when the dictation controller first calls `-insertText:` after beginning the undo
group, this inserted text is added to the last open typing command (after the user types `"Hello"`)
instead of being a part of the newly established group that encapsulates all of the edit commands
triggered by dictation. As such, when the undo group is undone, we end up with `"Hello"` along with
the first piece of text, with which the dictation controller called `-insertText:`.

To fix this, we detect when any WebKit client (or the system, in this case dictation code) tells the
`WKContentView`'s undo manager to `-beginUndoGrouping`, and close the current typing command to
ensure that edit commands triggered in the new undo group aren't merged into the previous typing
command before the undo group.

Test: KeyboardInputTests.NewUndoGroupClosesPreviousTypingCommand

* Source/WebCore/editing/Editor.cpp:
(WebCore::Editor::closeTyping):
* Source/WebCore/editing/Editor.h:

Add a helper command to close the typing command if needed.

* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::closeCurrentTypingCommand):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/UIProcess/ios/WKContentView.mm:
(-[WKNSUndoManager initWithContentView:]):
(-[WKNSUndoManager beginUndoGrouping]):
(-[WKNSUndoManager registerUndoWithTarget:selector:object:]):
(-[WKNSUndoManager registerUndoWithTarget:handler:]):

Add a helper class that overrides `-beginUndoGrouping` and tells the webpage to close the current
typing command when a new undo group starts. Note that we avoid this codepath when a new command is
being registered, so that we don't prematurely close typing commands while typing.

(-[WKContentView undoManagerForWebView]):
(-[WKQuirkyNSUndoManager initWithContentView:]): Deleted.
(-[WKQuirkyNSUndoManager canUndo]): Deleted.
(-[WKQuirkyNSUndoManager canRedo]): Deleted.
(-[WKQuirkyNSUndoManager undo]): Deleted.
(-[WKQuirkyNSUndoManager redo]): Deleted.

Rename this helper class to `WKNSKeyEventSimulatorUndoManager` to better reflect its purpose, and
make it subclass `WKNSUndoManager`.

* Source/WebKit/UIProcess/ios/WKContentViewInteraction.h:
* Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _closeCurrentTypingCommand]):
* Source/WebKit/WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::closeCurrentTypingCommand):
* Source/WebKit/WebProcess/WebPage/WebPage.h:
* Source/WebKit/WebProcess/WebPage/WebPage.messages.in:
* Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
(TestWebKitAPI::TEST(KeyboardInputTests, NewUndoGroupClosesPreviousTypingCommand)):

Add a new API test to exercise the change by inserting text within an undo group, bookended using
`-(begin|end)UndoGrouping`.

Canonical link: https://commits.webkit.org/280737@main



To unsubscribe from these emails, change your notification settings at https://github.com/WebKit/WebKit/settings/notifications


More information about the webkit-changes mailing list