Add an undo group for each dictated utterance in WebKit
authorcfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jun 2014 23:50:44 +0000 (23:50 +0000)
committercfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jun 2014 23:50:44 +0000 (23:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=134086

Reviewed by Enrica Casucci.

Source/WebCore:
Provide a mechanism for ending the current undo group on a text insertion.
This allows a stream of text, that is normally part of one undo group, to be
broken up so that subsequent undo commands will only undo portions of the text stream.

* WebCore.exp.in:
* WebCore.xcodeproj/project.pbxproj:
* editing/mac/TextUndoInsertionMarkup.h: Added.
* editing/mac/TextUndoInsertionMarkup.mm: Added.
(WebCore::shouldRegisterInsertionUndoGroup):
(WebCore::registerInsertionUndoGrouping):

Source/WebKit/mac:
* WebView/WebHTMLView.mm:
(-[WebHTMLView validAttributesForMarkedText]):
(-[WebHTMLView insertText:]):

Source/WebKit2:
* UIProcess/API/mac/WKView.mm:
(-[WKView insertText:replacementRange:]):
(-[WKView validAttributesForMarkedText]):
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::registerInsertionUndoGrouping):
(WebKit::WebPageProxy::insertTextAsync):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::registerInsertionUndoGrouping):
* UIProcess/mac/PageClientImpl.h:
* UIProcess/mac/PageClientImpl.mm:
(WebKit::PageClientImpl::registerInsertionUndoGrouping):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::insertDictatedTextAsync):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::insertTextAsync):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::insertDictatedTextAsync):

Tools:
Create a method for creating attributed strings with the undo insertion marker.

* DumpRenderTree/mac/TextInputController.m:
(+[TextInputController isSelectorExcludedFromWebScript:]):
(+[TextInputController webScriptNameForSelector:]):
(-[TextInputController stringWithUndoGroupingInsertion:]):

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

24 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/editing/mac/TextUndoInsertionMarkup.h [new file with mode: 0644]
Source/WebCore/editing/mac/TextUndoInsertionMarkupMac.h [new file with mode: 0644]
Source/WebCore/editing/mac/TextUndoInsertionMarkupMac.mm [new file with mode: 0644]
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebView/WebHTMLView.mm
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/mac/WKView.mm
Source/WebKit2/UIProcess/PageClient.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm
Source/WebKit2/UIProcess/mac/PageClientImpl.h
Source/WebKit2/UIProcess/mac/PageClientImpl.mm
Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm
Tools/ChangeLog
Tools/DumpRenderTree/mac/TextInputController.m

index 918dc4b..b9b633f 100644 (file)
@@ -1,3 +1,21 @@
+2014-06-25  Chris Fleizach  <cfleizach@apple.com>
+
+        Add an undo group for each dictated utterance in WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=134086
+
+        Reviewed by Enrica Casucci.
+
+        Provide a mechanism for ending the current undo group on a text insertion.
+        This allows a stream of text, that is normally part of one undo group, to be
+        broken up so that subsequent undo commands will only undo portions of the text stream.
+
+        * WebCore.exp.in:
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/mac/TextUndoInsertionMarkup.h: Added.
+        * editing/mac/TextUndoInsertionMarkup.mm: Added.
+        (WebCore::shouldRegisterInsertionUndoGroup):
+        (WebCore::registerInsertionUndoGrouping):
+
 2014-06-25  Joseph Pecoraro  <pecoraro@apple.com>
 
         [iOS]: WK2 Inspector Node Search
index 18ebe4d..fdee291 100644 (file)
@@ -2427,6 +2427,11 @@ _wkNSReboundDeltaForElasticDelta
 _wkCreateMemoryStatusPressureCriticalDispatchOnMainQueue
 #endif
 
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 10100
+__ZN7WebCore32shouldRegisterInsertionUndoGroupEP18NSAttributedString
+__ZN7WebCore44registerInsertionUndoGroupingWithUndoManagerEP13NSUndoManager
+#endif
+
 #if PLATFORM(MAC) || PLATFORM(IOS_SIMULATOR)
 _wkSetCrashReportApplicationSpecificInformation
 #endif
index 4c3b31c..e673337 100644 (file)
                293EAE1F1356B2FE0067ACF9 /* RuntimeApplicationChecks.h in Headers */ = {isa = PBXBuildFile; fileRef = 293EAE1E1356B2FE0067ACF9 /* RuntimeApplicationChecks.h */; settings = {ATTRIBUTES = (Private, ); }; };
                293EAE211356B32E0067ACF9 /* RuntimeApplicationChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 293EAE201356B32E0067ACF9 /* RuntimeApplicationChecks.cpp */; };
                29489FC712C00F0300D83F0F /* AccessibilityScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = 29489FC512C00F0300D83F0F /* AccessibilityScrollView.h */; };
