Reviewed by Mark (age 21).
[WebKit-https.git] / WebKit / WebView / WebHTMLView.mm
index a865463..0bed84c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
- *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2006, 2007 Graham Dennis (graham.dennis@gmail.com)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #import <WebCore/EventHandler.h>
 #import <WebCore/EventNames.h>
 #import <WebCore/ExceptionHandlers.h>
+#import <WebCore/DragController.h>
 #import <WebCore/FloatRect.h>
 #import <WebCore/FocusController.h>
-#import <WebCore/FrameMac.h>
+#import <WebCore/Frame.h>
 #import <WebCore/HitTestResult.h>
 #import <WebCore/KeyboardEvent.h>
 #import <WebCore/MimeTypeRegistry.h>
 #import <WebCore/Page.h>
+#import <WebCore/PlatformKeyboardEvent.h>
+#import <WebCore/PlatformMouseEvent.h>
 #import <WebCore/Range.h>
 #import <WebCore/SelectionController.h>
+#import <WebCore/WebCoreObjCExtras.h>
 #import <WebCore/WebCoreTextRenderer.h>
-#import <WebCore/WebDataProtocol.h>
 #import <WebKit/DOM.h>
 #import <WebKit/DOMExtensions.h>
 #import <WebKit/DOMPrivate.h>
@@ -97,6 +100,9 @@ using namespace WebCore;
 
 extern "C" {
 
+// Fake URL scheme.
+static NSString *WebDataProtocolScheme = @"webkit-fake-url";
+
 // need to declare this because AppKit does not make it available as API or SPI
 extern NSString *NSMarkedClauseSegmentAttributeName; 
 extern NSString *NSTextInputReplacementRangeAttributeName; 
@@ -128,6 +134,7 @@ void _NSResetKillRingOperationFlag(void);
 
 @interface NSWindow (AppKitSecretsIKnowAbout)
 - (id)_newFirstResponderAfterResigning;
+- (void)_setForceActiveControls:(BOOL)flag;
 @end
 
 @interface NSAttributedString (AppKitSecretsIKnowAbout)
@@ -139,6 +146,10 @@ void _NSResetKillRingOperationFlag(void);
 - (void)learnWord:(NSString *)word;
 @end
 
+// Used to avoid linking with ApplicationServices framework for _DCMDictionaryServiceWindowShow
+extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFrameworkName,
+    NSString *inFrameworkName, const char *inFuncName, const struct mach_header **);
+
 // By imaging to a width a little wider than the available pixels,
 // thin pages will be scaled down a little, matching the way they
 // print in IE and Camino. This lets them use fewer sheets than they
@@ -165,6 +176,7 @@ void _NSResetKillRingOperationFlag(void);
 #define AUTOSCROLL_INTERVAL             0.1f
 
 #define DRAG_LABEL_BORDER_X             4.0f
+//Keep border_y in synch with DragController::LinkDragBorderInset
 #define DRAG_LABEL_BORDER_Y             2.0f
 #define DRAG_LABEL_RADIUS               5.0f
 #define DRAG_LABEL_BORDER_Y_OFFSET              2.0f
@@ -186,14 +198,12 @@ void _NSResetKillRingOperationFlag(void);
 #define STANDARD_BOLD_WEIGHT 10
 
 // if YES, do the standard NSView hit test (which can't give the right result when HTML overlaps a view)
-static BOOL forceNSViewHitTest = NO;
+static BOOL forceNSViewHitTest;
 
 // if YES, do the "top WebHTMLView" it test (which we'd like to do all the time but can't because of Java requirements [see bug 4349721])
-static BOOL forceWebHTMLViewHitTest = NO;
+static BOOL forceWebHTMLViewHitTest;
 
-// Used to avoid linking with ApplicationServices framework for _DCMDictionaryServiceWindowShow
-extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFrameworkName,
-    NSString *inFrameworkName, const char *inFuncName, const struct mach_header **);
+static WebHTMLView *lastHitView;
 
 @interface WebHTMLView (WebTextSizing) <_WebDocumentTextSizing>
 @end
@@ -225,7 +235,8 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
 
 @interface WebHTMLView (WebNSTextInputSupport) <NSTextInput>
 - (void)_updateSelectionForInputManager;
-- (void)_insertText:(NSString *)text selectInsertedText:(BOOL)selectText;
+- (BOOL)_insertNewlineWithEvent:(KeyboardEvent*)event isLineBreak:(BOOL)isLineBreak;
+- (BOOL)_insertTabWithEvent:(KeyboardEvent*)event isBackTab:(BOOL)isBackTab;
 @end
 
 @interface WebHTMLView (WebEditingStyleSupport)
@@ -262,6 +273,11 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
 - (void)_reflectSelection;
 @end
 
+struct WebHTMLViewInterpretKeyEventsParameters {
+    KeyboardEvent* event;
+    BOOL eventWasHandled;
+};
+
 @implementation WebHTMLViewPrivate
 
 - (void)dealloc
@@ -271,7 +287,6 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
     
     [mouseDownEvent release];
     [keyDownEvent release];
-    [draggingImageURL release];
     [pluginController release];
     [toolTip release];
     [compController release];
@@ -286,7 +301,6 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
 {
     [mouseDownEvent release];
     [keyDownEvent release];
-    [draggingImageURL release];
     [pluginController release];
     [toolTip release];
     [compController release];
@@ -296,7 +310,6 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
 
     mouseDownEvent = nil;
     keyDownEvent = nil;
-    draggingImageURL = nil;
     pluginController = nil;
     toolTip = nil;
     compController = nil;
@@ -369,7 +382,8 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
                 [resource release];
             }
         } else {
-            // Non-image file types
+            // Non-image file types; _web_userVisibleString is appropriate here because this will
+            // be pasted as visible text.
             NSString *url = [[[NSURL fileURLWithPath:path] _webkit_canonicalize] _web_userVisibleString];
             [domNodes addObject:[[[self _frame] DOMDocument] createTextNode: url]];
         }
@@ -397,10 +411,22 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
             @"applet", @"basefont", @"center", @"dir", @"font", @"isindex", @"menu", @"s", @"strike", @"u",
             // Omit object so no file attachments are part of the fragment.
             @"object", nil];
+        CFRetain(elements);
     }
     return elements;
 }
 
+static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
+{
+    CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
+    NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
+    CFRelease(UUIDRef);
+    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/%@", WebDataProtocolScheme, UUIDString, relativePart]];
+    CFRelease(UUIDString);
+
+    return URL;
+}
+
 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
                                                inContext:(DOMRange *)context
                                           allowPlainText:(BOOL)allowPlainText
@@ -408,105 +434,62 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
 {
     NSArray *types = [pasteboard types];
     *chosePlainText = NO;
+    DOMDocumentFragment *fragment;
 
-    if ([types containsObject:WebArchivePboardType]) {
-        WebArchive *archive = [[WebArchive alloc] initWithData:[pasteboard dataForType:WebArchivePboardType]];
-        if (archive) {
-            DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithArchive:archive];
-            [archive release];
-            if (fragment) {
-                return fragment;
-            }
-        }
-    }
-    
-    if ([types containsObject:NSFilenamesPboardType]) {
-        DOMDocumentFragment *fragment = [self _documentFragmentWithPaths:[pasteboard propertyListForType:NSFilenamesPboardType]];
-        if (fragment != nil) {
-            return fragment;
-        }
-    }
-    
-    NSURL *URL;
-    
-    if ([types containsObject:NSHTMLPboardType]) {
-        NSString *HTMLString = [pasteboard stringForType:NSHTMLPboardType];
-        // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
-        if ([HTMLString hasPrefix:@"Version:"]) {
-            NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
-            if (range.location != NSNotFound) {
-                HTMLString = [HTMLString substringFromIndex:range.location];
-            }
-        }
-        if ([HTMLString length] != 0) {
-            return [[self _bridge] documentFragmentWithMarkupString:HTMLString baseURLString:nil];
-        }
-    }
-        
-    NSAttributedString *string = nil;
-    if ([types containsObject:NSRTFDPboardType]) {
-        string = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
-    }
-    if (string == nil && [types containsObject:NSRTFPboardType]) {
-        string = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
-    }
-    if (string != nil) {
-        NSDictionary *documentAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
-            [[self class] _excludedElementsForAttributedStringConversion], NSExcludedElementsDocumentAttribute,
-            self, @"WebResourceHandler", nil];
-        NSArray *subresources;
-        DOMDocumentFragment *fragment = [string _documentFromRange:NSMakeRange(0, [string length]) 
-                                                          document:[[self _frame] DOMDocument] 
-                                                documentAttributes:documentAttributes
-                                                      subresources:&subresources];
-        [documentAttributes release];
-        [string release];
+    if ([types containsObject:WebArchivePboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:WebArchivePboardType
+                                                inContext:context]))
         return fragment;
-    }
-    
-    if ([types containsObject:NSTIFFPboardType]) {
-        WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSTIFFPboardType]
-                                                              URL:[NSURL _web_uniqueWebDataURLWithRelativeString:@"/image.tiff"]
-                                                         MIMEType:@"image/tiff" 
-                                                 textEncodingName:nil
-                                                        frameName:nil];
-        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
-        [resource release];
+                                           
+    if ([types containsObject:NSFilenamesPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSFilenamesPboardType
+                                                inContext:context]))
         return fragment;
-    }
     
-    if ([types containsObject:NSPICTPboardType]) {
-        WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSPICTPboardType]
-                                                              URL:[NSURL _web_uniqueWebDataURLWithRelativeString:@"/image.pict"]
-                                                         MIMEType:@"image/pict" 
-                                                 textEncodingName:nil
-                                                        frameName:nil];
-        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
-        [resource release];
+    if ([types containsObject:NSHTMLPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSHTMLPboardType
+                                                inContext:context]))
         return fragment;
-    }    
     
-    if ((URL = [NSURL URLFromPasteboard:pasteboard])) {
-        DOMDocument* document = [[self _frame] DOMDocument];
-        ASSERT(document);
-        if (document) {
-            DOMHTMLAnchorElement* anchor = (DOMHTMLAnchorElement*)[document createElement:@"a"];
-            NSString *URLString = [URL _web_userVisibleString];
-            NSString *URLTitleString = [pasteboard stringForType:WebURLNamePboardType];
-            DOMText* text = [document createTextNode:URLTitleString];
-            [anchor setHref:URLString];
-            [anchor appendChild:text];
-            DOMDocumentFragment* fragment = [document createDocumentFragment];
-            [fragment appendChild:anchor];
-            if ([URLString length] > 0)
-                return fragment;
-        }
-    }
+    if ([types containsObject:NSRTFPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSRTFPboardType
+                                                inContext:context]))
+        return fragment;
+
+    if ([types containsObject:NSRTFDPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSRTFDPboardType
+                                                inContext:context]))
+        return fragment;
+
+    if ([types containsObject:NSTIFFPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSTIFFPboardType
+                                                inContext:context]))
+        return fragment;
+
+    if ([types containsObject:NSPICTPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSPICTPboardType
+                                                inContext:context]))
+        return fragment;
     
