1563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/*
2563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Copyright (C) 2006 Jonas Witt <jonas.witt@gmail.com>
4563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
5563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
6563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *
7563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Redistribution and use in source and binary forms, with or without
8563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * modification, are permitted provided that the following conditions
9563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * are met:
10563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *
11563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 1.  Redistributions of source code must retain the above copyright
12563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     notice, this list of conditions and the following disclaimer.
13563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 2.  Redistributions in binary form must reproduce the above copyright
14563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     notice, this list of conditions and the following disclaimer in the
15563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     documentation and/or other materials provided with the distribution.
16563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
17563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     its contributors may be used to endorse or promote products derived
18563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     from this software without specific prior written permission.
19563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *
20563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */
31563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#import "config.h"
33563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import "EventSendingController.h"
34563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
35563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import "DumpRenderTree.h"
36563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import "DumpRenderTreeDraggingInfo.h"
370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#import "DumpRenderTreeFileDraggingSource.h"
38563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
39563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import <Carbon/Carbon.h>                           // for GetCurrentEventTime()
40563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import <WebKit/DOMPrivate.h>
41563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import <WebKit/WebKit.h>
42563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import <WebKit/WebViewPrivate.h>
43563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
44563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkextern "C" void _NSNewKillRingSequence();
45563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
46563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkenum MouseAction {
47563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    MouseDown,
48563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    MouseUp,
49563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    MouseDragged
50563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark};
51563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
52563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// Match the DOM spec (sadly the DOM spec does not provide an enum)
53563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkenum MouseButton {
54563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    LeftMouseButton = 0,
55563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    MiddleMouseButton = 1,
56563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    RightMouseButton = 2,
57563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NoMouseButton = -1
58563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark};
59563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
60563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkNSPoint lastMousePosition;
61563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkNSPoint lastClickPosition;
62563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkint lastClickButton = NoMouseButton;
63563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkNSArray *webkitDomEventNames;
64563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkNSMutableArray *savedMouseEvents; // mouse events sent between mouseDown and mouseUp are stored here, and then executed at once.
65563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkBOOL replayingSavedEvents;
66563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
67563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark@implementation EventSendingController
68563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
69563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark+ (void)initialize
70563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
71563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    webkitDomEventNames = [[NSArray alloc] initWithObjects:
72563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"abort",
73563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"beforecopy",
74563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"beforecut",
75563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"beforepaste",
76563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"blur",
77563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"change",
78563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"click",
79563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"contextmenu",
80563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"copy",
81563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"cut",
82563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"dblclick",
83563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"drag",
84563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"dragend",
85563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"dragenter",
86563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"dragleave",
87563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"dragover",
88563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"dragstart",
89563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"drop",
90563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"error",
91563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"focus",
92563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"input",
93563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"keydown",
94563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"keypress",
95563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"keyup",
96563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"load",
97563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"mousedown",
98563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"mousemove",
99563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"mouseout",
100563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"mouseover",
101563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"mouseup",
102563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"mousewheel",
103563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"beforeunload",
104563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"paste",
105563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"readystatechange",
106563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"reset",
107563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"resize",
108563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"scroll",
109563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"search",
110563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"select",
111563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"selectstart",
112563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"submit",
113563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"textInput",
114563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"textzoomin",
115563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"textzoomout",
116563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"unload",
117563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        @"zoom",
118563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        nil];
119563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
120563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
121563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
122563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (aSelector == @selector(beginDragWithFiles:)
1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            || aSelector == @selector(clearKillRing)
125545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            || aSelector == @selector(contextClick)
126563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            || aSelector == @selector(enableDOMUIEventLogging:)
127563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            || aSelector == @selector(fireKeyboardEventsToElement:)
128d0825bca7fe65beaee391d30da42e937db621564Steve Block            || aSelector == @selector(keyDown:withModifiers:withLocation:)
1290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            || aSelector == @selector(leapForward:)
130d0825bca7fe65beaee391d30da42e937db621564Steve Block            || aSelector == @selector(mouseDown:withModifiers:)
1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            || aSelector == @selector(mouseMoveToX:Y:)
132d0825bca7fe65beaee391d30da42e937db621564Steve Block            || aSelector == @selector(mouseUp:withModifiers:)
1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            || aSelector == @selector(scheduleAsynchronousClick)
134563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            || aSelector == @selector(textZoomIn)
135563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            || aSelector == @selector(textZoomOut)
136563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            || aSelector == @selector(zoomPageIn)
137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            || aSelector == @selector(zoomPageOut)
1382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            || aSelector == @selector(scalePageBy:atX:andY:)
139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            || aSelector == @selector(mouseScrollByX:andY:)
140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            || aSelector == @selector(continuousMouseScrollByX:andY:))
141563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return NO;
142563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return YES;
143563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
144563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
145563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark+ (BOOL)isKeyExcludedFromWebScript:(const char*)name
146563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
147563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (strcmp(name, "dragMode") == 0)
148563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return NO;
149563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return YES;
150563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
151563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
152563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark+ (NSString *)webScriptNameForSelector:(SEL)aSelector
153563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (aSelector == @selector(beginDragWithFiles:))
1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return @"beginDragWithFiles";
156545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    if (aSelector == @selector(contextClick))
1576c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        return @"contextClick";
1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (aSelector == @selector(enableDOMUIEventLogging:))
1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return @"enableDOMUIEventLogging";
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (aSelector == @selector(fireKeyboardEventsToElement:))
1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return @"fireKeyboardEventsToElement";
162d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (aSelector == @selector(keyDown:withModifiers:withLocation:))
1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return @"keyDown";
1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (aSelector == @selector(leapForward:))
1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return @"leapForward";
166d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (aSelector == @selector(mouseDown:withModifiers:))
167563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return @"mouseDown";
168d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (aSelector == @selector(mouseUp:withModifiers:))
169563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return @"mouseUp";
170563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (aSelector == @selector(mouseMoveToX:Y:))
171563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return @"mouseMoveTo";
172563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (aSelector == @selector(setDragMode:))
173563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return @"setDragMode";
174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (aSelector == @selector(mouseScrollByX:andY:))
175dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return @"mouseScrollBy";
176dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (aSelector == @selector(continuousMouseScrollByX:andY:))
177dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return @"continuousMouseScrollBy";
1782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (aSelector == @selector(scalePageBy:atX:andY:))
1792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return @"scalePageBy";
180563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return nil;
181563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
182563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
183563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (id)init
184563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
185563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    self = [super init];
186563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (self)
187563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        dragMode = YES;
188563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return self;
189563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
190563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
191563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)dealloc
192563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
193563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [super dealloc];
194563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
195563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
196563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (double)currentEventTime
197563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
198563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return GetCurrentEventTime() + timeOffset;
199563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
200563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
201563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)leapForward:(int)milliseconds
202563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
203563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (dragMode && leftMouseButtonDown && !replayingSavedEvents) {
204563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(leapForward:)]];
205563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setTarget:self];
206563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setSelector:@selector(leapForward:)];
207563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setArgument:&milliseconds atIndex:2];
208563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
209563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [EventSendingController saveEvent:invocation];
210563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
211563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return;
212563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
213563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
214563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    timeOffset += milliseconds / 1000.0;
215563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
216563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
217563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)clearKillRing
218563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
219563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    _NSNewKillRingSequence();
220563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
221563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
222563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkstatic NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction action)
223563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
224563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    switch (button) {
225563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case LeftMouseButton:
226563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            switch (action) {
227563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseDown:
228563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSLeftMouseDown;
229563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseUp:
230563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSLeftMouseUp;
231563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseDragged:
232563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSLeftMouseDragged;
233563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            }
234563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case RightMouseButton:
235563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            switch (action) {
236563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseDown:
237563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSRightMouseDown;
238563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseUp:
239563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSRightMouseUp;
240563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseDragged:
241563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSRightMouseDragged;
242563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            }
243563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        default:
244563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            switch (action) {
245563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseDown:
246563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSOtherMouseDown;
247563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseUp:
248563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSOtherMouseUp;
249563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                case MouseDragged:
250563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                    return NSOtherMouseDragged;
251563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            }
252563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
253563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    assert(0);
254563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return static_cast<NSEventType>(0);
255563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
256563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
2570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch- (void)beginDragWithFiles:(WebScriptObject*)jsFilePaths
2580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    assert(!draggingInfo);
2600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    assert([jsFilePaths isKindOfClass:[WebScriptObject class]]);
2610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSPasteboard *pboard = [NSPasteboard pasteboardWithUniqueName];
2630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];
2640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSURL *currentTestURL = [NSURL URLWithString:[[mainFrame webView] mainFrameURL]];
2660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSMutableArray *filePaths = [NSMutableArray array];
2680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    for (unsigned i = 0; [[jsFilePaths webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) {
2690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        NSString *filePath = (NSString *)[jsFilePaths webScriptValueAtIndex:i];
2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Have NSURL encode the name so that we handle '?' in file names correctly.
2710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        NSURL *fileURL = [NSURL fileURLWithPath:filePath];
2720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        NSURL *absoluteFileURL = [NSURL URLWithString:[fileURL relativeString]  relativeToURL:currentTestURL];
2730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [filePaths addObject:[absoluteFileURL path]];
2740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    [pboard setPropertyList:filePaths forType:NSFilenamesPboardType];
2770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    assert([pboard propertyListForType:NSFilenamesPboardType]); // setPropertyList will silently fail on error, assert that it didn't fail
2780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Provide a source, otherwise [DumpRenderTreeDraggingInfo draggingSourceOperationMask] defaults to NSDragOperationNone
2800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DumpRenderTreeFileDraggingSource *source = [[[DumpRenderTreeFileDraggingSource alloc] init] autorelease];
2810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    draggingInfo = [[DumpRenderTreeDraggingInfo alloc] initWithImage:nil offset:NSZeroSize pasteboard:pboard source:source];
2820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    [[mainFrame webView] draggingEntered:draggingInfo];
2830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    dragMode = NO; // dragMode saves events and then replays them later.  We don't need/want that.
2850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    leftMouseButtonDown = YES; // Make the rest of eventSender think a drag is in progress
2860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
288563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)updateClickCountForButton:(int)buttonNumber
289563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
290563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (([self currentEventTime] - lastClick >= 1) ||
291563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        !NSEqualPoints(lastMousePosition, lastClickPosition) ||
292563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        lastClickButton != buttonNumber) {
293563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        clickCount = 1;
294563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        lastClickButton = buttonNumber;
295563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else
296563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        clickCount++;
297563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
298563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
299d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic int buildModifierFlags(const WebScriptObject* modifiers)
300d0825bca7fe65beaee391d30da42e937db621564Steve Block{
301d0825bca7fe65beaee391d30da42e937db621564Steve Block    int flags = 0;
302d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (![modifiers isKindOfClass:[WebScriptObject class]])
303d0825bca7fe65beaee391d30da42e937db621564Steve Block        return flags;
304d0825bca7fe65beaee391d30da42e937db621564Steve Block    for (unsigned i = 0; [[modifiers webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) {
305d0825bca7fe65beaee391d30da42e937db621564Steve Block        NSString* modifierName = (NSString*)[modifiers webScriptValueAtIndex:i];
306d0825bca7fe65beaee391d30da42e937db621564Steve Block        if ([modifierName isEqual:@"ctrlKey"])
307d0825bca7fe65beaee391d30da42e937db621564Steve Block            flags |= NSControlKeyMask;
308d0825bca7fe65beaee391d30da42e937db621564Steve Block        else if ([modifierName isEqual:@"shiftKey"] || [modifierName isEqual:@"rangeSelectionKey"])
309d0825bca7fe65beaee391d30da42e937db621564Steve Block            flags |= NSShiftKeyMask;
310d0825bca7fe65beaee391d30da42e937db621564Steve Block        else if ([modifierName isEqual:@"altKey"])
311d0825bca7fe65beaee391d30da42e937db621564Steve Block            flags |= NSAlternateKeyMask;
312d0825bca7fe65beaee391d30da42e937db621564Steve Block        else if ([modifierName isEqual:@"metaKey"] || [modifierName isEqual:@"addSelectionKey"])
313d0825bca7fe65beaee391d30da42e937db621564Steve Block            flags |= NSCommandKeyMask;
314d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
315d0825bca7fe65beaee391d30da42e937db621564Steve Block    return flags;
316d0825bca7fe65beaee391d30da42e937db621564Steve Block}
317d0825bca7fe65beaee391d30da42e937db621564Steve Block
318d0825bca7fe65beaee391d30da42e937db621564Steve Block- (void)mouseDown:(int)buttonNumber withModifiers:(WebScriptObject*)modifiers
319563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
320563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[[mainFrame frameView] documentView] layout];
321563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [self updateClickCountForButton:buttonNumber];
322563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
323563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEventType eventType = eventTypeForMouseButtonAndAction(buttonNumber, MouseDown);
324563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEvent *event = [NSEvent mouseEventWithType:eventType
325563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        location:lastMousePosition
326d0825bca7fe65beaee391d30da42e937db621564Steve Block                                   modifierFlags:buildModifierFlags(modifiers)
327563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                       timestamp:[self currentEventTime]
328563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                    windowNumber:[[[mainFrame webView] window] windowNumber]
329563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                         context:[NSGraphicsContext currentContext]
330563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                     eventNumber:++eventNumber
331563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                      clickCount:clickCount
332563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        pressure:0.0];
333563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
334563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]];
335563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (subView) {
336563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [subView mouseDown:event];
337563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (buttonNumber == LeftMouseButton)
338563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            leftMouseButtonDown = YES;
339563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
340563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
341563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
342d0825bca7fe65beaee391d30da42e937db621564Steve Block- (void)mouseDown:(int)buttonNumber
343d0825bca7fe65beaee391d30da42e937db621564Steve Block{
344d0825bca7fe65beaee391d30da42e937db621564Steve Block    [self mouseDown:buttonNumber withModifiers:nil];
345d0825bca7fe65beaee391d30da42e937db621564Steve Block}
346d0825bca7fe65beaee391d30da42e937db621564Steve Block
347563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)textZoomIn
348563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
349563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[mainFrame webView] makeTextLarger:self];
350563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
351563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
352563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)textZoomOut
353563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
354563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[mainFrame webView] makeTextSmaller:self];
355563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
356563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
357563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)zoomPageIn
358563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
359563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[mainFrame webView] zoomPageIn:self];
360563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
361563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
362563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)zoomPageOut
363563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
364563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[mainFrame webView] zoomPageOut:self];
365563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
366563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
3672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch- (void)scalePageBy:(float)scale atX:(float)x andY:(float)y
3682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    [[mainFrame webView] _scaleWebView:scale atOrigin:NSMakePoint(x, y)];
3702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
372d0825bca7fe65beaee391d30da42e937db621564Steve Block- (void)mouseUp:(int)buttonNumber withModifiers:(WebScriptObject*)modifiers
373563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
374563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (dragMode && !replayingSavedEvents) {
375d0825bca7fe65beaee391d30da42e937db621564Steve Block        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp:withModifiers:)]];
376563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setTarget:self];
377d0825bca7fe65beaee391d30da42e937db621564Steve Block        [invocation setSelector:@selector(mouseUp:withModifiers:)];
378563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setArgument:&buttonNumber atIndex:2];
379d0825bca7fe65beaee391d30da42e937db621564Steve Block        [invocation setArgument:&modifiers atIndex:3];
380563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
381563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [EventSendingController saveEvent:invocation];
382563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [EventSendingController replaySavedEvents];
383563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
384563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return;
385563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
386563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
387563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[[mainFrame frameView] documentView] layout];
388563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEventType eventType = eventTypeForMouseButtonAndAction(buttonNumber, MouseUp);
389563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEvent *event = [NSEvent mouseEventWithType:eventType
390563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        location:lastMousePosition
391d0825bca7fe65beaee391d30da42e937db621564Steve Block                                   modifierFlags:buildModifierFlags(modifiers)
392563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                       timestamp:[self currentEventTime]
393563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                    windowNumber:[[[mainFrame webView] window] windowNumber]
394563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                         context:[NSGraphicsContext currentContext]
395563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                     eventNumber:++eventNumber
396563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                      clickCount:clickCount
397563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        pressure:0.0];
398563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
399563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSView *targetView = [[mainFrame webView] hitTest:[event locationInWindow]];
400563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    // FIXME: Silly hack to teach DRT to respect capturing mouse events outside the WebView.
401563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    // The right solution is just to use NSApplication's built-in event sending methods,
402563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    // instead of rolling our own algorithm for selecting an event target.
403563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    targetView = targetView ? targetView : [[mainFrame frameView] documentView];
404563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    assert(targetView);
405563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [targetView mouseUp:event];
406563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (buttonNumber == LeftMouseButton)
407563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        leftMouseButtonDown = NO;
408563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    lastClick = [event timestamp];
409563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    lastClickPosition = lastMousePosition;
410563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (draggingInfo) {
411563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        WebView *webView = [mainFrame webView];
412563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
413563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        NSDragOperation dragOperation = [webView draggingUpdated:draggingInfo];
414563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
415563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (dragOperation != NSDragOperationNone)
416563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            [webView performDragOperation:draggingInfo];
417563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        else
418563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            [webView draggingExited:draggingInfo];
4190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Per NSDragging.h: draggingSources may not implement draggedImage:endedAt:operation:
4200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if ([[draggingInfo draggingSource] respondsToSelector:@selector(draggedImage:endedAt:operation:)])
4210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] endedAt:lastMousePosition operation:dragOperation];
422563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [draggingInfo release];
423563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        draggingInfo = nil;
424563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
425563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
426563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
427d0825bca7fe65beaee391d30da42e937db621564Steve Block- (void)mouseUp:(int)buttonNumber
428d0825bca7fe65beaee391d30da42e937db621564Steve Block{
429d0825bca7fe65beaee391d30da42e937db621564Steve Block    [self mouseUp:buttonNumber withModifiers:nil];
430d0825bca7fe65beaee391d30da42e937db621564Steve Block}
431d0825bca7fe65beaee391d30da42e937db621564Steve Block
432563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)mouseMoveToX:(int)x Y:(int)y
433563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
434563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (dragMode && leftMouseButtonDown && !replayingSavedEvents) {
435563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseMoveToX:Y:)]];
436563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setTarget:self];
437563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setSelector:@selector(mouseMoveToX:Y:)];
438563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setArgument:&x atIndex:2];
439563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation setArgument:&y atIndex:3];
440563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
441563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [EventSendingController saveEvent:invocation];
442563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return;
443563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
444563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
445563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSView *view = [mainFrame webView];
446563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    lastMousePosition = [view convertPoint:NSMakePoint(x, [view frame].size.height - y) toView:nil];
447563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEvent *event = [NSEvent mouseEventWithType:(leftMouseButtonDown ? NSLeftMouseDragged : NSMouseMoved)
448563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        location:lastMousePosition
449563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                   modifierFlags:0
450563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                       timestamp:[self currentEventTime]
451563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                    windowNumber:[[view window] windowNumber]
452563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                         context:[NSGraphicsContext currentContext]
453563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                     eventNumber:++eventNumber
454563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                      clickCount:(leftMouseButtonDown ? clickCount : 0)
455563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        pressure:0.0];
456563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
457563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]];
458563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (subView) {
459563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (leftMouseButtonDown) {
460563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            if (draggingInfo) {
4610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // Per NSDragging.h: draggingSources may not implement draggedImage:movedTo:
4620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                if ([[draggingInfo draggingSource] respondsToSelector:@selector(draggedImage:movedTo:)])
4630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] movedTo:lastMousePosition];
464563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                [[mainFrame webView] draggingUpdated:draggingInfo];
465dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            } else
466dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch                [subView mouseDragged:event];
467563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        } else
468563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            [subView mouseMoved:event];
469563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
470563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
471563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
472dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block- (void)mouseScrollByX:(int)x andY:(int)y continuously:(BOOL)c
473dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
474dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // CGEventCreateScrollWheelEvent() was introduced in 10.5
475dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if !defined(BUILDING_ON_TIGER)
476dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    CGScrollEventUnit unit = c?kCGScrollEventUnitPixel:kCGScrollEventUnitLine;
477dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    CGEventRef cgScrollEvent = CGEventCreateScrollWheelEvent(NULL, unit, 2, y, x);
478dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
479dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // CGEvent locations are in global display coordinates.
480dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    CGPoint lastGlobalMousePosition = {
481dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        lastMousePosition.x,
482dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        [[NSScreen mainScreen] frame].size.height - lastMousePosition.y
483dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    };
484dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    CGEventSetLocation(cgScrollEvent, lastGlobalMousePosition);
485dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
486dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    NSEvent *scrollEvent = [NSEvent eventWithCGEvent:cgScrollEvent];
487dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    CFRelease(cgScrollEvent);
488dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
489dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    NSView *subView = [[mainFrame webView] hitTest:[scrollEvent locationInWindow]];
490dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (subView)
491dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        [subView scrollWheel:scrollEvent];
492dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif
493dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
494dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
495dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block- (void)continuousMouseScrollByX:(int)x andY:(int)y
496dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
497dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    [self mouseScrollByX:x andY:y continuously:YES];
498dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
499dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
500dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block- (void)mouseScrollByX:(int)x andY:(int)y
501dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
502dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    [self mouseScrollByX:x andY:y continuously:NO];
503dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
504dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
505545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch- (NSArray *)contextClick
506563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
507563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[[mainFrame frameView] documentView] layout];
508563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [self updateClickCountForButton:RightMouseButton];
509563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
510563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEvent *event = [NSEvent mouseEventWithType:NSRightMouseDown
511563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        location:lastMousePosition
512563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                   modifierFlags:0
513563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                       timestamp:[self currentEventTime]
514563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                    windowNumber:[[[mainFrame webView] window] windowNumber]
515563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                         context:[NSGraphicsContext currentContext]
516563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                     eventNumber:++eventNumber
517563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                      clickCount:clickCount
518563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        pressure:0.0];
519563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
520563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]];
521545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    NSMutableArray *menuItemStrings = [NSMutableArray array];
522545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
5236c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    if (subView) {
5246c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        NSMenu* menu = [subView menuForEvent:event];
525545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
526545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch        for (int i = 0; i < [menu numberOfItems]; ++i) {
527545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            NSMenuItem* menuItem = [menu itemAtIndex:i];
528545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            if (!strcmp("Inspect Element", [[menuItem title] UTF8String]))
529545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                continue;
530545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
531545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            if ([menuItem isSeparatorItem])
532545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                [menuItemStrings addObject:@"<separator>"];
533545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            else
534545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                [menuItemStrings addObject:[menuItem title]];
5356c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        }
5366c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    }
537545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
538545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    return menuItemStrings;
539563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
540563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
541563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)scheduleAsynchronousClick
542563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
543563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [self performSelector:@selector(mouseDown:) withObject:nil afterDelay:0];
544563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [self performSelector:@selector(mouseUp:) withObject:nil afterDelay:0];
545563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
546563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
547563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark+ (void)saveEvent:(NSInvocation *)event
548563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
549563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (!savedMouseEvents)
550563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        savedMouseEvents = [[NSMutableArray alloc] init];
551563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [savedMouseEvents addObject:event];
552563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
553563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
554563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark+ (void)replaySavedEvents
555563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
556563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    replayingSavedEvents = YES;
557563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    while ([savedMouseEvents count]) {
558563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        // if a drag is initiated, the remaining saved events will be dispatched from our dragging delegate
559563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        NSInvocation *invocation = [[[savedMouseEvents objectAtIndex:0] retain] autorelease];
560563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [savedMouseEvents removeObjectAtIndex:0];
561563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [invocation invoke];
562563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
563563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    replayingSavedEvents = NO;
564563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
565563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
566563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark+ (void)clearSavedEvents
567563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
568563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [savedMouseEvents release];
569563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    savedMouseEvents = nil;
570563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
571563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
572d0825bca7fe65beaee391d30da42e937db621564Steve Block- (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers withLocation:(unsigned long)keyLocation
573563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
574563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSString *eventCharacter = character;
575dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    unsigned short keyCode = 0;
576563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([character isEqualToString:@"leftArrow"]) {
577563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        const unichar ch = NSLeftArrowFunctionKey;
578563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
579dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x7B;
580563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else if ([character isEqualToString:@"rightArrow"]) {
581563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        const unichar ch = NSRightArrowFunctionKey;
582563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
583dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x7C;
584563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else if ([character isEqualToString:@"upArrow"]) {
585563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        const unichar ch = NSUpArrowFunctionKey;
586563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
587dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x7E;
588563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else if ([character isEqualToString:@"downArrow"]) {
589563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        const unichar ch = NSDownArrowFunctionKey;
590563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
591dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x7D;
592563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else if ([character isEqualToString:@"pageUp"]) {
593563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        const unichar ch = NSPageUpFunctionKey;
594563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
595dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x74;
596563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else if ([character isEqualToString:@"pageDown"]) {
597563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        const unichar ch = NSPageDownFunctionKey;
598563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
599dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x79;
600563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else if ([character isEqualToString:@"home"]) {
601563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        const unichar ch = NSHomeFunctionKey;
602563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
603dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x73;
604563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else if ([character isEqualToString:@"end"]) {
605563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        const unichar ch = NSEndFunctionKey;
606563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
607dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x77;
608db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    } else if ([character isEqualToString:@"insert"]) {
609db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        const unichar ch = NSInsertFunctionKey;
610db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        eventCharacter = [NSString stringWithCharacters:&ch length:1];
611db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        keyCode = 0x72;
612563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    } else if ([character isEqualToString:@"delete"]) {
61306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        const unichar ch = NSDeleteFunctionKey;
614563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        eventCharacter = [NSString stringWithCharacters:&ch length:1];
615dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x75;
616db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    } else if ([character isEqualToString:@"printScreen"]) {
617db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        const unichar ch = NSPrintScreenFunctionKey;
618db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        eventCharacter = [NSString stringWithCharacters:&ch length:1];
619db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        keyCode = 0x0; // There is no known virtual key code for PrintScreen.
620563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
621563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
622231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Compare the input string with the function-key names defined by the DOM spec (i.e. "F1",...,"F24").
623231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If the input string is a function-key name, set its key code.
624231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (unsigned i = 1; i <= 24; i++) {
625231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if ([character isEqualToString:[NSString stringWithFormat:@"F%u", i]]) {
626231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            const unichar ch = NSF1FunctionKey + (i - 1);
627231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            eventCharacter = [NSString stringWithCharacters:&ch length:1];
628dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            switch (i) {
629dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 1: keyCode = 0x7A; break;
630dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 2: keyCode = 0x78; break;
631dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 3: keyCode = 0x63; break;
632dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 4: keyCode = 0x76; break;
633dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 5: keyCode = 0x60; break;
634dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 6: keyCode = 0x61; break;
635dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 7: keyCode = 0x62; break;
636dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 8: keyCode = 0x64; break;
637dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 9: keyCode = 0x65; break;
638dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 10: keyCode = 0x6D; break;
639dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 11: keyCode = 0x67; break;
640dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 12: keyCode = 0x6F; break;
641dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 13: keyCode = 0x69; break;
642dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 14: keyCode = 0x6B; break;
643dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 15: keyCode = 0x71; break;
644dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 16: keyCode = 0x6A; break;
645dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 17: keyCode = 0x40; break;
646dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 18: keyCode = 0x4F; break;
647dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 19: keyCode = 0x50; break;
648dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                case 20: keyCode = 0x5A; break;
649dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
650231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
651231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
652231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
653dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // FIXME: No keyCode is set for most keys.
654dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ([character isEqualToString:@"\t"])
655dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x30;
656dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@" "])
657dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x31;
658dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"\r"])
659dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x24;
660dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"\n"])
661dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x4C;
662dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"\x8"])
663dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x33;
664dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"7"])
665dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x1A;
666dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"5"])
667dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x17;
668dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"9"])
669dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x19;
670dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"0"])
671dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x1D;
672dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"a"])
673dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x00;
674dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"b"])
675dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x0B;
676dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"d"])
677dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x02;
678dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if ([character isEqualToString:@"e"])
679dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        keyCode = 0x0E;
680dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
681563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSString *charactersIgnoringModifiers = eventCharacter;
682563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
683563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    int modifierFlags = 0;
684563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
685563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([character length] == 1 && [character characterAtIndex:0] >= 'A' && [character characterAtIndex:0] <= 'Z') {
686563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        modifierFlags |= NSShiftKeyMask;
687563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        charactersIgnoringModifiers = [character lowercaseString];
688563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
689563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
690d0825bca7fe65beaee391d30da42e937db621564Steve Block    modifierFlags |= buildModifierFlags(modifiers);
691d0825bca7fe65beaee391d30da42e937db621564Steve Block
692d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (keyLocation == DOM_KEY_LOCATION_NUMPAD)
693d0825bca7fe65beaee391d30da42e937db621564Steve Block        modifierFlags |= NSNumericPadKeyMask;
694563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
695563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[[mainFrame frameView] documentView] layout];
696563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
697563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEvent *event = [NSEvent keyEventWithType:NSKeyDown
698563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        location:NSMakePoint(5, 5)
699563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        modifierFlags:modifierFlags
700563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        timestamp:[self currentEventTime]
701563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        windowNumber:[[[mainFrame webView] window] windowNumber]
702563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        context:[NSGraphicsContext currentContext]
703563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        characters:eventCharacter
704563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        charactersIgnoringModifiers:charactersIgnoringModifiers
705563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        isARepeat:NO
706dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        keyCode:keyCode];
707563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
708563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[[[mainFrame webView] window] firstResponder] keyDown:event];
709563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
710563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    event = [NSEvent keyEventWithType:NSKeyUp
711563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        location:NSMakePoint(5, 5)
712563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        modifierFlags:modifierFlags
713563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        timestamp:[self currentEventTime]
714563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        windowNumber:[[[mainFrame webView] window] windowNumber]
715563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        context:[NSGraphicsContext currentContext]
716563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        characters:eventCharacter
717563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        charactersIgnoringModifiers:charactersIgnoringModifiers
718563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                        isARepeat:NO
719dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        keyCode:keyCode];
720563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
721563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[[[mainFrame webView] window] firstResponder] keyUp:event];
722563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
723563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
724563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)enableDOMUIEventLogging:(WebScriptObject *)node
725563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
726563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEnumerator *eventEnumerator = [webkitDomEventNames objectEnumerator];
727563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    id eventName;
728563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    while ((eventName = [eventEnumerator nextObject])) {
729563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [(id<DOMEventTarget>)node addEventListener:eventName listener:self useCapture:NO];
730563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
731563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
732563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
733563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)handleEvent:(DOMEvent *)event
734563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
735563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    DOMNode *target = [event target];
736563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
737563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    printf("event type:      %s\n", [[event type] UTF8String]);
738563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    printf("  target:        <%s>\n", [[[target nodeName] lowercaseString] UTF8String]);
739563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
740563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([event isKindOfClass:[DOMEvent class]]) {
741563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  eventPhase:    %d\n", [event eventPhase]);
742563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  bubbles:       %d\n", [event bubbles] ? 1 : 0);
743563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  cancelable:    %d\n", [event cancelable] ? 1 : 0);
744563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
745563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
746563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([event isKindOfClass:[DOMUIEvent class]]) {
747563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  detail:        %d\n", [(DOMUIEvent*)event detail]);
748563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
749563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        DOMAbstractView *view = [(DOMUIEvent*)event view];
750563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (view) {
751563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            printf("  view:          OK");
752563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            if ([view document])
753563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                printf(" (document: OK)");
754563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            printf("\n");
755563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
756563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
757563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
758563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([event isKindOfClass:[DOMKeyboardEvent class]]) {
759563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  keyIdentifier: %s\n", [[(DOMKeyboardEvent*)event keyIdentifier] UTF8String]);
760563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  keyLocation:   %d\n", [(DOMKeyboardEvent*)event keyLocation]);
761563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  modifier keys: c:%d s:%d a:%d m:%d\n",
762563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMKeyboardEvent*)event ctrlKey] ? 1 : 0,
763563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMKeyboardEvent*)event shiftKey] ? 1 : 0,
764563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMKeyboardEvent*)event altKey] ? 1 : 0,
765563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMKeyboardEvent*)event metaKey] ? 1 : 0);
766563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  keyCode:       %d\n", [(DOMKeyboardEvent*)event keyCode]);
767563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  charCode:      %d\n", [(DOMKeyboardEvent*)event charCode]);
768563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
769563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
770563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([event isKindOfClass:[DOMMouseEvent class]]) {
771563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  button:        %d\n", [(DOMMouseEvent*)event button]);
772563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  clientX:       %d\n", [(DOMMouseEvent*)event clientX]);
773563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  clientY:       %d\n", [(DOMMouseEvent*)event clientY]);
774563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  screenX:       %d\n", [(DOMMouseEvent*)event screenX]);
775563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  screenY:       %d\n", [(DOMMouseEvent*)event screenY]);
776563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  modifier keys: c:%d s:%d a:%d m:%d\n",
777563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMMouseEvent*)event ctrlKey] ? 1 : 0,
778563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMMouseEvent*)event shiftKey] ? 1 : 0,
779563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMMouseEvent*)event altKey] ? 1 : 0,
780563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMMouseEvent*)event metaKey] ? 1 : 0);
781563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        id relatedTarget = [(DOMMouseEvent*)event relatedTarget];
782563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (relatedTarget) {
783563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            printf("  relatedTarget: %s", [[[relatedTarget class] description] UTF8String]);
784563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            if ([relatedTarget isKindOfClass:[DOMNode class]])
785563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                printf(" (nodeName: %s)", [[(DOMNode*)relatedTarget nodeName] UTF8String]);
786563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            printf("\n");
787563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
788563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
789563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
790563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([event isKindOfClass:[DOMMutationEvent class]]) {
791563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  prevValue:     %s\n", [[(DOMMutationEvent*)event prevValue] UTF8String]);
792563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  newValue:      %s\n", [[(DOMMutationEvent*)event newValue] UTF8String]);
793563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  attrName:      %s\n", [[(DOMMutationEvent*)event attrName] UTF8String]);
794563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  attrChange:    %d\n", [(DOMMutationEvent*)event attrChange]);
795563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        DOMNode *relatedNode = [(DOMMutationEvent*)event relatedNode];
796563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (relatedNode) {
797563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            printf("  relatedNode:   %s (nodeName: %s)\n",
798563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                   [[[relatedNode class] description] UTF8String],
799563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                   [[relatedNode nodeName] UTF8String]);
800563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
801563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
802563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
803563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([event isKindOfClass:[DOMWheelEvent class]]) {
804563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  clientX:       %d\n", [(DOMWheelEvent*)event clientX]);
805563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  clientY:       %d\n", [(DOMWheelEvent*)event clientY]);
806563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  screenX:       %d\n", [(DOMWheelEvent*)event screenX]);
807563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  screenY:       %d\n", [(DOMWheelEvent*)event screenY]);
808563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  modifier keys: c:%d s:%d a:%d m:%d\n",
809563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMWheelEvent*)event ctrlKey] ? 1 : 0,
810563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMWheelEvent*)event shiftKey] ? 1 : 0,
811563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMWheelEvent*)event altKey] ? 1 : 0,
812563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark               [(DOMWheelEvent*)event metaKey] ? 1 : 0);
813563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  isHorizontal:  %d\n", [(DOMWheelEvent*)event isHorizontal] ? 1 : 0);
814563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        printf("  wheelDelta:    %d\n", [(DOMWheelEvent*)event wheelDelta]);
815563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
816563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
817563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
818563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// FIXME: It's not good to have a test hard-wired into this controller like this.
819563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// Instead we need to get testing framework based on the Objective-C bindings
820563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// to work well enough that we can test that way instead.
821563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)fireKeyboardEventsToElement:(WebScriptObject *)element {
822563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
8230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (![element isKindOfClass:[DOMHTMLElement class]])
824563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return;
825563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
826563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    DOMHTMLElement *target = (DOMHTMLElement*)element;
827563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    DOMDocument *document = [target ownerDocument];
828563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
829563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    // Keyboard Event 1
830563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
831563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    DOMEvent *domEvent = [document createEvent:@"KeyboardEvent"];
832563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keydown"
833563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                         canBubble:YES
834563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        cancelable:YES
835563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                              view:[document defaultView]
836563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                     keyIdentifier:@"U+000041"
837563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                       keyLocation:0
838563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                           ctrlKey:YES
839563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                            altKey:NO
840563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                          shiftKey:NO
841563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                           metaKey:NO];
842563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [target dispatchEvent:domEvent];
843563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
844563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    // Keyboard Event 2
845563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
846563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    domEvent = [document createEvent:@"KeyboardEvent"];
847563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keypress"
848563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                         canBubble:YES
849563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        cancelable:YES
850563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                              view:[document defaultView]
851563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                     keyIdentifier:@"U+000045"
852563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                       keyLocation:1
853563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                           ctrlKey:NO
854563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                            altKey:YES
855563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                          shiftKey:NO
856563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                           metaKey:NO];
857563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [target dispatchEvent:domEvent];
858563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
859563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    // Keyboard Event 3
860563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
861563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    domEvent = [document createEvent:@"KeyboardEvent"];
862563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keyup"
863563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                         canBubble:YES
864563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                        cancelable:YES
865563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                              view:[document defaultView]
866563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                     keyIdentifier:@"U+000056"
867563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                       keyLocation:0
868563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                           ctrlKey:NO
869563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                            altKey:NO
870563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                          shiftKey:NO
871563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                                           metaKey:NO];
872563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [target dispatchEvent:domEvent];
873563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
874563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
875563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
876563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark@end
877