+               29498682195341940072D2BD /* TextUndoInsertionMarkup.h in Headers */ = {isa = PBXBuildFile; fileRef = 29498680195341940072D2BD /* TextUndoInsertionMarkup.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               29498683195341940072D2BD /* TextUndoInsertionMarkupMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29498681195341940072D2BD /* TextUndoInsertionMarkupMac.mm */; };
                297BE3D516C03C08003316BD /* PlatformSpeechSynthesisUtterance.h in Headers */ = {isa = PBXBuildFile; fileRef = 2527CC9116BF8BA1009DDAC0 /* PlatformSpeechSynthesisUtterance.h */; };
                297BE3D616C03C0B003316BD /* PlatformSpeechSynthesisVoice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2527CC9216BF90B4009DDAC0 /* PlatformSpeechSynthesisVoice.h */; };
                297BE3D716C03C0E003316BD /* PlatformSpeechSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */; };
                29ACB214143E7498006BCA5F /* AccessibilityMockObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29ACB213143E7498006BCA5F /* AccessibilityMockObject.cpp */; };
                29D7BCF61444AF580070619C /* AccessibilitySpinButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29D7BCF51444AF580070619C /* AccessibilitySpinButton.cpp */; };
                29D7BCFA1444AF7D0070619C /* AccessibilitySpinButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 29D7BCF91444AF7D0070619C /* AccessibilitySpinButton.h */; };
+               29FAF4B6195AB08900A522DC /* TextUndoInsertionMarkupMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 29FAF4B5195AB08900A522DC /* TextUndoInsertionMarkupMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2B365C841525119E0091D27B /* RenderSVGEllipse.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B4235A015250F6000DBBCD8 /* RenderSVGEllipse.h */; };
                2BE8E2C712A589EC00FAD550 /* HTMLMetaCharsetParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BE8E2C612A589EC00FAD550 /* HTMLMetaCharsetParser.h */; };
                2BE8E2C912A58A0100FAD550 /* HTMLMetaCharsetParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BE8E2C812A58A0100FAD550 /* HTMLMetaCharsetParser.cpp */; };
                07AB996818DA3C010018771E /* RTCIceServer.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCIceServer.idl; sourceTree = "<group>"; };
                07AB996D18DA3C740018771E /* RTCConfigurationPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCConfigurationPrivate.h; sourceTree = "<group>"; };
                07AB996E18DA3C740018771E /* RTCIceServerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCIceServerPrivate.h; sourceTree = "<group>"; };
-               07AC46FF1952102100EE9723 /* ISOVTTCue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ISOVTTCue.cpp; path = ISOVTTCue.cpp; sourceTree = "<group>"; };
-               07AC47001952102100EE9723 /* ISOVTTCue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ISOVTTCue.h; path = ISOVTTCue.h; sourceTree = "<group>"; };
+               07AC46FF1952102100EE9723 /* ISOVTTCue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISOVTTCue.cpp; sourceTree = "<group>"; };
+               07AC47001952102100EE9723 /* ISOVTTCue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISOVTTCue.h; sourceTree = "<group>"; };
                07B0113E1032242200FBDC33 /* AccessibilityMediaControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityMediaControls.h; sourceTree = "<group>"; };
                07B442D4166C70B000556CAD /* InbandTextTrackPrivateAVF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InbandTextTrackPrivateAVF.cpp; sourceTree = "<group>"; };
                07B442D5166C70B000556CAD /* InbandTextTrackPrivateAVF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivateAVF.h; sourceTree = "<group>"; };
                293EAE1E1356B2FE0067ACF9 /* RuntimeApplicationChecks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeApplicationChecks.h; sourceTree = "<group>"; };
                293EAE201356B32E0067ACF9 /* RuntimeApplicationChecks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RuntimeApplicationChecks.cpp; sourceTree = "<group>"; };
                29489FC512C00F0300D83F0F /* AccessibilityScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityScrollView.h; sourceTree = "<group>"; };
+               29498680195341940072D2BD /* TextUndoInsertionMarkup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextUndoInsertionMarkup.h; path = mac/TextUndoInsertionMarkup.h; sourceTree = "<group>"; };
+               29498681195341940072D2BD /* TextUndoInsertionMarkupMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TextUndoInsertionMarkupMac.mm; path = mac/TextUndoInsertionMarkupMac.mm; sourceTree = "<group>"; };
                297BE3D916C043D8003316BD /* PlatformSpeechSynthesizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformSpeechSynthesizer.cpp; sourceTree = "<group>"; };
                2981CA9D131822EC00D12F2A /* AccessibilityARIAGrid.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityARIAGrid.cpp; sourceTree = "<group>"; };
                2981CA9E131822EC00D12F2A /* AccessibilityARIAGridCell.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityARIAGridCell.cpp; sourceTree = "<group>"; };
                29E04A27BED2F81F98E9022B /* JSBeforeUnloadEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBeforeUnloadEvent.h; sourceTree = "<group>"; };
                29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformSpeechSynthesizer.h; sourceTree = "<group>"; };
                29E4D8E016B0959800C84704 /* PlatformSpeechSynthesizerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSpeechSynthesizerMac.mm; sourceTree = "<group>"; };
+               29FAF4B5195AB08900A522DC /* TextUndoInsertionMarkupMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextUndoInsertionMarkupMac.h; path = mac/TextUndoInsertionMarkupMac.h; sourceTree = "<group>"; };
                2B42359F15250F6000DBBCD8 /* RenderSVGEllipse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGEllipse.cpp; sourceTree = "<group>"; };
                2B4235A015250F6000DBBCD8 /* RenderSVGEllipse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGEllipse.h; sourceTree = "<group>"; };
                2BE8E2C612A589EC00FAD550 /* HTMLMetaCharsetParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLMetaCharsetParser.h; path = parser/HTMLMetaCharsetParser.h; sourceTree = "<group>"; };
                                93309DCC099E64910056E581 /* TextIterator.cpp */,
                                93309DCD099E64910056E581 /* TextIterator.h */,
                                9392146818A6D791000EE688 /* TextIteratorBehavior.h */,