-    if (allowPlainText && [types containsObject:NSStringPboardType]) {
+    if ([types containsObject:NSURLPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard 
+                                                  forType:NSURLPboardType
+                                                inContext:context]))
+        return fragment;
+        
+    if (allowPlainText && [types containsObject:NSStringPboardType] &&
+        (fragment = [self _documentFragmentFromPasteboard:pasteboard
+                                                  forType:NSStringPboardType
+                                                inContext:context])) {
         *chosePlainText = YES;
-        return [[self _bridge] documentFragmentWithText:[pasteboard stringForType:NSStringPboardType]
-                                              inContext:context];
+        return fragment;
     }
     
     return nil;
@@ -994,8 +977,6 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
     return nil;
 }
 
-static WebHTMLView *lastHitView = nil;
-
 - (void)_clearLastHitViewIfSelf
 {
     if (lastHitView == self)
@@ -1154,14 +1135,14 @@ static WebHTMLView *lastHitView = nil;
                          windowNumber:[[view window] windowNumber]
                          context:[[NSApp currentEvent] context]
                          eventNumber:0 clickCount:0 pressure:0];
-        if (FrameMac* lastHitCoreFrame = core([lastHitView _frame]))
+        if (Frame* lastHitCoreFrame = core([lastHitView _frame]))
             lastHitCoreFrame->eventHandler()->mouseMoved(event);
     }
 
     lastHitView = view;
 
     if (view) {
-        if (FrameMac* coreFrame = core([view _frame]))
+        if (Frame* coreFrame = core([view _frame]))
             coreFrame->eventHandler()->mouseMoved(event);
 
         NSPoint point = [view convertPoint:[event locationInWindow] fromView:nil];
@@ -1200,6 +1181,7 @@ static WebHTMLView *lastHitView = nil;
     }
 }
 
+// keep in sync with WebPasteboardHelper::insertablePasteboardTypes
 + (NSArray *)_insertablePasteboardTypes
 {
     static NSArray *types = nil;
@@ -1207,6 +1189,7 @@ static WebHTMLView *lastHitView = nil;
         types = [[NSArray alloc] initWithObjects:WebArchivePboardType, NSHTMLPboardType,
             NSFilenamesPboardType, NSTIFFPboardType, NSPICTPboardType, NSURLPboardType, 
             NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, NSColorPboardType, nil];
+        CFRetain(types);
     }
     return types;
 }
@@ -1217,23 +1200,18 @@ static WebHTMLView *lastHitView = nil;
     return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
 }
 
-- (NSImage *)_dragImageForLinkElement:(NSDictionary *)element
+- (NSImage *)_dragImageForURL:(NSString*)urlString withLabel:(NSString*)label
 {
-    NSURL *linkURL = [element objectForKey: WebElementLinkURLKey];
-
     BOOL drawURLString = YES;
     BOOL clipURLString = NO, clipLabelString = NO;
     
-    NSString *label = [element objectForKey: WebElementLinkLabelKey];
-    NSString *urlString = [linkURL _web_userVisibleString];
-    
     if (!label) {
         drawURLString = NO;
         label = urlString;
     }
     
     NSFont *labelFont = [[NSFontManager sharedFontManager] convertFont:[NSFont systemFontOfSize:DRAG_LINK_LABEL_FONT_SIZE]
-                                                   toHaveTrait:NSBoldFontMask];
+                                                           toHaveTrait:NSBoldFontMask];
     NSFont *urlFont = [NSFont systemFontOfSize: DRAG_LINK_URL_FONT_SIZE];
     NSSize labelSize;
     labelSize.width = [label _web_widthWithFont: labelFont];
@@ -1273,27 +1251,36 @@ static WebHTMLView *lastHitView = nil;
     [path appendBezierPathWithRect: NSMakeRect(0.0f, DRAG_LABEL_RADIUS, DRAG_LABEL_RADIUS + 10.0f, imageSize.height - 2.0f * DRAG_LABEL_RADIUS)];
     [path appendBezierPathWithRect: NSMakeRect(imageSize.width - DRAG_LABEL_RADIUS - 20.0f, DRAG_LABEL_RADIUS, DRAG_LABEL_RADIUS + 20.0f, imageSize.height - 2.0f * DRAG_LABEL_RADIUS)];
     [path fill];
-        
+    
     NSColor *topColor = [NSColor colorWithCalibratedWhite:0.0f alpha:0.75f];
     NSColor *bottomColor = [NSColor colorWithCalibratedWhite:1.0f alpha:0.5f];
     if (drawURLString) {
         if (clipURLString)
             urlString = [WebStringTruncator centerTruncateString: urlString toWidth:imageSize.width - (DRAG_LABEL_BORDER_X * 2.0f) withFont:urlFont];
-
+        
         [urlString _web_drawDoubledAtPoint:NSMakePoint(DRAG_LABEL_BORDER_X, DRAG_LABEL_BORDER_Y - [urlFont descender]) 
-             withTopColor:topColor bottomColor:bottomColor font:urlFont];
+                              withTopColor:topColor bottomColor:bottomColor font:urlFont];
     }
-
+    
     if (clipLabelString)
         label = [WebStringTruncator rightTruncateString: label toWidth:imageSize.width - (DRAG_LABEL_BORDER_X * 2.0f) withFont:labelFont];
     [label _web_drawDoubledAtPoint:NSMakePoint (DRAG_LABEL_BORDER_X, imageSize.height - DRAG_LABEL_BORDER_Y_OFFSET - [labelFont pointSize])
-             withTopColor:topColor bottomColor:bottomColor font:labelFont];
+                      withTopColor:topColor bottomColor:bottomColor font:labelFont];
     
     [dragImage unlockFocus];
     
     return dragImage;
 }
 
+- (NSImage *)_dragImageForLinkElement:(NSDictionary *)element
+{
+    NSURL *linkURL = [element objectForKey: WebElementLinkURLKey];
+    
+    NSString *label = [element objectForKey: WebElementLinkLabelKey];
+    NSString *urlString = [linkURL _web_userVisibleString];
+    return [self _dragImageForURL:urlString withLabel:label];
+}
+
 - (BOOL)_startDraggingImage:(NSImage *)wcDragImage at:(NSPoint)wcDragLoc operation:(NSDragOperation)op event:(NSEvent *)mouseDraggedEvent sourceIsDHTML:(BOOL)srcIsDHTML DHTMLWroteData:(BOOL)dhtmlWroteData
 {
     WebHTMLView *topHTMLView = [self _topHTMLView];
@@ -1311,11 +1298,14 @@ static WebHTMLView *lastHitView = nil;
     NSURL *imageURL = [element objectForKey:WebElementImageURLKey];
     BOOL isSelected = [[element objectForKey:WebElementIsSelectedKey] boolValue];
 
-    [_private->draggingImageURL release];
-    _private->draggingImageURL = nil;
-
     NSPoint mouseDraggedPoint = [self convertPoint:[mouseDraggedEvent locationInWindow] fromView:nil];
-    _private->webCoreDragOp = op;     // will be DragNone if WebCore doesn't care
+    
+    Page* page = core([self _webView]);
+    ASSERT(page);
+    DragController *dragController = page->dragController();
+    dragController->setDraggingImageURL(KURL());
+    dragController->setDragOperation((DragOperation)op);     // will be DragNone if WebCore doesn't care
+    
     NSImage *dragImage = nil;
     NSPoint dragLoc = { 0, 0 }; // quiet gcc 4.0 warning
 
@@ -1331,7 +1321,7 @@ static WebHTMLView *lastHitView = nil;
             dragLoc = NSMakePoint(mouseDraggedPoint.x - wcDragLoc.x, mouseDraggedPoint.y + wcDragLoc.y);
         else
             dragLoc = NSMakePoint(mouseDownPoint.x - wcDragLoc.x, mouseDownPoint.y + wcDragLoc.y);
-        _private->dragOffset = wcDragLoc;
+        dragController->setDragOffset(IntPoint(wcDragLoc));
     }
     
     WebView *webView = [self _webView];
@@ -1345,13 +1335,13 @@ static WebHTMLView *lastHitView = nil;
     if (imageURL != nil
             && [node isKindOfClass:[DOMElement class]]
             && [(DOMElement *)node image]
-            && (_private->dragSourceActionMask & WebDragSourceActionImage)) {
+            && (dragController->dragSourceAction() & WebDragSourceActionImage)) {
         id source = self;
         if (!dhtmlWroteData) {
             // Select the image when it is dragged. This allows the image to be moved via MoveSelectionCommandImpl and this matches NSTextView's behavior.
             ASSERT(node != nil);
             [webView setSelectedDOMRange:[[node ownerDocument] _createRangeWithNode:node] affinity:NSSelectionAffinityDownstream];
-            _private->draggingImageURL = [imageURL retain];
+            dragController->setDraggingImageURL(imageURL);
             
             WebArchive *archive;
             
@@ -1369,14 +1359,16 @@ static WebHTMLView *lastHitView = nil;
                                                                   source:self];
         }
         [[webView _UIDelegateForwarder] webView:webView willPerformDragSourceAction:WebDragSourceActionImage fromPoint:mouseDownPoint withPasteboard:pasteboard];
-        if (dragImage == nil)
+        if (dragImage == nil) {
+            NSPoint point = dragController->dragOffset();
             [self _web_DragImageForElement:(DOMElement *)node
                                       rect:[self convertRect:[[element objectForKey:WebElementImageRectKey] rectValue] fromView:innerHTMLView]
                                      event:_private->mouseDownEvent
                                 pasteboard:pasteboard
                                     source:source
-                                    offset:&_private->dragOffset];
-        else
+                                    offset:&point];
+            dragController->setDragOffset(IntPoint(point));
+        } else
             [self dragImage:dragImage
                          at:dragLoc
                      offset:NSZeroSize
@@ -1384,7 +1376,7 @@ static WebHTMLView *lastHitView = nil;
                  pasteboard:pasteboard
                      source:source
                   slideBack:YES];
