/* * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. * Copyright (C) 2006 Jonas Witt * * 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 "EventSendingController.h" #import "DumpRenderTree.h" #import "DumpRenderTreeDraggingInfo.h" #import // for GetCurrentEventTime() #import #import NSPoint lastMousePosition; NSArray *webkitDomEventNames; NSArray *webkitDomEventProperties; @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", @"unload", @"zoom", nil]; webkitDomEventProperties = [[NSArray alloc] initWithObjects: @"clientX", @"clientY", nil]; } + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { if (aSelector == @selector(mouseDown) || aSelector == @selector(mouseUp) || aSelector == @selector(mouseClick) || aSelector == @selector(mouseMoveToX:Y:) || aSelector == @selector(leapForward:) || aSelector == @selector(keyDown:withModifiers:) || aSelector == @selector(enableDOMUIEventLogging:)) return NO; return YES; } + (NSString *)webScriptNameForSelector:(SEL)aSelector { if (aSelector == @selector(mouseMoveToX:Y:)) return @"mouseMoveTo"; if (aSelector == @selector(leapForward:)) return @"leapForward"; if (aSelector == @selector(keyDown:withModifiers:)) return @"keyDown"; if (aSelector == @selector(enableDOMUIEventLogging:)) return @"enableDOMUIEventLogging"; return nil; } - (id)init { lastMousePosition = NSMakePoint(0, 0); down = NO; clickCount = 0; lastClick = 0; return self; } - (double)currentEventTime { return GetCurrentEventTime() + timeOffset; } - (void)leapForward:(int)milliseconds { timeOffset += milliseconds / 1000.0; } - (void)mouseDown { [[[frame frameView] documentView] layout]; if ([self currentEventTime] - lastClick >= 1) clickCount = 1; else clickCount++; NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseDown location:lastMousePosition modifierFlags:nil timestamp:[self currentEventTime] windowNumber:[[[frame webView] window] windowNumber] context:[NSGraphicsContext currentContext] eventNumber:++eventNumber clickCount:clickCount pressure:nil]; NSView *subView = [[frame webView] hitTest:[event locationInWindow]]; if (subView) { [subView mouseDown:event]; down = YES; } } - (void)mouseUp { [[[frame frameView] documentView] layout]; NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseUp location:lastMousePosition modifierFlags:nil timestamp:[self currentEventTime] windowNumber:[[[frame webView] window] windowNumber] context:[NSGraphicsContext currentContext] eventNumber:++eventNumber clickCount:clickCount pressure:nil]; NSView *subView = [[frame webView] hitTest:[event locationInWindow]]; if (subView) { [subView mouseUp:event]; down = NO; lastClick = [event timestamp]; if (draggingInfo) { WebView *webView = [frame webView]; NSDragOperation dragOperation = [webView draggingUpdated:draggingInfo]; if (dragOperation != NSDragOperationNone) [webView performDragOperation:draggingInfo]; [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] endedAt:lastMousePosition operation:dragOperation]; [draggingInfo release]; draggingInfo = nil; } } } - (void)mouseMoveToX:(int)x Y:(int)y { lastMousePosition = NSMakePoint(x, [[frame webView] frame].size.height - y); NSEvent *event = [NSEvent mouseEventWithType:(down ? NSLeftMouseDragged : NSMouseMoved) location:lastMousePosition modifierFlags:nil timestamp:[self currentEventTime] windowNumber:[[[frame webView] window] windowNumber] context:[NSGraphicsContext currentContext] eventNumber:++eventNumber clickCount:(down ? clickCount : 0) pressure:nil]; NSView *subView = [[frame webView] hitTest:[event locationInWindow]]; if (subView) { if (down) { [subView mouseDragged:event]; [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] movedTo:lastMousePosition]; [[frame webView] draggingUpdated:draggingInfo]; } else [subView mouseMoved:event]; } } - (void)mouseClick { [[[frame frameView] documentView] layout]; if ([self currentEventTime] - lastClick >= 1) clickCount = 1; else clickCount++; NSEvent *mouseDownEvent = [NSEvent mouseEventWithType:NSLeftMouseDown location:lastMousePosition modifierFlags:nil timestamp:[self currentEventTime] windowNumber:[[[frame webView] window] windowNumber] context:[NSGraphicsContext currentContext] eventNumber:++eventNumber clickCount:clickCount pressure:nil]; NSView *subView = [[frame webView] hitTest:[mouseDownEvent locationInWindow]]; if (subView) { [self leapForward:1]; NSEvent *mouseUpEvent = [NSEvent mouseEventWithType:NSLeftMouseUp location:lastMousePosition modifierFlags:nil timestamp:[self currentEventTime] windowNumber:[[[frame webView] window] windowNumber] context:[NSGraphicsContext currentContext] eventNumber:++eventNumber clickCount:clickCount pressure:nil]; [NSApp postEvent:mouseUpEvent atStart:NO]; [subView mouseDown:mouseDownEvent]; lastClick = [mouseUpEvent timestamp]; } } - (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers { NSString *modifier = nil; int mask = 0; if ([modifiers isKindOfClass:[WebScriptObject class]]) for (unsigned i = 0; [[modifiers webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) { modifier = (NSString *)[modifiers webScriptValueAtIndex:i]; if ([modifier isEqual:@"ctrlKey"]) mask |= NSControlKeyMask; else if ([modifier isEqual:@"shiftKey"]) mask |= NSShiftKeyMask; else if ([modifier isEqual:@"altKey"]) mask |= NSAlternateKeyMask; else if ([modifier isEqual:@"metaKey"]) mask |= NSCommandKeyMask; else break; } [[[frame frameView] documentView] layout]; NSEvent *event = [NSEvent keyEventWithType:NSKeyDown location:NSMakePoint(5, 5) modifierFlags:mask timestamp:[self currentEventTime] windowNumber:[[[frame webView] window] windowNumber] context:[NSGraphicsContext currentContext] characters:character charactersIgnoringModifiers:character isARepeat:NO keyCode:0]; NSView *subView = [[frame webView] hitTest:[event locationInWindow]]; if (subView) { [subView keyDown:event]; down = YES; } } - (void)enableDOMUIEventLogging:(WebScriptObject *)node { NSEnumerator *eventEnumerator = [webkitDomEventNames objectEnumerator]; id eventName; while ((eventName = [eventEnumerator nextObject])) { [(id)node addEventListener:eventName :self :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(" screenX: %d\n", [(DOMMouseEvent*)event screenX]); printf(" screenY: %d (flipped)\n", (int) [[[NSScreen screens] objectAtIndex:0] frame].size.height - [(DOMMouseEvent*)event screenY]); printf(" clientX: %d\n", [(DOMMouseEvent*)event clientX]); printf(" clientY: %d\n", [(DOMMouseEvent*)event clientY]); 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(" screenX: %d\n", [(DOMWheelEvent*)event screenX]); printf(" screenY: %d (flipped)\n", (int) [[[NSScreen screens] objectAtIndex:0] frame].size.height - [(DOMWheelEvent*)event screenY]); printf(" clientX: %d\n", [(DOMWheelEvent*)event clientX]); printf(" clientY: %d\n", [(DOMWheelEvent*)event clientY]); 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]); } } @end