+                               29498680195341940072D2BD /* TextUndoInsertionMarkup.h */,
                                93309DCA099E64910056E581 /* TypingCommand.cpp */,
                                93309DCB099E64910056E581 /* TypingCommand.h */,
                                9B2D8A7814997CCF00ECEF3E /* UndoStep.h */,
                                4A8C96EA0BE69032004EEFF0 /* FrameSelectionMac.mm */,
                                CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */,
                                CE7B2DB21586ABAD0098B3FA /* TextAlternativeWithRange.mm */,
+                               29FAF4B5195AB08900A522DC /* TextUndoInsertionMarkupMac.h */,
+                               29498681195341940072D2BD /* TextUndoInsertionMarkupMac.mm */,
                        );
                        name = mac;
                        sourceTree = "<group>";
                                B2227A690D00BF220071B782 /* SVGPathSegCurvetoCubicSmooth.h in Headers */,
                                83C1D429178D5AB400141E68 /* SVGPathSegCurvetoCubicSmoothAbs.h in Headers */,
                                83C1D42A178D5AB400141E68 /* SVGPathSegCurvetoCubicSmoothRel.h in Headers */,
+                               29498682195341940072D2BD /* TextUndoInsertionMarkup.h in Headers */,
                                B2227A6D0D00BF220071B782 /* SVGPathSegCurvetoQuadratic.h in Headers */,
                                83C1D42B178D5AB400141E68 /* SVGPathSegCurvetoQuadraticAbs.h in Headers */,
                                83C1D42C178D5AB500141E68 /* SVGPathSegCurvetoQuadraticRel.h in Headers */,
                                93309E1C099E64920056E581 /* TextIterator.h in Headers */,
                                BCEF45E90E687767001C1287 /* TextMetrics.h in Headers */,
                                E4D988B417BFD1F60084FB88 /* TextNodeTraversal.h in Headers */,
+                               29FAF4B6195AB08900A522DC /* TextUndoInsertionMarkupMac.h in Headers */,
                                1C18DA59181AF6A500C4EF22 /* TextPainter.h in Headers */,
                                E4C91A0E1802343100A17F6D /* TextPaintStyle.h in Headers */,
                                930FC68A1072B9280045293E /* TextRenderingMode.h in Headers */,
                                8419D2AC120D92FC00141F8F /* SVGPathByteStreamSource.cpp in Sources */,
                                B2227A580D00BF220071B782 /* SVGPathElement.cpp in Sources */,
                                8476C9EF11DF6A5800555B02 /* SVGPathParser.cpp in Sources */,
+                               29498683195341940072D2BD /* TextUndoInsertionMarkupMac.mm in Sources */,
                                B2227A800D00BF220071B782 /* SVGPathSegList.cpp in Sources */,
                                8476C9E511DF6A0B00555B02 /* SVGPathSegListBuilder.cpp in Sources */,
                                08FF102012950F5A00F00276 /* SVGPathSegListPropertyTearOff.cpp in Sources */,