-    } else if (linkURL && (_private->dragSourceActionMask & WebDragSourceActionLink)) {
+    } else if (linkURL && (dragController->dragSourceAction() & WebDragSourceActionLink)) {
         if (!dhtmlWroteData) {
             NSArray *types = [NSPasteboard _web_writableTypesForURL];
             [pasteboard declareTypes:types owner:self];
@@ -1395,8 +1387,7 @@ static WebHTMLView *lastHitView = nil;
             dragImage = [self _dragImageForLinkElement:element];
             NSSize offset = NSMakeSize([dragImage size].width / 2, -DRAG_LABEL_BORDER_Y);
             dragLoc = NSMakePoint(mouseDraggedPoint.x - offset.width, mouseDraggedPoint.y - offset.height);
-            _private->dragOffset.x = offset.width;
-            _private->dragOffset.y = -offset.height;        // inverted because we are flipped
+            dragController->setDragOffset(IntPoint((int)offset.width, -(int)offset.height)); // height inverted because we are flipped
         }
         // HACK:  We should pass the mouseDown event instead of the mouseDragged!  This hack gets rid of
         // a flash of the image at the mouseDown location when the drag starts.
@@ -1407,7 +1398,7 @@ static WebHTMLView *lastHitView = nil;
              pasteboard:pasteboard
                  source:self
               slideBack:YES];
-    } else if (isSelected && (_private->dragSourceActionMask & WebDragSourceActionSelection)) {
+    } else if (isSelected && (dragController->dragSourceAction() & WebDragSourceActionSelection)) {
         if (!dhtmlWroteData)
             [innerHTMLView _writeSelectionToPasteboard:pasteboard];
         [[webView _UIDelegateForwarder] webView:webView willPerformDragSourceAction:WebDragSourceActionSelection fromPoint:mouseDownPoint withPasteboard:pasteboard];
@@ -1415,8 +1406,8 @@ static WebHTMLView *lastHitView = nil;
             dragImage = [innerHTMLView _selectionDraggingImage];
             NSRect draggingRect = [self convertRect:[innerHTMLView _selectionDraggingRect] fromView:innerHTMLView];
             dragLoc = NSMakePoint(NSMinX(draggingRect), NSMaxY(draggingRect));
-            _private->dragOffset.x = mouseDownPoint.x - dragLoc.x;
-            _private->dragOffset.y = dragLoc.y - mouseDownPoint.y;        // inverted because we are flipped
+            dragController->setDragOffset(IntPoint((int)(mouseDownPoint.x - dragLoc.x),
+                                                   (int)(dragLoc.y - mouseDownPoint.y)));        // y inverted because we are flipped
         }
         [self dragImage:dragImage
                      at:dragLoc
@@ -1426,7 +1417,7 @@ static WebHTMLView *lastHitView = nil;
                  source:self
               slideBack:YES];
     } else if (srcIsDHTML) {
-        ASSERT(_private->dragSourceActionMask & WebDragSourceActionDHTML);
+        ASSERT(dragController->dragSourceAction() & WebDragSourceActionDHTML);
         [[webView _UIDelegateForwarder] webView:webView willPerformDragSourceAction:WebDragSourceActionDHTML fromPoint:mouseDownPoint withPasteboard:pasteboard];
         if (dragImage == nil) {
             // WebCore should have given us an image, but we'll make one up
@@ -1435,8 +1426,7 @@ static WebHTMLView *lastHitView = nil;
             dragImage = [[[NSImage alloc] initWithContentsOfFile:imagePath] autorelease];
             NSSize imageSize = [dragImage size];
             dragLoc = NSMakePoint(mouseDownPoint.x - imageSize.width / 2, mouseDownPoint.y + imageSize.height / 2);
-            _private->dragOffset.x = imageSize.width / 2;
-            _private->dragOffset.y = imageSize.height / 2;
+            dragController->setDragOffset(IntPoint((int)(imageSize.width / 2), (int)(imageSize.height / 2)));
         }
         [self dragImage:dragImage
                      at:dragLoc
@@ -1459,35 +1449,6 @@ static WebHTMLView *lastHitView = nil;
     [self _startAutoscrollTimer:event]; 
 } 
 
-- (BOOL)_mayStartDragAtEventLocation:(NSPoint)location
-{
-    WebHTMLView *topHTMLView = [self _topHTMLView];
-    if (self != topHTMLView)
-        return [topHTMLView _mayStartDragAtEventLocation:location];
-
-    NSPoint mouseDownPoint = [self convertPoint:location fromView:nil];
-    NSDictionary *mouseDownElement = [self elementAtPoint:mouseDownPoint allowShadowContent:YES];
-
-    ASSERT([self _webView]);
-
-    if ([mouseDownElement objectForKey:WebElementImageKey]
-            && [mouseDownElement objectForKey:WebElementImageURLKey]
-            && [[[self _webView] preferences] loadsImagesAutomatically]
-            && (_private->dragSourceActionMask & WebDragSourceActionImage))
-        return YES;
-    
-    if ([mouseDownElement objectForKey:WebElementLinkURLKey]
-            && (_private->dragSourceActionMask & WebDragSourceActionLink)
-            && [[mouseDownElement objectForKey:WebElementLinkIsLiveKey] boolValue])
-        return YES;
-    
-    if ([[mouseDownElement objectForKey:WebElementIsSelectedKey] boolValue]
-            && (_private->dragSourceActionMask & WebDragSourceActionSelection))
-        return YES;
-    
-    return NO;
-}
-
 - (WebPluginController *)_pluginController
 {
     return _private->pluginController;
@@ -1629,7 +1590,7 @@ static WebHTMLView *lastHitView = nil;
 
 - (BOOL)_isEditable
 {
-    FrameMac* coreFrame = core([self _frame]);
+    Frame* coreFrame = core([self _frame]);
     if (!coreFrame)
         return NO;
     return coreFrame->selectionController()->isContentEditable();
@@ -1721,7 +1682,7 @@ static WebHTMLView *lastHitView = nil;
 
 - (BOOL)_web_firstResponderCausesFocusDisplay
 {
-    return [self _web_firstResponderIsSelfOrDescendantView] || [[self window] firstResponder] == [self _frameView];
+    return [[self window] firstResponder] == self || [[self window] firstResponder] == [self _frameView];
 }
 
 - (void)_updateActiveState
@@ -1752,7 +1713,7 @@ static WebHTMLView *lastHitView = nil;
     BOOL windowIsKey = [window isKeyWindow];
     BOOL windowOrSheetIsKey = windowIsKey || [[window attachedSheet] isKeyWindow];
 
-    BOOL isActive = !_private->resigningFirstResponder && windowIsKey && (_private->descendantBecomingFirstResponder || [self _web_firstResponderCausesFocusDisplay]);
+    BOOL isActive = !_private->resigningFirstResponder && windowIsKey && [self _web_firstResponderCausesFocusDisplay];
     frame->setIsActive(isActive);            
 
     Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
@@ -1816,6 +1777,115 @@ static WebHTMLView *lastHitView = nil;
     [self removeAllToolTips];
     [_private clear];
     _private->closed = YES;
+    Page* page = core([self _webView]);
+    if (page)
+        page->dragController()->setDraggingImageURL(KURL());
+}
+
+- (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
+                                                 forType:(NSString *)pboardType
+                                               inContext:(DOMRange *)context
+{
+    if (pboardType == WebArchivePboardType) {
+        WebArchive *archive = [[WebArchive alloc] initWithData:[pasteboard dataForType:WebArchivePboardType]];
+        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithArchive:archive];
+        [archive release];
+        return fragment;
+    }
+    if (pboardType == NSFilenamesPboardType)
+        return [self _documentFragmentWithPaths:[pasteboard propertyListForType:NSFilenamesPboardType]];
+        
+    if (pboardType == NSHTMLPboardType) {
+        NSString *HTMLString = [pasteboard stringForType:NSHTMLPboardType];
+        // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
+        if ([HTMLString hasPrefix:@"Version:"]) {
+            NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
+            if (range.location != NSNotFound)
+                HTMLString = [HTMLString substringFromIndex:range.location];
+        }
+        if ([HTMLString length] == 0)
+            return nil;
+        
+        return [[self _bridge] documentFragmentWithMarkupString:HTMLString baseURLString:nil];
+    }
+    if (pboardType == NSRTFPboardType || pboardType == NSRTFDPboardType) {
+        NSAttributedString *string = nil;
+        if (pboardType == NSRTFDPboardType)
+            string = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
+        if (string == nil)
+            string = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
+        if (string == nil)
+            return nil;
+            
+        NSDictionary *documentAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
+            [[self class] _excludedElementsForAttributedStringConversion], NSExcludedElementsDocumentAttribute,
+            self, @"WebResourceHandler", nil];
+        NSArray *subresources;
+        
+        BOOL wasDeferringCallbacks = [[self _webView] defersCallbacks];
+        if (!wasDeferringCallbacks)
+            [[self _webView] setDefersCallbacks:YES];
+            
+        DOMDocumentFragment *fragment = [string _documentFromRange:NSMakeRange(0, [string length]) 
+                                                          document:[[self _frame] DOMDocument] 
+                                                documentAttributes:documentAttributes
+                                                      subresources:&subresources];
+        
+        NSEnumerator *e = [subresources objectEnumerator];
+        WebResource *r;
+        while ((r = [e nextObject]))
+            [[self _dataSource] addSubresource:r];
+        
+        if (!wasDeferringCallbacks)
+            [[self _webView] setDefersCallbacks:NO];
+        
+        [documentAttributes release];
+        [string release];
+        return fragment;
+    }
+    if (pboardType == NSTIFFPboardType) {
+        WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSTIFFPboardType]
+                                                              URL:uniqueURLWithRelativePart(@"image.tiff")
+                                                         MIMEType:@"image/tiff" 
+                                                 textEncodingName:nil
+                                                        frameName:nil];
+        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
+        [resource release];
+        return fragment;
+    }
+    if (pboardType == NSPICTPboardType) {
+        WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSPICTPboardType]
+                                                              URL:uniqueURLWithRelativePart(@"image.pict")
+                                                         MIMEType:@"image/pict" 
+                                                 textEncodingName:nil
+                                                        frameName:nil];
+        DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
+        [resource release];
+        return fragment;
+    }
+    if (pboardType == NSURLPboardType) {
+        NSURL *URL = [NSURL URLFromPasteboard:pasteboard];
+        DOMDocument* document = [[self _frame] DOMDocument];
+        ASSERT(document);
+        if (!document)
+            return nil;
+        DOMHTMLAnchorElement *anchor = (DOMHTMLAnchorElement *)[document createElement:@"a"];
+        NSString *URLString = [URL _web_originalDataAsString];
+        if ([URLString length] == 0)
+            return nil;
+        NSString *URLTitleString = [pasteboard stringForType:WebURLNamePboardType];
+        DOMText *text = [document createTextNode:URLTitleString];
+        [anchor setHref:URLString];
+        [anchor appendChild:text];
+        DOMDocumentFragment *fragment = [document createDocumentFragment];
+        [fragment appendChild:anchor];
+        return fragment;
+    }
+    if (pboardType == NSStringPboardType)
+        return [[self _bridge] documentFragmentWithText:[pasteboard stringForType:NSStringPboardType]
+                                              inContext:context];
+                                              
+    return nil;
 }
 
 @end
