Fix for http://bugzilla.opendarwin.org/show_bug.cgi?id=7223
[WebKit-https.git] / WebKitTools / DumpRenderTree / EventSendingController.m
1 /*
2  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "EventSendingController.h"
30 #import "DumpRenderTree.h"
31
32 #import <Carbon/Carbon.h>                           // for GetCurrentEventTime()
33 #import <WebKit/WebKit.h>
34
35 NSPoint lastMousePosition;
36
37 @implementation EventSendingController
38
39 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
40 {
41     if (aSelector == @selector(mouseDown)
42             || aSelector == @selector(mouseUp)
43             || aSelector == @selector(mouseClick)
44             || aSelector == @selector(mouseMoveToX:Y:)
45             || aSelector == @selector(leapForward:)
46             || aSelector == @selector(keyDown:withModifiers:))
47         return NO;
48     return YES;
49 }
50
51 + (NSString *)webScriptNameForSelector:(SEL)aSelector
52 {
53     if (aSelector == @selector(mouseMoveToX:Y:))
54         return @"mouseMoveTo";
55     if (aSelector == @selector(leapForward:))
56         return @"leapForward";
57     if (aSelector == @selector(keyDown:withModifiers:))
58         return @"keyDown";
59     return nil;
60 }
61
62 - (id)init
63 {
64     lastMousePosition = NSMakePoint(0, 0);
65     down = NO;
66     clickCount = 0;
67     lastClick = 0;
68     return self;
69 }
70
71 - (double)currentEventTime
72 {
73     return GetCurrentEventTime() + timeOffset;
74 }
75
76 - (void)leapForward:(int)milliseconds
77 {
78     timeOffset += milliseconds / 1000.0;
79 }
80
81 - (void)mouseDown
82 {
83     [[[frame frameView] documentView] layout];
84     if ([self currentEventTime] - lastClick >= 1)
85         clickCount = 1;
86     else
87         clickCount++;
88     NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseDown 
89                                         location:lastMousePosition 
90                                    modifierFlags:nil 
91                                        timestamp:[self currentEventTime]
92                                     windowNumber:[[[frame webView] window] windowNumber] 
93                                          context:[NSGraphicsContext currentContext] 
94                                      eventNumber:++eventNumber 
95                                       clickCount:clickCount 
96                                         pressure:nil];
97
98     NSView *subView = [[frame webView] hitTest:[event locationInWindow]];
99     if (subView) {
100         [subView mouseDown:event];
101         down = YES;
102     }
103 }
104
105 - (void)mouseUp
106 {
107     [[[frame frameView] documentView] layout];
108     NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseUp 
109                                         location:lastMousePosition 
110                                    modifierFlags:nil 
111                                        timestamp:[self currentEventTime]
112                                     windowNumber:[[[frame webView] window] windowNumber] 
113                                          context:[NSGraphicsContext currentContext] 
114                                      eventNumber:++eventNumber 
115                                       clickCount:clickCount 
116                                         pressure:nil];
117
118     NSView *subView = [[frame webView] hitTest:[event locationInWindow]];
119     if (subView) {
120         [subView mouseUp:event];
121         down = NO;
122         lastClick = [event timestamp];
123         if (draggingInfo) {
124             WebView *webView = [frame webView];
125             
126             NSDragOperation dragOperation = [webView draggingUpdated:draggingInfo];
127             
128             [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] endedAt:lastMousePosition operation:dragOperation];
129             if (dragOperation != NSDragOperationNone)
130                 [webView performDragOperation:draggingInfo];
131             [draggingInfo release];
132             draggingInfo = nil;
133         }
134     }
135 }
136
137 - (void)mouseMoveToX:(int)x Y:(int)y
138 {
139     lastMousePosition = NSMakePoint(x, [[frame webView] frame].size.height - y);
140     NSEvent *event = [NSEvent mouseEventWithType:(down ? NSLeftMouseDragged : NSMouseMoved) 
141                                         location:lastMousePosition 
142                                    modifierFlags:nil 
143                                        timestamp:[self currentEventTime]
144                                     windowNumber:[[[frame webView] window] windowNumber] 
145                                          context:[NSGraphicsContext currentContext] 
146                                      eventNumber:++eventNumber 
147                                       clickCount:(down ? clickCount : 0) 
148                                         pressure:nil];
149
150     NSView *subView = [[frame webView] hitTest:[event locationInWindow]];
151     if (subView) {
152         if (down) {
153             [subView mouseDragged:event];
154             [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] movedTo:lastMousePosition];
155             [[frame webView] draggingUpdated:draggingInfo];
156         }
157         else
158             [subView mouseMoved:event];
159     }
160 }
161
162 - (void)mouseClick
163 {
164     [[[frame frameView] documentView] layout];
165     if ([self currentEventTime] - lastClick >= 1)
166         clickCount = 1;
167     else
168         clickCount++;
169     NSEvent *mouseDownEvent = [NSEvent mouseEventWithType:NSLeftMouseDown 
170                                         location:lastMousePosition 
171                                    modifierFlags:nil 
172                                        timestamp:[self currentEventTime]
173                                     windowNumber:[[[frame webView] window] windowNumber] 
174                                          context:[NSGraphicsContext currentContext] 
175                                      eventNumber:++eventNumber 
176                                       clickCount:clickCount 
177                                         pressure:nil];
178
179     NSView *subView = [[frame webView] hitTest:[mouseDownEvent locationInWindow]];
180     if (subView) {
181         [self leapForward:1];
182         NSEvent *mouseUpEvent = [NSEvent mouseEventWithType:NSLeftMouseUp
183                                                    location:lastMousePosition
184                                               modifierFlags:nil
185                                                   timestamp:[self currentEventTime]
186                                                windowNumber:[[[frame webView] window] windowNumber]
187                                                     context:[NSGraphicsContext currentContext]
188                                                 eventNumber:++eventNumber
189                                                  clickCount:clickCount
190                                                    pressure:nil];
191         [NSApp postEvent:mouseUpEvent atStart:NO];
192         [subView mouseDown:mouseDownEvent];
193         lastClick = [mouseUpEvent timestamp];
194     }
195 }
196
197 - (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers
198 {
199     NSString *modifier = nil;
200     int mask = 0;
201     
202     for (unsigned i = 0; modifiers && [modifiers webScriptValueAtIndex:i]; i++) {
203         modifier = (NSString *)[modifiers webScriptValueAtIndex:i];
204         if ([modifier isEqual:@"ctrlKey"])
205             mask |= NSControlKeyMask;
206         else if ([modifier isEqual:@"shiftKey"])
207             mask |= NSShiftKeyMask;
208         else if ([modifier isEqual:@"altKey"])
209             mask |= NSAlternateKeyMask;
210         else if ([modifier isEqual:@"metaKey"])
211             mask |= NSCommandKeyMask;
212         else
213             break;
214     }
215
216     [[[frame frameView] documentView] layout];
217     
218     NSEvent *event = [NSEvent keyEventWithType:NSKeyDown
219                         location:NSMakePoint(5, 5)
220                         modifierFlags:mask
221                         timestamp:[self currentEventTime]
222                         windowNumber:[[[frame webView] window] windowNumber]
223                         context:[NSGraphicsContext currentContext]
224                         characters:character
225                         charactersIgnoringModifiers:character
226                         isARepeat:NO
227                         keyCode:0];
228     
229
230     NSView *subView = [[frame webView] hitTest:[event locationInWindow]];
231     if (subView) {
232         [subView keyDown:event];
233         down = YES;
234     }
235 }
236
237 @end