diff --git a/Source/WebCore/editing/mac/TextUndoInsertionMarkup.h b/Source/WebCore/editing/mac/TextUndoInsertionMarkup.h
new file mode 100644 (file)
index 0000000..12df01c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014 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 TextUndoInsertionMarkup_h
+#define TextUndoInsertionMarkup_h
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 10100
+#define WTF_USE_INSERTION_UNDO_GROUPING 1
+#endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 10100
+
+#endif
diff --git a/Source/WebCore/editing/mac/TextUndoInsertionMarkupMac.h b/Source/WebCore/editing/mac/TextUndoInsertionMarkupMac.h
new file mode 100644 (file)
index 0000000..1153270
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 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 TextUndoInsertionMarkupMac_h
+#define TextUndoInsertionMarkupMac_h
+
+#import <WebCore/TextUndoInsertionMarkup.h>
+
+#if USE(INSERTION_UNDO_GROUPING)
+
+#if __has_include(<AppKit/NSTextInputContext_Private.h>)
+#import <AppKit/NSTextInputContext_Private.h>
+#else
+extern "C" NSString *NSTextInsertionUndoableAttributeName;
+#endif
+
+#endif // USE(INSERTION_UNDO_GROUPING)
+
+namespace WebCore {
+    
+#if USE(INSERTION_UNDO_GROUPING)
+bool shouldRegisterInsertionUndoGroup(NSAttributedString*);
+void registerInsertionUndoGroupingWithUndoManager(NSUndoManager*);
+#endif
+    
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/editing/mac/TextUndoInsertionMarkupMac.mm b/Source/WebCore/editing/mac/TextUndoInsertionMarkupMac.mm
new file mode 100644 (file)
index 0000000..c9268c0
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 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"
+#import "TextUndoInsertionMarkupMac.h"
+
+#if __has_include(<Foundation/NSUndoManager_Private.h>)
+#import <Foundation/NSUndoManager_Private.h>
+#else
+@interface NSUndoManager (WebCorePrivate)
+- (void)_processEndOfEventNotification:(id)arg;
+@end
+#endif
+
+namespace WebCore {
+    
+#if USE(INSERTION_UNDO_GROUPING)
+
+bool shouldRegisterInsertionUndoGroup(NSAttributedString* string)
+{
+    return [string attribute:NSTextInsertionUndoableAttributeName atIndex:0 effectiveRange:nil];
+}
+    
+void registerInsertionUndoGroupingWithUndoManager(NSUndoManager* undoManager)
+{
+    if ([undoManager groupingLevel])
+        [undoManager _processEndOfEventNotification:nil];
+}
+    
+#endif
+
+}
index 094b993..437a2b2 100644 (file)
@@ -1,3 +1,14 @@
+2014-06-25  Chris Fleizach  <cfleizach@apple.com>
+
+        Add an undo group for each dictated utterance in WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=134086
+
+        Reviewed by Enrica Casucci.
+
+        * WebView/WebHTMLView.mm:
+        (-[WebHTMLView validAttributesForMarkedText]):
+        (-[WebHTMLView insertText:]):
+
 2014-06-25  Dana Burkart  <dburkart@apple.com>
 
         Add support for 5-tuple versioning.
index ad4a7a0..aa0a72d 100644 (file)
 #import <WebCore/StyleProperties.h>
 #import <WebCore/Text.h>
 #import <WebCore/TextAlternativeWithRange.h>
+#import <WebCore/TextUndoInsertionMarkupMac.h>
 #import <WebCore/WebCoreObjCExtras.h>
 #import <WebCore/WebNSAttributedStringExtras.h>
 #import <WebCore/markup.h>
@@ -6041,6 +6042,9 @@ static BOOL writingDirectionKeyBindingsEnabled()
 #if USE(DICTATION_ALTERNATIVES)
                            NSTextAlternativesAttributeName,
 #endif
+#if USE(INSERTION_UNDO_GROUPING)
+                           NSTextInsertionUndoableAttributeName,
+#endif
                            nil];
         // NSText also supports the following attributes, but it's
         // hard to tell which are really required for text input to
@@ -6385,6 +6389,9 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
     NSString *text;
     NSRange replacementRange = { NSNotFound, 0 };
     bool isFromInputMethod = coreFrame && coreFrame->editor().hasComposition();
+#if USE(INSERTION_UNDO_GROUPING)
+    bool registerUndoGroup = false;
+#endif
 
     Vector<DictationAlternative> dictationAlternativeLocations;
 #if !PLATFORM(IOS)
@@ -6395,6 +6402,9 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
         if (!textAlternatives.isEmpty())
             [[self _webView] _getWebCoreDictationAlternatives:dictationAlternativeLocations fromTextAlternatives:textAlternatives];
 #endif
+#if USE(INSERTION_UNDO_GROUPING)
+        registerUndoGroup = shouldRegisterInsertionUndoGroup(string);
+#endif
         // FIXME: We ignore most attributes from the string, so for example inserting from Character Palette loses font and glyph variation data.
         // It does not look like any input methods ever use insertText: with attributes other than NSTextInputReplacementRangeAttributeName.
         text = [string string];
@@ -6439,6 +6449,11 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
             eventHandled = coreFrame->editor().insertDictatedText(eventText, dictationAlternativeLocations, event);
         else
             eventHandled = coreFrame->editor().insertText(eventText, event);
