diff -r 4f2f89ce4247 -r 303757a437d3 WebKitTools/DumpRenderTree/mac/EventSendingController.mm --- a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm Fri Sep 17 09:02:29 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,860 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2006 Jonas Witt - * Copyright (C) 2006 Samuel Weinig - * Copyright (C) 2006 Alexey Proskuryakov - * - * 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 "config.h" -#import "EventSendingController.h" - -#import "DumpRenderTree.h" -#import "DumpRenderTreeDraggingInfo.h" -#import "DumpRenderTreeFileDraggingSource.h" - -#import // for GetCurrentEventTime() -#import -#import -#import - -extern "C" void _NSNewKillRingSequence(); - -enum MouseAction { - MouseDown, - MouseUp, - MouseDragged -}; - -// Match the DOM spec (sadly the DOM spec does not provide an enum) -enum MouseButton { - LeftMouseButton = 0, - MiddleMouseButton = 1, - RightMouseButton = 2, - NoMouseButton = -1 -}; - -NSPoint lastMousePosition; -NSPoint lastClickPosition; -int lastClickButton = NoMouseButton; -NSArray *webkitDomEventNames; -NSMutableArray *savedMouseEvents; // mouse events sent between mouseDown and mouseUp are stored here, and then executed at once. -BOOL replayingSavedEvents; - -@implementation EventSendingController - -+ (void)initialize -{ - webkitDomEventNames = [[NSArray alloc] initWithObjects: - @"abort", - @"beforecopy", - @"beforecut", - @"beforepaste", - @"blur", - @"change", - @"click", - @"contextmenu", - @"copy", - @"cut", - @"dblclick", - @"drag", - @"dragend", - @"dragenter", - @"dragleave", - @"dragover", - @"dragstart", - @"drop", - @"error", - @"focus", - @"input", - @"keydown", - @"keypress", - @"keyup", - @"load", - @"mousedown", - @"mousemove", - @"mouseout", - @"mouseover", - @"mouseup", - @"mousewheel", - @"beforeunload", - @"paste", - @"readystatechange", - @"reset", - @"resize", - @"scroll", - @"search", - @"select", - @"selectstart", - @"submit", - @"textInput", - @"textzoomin", - @"textzoomout", - @"unload", - @"zoom", - nil]; -} - -+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector -{ - if (aSelector == @selector(beginDragWithFiles:) - || aSelector == @selector(clearKillRing) - || aSelector == @selector(contextClick) - || aSelector == @selector(enableDOMUIEventLogging:) - || aSelector == @selector(fireKeyboardEventsToElement:) - || aSelector == @selector(keyDown:withModifiers:withLocation:) - || aSelector == @selector(leapForward:) - || aSelector == @selector(mouseDown:withModifiers:) - || aSelector == @selector(mouseMoveToX:Y:) - || aSelector == @selector(mouseUp:withModifiers:) - || aSelector == @selector(scheduleAsynchronousClick) - || aSelector == @selector(textZoomIn) - || aSelector == @selector(textZoomOut) - || aSelector == @selector(zoomPageIn) - || aSelector == @selector(zoomPageOut) - || aSelector == @selector(mouseScrollByX:andY:) - || aSelector == @selector(continuousMouseScrollByX:andY:)) - return NO; - return YES; -} - -+ (BOOL)isKeyExcludedFromWebScript:(const char*)name -{ - if (strcmp(name, "dragMode") == 0) - return NO; - return YES; -} - -+ (NSString *)webScriptNameForSelector:(SEL)aSelector -{ - if (aSelector == @selector(beginDragWithFiles:)) - return @"beginDragWithFiles"; - if (aSelector == @selector(contextClick)) - return @"contextClick"; - if (aSelector == @selector(enableDOMUIEventLogging:)) - return @"enableDOMUIEventLogging"; - if (aSelector == @selector(fireKeyboardEventsToElement:)) - return @"fireKeyboardEventsToElement"; - if (aSelector == @selector(keyDown:withModifiers:withLocation:)) - return @"keyDown"; - if (aSelector == @selector(leapForward:)) - return @"leapForward"; - if (aSelector == @selector(mouseDown:withModifiers:)) - return @"mouseDown"; - if (aSelector == @selector(mouseUp:withModifiers:)) - return @"mouseUp"; - if (aSelector == @selector(mouseMoveToX:Y:)) - return @"mouseMoveTo"; - if (aSelector == @selector(setDragMode:)) - return @"setDragMode"; - if (aSelector == @selector(mouseScrollByX:andY:)) - return @"mouseScrollBy"; - if (aSelector == @selector(continuousMouseScrollByX:andY:)) - return @"continuousMouseScrollBy"; - return nil; -} - -- (id)init -{ - self = [super init]; - if (self) - dragMode = YES; - return self; -} - -- (void)dealloc -{ - [super dealloc]; -} - -- (double)currentEventTime -{ - return GetCurrentEventTime() + timeOffset; -} - -- (void)leapForward:(int)milliseconds -{ - if (dragMode && leftMouseButtonDown && !replayingSavedEvents) { - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(leapForward:)]]; - [invocation setTarget:self]; - [invocation setSelector:@selector(leapForward:)]; - [invocation setArgument:&milliseconds atIndex:2]; - - [EventSendingController saveEvent:invocation]; - - return; - } - - timeOffset += milliseconds / 1000.0; -} - -- (void)clearKillRing -{ - _NSNewKillRingSequence(); -} - -static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction action) -{ - switch (button) { - case LeftMouseButton: - switch (action) { - case MouseDown: - return NSLeftMouseDown; - case MouseUp: - return NSLeftMouseUp; - case MouseDragged: - return NSLeftMouseDragged; - } - case RightMouseButton: - switch (action) { - case MouseDown: - return NSRightMouseDown; - case MouseUp: - return NSRightMouseUp; - case MouseDragged: - return NSRightMouseDragged; - } - default: - switch (action) { - case MouseDown: - return NSOtherMouseDown; - case MouseUp: - return NSOtherMouseUp; - case MouseDragged: - return NSOtherMouseDragged; - } - } - assert(0); - return static_cast(0); -} - -- (void)beginDragWithFiles:(WebScriptObject*)jsFilePaths -{ - assert(!draggingInfo); - assert([jsFilePaths isKindOfClass:[WebScriptObject class]]); - - NSPasteboard *pboard = [NSPasteboard pasteboardWithUniqueName]; - [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil]; - - NSURL *currentTestURL = [NSURL URLWithString:[[mainFrame webView] mainFrameURL]]; - - NSMutableArray *filePaths = [NSMutableArray array]; - for (unsigned i = 0; [[jsFilePaths webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) { - NSString *filePath = (NSString *)[jsFilePaths webScriptValueAtIndex:i]; - // Have NSURL encode the name so that we handle '?' in file names correctly. - NSURL *fileURL = [NSURL fileURLWithPath:filePath]; - NSURL *absoluteFileURL = [NSURL URLWithString:[fileURL relativeString] relativeToURL:currentTestURL]; - [filePaths addObject:[absoluteFileURL path]]; - } - - [pboard setPropertyList:filePaths forType:NSFilenamesPboardType]; - assert([pboard propertyListForType:NSFilenamesPboardType]); // setPropertyList will silently fail on error, assert that it didn't fail - - // Provide a source, otherwise [DumpRenderTreeDraggingInfo draggingSourceOperationMask] defaults to NSDragOperationNone - DumpRenderTreeFileDraggingSource *source = [[[DumpRenderTreeFileDraggingSource alloc] init] autorelease]; - draggingInfo = [[DumpRenderTreeDraggingInfo alloc] initWithImage:nil offset:NSZeroSize pasteboard:pboard source:source]; - [[mainFrame webView] draggingEntered:draggingInfo]; - - dragMode = NO; // dragMode saves events and then replays them later. We don't need/want that. - leftMouseButtonDown = YES; // Make the rest of eventSender think a drag is in progress -} - -- (void)updateClickCountForButton:(int)buttonNumber -{ - if (([self currentEventTime] - lastClick >= 1) || - !NSEqualPoints(lastMousePosition, lastClickPosition) || - lastClickButton != buttonNumber) { - clickCount = 1; - lastClickButton = buttonNumber; - } else - clickCount++; -} - -static int buildModifierFlags(const WebScriptObject* modifiers) -{ - int flags = 0; - if (![modifiers isKindOfClass:[WebScriptObject class]]) - return flags; - for (unsigned i = 0; [[modifiers webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) { - NSString* modifierName = (NSString*)[modifiers webScriptValueAtIndex:i]; - if ([modifierName isEqual:@"ctrlKey"]) - flags |= NSControlKeyMask; - else if ([modifierName isEqual:@"shiftKey"] || [modifierName isEqual:@"rangeSelectionKey"]) - flags |= NSShiftKeyMask; - else if ([modifierName isEqual:@"altKey"]) - flags |= NSAlternateKeyMask; - else if ([modifierName isEqual:@"metaKey"] || [modifierName isEqual:@"addSelectionKey"]) - flags |= NSCommandKeyMask; - } - return flags; -} - -- (void)mouseDown:(int)buttonNumber withModifiers:(WebScriptObject*)modifiers -{ - [[[mainFrame frameView] documentView] layout]; - [self updateClickCountForButton:buttonNumber]; - - NSEventType eventType = eventTypeForMouseButtonAndAction(buttonNumber, MouseDown); - NSEvent *event = [NSEvent mouseEventWithType:eventType - location:lastMousePosition - modifierFlags:buildModifierFlags(modifiers) - timestamp:[self currentEventTime] - windowNumber:[[[mainFrame webView] window] windowNumber] - context:[NSGraphicsContext currentContext] - eventNumber:++eventNumber - clickCount:clickCount - pressure:0.0]; - - NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; - if (subView) { - [subView mouseDown:event]; - if (buttonNumber == LeftMouseButton) - leftMouseButtonDown = YES; - } -} - -- (void)mouseDown:(int)buttonNumber -{ - [self mouseDown:buttonNumber withModifiers:nil]; -} - -- (void)textZoomIn -{ - [[mainFrame webView] makeTextLarger:self]; -} - -- (void)textZoomOut -{ - [[mainFrame webView] makeTextSmaller:self]; -} - -- (void)zoomPageIn -{ - [[mainFrame webView] zoomPageIn:self]; -} - -- (void)zoomPageOut -{ - [[mainFrame webView] zoomPageOut:self]; -} - -- (void)mouseUp:(int)buttonNumber withModifiers:(WebScriptObject*)modifiers -{ - if (dragMode && !replayingSavedEvents) { - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp:withModifiers:)]]; - [invocation setTarget:self]; - [invocation setSelector:@selector(mouseUp:withModifiers:)]; - [invocation setArgument:&buttonNumber atIndex:2]; - [invocation setArgument:&modifiers atIndex:3]; - - [EventSendingController saveEvent:invocation]; - [EventSendingController replaySavedEvents]; - - return; - } - - [[[mainFrame frameView] documentView] layout]; - NSEventType eventType = eventTypeForMouseButtonAndAction(buttonNumber, MouseUp); - NSEvent *event = [NSEvent mouseEventWithType:eventType - location:lastMousePosition - modifierFlags:buildModifierFlags(modifiers) - timestamp:[self currentEventTime] - windowNumber:[[[mainFrame webView] window] windowNumber] - context:[NSGraphicsContext currentContext] - eventNumber:++eventNumber - clickCount:clickCount - pressure:0.0]; - - NSView *targetView = [[mainFrame webView] hitTest:[event locationInWindow]]; - // FIXME: Silly hack to teach DRT to respect capturing mouse events outside the WebView. - // The right solution is just to use NSApplication's built-in event sending methods, - // instead of rolling our own algorithm for selecting an event target. - targetView = targetView ? targetView : [[mainFrame frameView] documentView]; - assert(targetView); - [targetView mouseUp:event]; - if (buttonNumber == LeftMouseButton) - leftMouseButtonDown = NO; - lastClick = [event timestamp]; - lastClickPosition = lastMousePosition; - if (draggingInfo) { - WebView *webView = [mainFrame webView]; - - NSDragOperation dragOperation = [webView draggingUpdated:draggingInfo]; - - if (dragOperation != NSDragOperationNone) - [webView performDragOperation:draggingInfo]; - else - [webView draggingExited:draggingInfo]; - // Per NSDragging.h: draggingSources may not implement draggedImage:endedAt:operation: - if ([[draggingInfo draggingSource] respondsToSelector:@selector(draggedImage:endedAt:operation:)]) - [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] endedAt:lastMousePosition operation:dragOperation]; - [draggingInfo release]; - draggingInfo = nil; - } -} - -- (void)mouseUp:(int)buttonNumber -{ - [self mouseUp:buttonNumber withModifiers:nil]; -} - -- (void)mouseMoveToX:(int)x Y:(int)y -{ - if (dragMode && leftMouseButtonDown && !replayingSavedEvents) { - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseMoveToX:Y:)]]; - [invocation setTarget:self]; - [invocation setSelector:@selector(mouseMoveToX:Y:)]; - [invocation setArgument:&x atIndex:2]; - [invocation setArgument:&y atIndex:3]; - - [EventSendingController saveEvent:invocation]; - return; - } - - NSView *view = [mainFrame webView]; - lastMousePosition = [view convertPoint:NSMakePoint(x, [view frame].size.height - y) toView:nil]; - NSEvent *event = [NSEvent mouseEventWithType:(leftMouseButtonDown ? NSLeftMouseDragged : NSMouseMoved) - location:lastMousePosition - modifierFlags:0 - timestamp:[self currentEventTime] - windowNumber:[[view window] windowNumber] - context:[NSGraphicsContext currentContext] - eventNumber:++eventNumber - clickCount:(leftMouseButtonDown ? clickCount : 0) - pressure:0.0]; - - NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; - if (subView) { - if (leftMouseButtonDown) { - [subView mouseDragged:event]; - if (draggingInfo) { - // Per NSDragging.h: draggingSources may not implement draggedImage:movedTo: - if ([[draggingInfo draggingSource] respondsToSelector:@selector(draggedImage:movedTo:)]) - [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] movedTo:lastMousePosition]; - [[mainFrame webView] draggingUpdated:draggingInfo]; - } - } else - [subView mouseMoved:event]; - } -} - -- (void)mouseScrollByX:(int)x andY:(int)y continuously:(BOOL)c -{ - // CGEventCreateScrollWheelEvent() was introduced in 10.5 -#if !defined(BUILDING_ON_TIGER) - CGScrollEventUnit unit = c?kCGScrollEventUnitPixel:kCGScrollEventUnitLine; - CGEventRef cgScrollEvent = CGEventCreateScrollWheelEvent(NULL, unit, 2, y, x); - - // CGEvent locations are in global display coordinates. - CGPoint lastGlobalMousePosition = { - lastMousePosition.x, - [[NSScreen mainScreen] frame].size.height - lastMousePosition.y - }; - CGEventSetLocation(cgScrollEvent, lastGlobalMousePosition); - - NSEvent *scrollEvent = [NSEvent eventWithCGEvent:cgScrollEvent]; - CFRelease(cgScrollEvent); - - NSView *subView = [[mainFrame webView] hitTest:[scrollEvent locationInWindow]]; - if (subView) - [subView scrollWheel:scrollEvent]; -#endif -} - -- (void)continuousMouseScrollByX:(int)x andY:(int)y -{ - [self mouseScrollByX:x andY:y continuously:YES]; -} - -- (void)mouseScrollByX:(int)x andY:(int)y -{ - [self mouseScrollByX:x andY:y continuously:NO]; -} - -- (NSArray *)contextClick -{ - [[[mainFrame frameView] documentView] layout]; - [self updateClickCountForButton:RightMouseButton]; - - NSEvent *event = [NSEvent mouseEventWithType:NSRightMouseDown - location:lastMousePosition - modifierFlags:0 - timestamp:[self currentEventTime] - windowNumber:[[[mainFrame webView] window] windowNumber] - context:[NSGraphicsContext currentContext] - eventNumber:++eventNumber - clickCount:clickCount - pressure:0.0]; - - NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; - NSMutableArray *menuItemStrings = [NSMutableArray array]; - - if (subView) { - NSMenu* menu = [subView menuForEvent:event]; - - for (int i = 0; i < [menu numberOfItems]; ++i) { - NSMenuItem* menuItem = [menu itemAtIndex:i]; - if (!strcmp("Inspect Element", [[menuItem title] UTF8String])) - continue; - - if ([menuItem isSeparatorItem]) - [menuItemStrings addObject:@""]; - else - [menuItemStrings addObject:[menuItem title]]; - } - } - - return menuItemStrings; -} - -- (void)scheduleAsynchronousClick -{ - [self performSelector:@selector(mouseDown:) withObject:nil afterDelay:0]; - [self performSelector:@selector(mouseUp:) withObject:nil afterDelay:0]; -} - -+ (void)saveEvent:(NSInvocation *)event -{ - if (!savedMouseEvents) - savedMouseEvents = [[NSMutableArray alloc] init]; - [savedMouseEvents addObject:event]; -} - -+ (void)replaySavedEvents -{ - replayingSavedEvents = YES; - while ([savedMouseEvents count]) { - // if a drag is initiated, the remaining saved events will be dispatched from our dragging delegate - NSInvocation *invocation = [[[savedMouseEvents objectAtIndex:0] retain] autorelease]; - [savedMouseEvents removeObjectAtIndex:0]; - [invocation invoke]; - } - replayingSavedEvents = NO; -} - -+ (void)clearSavedEvents -{ - [savedMouseEvents release]; - savedMouseEvents = nil; -} - -- (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers withLocation:(unsigned long)keyLocation -{ - NSString *eventCharacter = character; - unsigned short keyCode = 0; - if ([character isEqualToString:@"leftArrow"]) { - const unichar ch = NSLeftArrowFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x7B; - } else if ([character isEqualToString:@"rightArrow"]) { - const unichar ch = NSRightArrowFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x7C; - } else if ([character isEqualToString:@"upArrow"]) { - const unichar ch = NSUpArrowFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x7E; - } else if ([character isEqualToString:@"downArrow"]) { - const unichar ch = NSDownArrowFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x7D; - } else if ([character isEqualToString:@"pageUp"]) { - const unichar ch = NSPageUpFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x74; - } else if ([character isEqualToString:@"pageDown"]) { - const unichar ch = NSPageDownFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x79; - } else if ([character isEqualToString:@"home"]) { - const unichar ch = NSHomeFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x73; - } else if ([character isEqualToString:@"end"]) { - const unichar ch = NSEndFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x77; - } else if ([character isEqualToString:@"delete"]) { - const unichar ch = NSDeleteFunctionKey; - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - keyCode = 0x75; - } - - // Compare the input string with the function-key names defined by the DOM spec (i.e. "F1",...,"F24"). - // If the input string is a function-key name, set its key code. - for (unsigned i = 1; i <= 24; i++) { - if ([character isEqualToString:[NSString stringWithFormat:@"F%u", i]]) { - const unichar ch = NSF1FunctionKey + (i - 1); - eventCharacter = [NSString stringWithCharacters:&ch length:1]; - switch (i) { - case 1: keyCode = 0x7A; break; - case 2: keyCode = 0x78; break; - case 3: keyCode = 0x63; break; - case 4: keyCode = 0x76; break; - case 5: keyCode = 0x60; break; - case 6: keyCode = 0x61; break; - case 7: keyCode = 0x62; break; - case 8: keyCode = 0x64; break; - case 9: keyCode = 0x65; break; - case 10: keyCode = 0x6D; break; - case 11: keyCode = 0x67; break; - case 12: keyCode = 0x6F; break; - case 13: keyCode = 0x69; break; - case 14: keyCode = 0x6B; break; - case 15: keyCode = 0x71; break; - case 16: keyCode = 0x6A; break; - case 17: keyCode = 0x40; break; - case 18: keyCode = 0x4F; break; - case 19: keyCode = 0x50; break; - case 20: keyCode = 0x5A; break; - } - } - } - - // FIXME: No keyCode is set for most keys. - if ([character isEqualToString:@"\t"]) - keyCode = 0x30; - else if ([character isEqualToString:@" "]) - keyCode = 0x31; - else if ([character isEqualToString:@"\r"]) - keyCode = 0x24; - else if ([character isEqualToString:@"\n"]) - keyCode = 0x4C; - else if ([character isEqualToString:@"\x8"]) - keyCode = 0x33; - else if ([character isEqualToString:@"7"]) - keyCode = 0x1A; - else if ([character isEqualToString:@"5"]) - keyCode = 0x17; - else if ([character isEqualToString:@"9"]) - keyCode = 0x19; - else if ([character isEqualToString:@"0"]) - keyCode = 0x1D; - else if ([character isEqualToString:@"a"]) - keyCode = 0x00; - else if ([character isEqualToString:@"b"]) - keyCode = 0x0B; - else if ([character isEqualToString:@"d"]) - keyCode = 0x02; - else if ([character isEqualToString:@"e"]) - keyCode = 0x0E; - - NSString *charactersIgnoringModifiers = eventCharacter; - - int modifierFlags = 0; - - if ([character length] == 1 && [character characterAtIndex:0] >= 'A' && [character characterAtIndex:0] <= 'Z') { - modifierFlags |= NSShiftKeyMask; - charactersIgnoringModifiers = [character lowercaseString]; - } - - modifierFlags |= buildModifierFlags(modifiers); - - if (keyLocation == DOM_KEY_LOCATION_NUMPAD) - modifierFlags |= NSNumericPadKeyMask; - - [[[mainFrame frameView] documentView] layout]; - - NSEvent *event = [NSEvent keyEventWithType:NSKeyDown - location:NSMakePoint(5, 5) - modifierFlags:modifierFlags - timestamp:[self currentEventTime] - windowNumber:[[[mainFrame webView] window] windowNumber] - context:[NSGraphicsContext currentContext] - characters:eventCharacter - charactersIgnoringModifiers:charactersIgnoringModifiers - isARepeat:NO - keyCode:keyCode]; - - [[[[mainFrame webView] window] firstResponder] keyDown:event]; - - event = [NSEvent keyEventWithType:NSKeyUp - location:NSMakePoint(5, 5) - modifierFlags:modifierFlags - timestamp:[self currentEventTime] - windowNumber:[[[mainFrame webView] window] windowNumber] - context:[NSGraphicsContext currentContext] - characters:eventCharacter - charactersIgnoringModifiers:charactersIgnoringModifiers - isARepeat:NO - keyCode:keyCode]; - - [[[[mainFrame webView] window] firstResponder] keyUp:event]; -} - -- (void)enableDOMUIEventLogging:(WebScriptObject *)node -{ - NSEnumerator *eventEnumerator = [webkitDomEventNames objectEnumerator]; - id eventName; - while ((eventName = [eventEnumerator nextObject])) { - [(id)node addEventListener:eventName listener:self useCapture:NO]; - } -} - -- (void)handleEvent:(DOMEvent *)event -{ - DOMNode *target = [event target]; - - printf("event type: %s\n", [[event type] UTF8String]); - printf(" target: <%s>\n", [[[target nodeName] lowercaseString] UTF8String]); - - if ([event isKindOfClass:[DOMEvent class]]) { - printf(" eventPhase: %d\n", [event eventPhase]); - printf(" bubbles: %d\n", [event bubbles] ? 1 : 0); - printf(" cancelable: %d\n", [event cancelable] ? 1 : 0); - } - - if ([event isKindOfClass:[DOMUIEvent class]]) { - printf(" detail: %d\n", [(DOMUIEvent*)event detail]); - - DOMAbstractView *view = [(DOMUIEvent*)event view]; - if (view) { - printf(" view: OK"); - if ([view document]) - printf(" (document: OK)"); - printf("\n"); - } - } - - if ([event isKindOfClass:[DOMKeyboardEvent class]]) { - printf(" keyIdentifier: %s\n", [[(DOMKeyboardEvent*)event keyIdentifier] UTF8String]); - printf(" keyLocation: %d\n", [(DOMKeyboardEvent*)event keyLocation]); - printf(" modifier keys: c:%d s:%d a:%d m:%d\n", - [(DOMKeyboardEvent*)event ctrlKey] ? 1 : 0, - [(DOMKeyboardEvent*)event shiftKey] ? 1 : 0, - [(DOMKeyboardEvent*)event altKey] ? 1 : 0, - [(DOMKeyboardEvent*)event metaKey] ? 1 : 0); - printf(" keyCode: %d\n", [(DOMKeyboardEvent*)event keyCode]); - printf(" charCode: %d\n", [(DOMKeyboardEvent*)event charCode]); - } - - if ([event isKindOfClass:[DOMMouseEvent class]]) { - printf(" button: %d\n", [(DOMMouseEvent*)event button]); - printf(" clientX: %d\n", [(DOMMouseEvent*)event clientX]); - printf(" clientY: %d\n", [(DOMMouseEvent*)event clientY]); - printf(" screenX: %d\n", [(DOMMouseEvent*)event screenX]); - printf(" screenY: %d\n", [(DOMMouseEvent*)event screenY]); - printf(" modifier keys: c:%d s:%d a:%d m:%d\n", - [(DOMMouseEvent*)event ctrlKey] ? 1 : 0, - [(DOMMouseEvent*)event shiftKey] ? 1 : 0, - [(DOMMouseEvent*)event altKey] ? 1 : 0, - [(DOMMouseEvent*)event metaKey] ? 1 : 0); - id relatedTarget = [(DOMMouseEvent*)event relatedTarget]; - if (relatedTarget) { - printf(" relatedTarget: %s", [[[relatedTarget class] description] UTF8String]); - if ([relatedTarget isKindOfClass:[DOMNode class]]) - printf(" (nodeName: %s)", [[(DOMNode*)relatedTarget nodeName] UTF8String]); - printf("\n"); - } - } - - if ([event isKindOfClass:[DOMMutationEvent class]]) { - printf(" prevValue: %s\n", [[(DOMMutationEvent*)event prevValue] UTF8String]); - printf(" newValue: %s\n", [[(DOMMutationEvent*)event newValue] UTF8String]); - printf(" attrName: %s\n", [[(DOMMutationEvent*)event attrName] UTF8String]); - printf(" attrChange: %d\n", [(DOMMutationEvent*)event attrChange]); - DOMNode *relatedNode = [(DOMMutationEvent*)event relatedNode]; - if (relatedNode) { - printf(" relatedNode: %s (nodeName: %s)\n", - [[[relatedNode class] description] UTF8String], - [[relatedNode nodeName] UTF8String]); - } - } - - if ([event isKindOfClass:[DOMWheelEvent class]]) { - printf(" clientX: %d\n", [(DOMWheelEvent*)event clientX]); - printf(" clientY: %d\n", [(DOMWheelEvent*)event clientY]); - printf(" screenX: %d\n", [(DOMWheelEvent*)event screenX]); - printf(" screenY: %d\n", [(DOMWheelEvent*)event screenY]); - printf(" modifier keys: c:%d s:%d a:%d m:%d\n", - [(DOMWheelEvent*)event ctrlKey] ? 1 : 0, - [(DOMWheelEvent*)event shiftKey] ? 1 : 0, - [(DOMWheelEvent*)event altKey] ? 1 : 0, - [(DOMWheelEvent*)event metaKey] ? 1 : 0); - printf(" isHorizontal: %d\n", [(DOMWheelEvent*)event isHorizontal] ? 1 : 0); - printf(" wheelDelta: %d\n", [(DOMWheelEvent*)event wheelDelta]); - } -} - -// FIXME: It's not good to have a test hard-wired into this controller like this. -// Instead we need to get testing framework based on the Objective-C bindings -// to work well enough that we can test that way instead. -- (void)fireKeyboardEventsToElement:(WebScriptObject *)element { - - if (![element isKindOfClass:[DOMHTMLElement class]]) - return; - - DOMHTMLElement *target = (DOMHTMLElement*)element; - DOMDocument *document = [target ownerDocument]; - - // Keyboard Event 1 - - DOMEvent *domEvent = [document createEvent:@"KeyboardEvent"]; - [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keydown" - canBubble:YES - cancelable:YES - view:[document defaultView] - keyIdentifier:@"U+000041" - keyLocation:0 - ctrlKey:YES - altKey:NO - shiftKey:NO - metaKey:NO]; - [target dispatchEvent:domEvent]; - - // Keyboard Event 2 - - domEvent = [document createEvent:@"KeyboardEvent"]; - [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keypress" - canBubble:YES - cancelable:YES - view:[document defaultView] - keyIdentifier:@"U+000045" - keyLocation:1 - ctrlKey:NO - altKey:YES - shiftKey:NO - metaKey:NO]; - [target dispatchEvent:domEvent]; - - // Keyboard Event 3 - - domEvent = [document createEvent:@"KeyboardEvent"]; - [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keyup" - canBubble:YES - cancelable:YES - view:[document defaultView] - keyIdentifier:@"U+000056" - keyLocation:0 - ctrlKey:NO - altKey:NO - shiftKey:NO - metaKey:NO]; - [target dispatchEvent:domEvent]; - -} - -@end