webengine/osswebengine/WebKitTools/DumpRenderTree/mac/EventSendingController.mm
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
       
     3  * Copyright (C) 2006 Jonas Witt <jonas.witt@gmail.com>
       
     4  * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
       
     5  * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
       
     6  *
       
     7  * Redistribution and use in source and binary forms, with or without
       
     8  * modification, are permitted provided that the following conditions
       
     9  * are met:
       
    10  *
       
    11  * 1.  Redistributions of source code must retain the above copyright
       
    12  *     notice, this list of conditions and the following disclaimer. 
       
    13  * 2.  Redistributions in binary form must reproduce the above copyright
       
    14  *     notice, this list of conditions and the following disclaimer in the
       
    15  *     documentation and/or other materials provided with the distribution. 
       
    16  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
       
    17  *     its contributors may be used to endorse or promote products derived
       
    18  *     from this software without specific prior written permission. 
       
    19  *
       
    20  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    23  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    27  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    30  */
       
    31 
       
    32 #import "EventSendingController.h"
       
    33 
       
    34 #import "DumpRenderTree.h"
       
    35 #import "DumpRenderTreeDraggingInfo.h"
       
    36 
       
    37 #import <Carbon/Carbon.h>                           // for GetCurrentEventTime()
       
    38 #import <WebKit/WebKit.h>
       
    39 #import <WebKit/DOMPrivate.h>
       
    40 
       
    41 extern "C" void _NSNewKillRingSequence();
       
    42 
       
    43 NSPoint lastMousePosition;
       
    44 NSArray *webkitDomEventNames;
       
    45 NSMutableArray *savedMouseEvents; // mouse events sent between mouseDown and mouseUp are stored here, and then executed at once.
       
    46 BOOL replayingSavedEvents;
       
    47 
       
    48 @implementation EventSendingController
       
    49 
       
    50 + (void)initialize
       
    51 {
       
    52     webkitDomEventNames = [[NSArray alloc] initWithObjects:
       
    53         @"abort",
       
    54         @"beforecopy",
       
    55         @"beforecut",
       
    56         @"beforepaste",
       
    57         @"blur",
       
    58         @"change",
       
    59         @"click",
       
    60         @"contextmenu",
       
    61         @"copy",
       
    62         @"cut",
       
    63         @"dblclick",
       
    64         @"drag",
       
    65         @"dragend",
       
    66         @"dragenter",
       
    67         @"dragleave",
       
    68         @"dragover",
       
    69         @"dragstart",
       
    70         @"drop",
       
    71         @"error",
       
    72         @"focus",
       
    73         @"input",
       
    74         @"keydown",
       
    75         @"keypress",
       
    76         @"keyup",
       
    77         @"load",
       
    78         @"mousedown",
       
    79         @"mousemove",
       
    80         @"mouseout",
       
    81         @"mouseover",
       
    82         @"mouseup",
       
    83         @"mousewheel",
       
    84         @"beforeunload",
       
    85         @"paste",
       
    86         @"readystatechange",
       
    87         @"reset",
       
    88         @"resize", 
       
    89         @"scroll", 
       
    90         @"search",
       
    91         @"select",
       
    92         @"selectstart",
       
    93         @"submit", 
       
    94         @"textInput", 
       
    95         @"textzoomin",
       
    96         @"textzoomout",
       
    97         @"unload",
       
    98         @"zoom",
       
    99         nil];
       
   100 }
       
   101 
       
   102 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
       
   103 {
       
   104     if (aSelector == @selector(mouseDown)
       
   105             || aSelector == @selector(mouseUp)
       
   106             || aSelector == @selector(contextClick)
       
   107             || aSelector == @selector(mouseMoveToX:Y:)
       
   108             || aSelector == @selector(leapForward:)
       
   109             || aSelector == @selector(keyDown:withModifiers:)
       
   110             || aSelector == @selector(enableDOMUIEventLogging:)
       
   111             || aSelector == @selector(fireKeyboardEventsToElement:)
       
   112             || aSelector == @selector(clearKillRing)
       
   113             || aSelector == @selector(textZoomIn)
       
   114             || aSelector == @selector(textZoomOut))
       
   115         return NO;
       
   116     return YES;
       
   117 }
       
   118 
       
   119 + (BOOL)isKeyExcludedFromWebScript:(const char*)name
       
   120 {
       
   121     if (strcmp(name, "dragMode") == 0)
       
   122         return NO;
       
   123     return YES;
       
   124 }
       
   125 
       
   126 + (NSString *)webScriptNameForSelector:(SEL)aSelector
       
   127 {
       
   128     if (aSelector == @selector(mouseMoveToX:Y:))
       
   129         return @"mouseMoveTo";
       
   130     if (aSelector == @selector(leapForward:))
       
   131         return @"leapForward";
       
   132     if (aSelector == @selector(keyDown:withModifiers:))
       
   133         return @"keyDown";
       
   134     if (aSelector == @selector(enableDOMUIEventLogging:))
       
   135         return @"enableDOMUIEventLogging";
       
   136     if (aSelector == @selector(fireKeyboardEventsToElement:))
       
   137         return @"fireKeyboardEventsToElement";
       
   138     if (aSelector == @selector(setDragMode:))
       
   139         return @"setDragMode";
       
   140     return nil;
       
   141 }
       
   142 
       
   143 - (id)init
       
   144 {
       
   145     self = [super init];
       
   146     if (self)
       
   147         dragMode = YES;
       
   148     return self;
       
   149 }
       
   150 
       
   151 - (void)dealloc
       
   152 {
       
   153     [super dealloc];
       
   154 }
       
   155 
       
   156 - (double)currentEventTime
       
   157 {
       
   158     return GetCurrentEventTime() + timeOffset;
       
   159 }
       
   160 
       
   161 - (void)leapForward:(int)milliseconds
       
   162 {
       
   163     if (dragMode && down && !replayingSavedEvents) {
       
   164         NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(leapForward:)]];
       
   165         [invocation setTarget:self];
       
   166         [invocation setSelector:@selector(leapForward:)];
       
   167         [invocation setArgument:&milliseconds atIndex:2];
       
   168         
       
   169         [EventSendingController saveEvent:invocation];
       
   170         
       
   171         return;
       
   172     }
       
   173 
       
   174     timeOffset += milliseconds / 1000.0;
       
   175 }
       
   176 
       
   177 - (void)clearKillRing
       
   178 {
       
   179     _NSNewKillRingSequence();
       
   180 }
       
   181 
       
   182 - (void)mouseDown
       
   183 {
       
   184     [[[mainFrame frameView] documentView] layout];
       
   185     if ([self currentEventTime] - lastClick >= 1)
       
   186         clickCount = 1;
       
   187     else
       
   188         clickCount++;
       
   189     NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseDown 
       
   190                                         location:lastMousePosition 
       
   191                                    modifierFlags:0 
       
   192                                        timestamp:[self currentEventTime]
       
   193                                     windowNumber:[[[mainFrame webView] window] windowNumber] 
       
   194                                          context:[NSGraphicsContext currentContext] 
       
   195                                      eventNumber:++eventNumber 
       
   196                                       clickCount:clickCount 
       
   197                                         pressure:0.0];
       
   198 
       
   199     NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]];
       
   200     if (subView) {
       
   201         [subView mouseDown:event];
       
   202         down = YES;
       
   203     }
       
   204 }
       
   205 
       
   206 - (void)textZoomIn
       
   207 {
       
   208     [[mainFrame webView] makeTextLarger:self];
       
   209 }
       
   210 
       
   211 - (void)textZoomOut
       
   212 {
       
   213     [[mainFrame webView] makeTextSmaller:self];
       
   214 }
       
   215 
       
   216 - (void)mouseUp
       
   217 {
       
   218     if (dragMode && !replayingSavedEvents) {
       
   219         NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp)]];
       
   220         [invocation setTarget:self];
       
   221         [invocation setSelector:@selector(mouseUp)];
       
   222         
       
   223         [EventSendingController saveEvent:invocation];
       
   224         [EventSendingController replaySavedEvents];
       
   225 
       
   226         return;
       
   227     }
       
   228 
       
   229     [[[mainFrame frameView] documentView] layout];
       
   230     NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseUp 
       
   231                                         location:lastMousePosition 
       
   232                                    modifierFlags:0 
       
   233                                        timestamp:[self currentEventTime]
       
   234                                     windowNumber:[[[mainFrame webView] window] windowNumber] 
       
   235                                          context:[NSGraphicsContext currentContext] 
       
   236                                      eventNumber:++eventNumber 
       
   237                                       clickCount:clickCount 
       
   238                                         pressure:0.0];
       
   239 
       
   240     NSView *targetView = [[mainFrame webView] hitTest:[event locationInWindow]];
       
   241     // FIXME: Silly hack to teach DRT to respect capturing mouse events outside the WebView.
       
   242     // The right solution is just to use NSApplication's built-in event sending methods, 
       
   243     // instead of rolling our own algorithm for selecting an event target.
       
   244     targetView = targetView ? targetView : [[mainFrame frameView] documentView];
       
   245     assert(targetView);
       
   246     [targetView mouseUp:event];
       
   247     down = NO;
       
   248     lastClick = [event timestamp];
       
   249     if (draggingInfo) {
       
   250         WebView *webView = [mainFrame webView];
       
   251         
       
   252         NSDragOperation dragOperation = [webView draggingUpdated:draggingInfo];
       
   253         
       
   254         if (dragOperation != NSDragOperationNone)
       
   255             [webView performDragOperation:draggingInfo];
       
   256         else
       
   257             [webView draggingExited:draggingInfo];
       
   258         [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] endedAt:lastMousePosition operation:dragOperation];
       
   259         [draggingInfo release];
       
   260         draggingInfo = nil;
       
   261     }
       
   262 }
       
   263 
       
   264 - (void)mouseMoveToX:(int)x Y:(int)y
       
   265 {
       
   266     if (dragMode && down && !replayingSavedEvents) {
       
   267         NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseMoveToX:Y:)]];
       
   268         [invocation setTarget:self];
       
   269         [invocation setSelector:@selector(mouseMoveToX:Y:)];
       
   270         [invocation setArgument:&x atIndex:2];
       
   271         [invocation setArgument:&y atIndex:3];
       
   272         
       
   273         [EventSendingController saveEvent:invocation];
       
   274         
       
   275         return;
       
   276     }
       
   277 
       
   278     NSView *view = [mainFrame webView];
       
   279     lastMousePosition = [view convertPoint:NSMakePoint(x, [view frame].size.height - y) toView:nil];
       
   280     NSEvent *event = [NSEvent mouseEventWithType:(down ? NSLeftMouseDragged : NSMouseMoved) 
       
   281                                         location:lastMousePosition 
       
   282                                    modifierFlags:0 
       
   283                                        timestamp:[self currentEventTime]
       
   284                                     windowNumber:[[view window] windowNumber] 
       
   285                                          context:[NSGraphicsContext currentContext] 
       
   286                                      eventNumber:++eventNumber 
       
   287                                       clickCount:(down ? clickCount : 0) 
       
   288                                         pressure:0.0];
       
   289 
       
   290     NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]];
       
   291     if (subView) {
       
   292         if (down) {
       
   293             [subView mouseDragged:event];
       
   294             if (draggingInfo) {
       
   295                 [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] movedTo:lastMousePosition];
       
   296                 [[mainFrame webView] draggingUpdated:draggingInfo];
       
   297             }
       
   298         } else
       
   299             [subView mouseMoved:event];
       
   300     }
       
   301 }
       
   302 
       
   303 - (void)contextClick
       
   304 {
       
   305     [[[mainFrame frameView] documentView] layout];
       
   306     if ([self currentEventTime] - lastClick >= 1)
       
   307         clickCount = 1;
       
   308     else
       
   309         clickCount++;
       
   310     NSEvent *event = [NSEvent mouseEventWithType:NSRightMouseDown 
       
   311                                         location:lastMousePosition 
       
   312                                    modifierFlags:0 
       
   313                                        timestamp:[self currentEventTime]
       
   314                                     windowNumber:[[[mainFrame webView] window] windowNumber] 
       
   315                                          context:[NSGraphicsContext currentContext] 
       
   316                                      eventNumber:++eventNumber 
       
   317                                       clickCount:clickCount 
       
   318                                         pressure:0.0];
       
   319 
       
   320     NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]];
       
   321     if (subView)
       
   322         [subView menuForEvent:event];
       
   323 }
       
   324 
       
   325 + (void)saveEvent:(NSInvocation *)event
       
   326 {
       
   327     if (!savedMouseEvents)
       
   328         savedMouseEvents = [[NSMutableArray alloc] init];
       
   329     [savedMouseEvents addObject:event];
       
   330 }
       
   331 
       
   332 + (void)replaySavedEvents
       
   333 {
       
   334     replayingSavedEvents = YES;
       
   335     while ([savedMouseEvents count]) {
       
   336         // if a drag is initiated, the remaining saved events will be dispatched from our dragging delegate
       
   337         NSInvocation *invocation = [[[savedMouseEvents objectAtIndex:0] retain] autorelease];
       
   338         [savedMouseEvents removeObjectAtIndex:0];
       
   339         [invocation invoke];
       
   340     }
       
   341     replayingSavedEvents = NO;
       
   342 }
       
   343 
       
   344 + (void)clearSavedEvents
       
   345 {
       
   346     [savedMouseEvents release];
       
   347     savedMouseEvents = nil;
       
   348 }
       
   349 
       
   350 - (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers
       
   351 {
       
   352     NSString *modifier = nil;
       
   353     int mask = 0;
       
   354     
       
   355     if ([modifiers isKindOfClass:[WebScriptObject class]])
       
   356         for (unsigned i = 0; [[modifiers webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) {
       
   357             modifier = (NSString *)[modifiers webScriptValueAtIndex:i];
       
   358             if ([modifier isEqual:@"ctrlKey"])
       
   359                 mask |= NSControlKeyMask;
       
   360             else if ([modifier isEqual:@"shiftKey"])
       
   361                 mask |= NSShiftKeyMask;
       
   362             else if ([modifier isEqual:@"altKey"])
       
   363                 mask |= NSAlternateKeyMask;
       
   364             else if ([modifier isEqual:@"metaKey"])
       
   365                 mask |= NSCommandKeyMask;
       
   366             else
       
   367                 break;
       
   368         }
       
   369 
       
   370     [[[mainFrame frameView] documentView] layout];
       
   371     
       
   372     NSEvent *event = [NSEvent keyEventWithType:NSKeyDown
       
   373                         location:NSMakePoint(5, 5)
       
   374                         modifierFlags:mask
       
   375                         timestamp:[self currentEventTime]
       
   376                         windowNumber:[[[mainFrame webView] window] windowNumber]
       
   377                         context:[NSGraphicsContext currentContext]
       
   378                         characters:character
       
   379                         charactersIgnoringModifiers:character
       
   380                         isARepeat:NO
       
   381                         keyCode:0];
       
   382     
       
   383 
       
   384     NSResponder *firstResponder = [[[mainFrame webView] window] firstResponder];
       
   385     [firstResponder keyDown:event];
       
   386 }
       
   387 
       
   388 - (void)enableDOMUIEventLogging:(WebScriptObject *)node
       
   389 {
       
   390     NSEnumerator *eventEnumerator = [webkitDomEventNames objectEnumerator];
       
   391     id eventName;
       
   392     while ((eventName = [eventEnumerator nextObject])) {
       
   393         [(id<DOMEventTarget>)node addEventListener:eventName listener:self useCapture:NO];
       
   394     }
       
   395 }
       
   396 
       
   397 - (void)handleEvent:(DOMEvent *)event
       
   398 {
       
   399     DOMNode *target = [event target];
       
   400 
       
   401     printf("event type:      %s\n", [[event type] UTF8String]);
       
   402     printf("  target:        <%s>\n", [[[target nodeName] lowercaseString] UTF8String]);
       
   403     
       
   404     if ([event isKindOfClass:[DOMEvent class]]) {
       
   405         printf("  eventPhase:    %d\n", [event eventPhase]);
       
   406         printf("  bubbles:       %d\n", [event bubbles] ? 1 : 0);
       
   407         printf("  cancelable:    %d\n", [event cancelable] ? 1 : 0);
       
   408     }
       
   409     
       
   410     if ([event isKindOfClass:[DOMUIEvent class]]) {
       
   411         printf("  detail:        %d\n", [(DOMUIEvent*)event detail]);
       
   412         
       
   413         DOMAbstractView *view = [(DOMUIEvent*)event view];
       
   414         if (view) {
       
   415             printf("  view:          OK");            
       
   416             if ([view document])
       
   417                 printf(" (document: OK)");
       
   418             printf("\n");
       
   419         }
       
   420     }
       
   421     
       
   422     if ([event isKindOfClass:[DOMKeyboardEvent class]]) {
       
   423         printf("  keyIdentifier: %s\n", [[(DOMKeyboardEvent*)event keyIdentifier] UTF8String]);
       
   424         printf("  keyLocation:   %d\n", [(DOMKeyboardEvent*)event keyLocation]);
       
   425         printf("  modifier keys: c:%d s:%d a:%d m:%d\n", 
       
   426                [(DOMKeyboardEvent*)event ctrlKey] ? 1 : 0, 
       
   427                [(DOMKeyboardEvent*)event shiftKey] ? 1 : 0, 
       
   428                [(DOMKeyboardEvent*)event altKey] ? 1 : 0, 
       
   429                [(DOMKeyboardEvent*)event metaKey] ? 1 : 0);
       
   430         printf("  keyCode:       %d\n", [(DOMKeyboardEvent*)event keyCode]);
       
   431         printf("  charCode:      %d\n", [(DOMKeyboardEvent*)event charCode]);
       
   432     }
       
   433     
       
   434     if ([event isKindOfClass:[DOMMouseEvent class]]) {
       
   435         printf("  button:        %d\n", [(DOMMouseEvent*)event button]);
       
   436         printf("  clientX:       %d\n", [(DOMMouseEvent*)event clientX]);
       
   437         printf("  clientY:       %d\n", [(DOMMouseEvent*)event clientY]);
       
   438         printf("  screenX:       %d\n", [(DOMMouseEvent*)event screenX]);
       
   439         printf("  screenY:       %d\n", [(DOMMouseEvent*)event screenY]);
       
   440         printf("  modifier keys: c:%d s:%d a:%d m:%d\n", 
       
   441                [(DOMMouseEvent*)event ctrlKey] ? 1 : 0, 
       
   442                [(DOMMouseEvent*)event shiftKey] ? 1 : 0, 
       
   443                [(DOMMouseEvent*)event altKey] ? 1 : 0, 
       
   444                [(DOMMouseEvent*)event metaKey] ? 1 : 0);
       
   445         id relatedTarget = [(DOMMouseEvent*)event relatedTarget];
       
   446         if (relatedTarget) {
       
   447             printf("  relatedTarget: %s", [[[relatedTarget class] description] UTF8String]);
       
   448             if ([relatedTarget isKindOfClass:[DOMNode class]])
       
   449                 printf(" (nodeName: %s)", [[(DOMNode*)relatedTarget nodeName] UTF8String]);
       
   450             printf("\n");
       
   451         }
       
   452     }
       
   453     
       
   454     if ([event isKindOfClass:[DOMMutationEvent class]]) {
       
   455         printf("  prevValue:     %s\n", [[(DOMMutationEvent*)event prevValue] UTF8String]);
       
   456         printf("  newValue:      %s\n", [[(DOMMutationEvent*)event newValue] UTF8String]);
       
   457         printf("  attrName:      %s\n", [[(DOMMutationEvent*)event attrName] UTF8String]);
       
   458         printf("  attrChange:    %d\n", [(DOMMutationEvent*)event attrChange]);
       
   459         DOMNode *relatedNode = [(DOMMutationEvent*)event relatedNode];
       
   460         if (relatedNode) {
       
   461             printf("  relatedNode:   %s (nodeName: %s)\n", 
       
   462                    [[[relatedNode class] description] UTF8String],
       
   463                    [[relatedNode nodeName] UTF8String]);
       
   464         }
       
   465     }
       
   466     
       
   467     if ([event isKindOfClass:[DOMWheelEvent class]]) {
       
   468         printf("  clientX:       %d\n", [(DOMWheelEvent*)event clientX]);
       
   469         printf("  clientY:       %d\n", [(DOMWheelEvent*)event clientY]);
       
   470         printf("  screenX:       %d\n", [(DOMWheelEvent*)event screenX]);
       
   471         printf("  screenY:       %d\n", [(DOMWheelEvent*)event screenY]);
       
   472         printf("  modifier keys: c:%d s:%d a:%d m:%d\n", 
       
   473                [(DOMWheelEvent*)event ctrlKey] ? 1 : 0, 
       
   474                [(DOMWheelEvent*)event shiftKey] ? 1 : 0, 
       
   475                [(DOMWheelEvent*)event altKey] ? 1 : 0, 
       
   476                [(DOMWheelEvent*)event metaKey] ? 1 : 0);
       
   477         printf("  isHorizontal:  %d\n", [(DOMWheelEvent*)event isHorizontal] ? 1 : 0);
       
   478         printf("  wheelDelta:    %d\n", [(DOMWheelEvent*)event wheelDelta]);
       
   479     }
       
   480 }
       
   481 
       
   482 // FIXME: It's not good to have a test hard-wired into this controller like this.
       
   483 // Instead we need to get testing framework based on the Objective-C bindings
       
   484 // to work well enough that we can test that way instead.
       
   485 - (void)fireKeyboardEventsToElement:(WebScriptObject *)element {
       
   486     
       
   487     if (![element isKindOfClass:[DOMHTMLElement class]]) {
       
   488         return;
       
   489     }
       
   490     
       
   491     DOMHTMLElement *target = (DOMHTMLElement*)element;
       
   492     DOMDocument *document = [target ownerDocument];
       
   493     
       
   494     // Keyboard Event 1
       
   495     
       
   496     DOMEvent *domEvent = [document createEvent:@"KeyboardEvent"];
       
   497     [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keydown" 
       
   498                                          canBubble:YES
       
   499                                         cancelable:YES
       
   500                                               view:[document defaultView]
       
   501                                      keyIdentifier:@"U+000041" 
       
   502                                        keyLocation:0
       
   503                                            ctrlKey:YES
       
   504                                             altKey:NO
       
   505                                           shiftKey:NO
       
   506                                            metaKey:NO];
       
   507     [target dispatchEvent:domEvent];  
       
   508         
       
   509     // Keyboard Event 2
       
   510     
       
   511     domEvent = [document createEvent:@"KeyboardEvent"];
       
   512     [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keypress" 
       
   513                                          canBubble:YES
       
   514                                         cancelable:YES
       
   515                                               view:[document defaultView]
       
   516                                      keyIdentifier:@"U+000045" 
       
   517                                        keyLocation:1
       
   518                                            ctrlKey:NO
       
   519                                             altKey:YES
       
   520                                           shiftKey:NO
       
   521                                            metaKey:NO];
       
   522     [target dispatchEvent:domEvent];    
       
   523     
       
   524     // Keyboard Event 3
       
   525     
       
   526     domEvent = [document createEvent:@"KeyboardEvent"];
       
   527     [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keyup" 
       
   528                                          canBubble:YES
       
   529                                         cancelable:YES
       
   530                                               view:[document defaultView]
       
   531                                      keyIdentifier:@"U+000056" 
       
   532                                        keyLocation:0
       
   533                                            ctrlKey:NO
       
   534                                             altKey:NO
       
   535                                           shiftKey:NO
       
   536                                            metaKey:NO];
       
   537     [target dispatchEvent:domEvent];   
       
   538     
       
   539 }
       
   540 
       
   541 @end