+        
+#if USE(INSERTION_UNDO_GROUPING)
+        if (registerUndoGroup)
+            registerInsertionUndoGroupingWithUndoManager([[self _webView] undoManager]);
+#endif
     } else {
         eventHandled = true;
         coreFrame->editor().confirmComposition(eventText);
index 247d3b1..db99e97 100644 (file)
@@ -1,3 +1,33 @@
+2014-06-25  Chris Fleizach  <cfleizach@apple.com>
+
+        Add an undo group for each dictated utterance in WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=134086
+
+        Reviewed by Enrica Casucci.
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView insertText:replacementRange:]):
+        (-[WKView validAttributesForMarkedText]):
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::registerInsertionUndoGrouping):
+        (WebKit::WebPageProxy::insertTextAsync):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::registerInsertionUndoGrouping):
+        * UIProcess/mac/PageClientImpl.h:
+        * UIProcess/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::registerInsertionUndoGrouping):
+        * UIProcess/mac/WebPageProxyMac.mm:
+        (WebKit::WebPageProxy::insertDictatedTextAsync):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::insertTextAsync):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::insertDictatedTextAsync):
+
 2014-06-25  Joseph Pecoraro  <pecoraro@apple.com>
 
         [iOS]: WK2 Inspector Node Search
index de41054..5be6056 100644 (file)
@@ -90,6 +90,7 @@
 #import <WebCore/Region.h>
 #import <WebCore/SharedBuffer.h>
 #import <WebCore/TextAlternativeWithRange.h>
+#import <WebCore/TextUndoInsertionMarkupMac.h>
 #import <WebCore/WebActionDisablingCALayerDelegate.h>
 #import <WebCore/WebCoreCALayerExtras.h>
 #import <WebCore/WebCoreFullScreenPlaceholderView.h>
@@ -1429,10 +1430,14 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
     NSString *text;
     Vector<TextAlternativeWithRange> dictationAlternatives;
 
+    bool registerUndoGroup = false;
     if (isAttributedString) {
 #if USE(DICTATION_ALTERNATIVES)
         collectDictationTextAlternatives(string, dictationAlternatives);
 #endif
+#if USE(INSERTION_UNDO_GROUPING)
+        registerUndoGroup = shouldRegisterInsertionUndoGroup(string);
+#endif
         // FIXME: We ignore most attributes from the string, so for example inserting from Character Palette loses font and glyph variation data.
         text = [string string];
     } else
@@ -1456,9 +1461,9 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
     String eventText = text;
     eventText.replace(NSBackTabCharacter, NSTabCharacter); // same thing is done in KeyEventMac.mm in WebCore
     if (!dictationAlternatives.isEmpty())
-        _data->_page->insertDictatedTextAsync(eventText, replacementRange, dictationAlternatives);
+        _data->_page->insertDictatedTextAsync(eventText, replacementRange, dictationAlternatives, registerUndoGroup);
     else
-        _data->_page->insertTextAsync(eventText, replacementRange);
+        _data->_page->insertTextAsync(eventText, replacementRange, registerUndoGroup);
 }
 
 - (void)selectedRangeWithCompletionHandler:(void(^)(NSRange selectedRange))completionHandlerPtr
@@ -2233,6 +2238,9 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
 #if USE(DICTATION_ALTERNATIVES)
                            NSTextAlternativesAttributeName,
 #endif
+#if USE(INSERTION_UNDO_GROUPING)
+                           NSTextInsertionUndoableAttributeName,
+#endif
                            nil];
         // NSText also supports the following attributes, but it's
         // hard to tell which are really required for text input to
index e7b92d0..71f8ae1 100644 (file)
@@ -36,6 +36,7 @@
 
 #if PLATFORM(COCOA)
 #include "PluginComplexTextInputState.h"
+#include <WebCore/TextUndoInsertionMarkup.h>
 
 OBJC_CLASS CALayer;
 
@@ -242,6 +243,9 @@ public:
     virtual void showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext) = 0;
     virtual Vector<String> dictationAlternatives(uint64_t dictationContext) = 0;
 #endif // USE(DICTATION_ALTERNATIVES)
+#if USE(INSERTION_UNDO_GROUPING)
+    virtual void registerInsertionUndoGrouping() = 0;
+#endif // USE(INSERTION_UNDO_GROUPING)
 #endif // USE(APPKIT)
 #endif // PLATFORM(MAC)
 
index 4862040..5cbbd9f 100644 (file)
@@ -3396,6 +3396,13 @@ void WebPageProxy::registerEditCommandForUndo(uint64_t commandID, uint32_t editA
 {
     registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), this), Undo);
 }
