+2005-10-08 Alexey Proskuryakov <ap@nypop.com>
+
+ Reviewed by Darin.
+
+ - Added a test for http://bugzilla.opendarwin.org/show_bug.cgi?id=4707
+ Need a way to automatically test for regressions in NSTextInput implementation
+
+ * editing/input/text-input-controller-expected.txt: Added.
+ * editing/input/text-input-controller.html: Added.
+
2005-10-08 Darin Adler <darin@apple.com>
- Updated test results for fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=3245
--- /dev/null
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertText:to be deleted replacingDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document givenAction:WebViewInsertActionTyped
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 13 of #text > DIV > BODY > HTML > #document to 13 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 13 of #text > DIV > BODY > HTML > #document to 13 of #text > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 13 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldDeleteDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 13 of #text > DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+Success
+
--- /dev/null
+<html>
+<head>
+<style>
+body { margin: 0; padding: 0 }
+</style>
+</head>
+<body>
+<div contenteditable>FAILURE</div>
+<script type="text/javascript">
+
+ if (window.layoutTestController) {
+
+ try {
+
+ layoutTestController.dumpAsText();
+ document.execCommand("SelectAll");
+
+ textInputController.insertText("to be deleted");
+ textInputController.doCommand("selectAll:");
+ textInputController.doCommand("delete:");
+
+ textInputController.setMarkedText("Failure", 0, 7);
+ if (textInputController.hasMarkedText() && textInputController.markedRange().toString() == "0,7")
+ textInputController.setMarkedText("Success", 0, 7);
+
+ var textAttributes = textInputController.validAttributesForMarkedText();
+ textInputController.unmarkText();
+
+ textInputController.doCommand("selectAll:");
+ if (textInputController.hasMarkedText() || textInputController.selectedRange().toString() != "0,7") {
+ textInputController.doCommand("delete:");
+ textInputController.insertText("Failure");
+ }
+
+ var charRect = textInputController.firstRectForCharacterRange(0, 1);
+ textInputController.characterIndexForPoint(0, 0); // currently unimplemented
+ textInputController.substringFromRange(1, 1); // currently unimplemented
+ textInputController.conversationIdentifier(); // just an identifier...
+
+ textAttributes = textAttributes.toString();
+ if (-1 == textAttributes.indexOf("NSUnderline"))
+ textInputController.insertText("Attribute NSUnderline is missing");
+
+ if (-1 == textAttributes.indexOf("NSUnderlineColor"))
+ textInputController.insertText("Attribute NSUnderlineColor is missing");
+
+ if (-1 == textAttributes.indexOf("NSMarkedClauseSegment"))
+ textInputController.insertText("Attribute NSMarkedClauseSegment is missing");
+
+ if (-1 == textAttributes.indexOf("NSTextInputReplacementRangeAttributeName"))
+ textInputController.insertText("Attribute NSTextInputReplacementRangeAttributeName is missing");
+
+ } catch (ex) {
+ document.write("Exception: " + ex.description);
+ }
+ } else {
+ document.write("(cannot run interactively)");
+ }
+</script>
+</body>
+</html>
+2005-10-08 Alexey Proskuryakov <ap@nypop.com>
+
+ Reviewed, rearranged and landed by Darin.
+
+ - fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4707
+ Need a way to automatically test for regressions in NSTextInput implementation
+
+ * DumpRenderTree/DumpRenderTree.m:
+ (-[WaitUntilDoneDelegate webView:windowScriptObjectAvailable:]):
+ Create a text input controller and put it in a property of the window object.
+
+ * DumpRenderTree/TextInputController.h: Added.
+ * DumpRenderTree/TextInputController.m: Added.
+ * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj: Added files.
+
2005-10-06 Darin Adler <darin@apple.com>
* Scripts/cvs-apply: Fixed merge option to work better when not all directories
#import <CommonCrypto/CommonDigest.h>
#import <getopt.h>
+#import "TextInputController.h"
+
@interface WaitUntilDoneDelegate : NSObject
@end
- (void)webView:(WebView *)sender windowScriptObjectAvailable:(WebScriptObject *)obj
{
LayoutTestController *ltc = [[LayoutTestController alloc] init];
- [(id)obj setValue:ltc forKey:@"layoutTestController"];
+ [obj setValue:ltc forKey:@"layoutTestController"];
[ltc release];
EventSendingController *esc = [[EventSendingController alloc] init];
- [(id)obj setValue:esc forKey:@"eventSender"];
+ [obj setValue:esc forKey:@"eventSender"];
[esc release];
-
+ TextInputController *tic = [[TextInputController alloc] initWithWebView:sender];
+ [obj setValue:tic forKey:@"textInputController"];
+ [tic release];
}
- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message
9340994C08540CAE007F3BC8 /* DumpRenderTreePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */; };
9340994E08540CAE007F3BC8 /* DumpRenderTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* DumpRenderTree.m */; settings = {ATTRIBUTES = (); }; };
9340995108540CAE007F3BC8 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9335435F03D75502008635CE /* WebKit.framework */; };
+ 93442CF608F8BA4900BFE8CA /* TextInputController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93442CF408F8BA4900BFE8CA /* TextInputController.h */; };
+ 93442CF708F8BA4900BFE8CA /* TextInputController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93442CF508F8BA4900BFE8CA /* TextInputController.m */; };
A817090008B163EF00CCB9FB /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A84F608908B136DA00E9745F /* Cocoa.framework */; };
A817090208B1643800CCB9FB /* WebCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A817090108B1643800CCB9FB /* WebCore.framework */; };
A817090408B164D300CCB9FB /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A817090308B164D300CCB9FB /* JavaScriptCore.framework */; };
32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DumpRenderTreePrefix.h; sourceTree = "<group>"; };
9335435F03D75502008635CE /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9340995408540CAF007F3BC8 /* DumpRenderTree */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = DumpRenderTree; sourceTree = BUILT_PRODUCTS_DIR; };
+ 93442CF408F8BA4900BFE8CA /* TextInputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextInputController.h; sourceTree = "<group>"; };
+ 93442CF508F8BA4900BFE8CA /* TextInputController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextInputController.m; sourceTree = "<group>"; };
A817090108B1643800CCB9FB /* WebCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A817090308B164D300CCB9FB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JavaScriptCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A84F608908B136DA00E9745F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
08FB7794FE84155DC02AAC07 /* DumpRenderTree */ = {
isa = PBXGroup;
children = (
- B5A7525808AF4A3600138E45 /* ImageDiff.m */,
08FB7796FE84155DC02AAC07 /* DumpRenderTree.m */,
32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */,
+ 93442CF408F8BA4900BFE8CA /* TextInputController.h */,
+ 93442CF508F8BA4900BFE8CA /* TextInputController.m */,
+ B5A7525808AF4A3600138E45 /* ImageDiff.m */,
9335435F03D75502008635CE /* WebKit.framework */,
A817090308B164D300CCB9FB /* JavaScriptCore.framework */,
A817090108B1643800CCB9FB /* WebCore.framework */,
buildActionMask = 2147483647;
files = (
9340994C08540CAE007F3BC8 /* DumpRenderTreePrefix.h in Headers */,
+ 93442CF608F8BA4900BFE8CA /* TextInputController.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
buildActionMask = 2147483647;
files = (
9340994E08540CAE007F3BC8 /* DumpRenderTree.m in Sources */,
+ 93442CF708F8BA4900BFE8CA /* TextInputController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
--- /dev/null
+/*
+ * Copyright (C) 2005 Apple Computer, 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 <Foundation/Foundation.h>
+
+@class WebView;
+
+@interface TextInputController : NSObject
+{
+ WebView *webView;
+}
+- (id)initWithWebView:(WebView *)view;
+@end
--- /dev/null
+/*
+ * Copyright (C) 2005 Apple Computer, 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "TextInputController.h"
+
+#import <AppKit/NSInputManager.h>
+#import <WebKit/WebDocument.h>
+#import <WebKit/WebFrame.h>
+#import <WebKit/WebFrameView.h>
+#import <WebKit/WebView.h>
+
+@implementation TextInputController
+
+// FIXME: need to support attributed strings
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
+{
+ if (aSelector == @selector(insertText:)
+ || aSelector == @selector(doCommand:)
+ || aSelector == @selector(setMarkedText:selectedFrom:length:)
+ || aSelector == @selector(unmarkText)
+ || aSelector == @selector(hasMarkedText)
+ || aSelector == @selector(conversationIdentifier)
+ || aSelector == @selector(substringFrom:length:)
+ || aSelector == @selector(markedRange)
+ || aSelector == @selector(selectedRange)
+ || aSelector == @selector(firstRectForCharactersFrom:length:)
+ || aSelector == @selector(characterIndexForPointX:Y:)
+ || aSelector == @selector(validAttributesForMarkedText))
+ return NO;
+ return YES;
+}
+
++ (NSString *)webScriptNameForSelector:(SEL)aSelector
+{
+ if (aSelector == @selector(insertText:))
+ return @"insertText";
+ else if (aSelector == @selector(doCommand:))
+ return @"doCommand";
+ else if (aSelector == @selector(setMarkedText:selectedFrom:length:))
+ return @"setMarkedText";
+ else if (aSelector == @selector(substringFrom:length:))
+ return @"substringFromRange";
+ else if (aSelector == @selector(firstRectForCharactersFrom:length:))
+ return @"firstRectForCharacterRange";
+ else if (aSelector == @selector(characterIndexForPointX:Y:))
+ return @"characterIndexForPoint";
+
+ return nil;
+}
+
+- (id)initWithWebView:(WebView *)wv
+{
+ self = [super init];
+ webView = wv;
+ return self;
+}
+
+- (NSObject <NSTextInput> *)textInput
+{
+ NSView <WebDocumentView> *view = [[[webView mainFrame] frameView] documentView];
+ return [view conformsToProtocol:@protocol(NSTextInput)] ? view : nil;
+}
+
+- (void)insertText:(NSString *)aString
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ [textInput insertText:aString];
+}
+
+- (void)doCommand:(NSString *)aCommand
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ [textInput doCommandBySelector:NSSelectorFromString(aCommand)];
+}
+
+- (void)setMarkedText:(NSString *)aString selectedFrom:(int)from length:(int)length
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ [textInput setMarkedText:aString selectedRange:NSMakeRange(from, length)];
+}
+
+- (void)unmarkText
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ [textInput unmarkText];
+}
+
+- (BOOL)hasMarkedText
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ return [textInput hasMarkedText];
+
+ return FALSE;
+}
+
+- (long)conversationIdentifier
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ return [textInput conversationIdentifier];
+
+ return 0;
+}
+
+- (NSString *)substringFrom:(int)from length:(int)length
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ return [[textInput attributedSubstringFromRange:NSMakeRange(from, length)] string];
+
+ return @"";
+}
+
+- (NSArray *)markedRange
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput) {
+ NSRange range = [textInput markedRange];
+ return [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:range.location], [NSNumber numberWithUnsignedInt:range.length], nil];
+ }
+
+ return nil;
+}
+
+- (NSArray *)selectedRange
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput) {
+ NSRange range = [textInput selectedRange];
+ return [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:range.location], [NSNumber numberWithUnsignedInt:range.length], nil];
+ }
+
+ return nil;
+}
+
+
+- (NSArray *)firstRectForCharactersFrom:(int)from length:(int)length
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput) {
+ NSRect rect = [textInput firstRectForCharacterRange:NSMakeRange(from, length)];
+ return [NSArray arrayWithObjects:
+ [NSNumber numberWithFloat:rect.origin.x],
+ [NSNumber numberWithFloat:rect.origin.y],
+ [NSNumber numberWithFloat:rect.size.width],
+ [NSNumber numberWithFloat:rect.size.height],
+ nil];
+ }
+
+ return nil;
+}
+
+- (int)characterIndexForPointX:(float)x Y:(float)y
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ return [textInput characterIndexForPoint:NSMakePoint(x, y)];
+
+ return 0;
+}
+
+- (NSArray *)validAttributesForMarkedText
+{
+ NSObject <NSTextInput> *textInput = [self textInput];
+
+ if (textInput)
+ return [textInput validAttributesForMarkedText];
+
+ return nil;
+}
+
+@end