@@ -1894,6 +1964,9 @@ static WebHTMLView *lastHitView = nil;
     [NSApp registerServicesMenuSendTypes:[[self class] _selectionPasteboardTypes] 
                              returnTypes:[[self class] _insertablePasteboardTypes]];
     _NSInitializeKillRing();
+#ifndef BUILDING_ON_TIGER
+    WebCoreObjCFinalizeOnMainThread(self);
+#endif
 }
 
 - (void)_resetCachedWebPreferences:(NSNotification *)ignored
@@ -1912,6 +1985,8 @@ static WebHTMLView *lastHitView = nil;
     if (!self)
         return nil;
     
+    [self setFocusRingType:NSFocusRingTypeNone];
+    
     // Make all drawing go through us instead of subviews.
     if (NSAppKitVersionNumber >= 711) {
         [self _setDrawsOwnDescendants:YES];
@@ -1942,6 +2017,7 @@ static WebHTMLView *lastHitView = nil;
 
 - (void)finalize
 {
+    ASSERT_MAIN_THREAD();
     // We can't assert that close has already been called because
     // this view can be removed from it's superview, even though
     // it could be needed later, so close if needed.
@@ -2006,7 +2082,7 @@ static WebHTMLView *lastHitView = nil;
 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item 
 {
     SEL action = [item action];
-    FrameMac* frame = core([self _frame]);
+    Frame* frame = core([self _frame]);
 
     if (action == @selector(changeSpelling:)
             || action == @selector(_changeSpellingFromMenu:)
@@ -2078,7 +2154,7 @@ static WebHTMLView *lastHitView = nil;
         return [self _canEdit];
     
     if (action == @selector(showGuessPanel:)) {
-#if !BUILDING_ON_TIGER
+#ifndef BUILDING_ON_TIGER
         // Match OS X AppKit behavior for post-Tiger. Don't change Tiger behavior.
         NSMenuItem *menuItem = (NSMenuItem *)item;
         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
@@ -2214,7 +2290,7 @@ static WebHTMLView *lastHitView = nil;
         return [self _hasSelection];
     } 
     
-#if !BUILDING_ON_TIGER
+#ifndef BUILDING_ON_TIGER
     if (action == @selector(toggleGrammarChecking:)) {
         // FIXME 4799134: WebView is the bottleneck for this grammar-checking logic, but we must validate 
         // the selector here because we implement it here, and we must implement it here because the AppKit 
@@ -2276,7 +2352,7 @@ static WebHTMLView *lastHitView = nil;
     if (nextResponder == self)
         return YES;
 
-    FrameMac* coreFrame = core([self _frame]);
+    Frame* coreFrame = core([self _frame]);
     bool selectionIsEditable = coreFrame && coreFrame->selectionController()->isContentEditable();
     bool nextResponderIsInWebView = [nextResponder isKindOfClass:[NSView class]]
         && [nextResponder isDescendantOf:[[[self _webView] mainFrame] frameView]];
@@ -2550,7 +2626,7 @@ static WebHTMLView *lastHitView = nil;
         return nil;
     }
 
-    handledEvent = coreFrame->eventHandler()->sendContextMenuEvent(event);
+    handledEvent = coreFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event));
     _private->handlingMouseDownEvent = NO;
 
     if (!handledEvent)
@@ -2769,7 +2845,7 @@ static WebHTMLView *lastHitView = nil;
 - (void)scrollWheel:(NSEvent *)event
 {
     [self retain];
-    FrameMac* frame = core([self _frame]);
+    Frame* frame = core([self _frame]);
     if (!frame || !frame->eventHandler()->wheelEvent(event))
         [[self nextResponder] scrollWheel:event];    
     [self release];
@@ -2791,7 +2867,7 @@ static WebHTMLView *lastHitView = nil;
     
     if (hitHTMLView) {
         bool result = false;
-        if (FrameMac* coreFrame = core([hitHTMLView _frame])) {
+        if (Frame* coreFrame = core([hitHTMLView _frame])) {
             coreFrame->eventHandler()->setActivationEventNumber([event eventNumber]);
             [hitHTMLView _setMouseDownEvent:event];
             if ([hitHTMLView _isSelectionEvent:event])
@@ -2810,7 +2886,7 @@ static WebHTMLView *lastHitView = nil;
     if (hitHTMLView) {
         bool result = false;
         if ([hitHTMLView _isSelectionEvent:event])
-            if (FrameMac* coreFrame = core([hitHTMLView _frame])) {
+            if (Frame* coreFrame = core([hitHTMLView _frame])) {
                 [hitHTMLView _setMouseDownEvent:event];
                 result = coreFrame->eventHandler()->eventMayStartDrag(event);
                 [hitHTMLView _setMouseDownEvent:nil];
@@ -2866,28 +2942,8 @@ done:
            source:(id)source
         slideBack:(BOOL)slideBack
 {
-    [self _stopAutoscrollTimer];
-
-    WebHTMLView *topHTMLView = [self _topHTMLView];
-    if (self != topHTMLView) {
-        [topHTMLView dragImage:dragImage at:[self convertPoint:at toView:topHTMLView]
-            offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
-        return;
-    }
-
-    WebView *webView = [self _webView];
-    
-    [webView _setInitiatedDrag:YES];
-
-    // Retain this view during the drag because it may be released before the drag ends.
-    [self retain];
-
-    id UIDelegate = [webView UIDelegate];
-    // If a delegate takes over the drag but never calls draggedImage: endedAt:, we'll leak the WebHTMLView.
-    if ([UIDelegate respondsToSelector:@selector(webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:)])
-        [UIDelegate webView:webView dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack forView:self];
-    else
-        [super dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
+    ASSERT(self == [self _topHTMLView]);
+    [super dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
 }
 
 - (void)mouseDragged:(NSEvent *)event
@@ -2907,32 +2963,48 @@ done:
 
 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
 {
-    ASSERT([self _isTopHTMLView]);
-
-    if (_private->webCoreDragOp == NSDragOperationNone)
+    ASSERT(![self _webView] || [self _isTopHTMLView]);
+    
+    Page *page = core([self _webView]);
+    
+    if (!page)
+        return NSDragOperationNone;
+    
+    if (page->dragController()->dragOperation() == DragOperationNone)
         return NSDragOperationGeneric | NSDragOperationCopy;
-    return _private->webCoreDragOp;
+    
+    return (NSDragOperation)page->dragController()->dragOperation();
 }
 
 - (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenLoc
 {
-    ASSERT([self _isTopHTMLView]);
-
+    ASSERT(![self _webView] || [self _isTopHTMLView]);
+    
     NSPoint windowImageLoc = [[self window] convertScreenToBase:screenLoc];
-    NSPoint windowMouseLoc = NSMakePoint(windowImageLoc.x + _private->dragOffset.x, windowImageLoc.y + _private->dragOffset.y);
+    NSPoint windowMouseLoc = windowImageLoc;
+    
+    if (Page* page = core([self _webView])) {
+        DragController* dragController = page->dragController();
+        NSPoint windowMouseLoc = NSMakePoint(windowImageLoc.x + dragController->dragOffset().x(), windowImageLoc.y + dragController->dragOffset().y());
+    }
+    
     [[self _bridge] dragSourceMovedTo:windowMouseLoc];
 }
 
 - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
 {
     ASSERT(![self _webView] || [self _isTopHTMLView]);
-
+    
     NSPoint windowImageLoc = [[self window] convertScreenToBase:aPoint];
-    NSPoint windowMouseLoc = NSMakePoint(windowImageLoc.x + _private->dragOffset.x, windowImageLoc.y + _private->dragOffset.y);
+    NSPoint windowMouseLoc = windowImageLoc;
+    
+    if (Page* page = core([self _webView])) {
+        DragController* dragController = page->dragController();
+        windowMouseLoc = NSMakePoint(windowImageLoc.x + dragController->dragOffset().x(), windowImageLoc.y + dragController->dragOffset().y());
+        dragController->dragEnded();
+    }
+    
     [[self _bridge] dragSourceEndedAt:windowMouseLoc operation:operation];
-
-    _private->initiatedDrag = NO;
-    [[self _webView] _setInitiatedDrag:NO];
     
     // Prevent queued mouseDragged events from coming after the drag and fake mouseUp event.
     _private->ignoringMouseDraggedEvents = YES;
@@ -2947,17 +3019,23 @@ done:
                                              context:[[NSApp currentEvent] context]
                                          eventNumber:0 clickCount:0 pressure:0];
     [self mouseUp:fakeEvent]; // This will also update the mouseover state.
-    
-    // Balance the previous retain from when the drag started.
-    [self release];
 }
 
 - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
 {
-    ASSERT([self _isTopHTMLView]);
-    ASSERT(_private->draggingImageURL);
-
-    NSFileWrapper *wrapper = [[self _dataSource] _fileWrapperForURL:_private->draggingImageURL];
+    ASSERT(![self _webView] || [self _isTopHTMLView]);
+    Page* page = core([self _webView]);
+    
+    //If a load occurs midway through a drag, the view may be detached, which gives
+    //us no ability to get to the original Page, so we cannot access any drag state
+    //FIXME: is there a way to recover?
+    if (!page) 
+        return nil; 
+    
+    KURL imageURL = page->dragController()->draggingImageURL();
+    ASSERT(!imageURL.isEmpty());
+    
+    NSFileWrapper *wrapper = [[self _dataSource] _fileWrapperForURL:imageURL.getNSURL()];
     if (wrapper == nil) {
         LOG_ERROR("Failed to create image file. Did the source image change while dragging? (<rdar://problem/4244861>)");
         return nil;
@@ -3028,22 +3106,7 @@ done:
     page->focusController()->setFocusedFrame(frame);
     if (Document* document = frame->document())
         document->setFocusedNode(0);
-    
-    BOOL createdFakeEvent = NO;
-    KeyboardEvent* currentEvent = frame->eventHandler()->currentKeyboardEvent().get();
-    if (!currentEvent) {
-        // If we didn't get an event (for example, when using eventSender.keyDown() under DumpRenderTree), just fake a Tab keydown.
-        currentEvent = new KeyboardEvent(EventNames::keydownEvent, true, true,
-                                         frame->document() ? frame->document()->defaultView() : 0,
-                                         "U+000009", KeyboardEvent::DOM_KEY_LOCATION_STANDARD, false, false, false, false, false);
-        createdFakeEvent = YES;
-    }
-    
-    page->focusController()->advanceFocus(currentEvent);
-    
-    if (createdFakeEvent)
-        delete currentEvent;
-
+    page->focusController()->advanceFocus(frame->eventHandler()->currentKeyboardEvent().get());
     return YES;
 }
 
@@ -3308,27 +3371,6 @@ done:
     [self _endPrintMode];
 }
 
-- (BOOL)_interceptEditingKeyEvent:(NSEvent *)event
-{   
-    // Use WebView's tabKeyCyclesThroughElements state to determine whether or not
-    // to process tab key events. The idea here is that tabKeyCyclesThroughElements
-    // will be YES when this WebView is being used in a browser, and we desire the
-    // behavior where tab moves to the next element in tab order. If tabKeyCyclesThroughElements
-    // is NO, it is likely that the WebView is being embedded as the whole view, as in Mail,
-    // and tabs should input tabs as expected in a text editor. Using Option-Tab always cycles
-    // through elements.
-
-    if ([[self _webView] tabKeyCyclesThroughElements] && [event _web_isTabKeyEvent]) 
-        return NO;
-
-    if (![[self _webView] tabKeyCyclesThroughElements] && [event _web_isOptionTabKeyEvent])
-        return NO;
-
-    // Now process the key normally
-    [self interpretKeyEvents:[NSArray arrayWithObject:event]];
-    return YES;
-}
-
 - (void)keyDown:(NSEvent *)event
 {
     BOOL eventWasSentToWebCore = (_private->keyDownEvent == event);
@@ -3346,11 +3388,8 @@ done:
     } else if (_private->compController && [_private->compController filterKeyDown:event]) {
         // Consumed by complete: popup window
     } else {
-        // We're going to process a key event, bail on any outstanding complete: UI
         [_private->compController endRevertingChange:YES moveLeft:NO];
-        BOOL handledKey = [self _canEdit] && [self _interceptEditingKeyEvent:event];
-        if (!handledKey)
-            callSuper = YES;
+        callSuper = YES;
     }
     if (callSuper)
         [super keyDown:event];
@@ -3701,8 +3740,10 @@ done:
 
     EAffinity affinity = coreFrame->selectionController()->affinity();
     WebView *webView = [self _webView];
-    if ([[webView _editingDelegateForwarder] webView:webView shouldChangeSelectedDOMRange:[self _selectedRange] toDOMRange:domRange affinity:kit(affinity) stillSelecting:NO])
-        selectRange(coreFrame->selectionController(), range.get(), affinity, true);
+    if ([[webView _editingDelegateForwarder] webView:webView shouldChangeSelectedDOMRange:[self _selectedRange] toDOMRange:domRange affinity:kit(affinity) stillSelecting:NO]) {
+        ExceptionCode ec = 0;
+        coreFrame->selectionController()->setSelectedRange(range.get(), affinity, true, ec);
+    }
 }
 
 - (void)selectParagraph:(id)sender
@@ -3727,7 +3768,7 @@ done:
 
 - (void)delete:(id)sender
 {
-#if USING_WEBCORE_DELETE
+#ifdef USING_WEBCORE_DELETE
     Frame* coreFrame = core([self _frame]);
     if (coreFrame)
         coreFrame->editor()->performDelete();
@@ -3925,19 +3966,18 @@ done:
     _private->keyDownEvent = [event retain];
     
     [self retain];
-    
+
     // Pass command-key combos through WebCore if there is a key binding available for
     // this event. This lets web pages have a crack at intercepting command-modified keypresses.
     // But don't do it if we have already handled the event.
-    if (!eventWasSentToWebCore 
-            && event == [NSApp currentEvent]    // Pressing Esc results in a fake event being sent - don't pass it to WebCore
-            && self == [[self window] firstResponder]
-            && core([self _frame])
-            && core([self _frame])->eventHandler()->keyEvent(event))
-        ret = YES;
-    else
+    // Pressing Esc results in a fake event being sent - don't pass it to WebCore.
+    if (!eventWasSentToWebCore && event == [NSApp currentEvent] && self == [[self window] firstResponder])
+        if (Frame* frame = core([self _frame]))
+            ret = frame->eventHandler()->keyEvent(event);
+
+    if (!ret)
         ret = [super performKeyEquivalent:event];
-    
+
     [self release];
     
     return ret;
@@ -4256,54 +4296,27 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
 
 - (void)insertTab:(id)sender
 {
-    [self insertText:@"\t"];
+    [self _insertTabWithEvent:0 isBackTab:NO];
 }
 
 - (void)insertBacktab:(id)sender
 {
-    // Doing nothing matches normal NSTextView behavior. If we ever use WebView for a field-editor-type purpose
-    // we might add code here.
+    [self _insertTabWithEvent:0 isBackTab:YES];
 }
 
 - (void)insertNewline:(id)sender
 {
-    if (![self _canEdit])
-        return;
-        
-    // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
-    WebFrameBridge *bridge = [self _bridge];
-    if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped]) {
-        if ([self _canEditRichly])
-            [bridge insertParagraphSeparator];
-        else
-            [bridge insertLineBreak];
-    }
+    [self _insertNewlineWithEvent:0 isLineBreak:NO];
 }
 
 - (void)insertLineBreak:(id)sender
 {
-    if (![self _canEdit])
-        return;
-        
-    // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
-    WebFrameBridge *bridge = [self _bridge];
-    if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped])
-        [bridge insertLineBreak];
+    [self _insertNewlineWithEvent:0 isLineBreak:YES];
 }
 
 - (void)insertParagraphSeparator:(id)sender
 {
-    if (![self _canEdit])
-        return;
-
-    // Perhaps we should make this delegate call sensitive to the real DOM operation we actually do.
-    WebFrameBridge *bridge = [self _bridge];
-    if ([self _shouldReplaceSelectionWithText:@"\n" givenAction:WebViewInsertActionTyped]) {
-        if ([self _canEditRichly])
-            [bridge insertParagraphSeparator];
-        else
-            [bridge insertLineBreak];
-    }
+    [self _insertNewlineWithEvent:0 isLineBreak:NO];
 }
 
 - (void)_changeWordCaseWithSelector:(SEL)selector
@@ -4438,7 +4451,7 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
     }
     
     NSPanel *spellingPanel = [checker spellingPanel];
-#if !BUILDING_ON_TIGER
+#ifndef BUILDING_ON_TIGER
     // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone
     // to match rest of OS X.
     if ([spellingPanel isVisible]) {
@@ -4513,12 +4526,12 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
 
 - (void)insertNewlineIgnoringFieldEditor:(id)sender
 {
-    [self insertNewline:sender];
+    [self _insertNewlineWithEvent:0 isLineBreak:NO];
 }
 
 - (void)insertTabIgnoringFieldEditor:(id)sender
 {
-    [self insertTab:sender];
+    [self _insertTabWithEvent:0 isBackTab:NO];
 }
 
 - (void)subscript:(id)sender
@@ -4562,9 +4575,10 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
         return;
     
     NSString* yankee = _NSYankFromKillRing();
-    if ([yankee length])
-        [self insertText:yankee];
-    else
+    if ([yankee length]) {
+        if (Frame* coreFrame = core([self _frame]))
+            coreFrame->editor()->insertText(yankee, false);
+    } else
         [self deleteBackward:nil];
 
     _NSSetKillRingToYankedState();
@@ -4576,9 +4590,10 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
         return;
 
     NSString* yankee = _NSYankPreviousFromKillRing();
-    if ([yankee length])
-        [self _insertText:yankee selectInsertedText:YES];
-    else
+    if ([yankee length]) {
+        if (Frame* coreFrame = core([self _frame]))
+            coreFrame->editor()->insertText(yankee, true);
+    } else
         [self deleteBackward:nil];
         
     _NSSetKillRingToYankedState();
@@ -4629,40 +4644,31 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 {
     WebFrameBridge *bridge = [self _bridge];
     DOMRange *mark = [bridge markDOMRange];
-    if (mark == nil) {
-        NSBeep();
-        return;
-    }
     DOMRange *selection = [self _selectedRange];
     Frame* coreFrame = core([self _frame]);
-    NS_DURING
-        if (coreFrame)
-            selectRange(coreFrame->selectionController(), core(unionDOMRanges(mark, selection)), DOWNSTREAM, true);
-    NS_HANDLER
+    if (!mark || !selection || !coreFrame) {
         NSBeep();
-    NS_ENDHANDLER
+        return;
+    }
+    ExceptionCode ec = 0;
+    coreFrame->selectionController()->setSelectedRange(core(unionDOMRanges(mark, [self _selectedRange])), DOWNSTREAM, true, ec);
 }
 
 - (void)swapWithMark:(id)sender
 {
     WebFrameBridge *bridge = [self _bridge];
     DOMRange *mark = [bridge markDOMRange];
-
-    if (mark == nil) {
-        NSBeep();
-        return;
-    }
-
     DOMRange *selection = [self _selectedRange];
     Frame* coreFrame = core([self _frame]);
-    NS_DURING
-        if (coreFrame)
-            selectRange(coreFrame->selectionController(), core(mark), DOWNSTREAM, true);
-    NS_HANDLER
+    if (!mark || !selection || !coreFrame) {
         NSBeep();
         return;
-    NS_ENDHANDLER
-    [bridge setMarkDOMRange:selection];
+    }
+
+    ExceptionCode ec = 0;
+    coreFrame->selectionController()->setSelectedRange(core(mark), DOWNSTREAM, true, ec);
+    if (ec == 0)
+        [bridge setMarkDOMRange:selection];
 }
 
 - (void)transpose:(id)sender
@@ -4684,8 +4690,11 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
         return;
 
     Frame* coreFrame = core([self _frame]);
-    if (coreFrame)
-        selectRange(coreFrame->selectionController(), core(r), DOWNSTREAM, true);
+    if (!coreFrame)
+        return;
+
+    ExceptionCode ec = 0;
+    coreFrame->selectionController()->setSelectedRange(core(r), DOWNSTREAM, true, ec);
     if ([self _shouldReplaceSelectionWithText:transposed givenAction:WebViewInsertActionTyped])
         [bridge replaceSelectionWithText:transposed selectReplacement:NO smartReplace:NO];
 }
@@ -4903,26 +4912,6 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
         core([self _frame])->editor()->setStartNewKillRingSequence(true);
 }
 
-- (void)_formControlIsBecomingFirstResponder:(NSView *)formControl
-{
-    if (![formControl isDescendantOf:self])
-        return;
-    _private->descendantBecomingFirstResponder = YES;
-    [self _updateActiveState];
-    _private->descendantBecomingFirstResponder = NO;
-}
-
-- (void)_formControlIsResigningFirstResponder:(NSView *)formControl
-{
-    // set resigningFirstResponder so _updateActiveState behaves the same way it does when
-    // the WebHTMLView itself is resigningFirstResponder; don't use the primary selection feedback.
-    // If the first responder is in the process of being set on the WebHTMLView itself, it will
-    // get another chance at _updateActiveState in its own becomeFirstResponder method.
-    _private->resigningFirstResponder = YES;
-    [self _updateActiveState];
-    _private->resigningFirstResponder = NO;
-}
-
 - (void)_updateFontPanel
 {
     // FIXME: NSTextView bails out if becoming or resigning first responder, for which it has ivar flags. Not
@@ -4953,23 +4942,6 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     // not reflected in the font panel. Maybe someday this will change.
 }
 
-- (unsigned)_delegateDragSourceActionMask
-{
-    ASSERT(_private->mouseDownEvent != nil);
-    WebHTMLView *topHTMLView = [self _topHTMLView];
-    if (self != topHTMLView) {
-        [topHTMLView _setMouseDownEvent:_private->mouseDownEvent];
-        unsigned result = [topHTMLView _delegateDragSourceActionMask];
-        [topHTMLView _setMouseDownEvent:nil];
-        return result;
-    }
-
-    WebView *webView = [self _webView];
-    NSPoint point = [webView convertPoint:[_private->mouseDownEvent locationInWindow] fromView:nil];
-    _private->dragSourceActionMask = [[webView _UIDelegateForwarder] webView:webView dragSourceActionMaskForPoint:point];
-    return _private->dragSourceActionMask;
-}
-
 - (BOOL)_canSmartCopyOrDelete
 {
     return [[self _webView] smartInsertDeleteEnabled] && [[self _bridge] selectionGranularity] == WordGranularity;
@@ -5001,6 +4973,12 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     return textView == _private->firstResponderTextViewAtMouseDownTime;
 }
 
+
+- (NSEvent *)_mouseDownEvent
+{
+    return _private->mouseDownEvent;
+}
+
 - (void)_pauseNullEventsForAllNetscapePlugins
 {
     NSArray *subviews = [self subviews];
@@ -5042,19 +5020,9 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     return [_private->dataSource webFrame];
 }
 
-- (void)_setInitiatedDrag:(BOOL)flag
-{
-    _private->initiatedDrag = flag;
-}
-
-- (BOOL)_initiatedDrag
-{
-    return _private->initiatedDrag;
-}
-
 - (void)copy:(id)sender
 {
-#if USING_WEBCORE_COPY
+#ifdef USING_WEBCORE_COPY
     Frame* coreFrame = core([self _frame]);
     if (coreFrame)
         coreFrame->editor()->copy();
@@ -5072,12 +5040,12 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (void)cut:(id)sender
 {
-#if USING_WEBCORE_CUT
+#ifdef USING_WEBCORE_CUT
     Frame* coreFrame = core([self _frame]);
     if (coreFrame)
         coreFrame->editor()->cut();
 #else
-    FrameMac* coreFrame = core([self _frame]);
+    Frame* coreFrame = core([self _frame]);
     if (coreFrame && coreFrame->editor()->tryDHTMLCut())
         return; // DHTML did the whole operation
     if (!coreFrame->editor()->canCut()) {
@@ -5095,12 +5063,12 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (void)paste:(id)sender
 {
-#if USING_WEBCORE_PASTE
+#ifdef USING_WEBCORE_PASTE
     Frame* coreFrame = core([self _frame]);
     if (coreFrame)
         coreFrame->editor()->paste();
 #else
-    FrameMac* coreFrame = core([self _frame]);
+    Frame* coreFrame = core([self _frame]);
     if (coreFrame && coreFrame->editor()->tryDHTMLPaste())
         return; // DHTML did the whole operation
     if (!coreFrame->editor()->canPaste())
@@ -5108,7 +5076,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     if (coreFrame && coreFrame->selectionController()->isContentRichlyEditable())
         [self _pasteWithPasteboard:[NSPasteboard generalPasteboard] allowPlainText:YES];
     else
-        [self _pasteAsPlainTextWithPasteboard:[NSPasteboard generalPasteboard]];
+        coreFrame->editor()->pasteAsPlainText();
 #endif
 }
 
@@ -5125,7 +5093,13 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
         [self close];
 }
 
-#if !BUILDING_ON_TIGER
+- (DOMDocumentFragment*)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
+{
+    BOOL discard;
+    return [self _documentFragmentFromPasteboard:pasteboard inContext:nil allowPlainText:NO chosePlainText:&discard];
+}
+
+#ifndef BUILDING_ON_TIGER
 
 - (BOOL)isGrammarCheckingEnabled
 {
@@ -5148,32 +5122,59 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     [[self _webView] toggleGrammarChecking:sender];
 }
 
-#endif /* !BUILDING_ON_TIGER */
+
+static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
+{
+    NSRect allScreensFrame = NSZeroRect;
+    NSArray *screens = [NSScreen screens];
+    unsigned int screenCount = [screens count];
+    unsigned int screenIndex;
+    
+    // Linear search here is warranted by the fact that nobody will ever have enough screens to make this slow
+    for (screenIndex = 0; screenIndex < screenCount; screenIndex++) {
+        NSScreen *screen = [screens objectAtIndex:screenIndex];
+        NSRect screenFrame = [screen frame];
+        if (NSEqualRects(allScreensFrame, NSZeroRect))
+            allScreensFrame = screenFrame;
+        else
+            allScreensFrame = NSUnionRect(allScreensFrame, screenFrame);
+    }
+    
+    return CGPointMake(point.x, NSMaxY(allScreensFrame) - point.y);
+}
+#endif
 
 - (void)_lookUpInDictionaryFromMenu:(id)sender
 {
-    // This should only be called when there's a selection, but play it safe.
-    if (![self _hasSelection])
+    // Dictionary API will accept a whitespace-only string and display UI as if it were real text,
+    // so bail out early to avoid that.
+    if ([[[self selectedString] _webkit_stringByTrimmingWhitespace] length] == 0)
         return;
     
-    // Soft link to dictionary-display function to avoid linking another framework (ApplicationServices/LangAnalysis)
+    // We soft link to get the function that displays the dictionary (either pop-up window or app) to avoid the performance
+    // penalty of linking to another framework. This function changed signature as well as framework between Tiger and Leopard,
+    // so the two cases are handled separately.
+#ifdef BUILDING_ON_TIGER
     static bool lookedForFunction = false;
+    
     typedef OSStatus (*ServiceWindowShowFunction)(id inWordString, NSRect inWordBoundary, UInt16 inLineDirection);
     static ServiceWindowShowFunction dictionaryServiceWindowShow;
+    
     if (!lookedForFunction) {
         const struct mach_header *frameworkImageHeader = 0;
         dictionaryServiceWindowShow = reinterpret_cast<ServiceWindowShowFunction>(
             _NSSoftLinkingGetFrameworkFuncPtr(@"ApplicationServices", @"LangAnalysis", "_DCMDictionaryServiceWindowShow", &frameworkImageHeader));
         lookedForFunction = true;
     }
+    
     if (!dictionaryServiceWindowShow) {
         LOG_ERROR("Couldn't find _DCMDictionaryServiceWindowShow"); 
         return;
     }
-
+    
     // FIXME: must check for right-to-left here
     NSWritingDirection writingDirection = NSWritingDirectionLeftToRight;
-
+    
     NSAttributedString *attrString = [self selectedAttributedString];
     // FIXME: the dictionary API expects the rect for the first line of selection. Passing
     // the rect for the entire selection, as we do here, positions the pop-up window near
@@ -5182,6 +5183,41 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     rect.origin = [[self window] convertBaseToScreen:rect.origin];
     NSData *data = [attrString RTFFromRange:NSMakeRange(0, [attrString length]) documentAttributes:nil];
     dictionaryServiceWindowShow(data, rect, (writingDirection == NSWritingDirectionRightToLeft) ? 1 : 0);
+#else
+    static bool lookedForFunction = false;
+    
+    typedef void (*ServiceWindowShowFunction)(id unusedDictionaryRef, id inWordString, CFRange selectionRange, id unusedFont, CGPoint textOrigin, Boolean verticalText, id unusedTransform);
+    static ServiceWindowShowFunction dictionaryServiceWindowShow;
+    
+    if (!lookedForFunction) {
+        const struct mach_header *frameworkImageHeader = 0;
+        dictionaryServiceWindowShow = reinterpret_cast<ServiceWindowShowFunction>(
+            _NSSoftLinkingGetFrameworkFuncPtr(nil, @"DictionaryServices", "_DCSShowDictionaryServiceWindow", &frameworkImageHeader));
+        lookedForFunction = true;
+    }
+        
+    if (!dictionaryServiceWindowShow) {
+        LOG_ERROR("Couldn't find _DCSShowDictionaryServiceWindow"); 
+        return;
+    }
+    
+    // The DictionaryServices API requires the origin, in CG screen coordinates, of the first character of text in the selection.
+    // FIXME 4945808: We approximate this in a way that works well when a single word is selected, and less well in some other cases
+    // (but no worse than we did in Tiger)
+    NSAttributedString *attrString = [self selectedAttributedString];
+    NSRect rect = core([self _frame])->visibleSelectionRect();
+    
+    NSDictionary *attributes = [attrString fontAttributesInRange:NSMakeRange(0,1)];
+    NSFont *font = [attributes objectForKey:NSFontAttributeName];
+    if (font)
+        rect.origin.y += [font ascender];
+    
+    NSPoint windowPoint = [self convertPoint:rect.origin toView:nil];
+    NSPoint screenPoint = [[self window] convertBaseToScreen:windowPoint];
+    
+    dictionaryServiceWindowShow(nil, attrString, CFRangeMake(0, [attrString length]), nil, 
+                                coreGraphicsScreenPointForAppKitScreenPoint(screenPoint), false, nil);
+#endif    
 }
 
 - (void)_hoverFeedbackSuspendedChanged
@@ -5189,6 +5225,20 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     [self _updateMouseoverWithFakeEvent];
 }
 
+- (BOOL)_interceptEditingKeyEvent:(KeyboardEvent *)event
+{
+    // Ask AppKit to process the key event -- it will call back with either insertText or doCommandBySelector.
+    WebHTMLViewInterpretKeyEventsParameters parameters;
+    parameters.eventWasHandled = false;
+    if (const PlatformKeyboardEvent* platformEvent = event->keyEvent()) {
+        parameters.event = event;
+        _private->interpretKeyEventsParameters = &parameters;
+        [self interpretKeyEvents:[NSArray arrayWithObject:platformEvent->macEvent()]];
+        _private->interpretKeyEventsParameters = 0;
+    }
+    return parameters.eventWasHandled;
+}
+
 @end
 
 @implementation WebHTMLView (WebNSTextInputSupport)
@@ -5196,15 +5246,17 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 - (NSArray *)validAttributesForMarkedText
 {
     static NSArray *validAttributes;
-    if (!validAttributes)
-        validAttributes = [[NSArray allocWithZone:[self zone]] initWithObjects:
+    if (!validAttributes) {
+        validAttributes = [[NSArray alloc] initWithObjects:
             NSUnderlineStyleAttributeName, NSUnderlineColorAttributeName,
             NSMarkedClauseSegmentAttributeName, NSTextInputReplacementRangeAttributeName, nil];
-    // NSText also supports the following attributes, but it's
-    // hard to tell which are really required for text input to
-    // work well; I have not seen any input method make use of them yet.
-    //     NSFontAttributeName, NSForegroundColorAttributeName,
-    //     NSBackgroundColorAttributeName, NSLanguageAttributeName.
+        // NSText also supports the following attributes, but it's
+        // hard to tell which are really required for text input to
+        // work well; I have not seen any input method make use of them yet.
+        //     NSFontAttributeName, NSForegroundColorAttributeName,
+        //     NSBackgroundColorAttributeName, NSLanguageAttributeName.
+        CFRetain(validAttributes);
+    }
     return validAttributes;
 }
 
@@ -5292,18 +5344,15 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (void)unmarkText
 {
-    [[self _bridge] setMarkedTextDOMRange:nil customAttributes:nil ranges:nil];
-}
+    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
+    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
+    _private->interpretKeyEventsParameters = 0;
 
-- (void)_selectMarkedText
-{
-    if ([self hasMarkedText]) {
-        WebFrameBridge *bridge = [self _bridge];
-        DOMRange *markedTextRange = [bridge markedTextDOMRange];
-        Frame* coreFrame = core([self _frame]);
-        if (coreFrame)
-            selectRange(coreFrame->selectionController(), core(markedTextRange), DOWNSTREAM, false);
-    }
+    if (parameters)
+        parameters->eventWasHandled = YES;
+
+    if (Frame* coreFrame = core([self _frame]))
+        coreFrame->editor()->unmarkText();
 }
 
 - (void)_selectRangeInMarkedText:(NSRange)range
@@ -5323,8 +5372,10 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     [selectedRange setEnd:[markedTextRange startContainer] offset:selectionEnd];
 
     Frame* coreFrame = core([self _frame]);
-    if (coreFrame)
-        selectRange(coreFrame->selectionController(), core(selectedRange), DOWNSTREAM, false);
+    if (coreFrame) {
+        ExceptionCode ec = 0;
+        coreFrame->selectionController()->setSelectedRange(core(selectedRange), DOWNSTREAM, false, ec);
+    }
 }
 
 - (void)_extractAttributes:(NSArray **)a ranges:(NSArray **)r fromAttributedString:(NSAttributedString *)string
@@ -5346,6 +5397,17 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (void)setMarkedText:(id)string selectedRange:(NSRange)newSelRange
 {
+    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
+    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
+    _private->interpretKeyEventsParameters = 0;
+
+    if (parameters)
+        parameters->eventWasHandled = YES;
+
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return;
+
     WebFrameBridge *bridge = [self _bridge];
 
     if (![self _isEditable])
@@ -5363,11 +5425,11 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
             [[self _bridge] selectNSRange:NSRangeFromString(rangeString)];
     }
 
-    _private->ignoreMarkedTextSelectionChange = YES;
+    coreFrame->editor()->setIgnoreMarkedTextSelectionChange(true);
 
     // if we had marked text already, we need to make sure to replace
     // that, instead of the selection/caret
-    [self _selectMarkedText];
+    coreFrame->editor()->selectMarkedText();
 
     NSString *text = string;
     NSArray *attributes = nil;
@@ -5382,65 +5444,75 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     if ([self hasMarkedText])
         [self _selectRangeInMarkedText:newSelRange];
 
-    _private->ignoreMarkedTextSelectionChange = NO;
+    coreFrame->editor()->setIgnoreMarkedTextSelectionChange(false);
 }
 
 - (void)doCommandBySelector:(SEL)aSelector
 {
-    WebView *webView = [self _webView];
-    if (![[webView _editingDelegateForwarder] webView:webView doCommandBySelector:aSelector])
-        [super doCommandBySelector:aSelector];
-}
+    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
+    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
+    _private->interpretKeyEventsParameters = 0;
 
-- (void)_discardMarkedText
-{
-    if (![self hasMarkedText])
+    if (aSelector == @selector(noop:))
         return;
 
-    _private->ignoreMarkedTextSelectionChange = YES;
+    KeyboardEvent* event = parameters ? parameters->event : 0;
+    bool eventWasHandled = true;
 
-    [self _selectMarkedText];
-    [self unmarkText];
-    [[NSInputManager currentInputManager] markedTextAbandoned:self];
-    // FIXME: Should we be calling the delegate here?
-    if (Frame* coreFrame = core([self _frame]))
-        coreFrame->editor()->deleteSelectionWithSmartDelete(false);
-
-    _private->ignoreMarkedTextSelectionChange = NO;
-}
-
-- (void)_insertText:(NSString *)text selectInsertedText:(BOOL)selectText
-{
-    if (text == nil || [text length] == 0 || (![self _isEditable] && ![self hasMarkedText]))
-        return;
-
-    if (![self _shouldReplaceSelectionWithText:text givenAction:WebViewInsertActionTyped]) {
-        [self _discardMarkedText];
-        return;
+    WebView *webView = [self _webView];
+    if (![[webView _editingDelegateForwarder] webView:webView doCommandBySelector:aSelector]) {
+        if (aSelector == @selector(insertNewline:) || aSelector == @selector(insertParagraphSeparator:) || aSelector == @selector(insertNewlineIgnoringFieldEditor:))
+            eventWasHandled = [self _insertNewlineWithEvent:event isLineBreak:NO];
+        else if (aSelector == @selector(insertLineBreak:))
+            eventWasHandled = [self _insertNewlineWithEvent:event isLineBreak:YES];
+        else if (aSelector == @selector(insertTab:) || aSelector == @selector(insertTabIgnoringFieldEditor:))
+            eventWasHandled = [self _insertTabWithEvent:event isBackTab:NO];
+        else if (aSelector == @selector(insertBacktab:))
+            eventWasHandled = [self _insertTabWithEvent:event isBackTab:YES];
+        else
+            [super doCommandBySelector:aSelector];
     }
 
-    _private->ignoreMarkedTextSelectionChange = YES;
-
-    // If we had marked text, we replace that, instead of the selection/caret.
-    [self _selectMarkedText];
-
-    [[self _bridge] insertText:text selectInsertedText:selectText];
-
-    _private->ignoreMarkedTextSelectionChange = NO;
-
-    // Inserting unmarks any marked text.
-    [self unmarkText];
+    if (parameters)
+        parameters->eventWasHandled = eventWasHandled;
 }
 
 - (void)insertText:(id)string
 {
-    // We don't yet support inserting an attributed string but input methods don't appear to require this.
+    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
+    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
+    _private->interpretKeyEventsParameters = 0;
+
+    // We don't support inserting an attributed string but input methods don't appear to require this.
     NSString *text;
     if ([string isKindOfClass:[NSAttributedString class]])
         text = [string string];
     else
         text = string;
-    [self _insertText:text selectInsertedText:NO];
+
+    bool eventHandled = false;
+    if ([text length]) {
+        Frame* coreFrame = core([self _frame]);
+        KeyboardEvent* event = parameters ? parameters->event : 0;
+        String eventText = text;
+        eventText.replace(NSBackTabCharacter, NSTabCharacter); // same thing is done in KeyEventMac.mm in WebCore
+        eventHandled = coreFrame && coreFrame->eventHandler()->handleTextInputEvent(eventText, event);
+    }
+
+    if (parameters)
+        parameters->eventWasHandled = eventHandled;
+}
+
+- (BOOL)_insertNewlineWithEvent:(KeyboardEvent*)event isLineBreak:(BOOL)isLineBreak
+{
+    Frame* coreFrame = core([self _frame]);
+    return coreFrame && coreFrame->eventHandler()->handleTextInputEvent("\n", event, isLineBreak);
+}
+
+- (BOOL)_insertTabWithEvent:(KeyboardEvent*)event isBackTab:(BOOL)isBackTab
+{
+    Frame* coreFrame = core([self _frame]);
+    return coreFrame && coreFrame->eventHandler()->handleTextInputEvent("\t", event, false, isBackTab);
 }
 
 - (BOOL)_selectionIsInsideMarkedText
@@ -5468,7 +5540,14 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (void)_updateSelectionForInputManager
 {
-    if (![self hasMarkedText] || _private->ignoreMarkedTextSelectionChange)
+    if (![self hasMarkedText])
+        return;
+
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return;
+
+    if (coreFrame->editor()->ignoreMarkedTextSelectionChange())
         return;
 
     if ([self _selectionIsInsideMarkedText]) {
@@ -5543,7 +5622,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     [_tableView setDrawsGrid:NO];
     [_tableView setCornerView:nil];
     [_tableView setHeaderView:nil];
-    [_tableView setAutoresizesAllColumnsToFit:YES];
+    [_tableView setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
     [_tableView setDelegate:self];
     [_tableView setDataSource:self];
     [_tableView setTarget:self];
@@ -5562,7 +5641,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     [scrollView release];
     [_popupWindow setHasShadow:YES];
     [_popupWindow setOneShot:YES];
-    //[_popupWindow _setForceActiveControls:YES];   // AK secret - no known problem from leaving this out
+    [_popupWindow _setForceActiveControls:YES];
     [_popupWindow setReleasedWhenClosed:NO];
 }
 
@@ -5855,7 +5934,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 {
     NSAttributedString *attributedString = [self _attributeStringFromDOMRange:[self _selectedRange]];
     if (!attributedString) {
-        FrameMac* coreFrame = core([self _frame]);
+        Frame* coreFrame = core([self _frame]);
         if (coreFrame) {
             RefPtr<Range> range = coreFrame->selectionController()->selection().toRange();
             attributedString = [NSAttributedString _web_attributedStringFromRange:range.get()];
@@ -5881,168 +5960,6 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 @implementation WebHTMLView (WebDocumentInternalProtocols)
 
-- (BOOL)_canProcessDragWithDraggingInfo:(id <NSDraggingInfo>)draggingInfo
-{
-    ASSERT([self _isTopHTMLView]);
-
-    NSPasteboard *pasteboard = [draggingInfo draggingPasteboard];
-    NSMutableSet *types = [NSMutableSet setWithArray:[pasteboard types]];
-    [types intersectSet:[NSSet setWithArray:[WebHTMLView _insertablePasteboardTypes]]];
-    if ([types count] == 0)
-        return NO;
-    if ([types count] == 1
-            && [types containsObject:NSFilenamesPboardType]
-            && ![self _imageExistsAtPaths:[pasteboard propertyListForType:NSFilenamesPboardType]])
-        return NO;
-
-    NSPoint point = [self convertPoint:[draggingInfo draggingLocation] fromView:nil];
-    NSDictionary *element = [self elementAtPoint:point allowShadowContent:YES];
-    ASSERT(element);
-    WebFrame *innerFrame = (WebFrame *)[element objectForKey:WebElementFrameKey];
-    ASSERT(innerFrame);
-    ASSERT([innerFrame isKindOfClass:[WebFrame class]]);
-    WebHTMLView* innerView = (WebHTMLView *)[[innerFrame frameView] documentView];
-    if ([[element objectForKey:WebElementDOMNodeKey] isContentEditable]) {
-        // Can't drag onto the selection being dragged.
-        if ([innerView _initiatedDrag] && [[element objectForKey:WebElementIsSelectedKey] boolValue])
-            return NO;
-        return YES;
-    }
-
-    return NO;
-}
-
-- (BOOL)_isMoveDrag:(id <NSDraggingInfo>)draggingInfo
-{
-    FrameMac* coreFrame = core([self _frame]);
-    return _private->initiatedDrag
-        && coreFrame
-        && coreFrame->selectionController()->isContentEditable()
-        && !([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask)
-        && ![[[draggingInfo draggingPasteboard] types] containsObject:NSURLPboardType];
-}
-
-- (BOOL)_isNSColorDrag:(id <NSDraggingInfo>)draggingInfo
-{
-    return [[[draggingInfo draggingPasteboard] types] containsObject:NSColorPboardType];
-}
-
-- (NSDragOperation)draggingUpdatedWithDraggingInfo:(id <NSDraggingInfo>)draggingInfo actionMask:(unsigned int)actionMask
-{
-    ASSERT([self _isTopHTMLView]);
-
-    NSDragOperation operation = NSDragOperationNone;
-    if (actionMask & WebDragDestinationActionDHTML)
-        operation = [[self _bridge] dragOperationForDraggingInfo:draggingInfo];
-    _private->webCoreHandlingDrag = (operation != NSDragOperationNone);
-
-    if ((actionMask & WebDragDestinationActionEdit) && !_private->webCoreHandlingDrag && [self _canProcessDragWithDraggingInfo:draggingInfo]) {
-        if ([self _isNSColorDrag:draggingInfo])
-            operation = NSDragOperationGeneric;
-        else {
-            WebView *webView = [self _webView];
-            [webView moveDragCaretToPoint:[webView convertPoint:[draggingInfo draggingLocation] fromView:nil]];
-            NSPoint point = [self convertPoint:[draggingInfo draggingLocation] fromView:nil];
-            NSDictionary *element = [self elementAtPoint:point allowShadowContent:YES];
-            ASSERT(element);
-            WebFrame *innerFrame = (WebFrame *)[element objectForKey:WebElementFrameKey];
-            ASSERT(innerFrame);
-            ASSERT([innerFrame isKindOfClass:[WebFrame class]]);
-            WebHTMLView* innerView = (WebHTMLView *)[[innerFrame frameView] documentView];
-            operation = [innerView _isMoveDrag:draggingInfo] ? NSDragOperationMove : NSDragOperationCopy;
-        }
-    } else
-        [[self _webView] removeDragCaret];
-
-    return operation;
-}
-
-- (void)draggingCancelledWithDraggingInfo:(id <NSDraggingInfo>)draggingInfo
-{
-    ASSERT([self _isTopHTMLView]);
-
-    [[self _bridge] dragExitedWithDraggingInfo:draggingInfo];
-    [[self _webView] removeDragCaret];
-}
-
-- (BOOL)concludeDragForDraggingInfo:(id <NSDraggingInfo>)draggingInfo actionMask:(unsigned int)actionMask
-{
-    ASSERT([self _isTopHTMLView]);
-
-    WebView *webView = [self _webView];
-    WebFrameBridge *bridge = [self _bridge];
-    if (_private->webCoreHandlingDrag) {
-        ASSERT(actionMask & WebDragDestinationActionDHTML);
-        [[webView _UIDelegateForwarder] webView:webView willPerformDragDestinationAction:WebDragDestinationActionDHTML forDraggingInfo:draggingInfo];
-        [bridge concludeDragForDraggingInfo:draggingInfo];
-        return YES;
-    }
-
-    if (!(actionMask & WebDragDestinationActionEdit))
-        return NO;
-
-    NSPoint point = [self convertPoint:[draggingInfo draggingLocation] fromView:nil];
-    NSDictionary *element = [self elementAtPoint:point allowShadowContent:YES];
-    ASSERT(element);
-    WebFrame *innerFrame = (WebFrame *)[element objectForKey:WebElementFrameKey];
-    ASSERT(innerFrame);
-    ASSERT([innerFrame isKindOfClass:[WebFrame class]]);
-    WebHTMLView* innerView = (WebHTMLView *)[[innerFrame frameView] documentView];
-    WebFrameBridge *innerBridge = [innerFrame _bridge];
-
-    if ([self _isNSColorDrag:draggingInfo]) {
-        NSColor *color = [NSColor colorFromPasteboard:[draggingInfo draggingPasteboard]];
-        if (!color)
-            return NO;
-        Frame* coreFrame = core(innerFrame);
-        if (!coreFrame)
-            return NO;
-        DOMRange *innerRange = kit(coreFrame->selectionController()->toRange().get());
-        DOMCSSStyleDeclaration *style = [self _emptyStyle];
-        [style setProperty:@"color" value:[self _colorAsString:color] priority:@""];
-        if (![[webView _editingDelegateForwarder] webView:webView
-                shouldApplyStyle:style toElementsInDOMRange:innerRange])
-            return NO;
-        [[webView _UIDelegateForwarder] webView:webView
-            willPerformDragDestinationAction:WebDragDestinationActionEdit
-            forDraggingInfo:draggingInfo];
-        coreFrame->editor()->applyStyle(core(style), EditActionSetColor);
-        return YES;
-    }
-
-    BOOL didInsert = NO;
-    if ([self _canProcessDragWithDraggingInfo:draggingInfo]) {
-        NSPasteboard *pasteboard = [draggingInfo draggingPasteboard];
-        if ([innerView _isMoveDrag:draggingInfo] || [innerBridge isDragCaretRichlyEditable]) { 
-            DOMRange *range = [innerBridge dragCaretDOMRange];
-            BOOL chosePlainText;
-            DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard
-                inContext:range allowPlainText:YES chosePlainText:&chosePlainText];
-            if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:range givenAction:WebViewInsertActionDropped]) {
-                [[webView _UIDelegateForwarder] webView:webView willPerformDragDestinationAction:WebDragDestinationActionEdit forDraggingInfo:draggingInfo];
-                if ([innerView _isMoveDrag:draggingInfo]) {
-                    BOOL smartMove = [innerBridge selectionGranularity] == WordGranularity && [self _canSmartReplaceWithPasteboard:pasteboard];
-                    [innerBridge moveSelectionToDragCaret:fragment smartMove:smartMove];
-                } else {
-                    [innerBridge setSelectionToDragCaret];
-                    [innerBridge replaceSelectionWithFragment:fragment selectReplacement:YES smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard] matchStyle:chosePlainText];
-                }
-                didInsert = YES;
-            }
-        } else {
-            NSString *text = [self _plainTextFromPasteboard:pasteboard];
-            if (text && [self _shouldInsertText:text replacingDOMRange:[innerBridge dragCaretDOMRange] givenAction:WebViewInsertActionDropped]) {
-                [[webView _UIDelegateForwarder] webView:webView willPerformDragDestinationAction:WebDragDestinationActionEdit forDraggingInfo:draggingInfo];
-                [innerBridge setSelectionToDragCaret];
-                [innerBridge replaceSelectionWithText:text selectReplacement:YES smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard]];
-                didInsert = YES;
-            }
-        }
-    }
-    [webView removeDragCaret];
-    return didInsert;
-}
-
 - (NSDictionary *)elementAtPoint:(NSPoint)point
 {
     return [self elementAtPoint:point allowShadowContent:NO];
@@ -6057,3 +5974,18 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 }
 
 @end
+
+// This is used by AppKit and is included here so that WebDataProtocolScheme is only defined once.
+@implementation NSURL (WebDataURL)
+
++ (NSURL *)_web_uniqueWebDataURL
+{
+    CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
+    NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
+    CFRelease(UUIDRef);
+    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@", WebDataProtocolScheme, UUIDString]];
+    CFRelease(UUIDString);
+    return URL;
+}
+
+@end