+    
+void WebPageProxy::registerInsertionUndoGrouping()
+{
+#if USE(INSERTION_UNDO_GROUPING)
+    m_pageClient.registerInsertionUndoGrouping();
+#endif
+}
 
 void WebPageProxy::canUndoRedo(uint32_t action, bool& result)
 {
@@ -4951,12 +4958,12 @@ void WebPageProxy::addMIMETypeWithCustomContentProvider(const String& mimeType)
 
 #if PLATFORM(COCOA)
 
-void WebPageProxy::insertTextAsync(const String& text, const EditingRange& replacementRange)
+void WebPageProxy::insertTextAsync(const String& text, const EditingRange& replacementRange, bool registerUndoGroup)
 {
     if (!isValid())
         return;
 
-    process().send(Messages::WebPage::InsertTextAsync(text, replacementRange), m_pageID);
+    process().send(Messages::WebPage::InsertTextAsync(text, replacementRange, registerUndoGroup), m_pageID);
 }
 
 void WebPageProxy::getMarkedRangeAsync(std::function<void (EditingRange, CallbackBase::Error)> callbackFunction)
index 9979693..f16a5c4 100644 (file)
@@ -472,7 +472,7 @@ public:
     void setAcceleratedCompositingRootLayer(LayerOrView*);
     LayerOrView* acceleratedCompositingRootLayer() const;
 
-    void insertTextAsync(const String& text, const EditingRange& replacementRange);
+    void insertTextAsync(const String& text, const EditingRange& replacementRange, bool registerUndoGroup = false);
     void getMarkedRangeAsync(std::function<void (EditingRange, CallbackBase::Error)>);
     void getSelectedRangeAsync(std::function<void (EditingRange, CallbackBase::Error)>);
     void characterIndexForPointAsync(const WebCore::IntPoint&, std::function<void (uint64_t, CallbackBase::Error)>);
@@ -481,7 +481,7 @@ public:
     void confirmCompositionAsync();
 
 #if PLATFORM(MAC)
-    void insertDictatedTextAsync(const String& text, const EditingRange& replacementRange, const Vector<WebCore::TextAlternativeWithRange>& dictationAlternatives);
+    void insertDictatedTextAsync(const String& text, const EditingRange& replacementRange, const Vector<WebCore::TextAlternativeWithRange>& dictationAlternatives, bool registerUndoGroup);
     void attributedSubstringForCharacterRangeAsync(const EditingRange&, std::function<void (const AttributedString&, const EditingRange&, CallbackBase::Error)>);
 
 #if !USE(ASYNC_NSTEXTINPUTCLIENT)
@@ -1058,6 +1058,7 @@ private:
 
     // Undo management
     void registerEditCommandForUndo(uint64_t commandID, uint32_t editAction);
+    void registerInsertionUndoGrouping();
     void clearAllEditCommands();
     void canUndoRedo(uint32_t action, bool& result);
     void executeUndoRedo(uint32_t action, bool& result);
index e8a1720..9175948 100644 (file)
@@ -210,6 +210,7 @@ messages -> WebPageProxy {
     # Undo/Redo messages
     RegisterEditCommandForUndo(uint64_t commandID, uint32_t editAction)
     ClearAllEditCommands()
+    RegisterInsertionUndoGrouping()
     CanUndoRedo(uint32_t action) -> (bool result)
     ExecuteUndoRedo(uint32_t action) -> (bool result)
 
index a7ac571..a5bcd1c 100644 (file)
@@ -235,6 +235,13 @@ void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPag
     notImplemented();
 }
 
+#if USE(INSERTION_UNDO_GROUPING)
+void PageClientImpl::registerInsertionUndoGrouping()
+{
+    notImplemented();
+}
+#endif
+
 void PageClientImpl::clearAllEditCommands()
 {
     notImplemented();
index 0dae87c..611fa97 100644 (file)
@@ -154,6 +154,9 @@ private:
     virtual void showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext);
     virtual Vector<String> dictationAlternatives(uint64_t dictationContext);
 #endif
+#if USE(INSERTION_UNDO_GROUPING)
+    virtual void registerInsertionUndoGrouping() override;
+#endif
 
     // Auxiliary Client Creation
 #if ENABLE(FULLSCREEN_API)
index a84f94b..47a8746 100644 (file)
@@ -58,6 +58,7 @@
 #import <WebCore/KeyboardEvent.h>
 #import <WebCore/NotImplemented.h>
 #import <WebCore/SharedBuffer.h>
+#import <WebCore/TextUndoInsertionMarkupMac.h>
 #import <WebKitSystemInterface.h>
 #import <wtf/text/CString.h>
 #import <wtf/text/WTFString.h>
@@ -360,6 +361,13 @@ void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpComm
         [undoManager setActionName:(NSString *)actionName];
 }
 
+#if USE(INSERTION_UNDO_GROUPING)
+void PageClientImpl::registerInsertionUndoGrouping()
+{
+    registerInsertionUndoGroupingWithUndoManager([m_wkView undoManager]);
+}
+#endif
+
 void PageClientImpl::clearAllEditCommands()
 {
     [[m_wkView undoManager] removeAllActionsWithTarget:m_undoTarget.get()];
index bd0c6a6..87ddd01 100644 (file)
@@ -300,7 +300,7 @@ void WebPageProxy::cancelComposition()
 
 #endif // !USE(ASYNC_NSTEXTINPUTCLIENT)
 
-void WebPageProxy::insertDictatedTextAsync(const String& text, const EditingRange& replacementRange, const Vector<TextAlternativeWithRange>& dictationAlternativesWithRange)
+void WebPageProxy::insertDictatedTextAsync(const String& text, const EditingRange& replacementRange, const Vector<TextAlternativeWithRange>& dictationAlternativesWithRange, bool registerUndoGroup)
 {
 #if USE(DICTATION_ALTERNATIVES)
     if (!isValid())
@@ -315,13 +315,13 @@ void WebPageProxy::insertDictatedTextAsync(const String& text, const EditingRang
     }
 
     if (dictationAlternatives.isEmpty()) {
-        insertTextAsync(text, replacementRange);
+        insertTextAsync(text, replacementRange, registerUndoGroup);
         return;
     }
 
-    process().send(Messages::WebPage::InsertDictatedTextAsync(text, replacementRange, dictationAlternatives), m_pageID);
+    process().send(Messages::WebPage::InsertDictatedTextAsync(text, replacementRange, dictationAlternatives, registerUndoGroup), m_pageID);
 #else
-    insertTextAsync(text, replacementRange);
+    insertTextAsync(text, replacementRange, registerUndoGroup);
 #endif
 }
 
index e3ecdcd..4b4ee36 100644 (file)
@@ -4035,7 +4035,7 @@ bool WebPage::shouldUseCustomContentProviderForResponse(const ResourceResponse&
 
 #if PLATFORM(COCOA)
 
-void WebPage::insertTextAsync(const String& text, const EditingRange& replacementEditingRange)
+void WebPage::insertTextAsync(const String& text, const EditingRange& replacementEditingRange, bool registerUndoGroup)
 {
     Frame& frame = m_page->focusController().focusedOrMainFrame();
 
@@ -4044,7 +4044,10 @@ void WebPage::insertTextAsync(const String& text, const EditingRange& replacemen
         if (replacementRange)
             frame.selection().setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY));
     }
-
+    
+    if (registerUndoGroup)
+        send(Messages::WebPageProxy::RegisterInsertionUndoGrouping());
+    
     if (!frame.editor().hasComposition()) {
         // An insertText: might be handled by other responders in the chain if we don't handle it.
         // One example is space bar that results in scrolling down the page.
index 214ca14..fa0bd42 100644 (file)
@@ -589,7 +589,7 @@ public:
     
     void sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput);
 
-    void insertTextAsync(const String& text, const EditingRange& replacementRange);
+    void insertTextAsync(const String& text, const EditingRange& replacementRange, bool registerUndoGroup = false);
     void getMarkedRangeAsync(uint64_t callbackID);
     void getSelectedRangeAsync(uint64_t callbackID);
     void characterIndexForPointAsync(const WebCore::IntPoint&, uint64_t callbackID);
@@ -598,7 +598,7 @@ public:
     void confirmCompositionAsync();
 
 #if PLATFORM(MAC)
-    void insertDictatedTextAsync(const String& text, const EditingRange& replacementRange, const Vector<WebCore::DictationAlternative>& dictationAlternativeLocations);
+    void insertDictatedTextAsync(const String& text, const EditingRange& replacementRange, const Vector<WebCore::DictationAlternative>& dictationAlternativeLocations, bool registerUndoGroup = false);
     void attributedSubstringForCharacterRangeAsync(const EditingRange&, uint64_t callbackID);
 #if !USE(ASYNC_NSTEXTINPUTCLIENT)
     void insertText(const String& text, const EditingRange& replacementRange, bool& handled, EditorState& newState);
index c6b4e2e..6b7875b 100644 (file)
@@ -326,7 +326,7 @@ messages -> WebPage LegacyReceiver {
     ShouldDelayWindowOrderingEvent(WebKit::WebMouseEvent event) -> (bool result)
     AcceptsFirstMouse(int eventNumber, WebKit::WebMouseEvent event) -> (bool result)
 
-    InsertTextAsync(String text, WebKit::EditingRange replacementRange)
+    InsertTextAsync(String text, WebKit::EditingRange replacementRange, bool registerUndoGroup)
     GetMarkedRangeAsync(uint64_t callbackID)
     GetSelectedRangeAsync(uint64_t callbackID)
     CharacterIndexForPointAsync(WebCore::IntPoint point, uint64_t callbackID);
@@ -335,7 +335,7 @@ messages -> WebPage LegacyReceiver {
     ConfirmCompositionAsync()
 #endif
 #if PLATFORM(MAC)
-    InsertDictatedTextAsync(String text, WebKit::EditingRange replacementRange, Vector<WebCore::DictationAlternative> dictationAlternatives)
+    InsertDictatedTextAsync(String text, WebKit::EditingRange replacementRange, Vector<WebCore::DictationAlternative> dictationAlternatives, bool registerUndoGroup)
     AttributedSubstringForCharacterRangeAsync(WebKit::EditingRange range, uint64_t callbackID);
 #endif
 #if PLATFORM(MAC) && !USE(ASYNC_NSTEXTINPUTCLIENT)
index 0172038..67c2755 100644 (file)
@@ -412,7 +412,7 @@ void WebPage::cancelComposition(EditorState& newState)
 
 #endif // !USE(ASYNC_NSTEXTINPUTCLIENT)
 
-void WebPage::insertDictatedTextAsync(const String& text, const EditingRange& replacementEditingRange, const Vector<WebCore::DictationAlternative>& dictationAlternativeLocations)
+void WebPage::insertDictatedTextAsync(const String& text, const EditingRange& replacementEditingRange, const Vector<WebCore::DictationAlternative>& dictationAlternativeLocations, bool registerUndoGroup)
 {
     Frame& frame = m_page->focusController().focusedOrMainFrame();
 
@@ -422,6 +422,9 @@ void WebPage::insertDictatedTextAsync(const String& text, const EditingRange& re
             frame.selection().setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY));
     }
 
+    if (registerUndoGroup)
+        send(Messages::WebPageProxy::RegisterInsertionUndoGrouping());
+    
     ASSERT(!frame.editor().hasComposition());
     frame.editor().insertDictatedText(text, dictationAlternativeLocations, nullptr);
 }
index a9b8352..f616382 100644 (file)
@@ -1,3 +1,17 @@
+2014-06-25  Chris Fleizach  <cfleizach@apple.com>
+
+        Add an undo group for each dictated utterance in WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=134086
+
+        Reviewed by Enrica Casucci.
+
+        Create a method for creating attributed strings with the undo insertion marker.
+
+        * DumpRenderTree/mac/TextInputController.m:
+        (+[TextInputController isSelectorExcludedFromWebScript:]):
+        (+[TextInputController webScriptNameForSelector:]):
+        (-[TextInputController stringWithUndoGroupingInsertion:]):
+
 2014-06-25  Michael Saboff  <msaboff@apple.com>
 
         Provide javascript aware backtrace script for lldb
index 63c8311..fb93346 100644 (file)
 #define SUPPORT_DICTATION_ALTERNATIVES
 #import <AppKit/NSTextAlternatives.h>
 #endif
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 10100
+#define SUPPORT_INSERTION_UNDO_GROUPING
+#if __has_include(<AppKit/NSTextInputContext_Private.h>)
+#import <AppKit/NSTextInputContext_Private.h>
+#else
+extern "C" NSString *NSTextInsertionUndoableAttributeName;
+#endif
+#endif
+
 #import <WebKit/WebDocument.h>
 #import <WebKit/WebFrame.h>
 #import <WebKit/WebFramePrivate.h>
             || aSelector == @selector(validAttributesForMarkedText)
             || aSelector == @selector(attributedStringWithString:)
             || aSelector == @selector(setInputMethodHandler:)
-            || aSelector == @selector(dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:))
+            || aSelector == @selector(dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:)
+            || aSelector == @selector(stringWithUndoGroupingInsertion:))
         return NO;
     return YES;
 }
         return @"setInputMethodHandler";
     else if (aSelector == @selector(dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:))
         return @"makeDictatedString";
+    else if (aSelector == @selector(stringWithUndoGroupingInsertion:))
+        return @"makeUndoGroupingInsertionString";
 
     return nil;
 }
     return [[[NSMutableAttributedString alloc] initWithString:aString] autorelease];
 }
 
+- (NSMutableAttributedString*)stringWithUndoGroupingInsertion:(NSString*)aString
+{
+#if defined(SUPPORT_INSERTION_UNDO_GROUPING) && defined(SUPPORT_DICTATION_ALTERNATIVES)
+    NSMutableAttributedString* attributedString = [self dictatedStringWithPrimaryString:aString alternative:@"test" alternativeOffset:0 alternativeLength:1];
+    [attributedString addAttribute:NSTextInsertionUndoableAttributeName value:@YES range:NSMakeRange(0, [attributedString length])];
+    return attributedString;
+#else
+    return nil;
+#endif
+}
+
 - (NSMutableAttributedString*)dictatedStringWithPrimaryString:(NSString*)aString alternative:(NSString*)alternative alternativeOffset:(int)offset alternativeLength:(int)length
 {
 #if defined(SUPPORT_DICTATION_ALTERNATIVES)