Fix the iOS build.
[WebKit-https.git] / Source / WebKit / mac / WebView / WebHTMLView.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3  *           (C) 2006, 2007 Graham Dennis (graham.dennis@gmail.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer. 
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution. 
14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission. 
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #import "WebHTMLView.h"
31
32 #import "DOMCSSStyleDeclarationInternal.h"
33 #import "DOMDocumentFragmentInternal.h"
34 #import "DOMDocumentInternal.h"
35 #import "DOMNodeInternal.h"
36 #import "DOMRangeInternal.h"
37 #import "WebActionMenuController.h"
38 #import "WebArchive.h"
39 #import "WebClipView.h"
40 #import "WebDOMOperationsInternal.h"
41 #import "WebDataSourceInternal.h"
42 #import "WebDefaultUIDelegate.h"
43 #import "WebDelegateImplementationCaching.h"
44 #import "WebDocumentInternal.h"
45 #import "WebDynamicScrollBarsViewInternal.h"
46 #import "WebEditingDelegate.h"
47 #import "WebElementDictionary.h"
48 #import "WebFrameInternal.h"
49 #import "WebFramePrivate.h"
50 #import "WebFrameViewInternal.h"
51 #import "WebHTMLRepresentationPrivate.h"
52 #import "WebHTMLViewInternal.h"
53 #import "WebKitLogging.h"
54 #import "WebKitNSStringExtras.h"
55 #import "WebKitVersionChecks.h"
56 #import "WebLocalizableStringsInternal.h"
57 #import "WebNSFileManagerExtras.h"
58 #import "WebNSImageExtras.h"
59 #import "WebNSObjectExtras.h"
60 #import "WebNSPrintOperationExtras.h"
61 #import "WebNSURLExtras.h"
62 #import "WebNSViewExtras.h"
63 #import "WebNetscapePluginView.h"
64 #import "WebNodeHighlight.h"
65 #import "WebPluginController.h"
66 #import "WebPreferences.h"
67 #import "WebPreferencesPrivate.h"
68 #import "WebResourcePrivate.h"
69 #import "WebTextCompletionController.h"
70 #import "WebTypesInternal.h"
71 #import "WebUIDelegatePrivate.h"
72 #import "WebViewInternal.h"
73 #import <WebCore/BlockExceptions.h>
74 #import <WebCore/CSSStyleDeclaration.h>
75 #import <WebCore/CachedImage.h>
76 #import <WebCore/CachedResourceClient.h>
77 #import <WebCore/CachedResourceLoader.h>
78 #import <WebCore/Chrome.h>
79 #import <WebCore/ColorMac.h>
80 #import <WebCore/ContextMenu.h>
81 #import <WebCore/ContextMenuController.h>
82 #import <WebCore/Document.h>
83 #import <WebCore/DocumentFragment.h>
84 #import <WebCore/DocumentMarkerController.h>
85 #import <WebCore/DragController.h>
86 #import <WebCore/DragImage.h>
87 #import <WebCore/Editor.h>
88 #import <WebCore/EditorDeleteAction.h>
89 #import <WebCore/Element.h>
90 #import <WebCore/EventHandler.h>
91 #import <WebCore/ExceptionHandlers.h>
92 #import <WebCore/FloatRect.h>
93 #import <WebCore/FocusController.h>
94 #import <WebCore/FontCache.h>
95 #import <WebCore/Frame.h>
96 #import <WebCore/FrameLoader.h>
97 #import <WebCore/FrameSelection.h>
98 #import <WebCore/FrameView.h>
99 #import <WebCore/HTMLConverter.h>
100 #import <WebCore/HTMLNames.h>
101 #import <WebCore/HitTestResult.h>
102 #import <WebCore/Image.h>
103 #import <WebCore/KeyboardEvent.h>
104 #import <WebCore/LegacyWebArchive.h>
105 #import <WebCore/MIMETypeRegistry.h>
106 #import <WebCore/MainFrame.h>
107 #import <WebCore/NSURLFileTypeMappingsSPI.h>
108 #import <WebCore/Page.h>
109 #import <WebCore/Range.h>
110 #import <WebCore/RenderView.h>
111 #import <WebCore/RenderWidget.h>
112 #import <WebCore/RuntimeApplicationChecks.h>
113 #import <WebCore/SharedBuffer.h>
114 #import <WebCore/SimpleFontData.h>
115 #import <WebCore/StyleProperties.h>
116 #import <WebCore/Text.h>
117 #import <WebCore/TextAlternativeWithRange.h>
118 #import <WebCore/TextUndoInsertionMarkupMac.h>
119 #import <WebCore/WebCoreObjCExtras.h>
120 #import <WebCore/WebNSAttributedStringExtras.h>
121 #import <WebCore/markup.h>
122 #import <WebKitLegacy/DOM.h>
123 #import <WebKitLegacy/DOMExtensions.h>
124 #import <WebKitLegacy/DOMPrivate.h>
125 #import <WebKitSystemInterface.h>
126 #import <dlfcn.h>
127 #import <limits>
128 #import <runtime/InitializeThreading.h>
129 #import <wtf/MainThread.h>
130 #import <wtf/MathExtras.h>
131 #import <wtf/ObjcRuntimeExtras.h>
132 #import <wtf/RunLoop.h>
133
134 #if !PLATFORM(IOS)
135 #import <AppKit/NSAccessibility.h>
136 #import <ApplicationServices/ApplicationServices.h>
137 #import "WebNSEventExtras.h"
138 #import "WebNSPasteboardExtras.h"
139 #import <WebCore/PlatformEventFactoryMac.h>
140 #endif
141
142 #import <QuartzCore/QuartzCore.h>
143
144 #if PLATFORM(IOS)
145 #import "WebUIKitDelegate.h"
146 #import <WebCore/KeyEventCodesIOS.h>
147 #import <WebCore/PlatformEventFactoryIOS.h>
148 #import <WebCore/WAKClipView.h>
149 #import <WebCore/WAKScrollView.h>
150 #import <WebCore/WAKViewPrivate.h>
151 #import <WebCore/WAKWindow.h>
152 #import <WebCore/WKGraphics.h>
153 #import <WebCore/WebEvent.h>
154 #endif
155
156 using namespace WebCore;
157 using namespace HTMLNames;
158 using namespace WTF;
159
160 #if PLATFORM(IOS)
161 @interface NSObject (Accessibility)
162 - (id)accessibilityHitTest:(NSPoint)point;
163 - (id)accessibilityFocusedUIElement;
164 @end
165 #endif
166
167 #if !PLATFORM(IOS)
168 @interface WebMenuTarget : NSObject {
169     WebCore::ContextMenuController* _menuController;
170 }
171 + (WebMenuTarget*)sharedMenuTarget;
172 - (WebCore::ContextMenuController*)menuController;
173 - (void)setMenuController:(WebCore::ContextMenuController*)menuController;
174 - (void)forwardContextMenuAction:(id)sender;
175 - (BOOL)validateMenuItem:(NSMenuItem *)item;
176 @end
177
178 static WebMenuTarget* target;
179
180 @implementation WebMenuTarget
181
182 + (WebMenuTarget*)sharedMenuTarget
183 {
184     if (!target)
185         target = [[WebMenuTarget alloc] init];
186     return target;
187 }
188
189 - (WebCore::ContextMenuController*)menuController
190 {
191     return _menuController;
192 }
193
194 - (void)setMenuController:(WebCore::ContextMenuController*)menuController
195 {
196     _menuController = menuController;
197 }
198
199 - (void)forwardContextMenuAction:(id)sender
200 {
201     WebCore::ContextMenuItem item(WebCore::ActionType, static_cast<WebCore::ContextMenuAction>([sender tag]), [sender title]);
202     _menuController->contextMenuItemSelected(&item);
203 }
204
205 - (BOOL)validateMenuItem:(NSMenuItem *)item
206 {
207     WebCore::ContextMenuItem coreItem(item);
208     ASSERT(_menuController->contextMenu());
209     _menuController->checkOrEnableIfNeeded(coreItem);
210     return coreItem.enabled();
211 }
212
213 @end
214
215 @interface NSWindow (BorderViewAccess)
216 - (NSView*)_web_borderView;
217 @end
218
219 @implementation NSWindow (BorderViewAccess)
220 - (NSView*)_web_borderView
221 {
222     return _borderView;
223 }
224 @end
225
226 @interface WebResponderChainSink : NSResponder {
227     NSResponder* _lastResponderInChain;
228     BOOL _receivedUnhandledCommand;
229 }
230 - (id)initWithResponderChain:(NSResponder *)chain;
231 - (void)detach;
232 - (BOOL)receivedUnhandledCommand;
233 @end
234
235 @interface WebLayerHostingFlippedView : NSView
236 @end
237
238 @implementation WebLayerHostingFlippedView
239 - (BOOL)isFlipped
240 {
241     return YES;
242 }
243 @end
244
245 @interface WebRootLayer : CALayer
246 @end
247
248 @implementation WebRootLayer
249 - (void)renderInContext:(CGContextRef)ctx
250 {
251     // AppKit calls -[CALayer renderInContext:] to render layer-backed views
252     // into bitmap contexts, but renderInContext: doesn't capture mask layers
253     // (<rdar://problem/9539526>), so we can't rely on it. Since our layer
254     // contents will have already been rendered by drawRect:, we can safely make
255     // this a NOOP.
256 }
257 @end
258
259 // if YES, do the standard NSView hit test (which can't give the right result when HTML overlaps a view)
260 static BOOL forceNSViewHitTest;
261
262 // if YES, do the "top WebHTMLView" hit test (which we'd like to do all the time but can't because of Java requirements [see bug 4349721])
263 static BOOL forceWebHTMLViewHitTest;
264 #endif // !PLATFORM(IOS)
265
266 static WebHTMLView *lastHitView;
267
268 #if !PLATFORM(IOS)
269 static bool needsCursorRectsSupportAtPoint(NSWindow* window, NSPoint point)
270 {
271     forceNSViewHitTest = YES;
272     NSView* view = [[window _web_borderView] hitTest:point];
273     forceNSViewHitTest = NO;
274
275     // WebHTMLView doesn't use cursor rects.
276     if ([view isKindOfClass:[WebHTMLView class]])
277         return false;
278
279 #if ENABLE(NETSCAPE_PLUGIN_API)
280     // Neither do NPAPI plug-ins.
281     if ([view isKindOfClass:[WebBaseNetscapePluginView class]])
282         return false;
283 #endif
284
285     // Non-Web content, WebPDFView, and WebKit plug-ins use normal cursor handling.
286     return true;
287 }
288
289
290 static IMP oldSetCursorForMouseLocationIMP;
291
292 // Overriding an internal method is a hack; <rdar://problem/7662987> tracks finding a better solution.
293 static void setCursor(NSWindow *self, SEL cmd, NSPoint point)
294 {
295     if (needsCursorRectsSupportAtPoint(self, point))
296         wtfCallIMP<id>(oldSetCursorForMouseLocationIMP, self, cmd, point);
297 }
298
299 #endif
300
301 extern "C" {
302
303 // Need to declare these attribute names because AppKit exports them but does not make them available in API or SPI headers.
304
305 extern NSString *NSMarkedClauseSegmentAttributeName;
306 extern NSString *NSTextInputReplacementRangeAttributeName;
307
308 }
309
310 @interface NSView (WebNSViewDetails)
311 - (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView;
312 - (void)_recursiveDisplayAllDirtyWithLockFocus:(BOOL)needsLockFocus visRect:(NSRect)visRect;
313 #if !PLATFORM(IOS)
314 - (void)_recursive:(BOOL)recurse displayRectIgnoringOpacity:(NSRect)displayRect inContext:(NSGraphicsContext *)context topView:(BOOL)topView;
315 - (void)_recursive:(BOOL)recurseX displayRectIgnoringOpacity:(NSRect)displayRect inGraphicsContext:(NSGraphicsContext *)graphicsContext CGContext:(CGContextRef)ctx topView:(BOOL)isTopView shouldChangeFontReferenceColor:(BOOL)shouldChangeFontReferenceColor;
316 #endif
317 - (NSRect)_dirtyRect;
318 - (void)_setDrawsOwnDescendants:(BOOL)drawsOwnDescendants;
319 - (BOOL)_drawnByAncestor;
320 - (void)_invalidateGStatesForTree;
321 - (void)_propagateDirtyRectsToOpaqueAncestors;
322 - (void)_windowChangedKeyState;
323 #if PLATFORM(IOS)
324 - (void)centerSelectionInVisibleArea:(id)sender;
325 #endif
326 @end
327
328 #if !PLATFORM(IOS)
329 static IMP oldSetNeedsDisplayInRectIMP;
330
331 static void setNeedsDisplayInRect(NSView *self, SEL cmd, NSRect invalidRect)
332 {
333     if (![self _drawnByAncestor]) {
334         wtfCallIMP<id>(oldSetNeedsDisplayInRectIMP, self, cmd, invalidRect);
335         return;
336     }
337
338     static Class webFrameViewClass = [WebFrameView class];
339     WebFrameView *enclosingWebFrameView = (WebFrameView *)self;
340     while (enclosingWebFrameView && ![enclosingWebFrameView isKindOfClass:webFrameViewClass])
341         enclosingWebFrameView = (WebFrameView *)[enclosingWebFrameView superview];
342
343     if (!enclosingWebFrameView) {
344         wtfCallIMP<id>(oldSetNeedsDisplayInRectIMP, self, cmd, invalidRect);
345         return;
346     }
347
348     Frame* coreFrame = core([enclosingWebFrameView webFrame]);
349     FrameView* frameView = coreFrame ? coreFrame->view() : 0;
350     if (!frameView || !frameView->isEnclosedInCompositingLayer()) {
351         wtfCallIMP<id>(oldSetNeedsDisplayInRectIMP, self, cmd, invalidRect);
352         return;
353     }
354
355     NSRect invalidRectInWebFrameViewCoordinates = [enclosingWebFrameView convertRect:invalidRect fromView:self];
356     IntRect invalidRectInFrameViewCoordinates(invalidRectInWebFrameViewCoordinates);
357     if (![enclosingWebFrameView isFlipped])
358         invalidRectInFrameViewCoordinates.setY(frameView->frameRect().size().height() - invalidRectInFrameViewCoordinates.maxY());
359
360     frameView->invalidateRect(invalidRectInFrameViewCoordinates);
361 }
362
363 @interface NSApplication (WebNSApplicationDetails)
364 - (void)speakString:(NSString *)string;
365 @end
366
367 @interface NSWindow (WebNSWindowDetails)
368 - (id)_newFirstResponderAfterResigning;
369 @end
370
371 @interface NSAttributedString (WebNSAttributedStringDetails)
372 - (id)_initWithDOMRange:(DOMRange *)range;
373 - (DOMDocumentFragment *)_documentFromRange:(NSRange)range document:(DOMDocument *)document documentAttributes:(NSDictionary *)dict subresources:(NSArray **)subresources;
374 @end
375
376 @interface NSSpellChecker (WebNSSpellCheckerDetails)
377 - (void)learnWord:(NSString *)word;
378 @end
379 #endif // !PLATFORM(IOS)
380
381 // By imaging to a width a little wider than the available pixels,
382 // thin pages will be scaled down a little, matching the way they
383 // print in IE and Camino. This lets them use fewer sheets than they
384 // would otherwise, which is presumably why other browsers do this.
385 // Wide pages will be scaled down more than this.
386 const float _WebHTMLViewPrintingMinimumShrinkFactor = 1.25;
387
388 // This number determines how small we are willing to reduce the page content
389 // in order to accommodate the widest line. If the page would have to be
390 // reduced smaller to make the widest line fit, we just clip instead (this
391 // behavior matches MacIE and Mozilla, at least)
392 const float _WebHTMLViewPrintingMaximumShrinkFactor = 2;
393
394 #define AUTOSCROLL_INTERVAL             0.1f
395
396 // Any non-zero value will do, but using something recognizable might help us debug some day.
397 #define TRACKING_RECT_TAG 0xBADFACE
398
399 // FIXME: This constant is copied from AppKit's _NXSmartPaste constant.
400 #define WebSmartPastePboardType @"NeXT smart paste pasteboard type"
401
402 #define STANDARD_WEIGHT 5
403 #define MIN_BOLD_WEIGHT 7
404 #define STANDARD_BOLD_WEIGHT 9
405
406 // Fake URL scheme.
407 #define WebDataProtocolScheme @"webkit-fake-url"
408
409 // <rdar://problem/4985524> References to WebCoreScrollView as a subview of a WebHTMLView may be present
410 // in some NIB files, so NSUnarchiver must be still able to look up this now-unused class.
411 @interface WebCoreScrollView : NSScrollView
412 @end
413
414 @implementation WebCoreScrollView
415 @end
416
417 #if !PLATFORM(IOS)
418 // We need this to be able to safely reference the CachedImage for the promised drag data
419 static CachedImageClient* promisedDataClient()
420 {
421     static CachedImageClient* staticCachedResourceClient = new CachedImageClient;
422     return staticCachedResourceClient;
423 }
424 #endif
425
426 #if PLATFORM(IOS)
427 static NSString * const WebMarkedTextUpdatedNotification = @"WebMarkedTextUpdated";
428 #endif
429
430 @interface WebHTMLView (WebHTMLViewFileInternal)
431 #if !PLATFORM(IOS)
432 - (BOOL)_imageExistsAtPaths:(NSArray *)paths;
433 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard inContext:(DOMRange *)context allowPlainText:(BOOL)allowPlainText;
434 - (NSString *)_plainTextFromPasteboard:(NSPasteboard *)pasteboard;
435 - (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText;
436 - (void)_pasteAsPlainTextWithPasteboard:(NSPasteboard *)pasteboard;
437 - (void)_postFakeMouseMovedEventForFlagsChangedEvent:(NSEvent *)flagsChangedEvent;
438 - (void)_removeSuperviewObservers;
439 - (void)_removeWindowObservers;
440 #endif
441 - (BOOL)_shouldInsertFragment:(DOMDocumentFragment *)fragment replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action;
442 - (BOOL)_shouldInsertText:(NSString *)text replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action;
443 - (BOOL)_shouldReplaceSelectionWithText:(NSString *)text givenAction:(WebViewInsertAction)action;
444 - (DOMRange *)_selectedRange;
445 - (BOOL)_shouldDeleteRange:(DOMRange *)range;
446 #if !PLATFORM(IOS)
447 - (NSView *)_hitViewForEvent:(NSEvent *)event;
448 - (void)_writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard cachedAttributedString:(NSAttributedString *)attributedString;
449 #endif
450 - (DOMRange *)_documentRange;
451 #if !PLATFORM(IOS)
452 - (void)_setMouseDownEvent:(NSEvent *)event;
453 #else
454 - (void)_setMouseDownEvent:(WebEvent *)event;
455 #endif
456 - (WebHTMLView *)_topHTMLView;
457 - (BOOL)_isTopHTMLView;
458 #if !PLATFORM(IOS)
459 - (void)_web_setPrintingModeRecursive;
460 - (void)_web_setPrintingModeRecursiveAndAdjustViewSize;
461 - (void)_web_clearPrintingModeRecursive;
462 #endif
463 @end
464
465 @interface WebHTMLView (WebHTMLViewTextCheckingInternal)
466 - (void)orderFrontSubstitutionsPanel:(id)sender;
467 - (BOOL)smartInsertDeleteEnabled;
468 - (void)setSmartInsertDeleteEnabled:(BOOL)flag;
469 - (void)toggleSmartInsertDelete:(id)sender;
470 - (BOOL)isAutomaticQuoteSubstitutionEnabled;
471 - (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag;
472 - (void)toggleAutomaticQuoteSubstitution:(id)sender;
473 - (BOOL)isAutomaticLinkDetectionEnabled;
474 - (void)setAutomaticLinkDetectionEnabled:(BOOL)flag;
475 - (void)toggleAutomaticLinkDetection:(id)sender;
476 - (BOOL)isAutomaticDashSubstitutionEnabled;
477 - (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag;
478 - (void)toggleAutomaticDashSubstitution:(id)sender;
479 - (BOOL)isAutomaticTextReplacementEnabled;
480 - (void)setAutomaticTextReplacementEnabled:(BOOL)flag;
481 - (void)toggleAutomaticTextReplacement:(id)sender;
482 - (BOOL)isAutomaticSpellingCorrectionEnabled;
483 - (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag;
484 - (void)toggleAutomaticSpellingCorrection:(id)sender;
485 @end
486
487 @interface WebHTMLView (WebForwardDeclaration) // FIXME: Put this in a normal category and stop doing the forward declaration trick.
488 - (void)_setPrinting:(BOOL)printing minimumPageLogicalWidth:(float)minPageWidth logicalHeight:(float)minPageHeight originalPageWidth:(float)pageLogicalWidth originalPageHeight:(float)pageLogicalHeight maximumShrinkRatio:(float)maximumShrinkRatio adjustViewSize:(BOOL)adjustViewSize paginateScreenContent:(BOOL)paginateScreenContent;
489 #if !PLATFORM(IOS)
490 - (void)_updateSecureInputState;
491 #endif
492 @end
493
494 #if !PLATFORM(IOS)
495 @class NSTextInputContext;
496 @interface NSResponder (AppKitDetails)
497 - (NSTextInputContext *)inputContext;
498 @end
499
500 @interface NSObject (NSTextInputContextDetails)
501 - (BOOL)wantsToHandleMouseEvents;
502 - (BOOL)handleMouseEvent:(NSEvent *)event;
503 @end
504 #endif
505
506 #if !PLATFORM(IOS)
507 @interface WebHTMLView (WebNSTextInputSupport) <NSTextInput>
508 #else
509 @interface WebHTMLView (WebNSTextInputSupport)
510 #endif
511 - (void)_updateSelectionForInputManager;
512 #if PLATFORM(IOS)
513 - (void)doCommandBySelector:(SEL)selector;
514 #endif
515 @end
516
517 @interface WebHTMLView (WebEditingStyleSupport)
518 - (DOMCSSStyleDeclaration *)_emptyStyle;
519 #if !PLATFORM(IOS)
520 - (NSString *)_colorAsString:(NSColor *)color;
521 #endif
522 @end
523
524 @interface NSView (WebHTMLViewFileInternal)
525 - (void)_web_addDescendantWebHTMLViewsToArray:(NSMutableArray *) array;
526 @end
527
528 @interface NSMutableDictionary (WebHTMLViewFileInternal)
529 - (void)_web_setObjectIfNotNil:(id)object forKey:(id)key;
530 @end
531
532 struct WebHTMLViewInterpretKeyEventsParameters {
533     KeyboardEvent* event;
534     bool eventInterpretationHadSideEffects;
535     bool shouldSaveCommands;
536     bool consumedByIM;
537     bool executingSavedKeypressCommands;
538 };
539
540 @interface WebHTMLViewPrivate : NSObject {
541 @public
542     BOOL closed;
543     BOOL ignoringMouseDraggedEvents;
544     BOOL printing;
545     BOOL paginateScreenContent;
546 #if !PLATFORM(IOS)
547     BOOL observingSuperviewNotifications;
548     BOOL observingWindowNotifications;
549     
550     id savedSubviews;
551     BOOL subviewsSetAside;
552 #endif
553
554     NSView *layerHostingView;
555     BOOL drawingIntoLayer;
556
557 #if !PLATFORM(IOS)
558     NSEvent *mouseDownEvent; // Kept after handling the event.
559 #else
560     WebEvent *mouseDownEvent; // Kept after handling the event.
561 #endif
562     BOOL handlingMouseDownEvent;
563 #if !PLATFORM(IOS)    
564     NSEvent *keyDownEvent; // Kept after handling the event.
565 #else
566     WebEvent *keyDownEvent; // Kept after handling the event.
567 #endif
568
569     // A WebHTMLView has a single input context, but we return nil when in non-editable content to avoid making input methods do their work.
570     // This state is saved each time selection changes, because computing it causes style recalc, which is not always safe to do.
571     BOOL exposeInputContext;
572
573 #if !PLATFORM(IOS)
574     // Track whether the view has set a secure input state.
575     BOOL isInSecureInputState;
576
577     BOOL _forceUpdateSecureInputState;
578 #endif
579
580     NSPoint lastScrollPosition;
581     BOOL inScrollPositionChanged;
582
583     WebPluginController *pluginController;
584     
585     NSString *toolTip;
586 #if !PLATFORM(IOS)
587     NSToolTipTag lastToolTipTag;
588 #endif
589     id trackingRectOwner;
590     void *trackingRectUserData;
591     
592     NSTimer *autoscrollTimer;
593 #if !PLATFORM(IOS)    
594     NSEvent *autoscrollTriggerEvent;
595 #else
596     WebEvent *autoscrollTriggerEvent;
597 #endif
598     
599     NSArray *pageRects;
600
601 #if !PLATFORM(IOS)
602     WebTextCompletionController *completionController;
603 #endif
604     
605     BOOL transparentBackground;
606
607     WebHTMLViewInterpretKeyEventsParameters* interpretKeyEventsParameters;
608     
609     WebDataSource *dataSource;
610 #if !PLATFORM(IOS)
611     WebCore::CachedImage* promisedDragTIFFDataSource;
612 #endif
613
614     SEL selectorForDoCommandBySelector;
615
616 #if !PLATFORM(IOS)
617     BOOL installedTrackingArea;
618     id flagsChangedEventMonitor;
619 #endif
620
621 #ifndef NDEBUG
622     BOOL enumeratingSubviews;
623 #endif
624 }
625 - (void)clear;
626 @end
627
628 #if !PLATFORM(IOS)
629 static NSCellStateValue kit(TriState state)
630 {
631     switch (state) {
632         case FalseTriState:
633             return NSOffState;
634         case TrueTriState:
635             return NSOnState;
636         case MixedTriState:
637             return NSMixedState;
638     }
639     ASSERT_NOT_REACHED();
640     return NSOffState;
641 }
642 #endif
643
644 @implementation WebHTMLViewPrivate
645
646 + (void)initialize
647 {
648 #if !PLATFORM(IOS)
649     JSC::initializeThreading();
650     WTF::initializeMainThreadToProcessMainThread();
651     RunLoop::initializeMainRunLoop();
652 #endif
653     WebCoreObjCFinalizeOnMainThread(self);
654     
655 #if !PLATFORM(IOS)
656     if (!oldSetCursorForMouseLocationIMP) {
657         Method setCursorMethod = class_getInstanceMethod([NSWindow class], @selector(_setCursorForMouseLocation:));
658         ASSERT(setCursorMethod);
659         oldSetCursorForMouseLocationIMP = method_setImplementation(setCursorMethod, (IMP)setCursor);
660         ASSERT(oldSetCursorForMouseLocationIMP);
661     }
662
663     if (!oldSetNeedsDisplayInRectIMP) {
664         Method setNeedsDisplayInRectMethod = class_getInstanceMethod([NSView class], @selector(setNeedsDisplayInRect:));
665         ASSERT(setNeedsDisplayInRectMethod);
666         oldSetNeedsDisplayInRectIMP = method_setImplementation(setNeedsDisplayInRectMethod, (IMP)setNeedsDisplayInRect);
667         ASSERT(oldSetNeedsDisplayInRectIMP);
668     }
669
670 #endif
671
672 }
673
674 - (void)dealloc
675 {
676     if (WebCoreObjCScheduleDeallocateOnMainThread([WebHTMLViewPrivate class], self))
677         return;
678
679     ASSERT(!autoscrollTimer);
680     ASSERT(!autoscrollTriggerEvent);
681     
682 #if !PLATFORM(IOS)
683     [mouseDownEvent release];
684     [keyDownEvent release];
685 #else
686     if (mouseDownEvent)
687         CFRelease (mouseDownEvent);
688     if (keyDownEvent)
689         CFRelease(keyDownEvent);
690 #endif
691     [pluginController release];
692     [toolTip release];
693 #if !PLATFORM(IOS)
694     [completionController release];
695 #endif
696     [dataSource release];
697 #if !PLATFORM(IOS)
698     if (promisedDragTIFFDataSource)
699         promisedDragTIFFDataSource->removeClient(promisedDataClient());
700 #endif
701
702     [super dealloc];
703 }
704
705 - (void)finalize
706 {
707     ASSERT_MAIN_THREAD();
708
709 #if !PLATFORM(IOS)
710     if (promisedDragTIFFDataSource)
711         promisedDragTIFFDataSource->removeClient(promisedDataClient());
712 #endif
713
714     [super finalize];
715 }
716
717 - (void)clear
718 {
719 #if !PLATFORM(IOS)
720     [mouseDownEvent release];
721     [keyDownEvent release];
722 #else
723     if (mouseDownEvent)
724         CFRelease(mouseDownEvent);
725     if (keyDownEvent)
726         CFRelease(keyDownEvent);
727 #endif
728     [pluginController release];
729     [toolTip release];
730 #if !PLATFORM(IOS)
731     [completionController release];
732 #endif
733     [dataSource release];
734 #if !PLATFORM(IOS)
735     if (promisedDragTIFFDataSource)
736         promisedDragTIFFDataSource->removeClient(promisedDataClient());
737 #endif
738
739     mouseDownEvent = nil;
740     keyDownEvent = nil;
741     pluginController = nil;
742     toolTip = nil;
743 #if !PLATFORM(IOS)
744     completionController = nil;
745 #endif
746     dataSource = nil;
747 #if !PLATFORM(IOS)
748     promisedDragTIFFDataSource = 0;
749 #endif
750
751     layerHostingView = nil;
752 }
753
754 @end
755
756 @implementation WebHTMLView (WebHTMLViewFileInternal)
757
758 - (DOMRange *)_documentRange
759 {
760     return [[[self _frame] DOMDocument] _documentRange];
761 }
762
763 #if !PLATFORM(IOS)
764 - (BOOL)_imageExistsAtPaths:(NSArray *)paths
765 {
766     NSEnumerator *enumerator = [paths objectEnumerator];
767     NSString *path;
768     
769     while ((path = [enumerator nextObject]) != nil) {
770         NSString *MIMEType = [[NSURLFileTypeMappings sharedMappings] MIMETypeForExtension:[path pathExtension]];
771         if (MIMETypeRegistry::isSupportedImageResourceMIMEType(MIMEType))
772             return YES;
773     }
774     
775     return NO;
776 }
777 #endif
778
779 - (WebDataSource *)_dataSource
780 {
781     return _private->dataSource;
782 }
783
784 - (WebView *)_webView
785 {
786     return [_private->dataSource _webView];
787 }
788
789 - (WebFrameView *)_frameView
790 {
791     return [[_private->dataSource webFrame] frameView];
792 }
793
794 #if !PLATFORM(IOS)
795 - (DOMDocumentFragment *)_documentFragmentWithPaths:(NSArray *)paths
796 {
797     DOMDocumentFragment *fragment;
798     NSEnumerator *enumerator = [paths objectEnumerator];
799     NSMutableArray *domNodes = [[NSMutableArray alloc] init];
800     NSString *path;
801     
802     while ((path = [enumerator nextObject]) != nil) {
803         // Non-image file types; _web_userVisibleString is appropriate here because this will
804         // be pasted as visible text.
805         NSString *url = [[[NSURL fileURLWithPath:path] _webkit_canonicalize] _web_userVisibleString];
806         [domNodes addObject:[[[self _frame] DOMDocument] createTextNode: url]];
807     }
808     
809     fragment = [[self _frame] _documentFragmentWithNodesAsParagraphs:domNodes]; 
810     
811     [domNodes release];
812     
813     return [fragment firstChild] != nil ? fragment : nil;
814 }
815
816 + (NSArray *)_excludedElementsForAttributedStringConversion
817 {
818     static NSArray *elements = nil;
819     if (elements == nil) {
820         elements = [[NSArray alloc] initWithObjects:
821             // Omit style since we want style to be inline so the fragment can be easily inserted.
822             @"style",
823             // Omit xml so the result is not XHTML.
824             @"xml", 
825             // Omit tags that will get stripped when converted to a fragment anyway.
826             @"doctype", @"html", @"head", @"body",
827             // Omit deprecated tags.
828             @"applet", @"basefont", @"center", @"dir", @"font", @"isindex", @"menu", @"s", @"strike", @"u",
829             // Omit object so no file attachments are part of the fragment.
830             @"object", nil];
831         CFRetain(elements);
832     }
833     return elements;
834 }
835
836 static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
837 {
838     CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
839     NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
840     CFRelease(UUIDRef);
841     NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/%@", WebDataProtocolScheme, UUIDString, relativePart]];
842     CFRelease(UUIDString);
843
844     return URL;
845 }
846
847 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
848                                                inContext:(DOMRange *)context
849                                           allowPlainText:(BOOL)allowPlainText
850 {
851     NSArray *types = [pasteboard types];
852     DOMDocumentFragment *fragment = nil;
853
854     if ([types containsObject:WebArchivePboardType] &&
855         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
856                                                   forType:WebArchivePboardType
857                                                 inContext:context
858                                              subresources:0]))
859         return fragment;
860                                            
861     if ([types containsObject:NSFilenamesPboardType] &&
862         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
863                                                   forType:NSFilenamesPboardType
864                                                 inContext:context
865                                              subresources:0]))
866         return fragment;
867     
868     if ([types containsObject:NSHTMLPboardType] &&
869         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
870                                                   forType:NSHTMLPboardType
871                                                 inContext:context
872                                              subresources:0]))
873         return fragment;
874     
875     if ([types containsObject:NSRTFDPboardType] &&
876         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
877                                                   forType:NSRTFDPboardType
878                                                 inContext:context
879                                              subresources:0]))
880         return fragment;
881     
882     if ([types containsObject:NSRTFPboardType] &&
883         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
884                                                   forType:NSRTFPboardType
885                                                 inContext:context
886                                              subresources:0]))
887         return fragment;
888
889     if ([types containsObject:NSTIFFPboardType] &&
890         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
891                                                   forType:NSTIFFPboardType
892                                                 inContext:context
893                                              subresources:0]))
894         return fragment;
895
896     if ([types containsObject:NSPDFPboardType] &&
897         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
898                                                   forType:NSPDFPboardType
899                                                 inContext:context
900                                              subresources:0]))
901         return fragment;
902
903     if ([types containsObject:(NSString*)kUTTypePNG] &&
904         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
905                                                   forType:(NSString*)kUTTypePNG
906                                                 inContext:context
907                                              subresources:0]))
908         return fragment;
909         
910     if ([types containsObject:NSURLPboardType] &&
911         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
912                                                   forType:NSURLPboardType
913                                                 inContext:context
914                                              subresources:0]))
915         return fragment;
916         
917     if (allowPlainText && [types containsObject:NSStringPboardType] &&
918         (fragment = [self _documentFragmentFromPasteboard:pasteboard
919                                                   forType:NSStringPboardType
920                                                 inContext:context
921                                              subresources:0])) {
922         return fragment;
923     }
924     
925     return nil;
926 }
927
928 - (NSString *)_plainTextFromPasteboard:(NSPasteboard *)pasteboard
929 {
930     NSArray *types = [pasteboard types];
931     
932     if ([types containsObject:NSStringPboardType])
933         return [[pasteboard stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping];
934     
935     NSAttributedString *attributedString = nil;
936     NSString *string;
937
938     if ([types containsObject:NSRTFDPboardType])
939         attributedString = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
940     if (attributedString == nil && [types containsObject:NSRTFPboardType])
941         attributedString = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
942     if (attributedString != nil) {
943         string = [[attributedString string] copy];
944         [attributedString release];
945         return [string autorelease];
946     }
947     
948     if ([types containsObject:NSFilenamesPboardType]) {
949         string = [[pasteboard propertyListForType:NSFilenamesPboardType] componentsJoinedByString:@"\n"];
950         if (string != nil)
951             return string;
952     }
953     
954     NSURL *URL;
955     
956     if ((URL = [NSURL URLFromPasteboard:pasteboard])) {
957         string = [URL _web_userVisibleString];
958         if ([string length] > 0)
959             return string;
960     }
961     
962     return nil;
963 }
964
965 - (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText
966 {
967     WebView *webView = [[self _webView] retain];
968     [webView _setInsertionPasteboard:pasteboard];
969
970     DOMRange *range = [self _selectedRange];
971     Frame* coreFrame = core([self _frame]);
972
973     DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard inContext:range allowPlainText:allowPlainText];
974     if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:range givenAction:WebViewInsertActionPasted])
975         coreFrame->editor().pasteAsFragment(core(fragment), [self _canSmartReplaceWithPasteboard:pasteboard], false);
976
977     [webView _setInsertionPasteboard:nil];
978     [webView release];
979 }
980
981 - (void)_pasteAsPlainTextWithPasteboard:(NSPasteboard *)pasteboard 
982
983     WebView *webView = [[self _webView] retain]; 
984     [webView _setInsertionPasteboard:pasteboard]; 
985
986     NSString *text = [self _plainTextFromPasteboard:pasteboard]; 
987     if ([self _shouldReplaceSelectionWithText:text givenAction:WebViewInsertActionPasted]) 
988         [[self _frame] _replaceSelectionWithText:text selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard]]; 
989
990     [webView _setInsertionPasteboard:nil]; 
991     [webView release];
992 }
993
994 - (void)_postFakeMouseMovedEventForFlagsChangedEvent:(NSEvent *)flagsChangedEvent
995 {
996     NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved location:flagsChangedEvent.window.mouseLocationOutsideOfEventStream
997         modifierFlags:flagsChangedEvent.modifierFlags timestamp:flagsChangedEvent.timestamp windowNumber:flagsChangedEvent.windowNumber
998         context:flagsChangedEvent.context eventNumber:0 clickCount:0 pressure:0];
999
1000     [self mouseMoved:fakeEvent];
1001 }
1002
1003 // This method is needed to support Mac OS X services.
1004 - (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pasteboard 
1005
1006     Frame* coreFrame = core([self _frame]); 
1007     if (!coreFrame) 
1008         return NO; 
1009     if (coreFrame->selection().selection().isContentRichlyEditable())
1010         [self _pasteWithPasteboard:pasteboard allowPlainText:YES]; 
1011     else 
1012         [self _pasteAsPlainTextWithPasteboard:pasteboard]; 
1013     return YES; 
1014 }
1015
1016 - (void)_removeSuperviewObservers
1017 {
1018     if (!_private || !_private->observingSuperviewNotifications)
1019         return;
1020     
1021     NSView *superview = [self superview];
1022     if (!superview || ![self window])
1023         return;
1024     
1025     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
1026     [notificationCenter removeObserver:self name:NSViewFrameDidChangeNotification object:superview];
1027     [notificationCenter removeObserver:self name:NSViewBoundsDidChangeNotification object:superview];
1028     
1029     _private->observingSuperviewNotifications = false;
1030 }
1031
1032 - (void)_removeWindowObservers
1033 {
1034     if (!_private->observingWindowNotifications)
1035         return;
1036     
1037     NSWindow *window = [self window];
1038     if (!window)
1039         return;
1040     
1041     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
1042     [notificationCenter removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil];
1043     [notificationCenter removeObserver:self name:NSWindowDidResignKeyNotification object:nil];
1044     [notificationCenter removeObserver:self name:WKWindowWillOrderOnScreenNotification() object:window];
1045     [notificationCenter removeObserver:self name:WKWindowWillOrderOffScreenNotification() object:window];
1046     [notificationCenter removeObserver:self name:NSWindowWillCloseNotification object:window];
1047     
1048     _private->observingWindowNotifications = false;
1049 }
1050 #endif // !PLATFORM(IOS)
1051
1052 - (BOOL)_shouldInsertFragment:(DOMDocumentFragment *)fragment replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action
1053 {
1054     WebView *webView = [self _webView];
1055     DOMNode *child = [fragment firstChild];
1056     if ([fragment lastChild] == child && [child isKindOfClass:[DOMCharacterData class]])
1057         return [[webView _editingDelegateForwarder] webView:webView shouldInsertText:[(DOMCharacterData *)child data] replacingDOMRange:range givenAction:action];
1058     return [[webView _editingDelegateForwarder] webView:webView shouldInsertNode:fragment replacingDOMRange:range givenAction:action];
1059 }
1060
1061 - (BOOL)_shouldInsertText:(NSString *)text replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action
1062 {
1063     WebView *webView = [self _webView];
1064     return [[webView _editingDelegateForwarder] webView:webView shouldInsertText:text replacingDOMRange:range givenAction:action];
1065 }
1066
1067 - (BOOL)_shouldReplaceSelectionWithText:(NSString *)text givenAction:(WebViewInsertAction)action
1068 {
1069     return [self _shouldInsertText:text replacingDOMRange:[self _selectedRange] givenAction:action];
1070 }
1071
1072 - (DOMRange *)_selectedRange
1073 {
1074     Frame* coreFrame = core([self _frame]);
1075     return coreFrame ? kit(coreFrame->selection().toNormalizedRange().get()) : nil;
1076 }
1077
1078 - (BOOL)_shouldDeleteRange:(DOMRange *)range
1079 {
1080     Frame* coreFrame = core([self _frame]);
1081     return coreFrame && coreFrame->editor().shouldDeleteRange(core(range));
1082 }
1083
1084 #if !PLATFORM(IOS)
1085 - (NSView *)_hitViewForEvent:(NSEvent *)event
1086 {
1087     // Usually, we hack AK's hitTest method to catch all events at the topmost WebHTMLView.  
1088     // Callers of this method, however, want to query the deepest view instead.
1089     forceNSViewHitTest = YES;
1090     NSView *hitView = [(NSView *)[[self window] contentView] hitTest:[event locationInWindow]];
1091     forceNSViewHitTest = NO;    
1092     return hitView;
1093 }
1094 #endif
1095
1096 #if !PLATFORM(IOS)
1097 - (void)_writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard cachedAttributedString:(NSAttributedString *)attributedString
1098 {
1099     // Put HTML on the pasteboard.
1100     if ([types containsObject:WebArchivePboardType]) {
1101         if (RefPtr<LegacyWebArchive> coreArchive = LegacyWebArchive::createFromSelection(core([self _frame]))) {
1102             if (RetainPtr<CFDataRef> data = coreArchive ? coreArchive->rawDataRepresentation() : 0)
1103                 [pasteboard setData:(NSData *)data.get() forType:WebArchivePboardType];
1104         }
1105     }
1106     
1107     // Put the attributed string on the pasteboard (RTF/RTFD format).
1108     if ([types containsObject:NSRTFDPboardType]) {
1109         if (attributedString == nil) {
1110             attributedString = [self selectedAttributedString];
1111         }        
1112         NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
1113         [pasteboard setData:RTFDData forType:NSRTFDPboardType];
1114     }        
1115     if ([types containsObject:NSRTFPboardType]) {
1116         if (!attributedString)
1117             attributedString = [self selectedAttributedString];
1118         if ([attributedString containsAttachments])
1119             attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
1120         NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
1121         [pasteboard setData:RTFData forType:NSRTFPboardType];
1122     }
1123     
1124     // Put plain string on the pasteboard.
1125     if ([types containsObject:NSStringPboardType]) {
1126         // Map &nbsp; to a plain old space because this is better for source code, other browsers do it,
1127         // and because HTML forces you to do this any time you want two spaces in a row.
1128         NSMutableString *s = [[self selectedString] mutableCopy];
1129         const unichar NonBreakingSpaceCharacter = 0xA0;
1130         NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&NonBreakingSpaceCharacter length:1];
1131         [s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
1132         [pasteboard setString:s forType:NSStringPboardType];
1133         [s release];
1134     }
1135     
1136     if ([self _canSmartCopyOrDelete] && [types containsObject:WebSmartPastePboardType]) {
1137         [pasteboard setData:nil forType:WebSmartPastePboardType];
1138     }
1139 }
1140 #endif // !PLATFORM(IOS)
1141
1142 #if !PLATFORM(IOS)
1143 - (void)_setMouseDownEvent:(NSEvent *)event
1144 #else
1145 - (void)_setMouseDownEvent:(WebEvent *)event
1146 #endif
1147 {
1148 #if !PLATFORM(IOS)
1149     ASSERT(!event || [event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown);
1150 #else
1151     ASSERT(!event || event.type == WebEventMouseDown);
1152 #endif
1153
1154     if (event == _private->mouseDownEvent)
1155         return;
1156
1157     [event retain];
1158     [_private->mouseDownEvent release];
1159     _private->mouseDownEvent = event;
1160 }
1161
1162 - (WebHTMLView *)_topHTMLView
1163 {
1164     // FIXME: this can fail if the dataSource is nil, which happens when the WebView is tearing down from the window closing.
1165     WebHTMLView *view = (WebHTMLView *)[[[[_private->dataSource _webView] mainFrame] frameView] documentView];
1166     ASSERT(!view || [view isKindOfClass:[WebHTMLView class]]);
1167     return view;
1168 }
1169
1170 - (BOOL)_isTopHTMLView
1171 {
1172     // FIXME: this should be a cached boolean that doesn't rely on _topHTMLView since that can fail (see _topHTMLView).
1173     return self == [self _topHTMLView];
1174 }
1175
1176 #if !PLATFORM(IOS)
1177 - (void)_web_setPrintingModeRecursive
1178 {
1179     [self _setPrinting:YES minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:NO paginateScreenContent:[self _isInScreenPaginationMode]];
1180
1181 #ifndef NDEBUG
1182     _private->enumeratingSubviews = YES;
1183 #endif
1184
1185     NSMutableArray *descendantWebHTMLViews = [[NSMutableArray alloc] init];
1186
1187     [self _web_addDescendantWebHTMLViewsToArray:descendantWebHTMLViews];
1188
1189     unsigned count = [descendantWebHTMLViews count];
1190     for (unsigned i = 0; i < count; ++i)
1191         [[descendantWebHTMLViews objectAtIndex:i] _setPrinting:YES minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:NO paginateScreenContent:[self _isInScreenPaginationMode]];
1192
1193     [descendantWebHTMLViews release];
1194
1195 #ifndef NDEBUG
1196     _private->enumeratingSubviews = NO;
1197 #endif
1198 }
1199
1200 - (void)_web_clearPrintingModeRecursive
1201 {
1202     [self _setPrinting:NO minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:NO paginateScreenContent:[self _isInScreenPaginationMode]];
1203
1204 #ifndef NDEBUG
1205     _private->enumeratingSubviews = YES;
1206 #endif
1207
1208     NSMutableArray *descendantWebHTMLViews = [[NSMutableArray alloc] init];
1209
1210     [self _web_addDescendantWebHTMLViewsToArray:descendantWebHTMLViews];
1211
1212     unsigned count = [descendantWebHTMLViews count];
1213     for (unsigned i = 0; i < count; ++i)
1214         [[descendantWebHTMLViews objectAtIndex:i] _setPrinting:NO minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:NO paginateScreenContent:[self _isInScreenPaginationMode]];
1215
1216     [descendantWebHTMLViews release];
1217
1218 #ifndef NDEBUG
1219     _private->enumeratingSubviews = NO;
1220 #endif
1221 }
1222
1223 - (void)_web_setPrintingModeRecursiveAndAdjustViewSize
1224 {
1225     [self _setPrinting:YES minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
1226
1227 #ifndef NDEBUG
1228     _private->enumeratingSubviews = YES;
1229 #endif
1230
1231     NSMutableArray *descendantWebHTMLViews = [[NSMutableArray alloc] init];
1232
1233     [self _web_addDescendantWebHTMLViewsToArray:descendantWebHTMLViews];
1234
1235     unsigned count = [descendantWebHTMLViews count];
1236     for (unsigned i = 0; i < count; ++i)
1237         [[descendantWebHTMLViews objectAtIndex:i] _setPrinting:YES minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
1238
1239     [descendantWebHTMLViews release];
1240
1241 #ifndef NDEBUG
1242     _private->enumeratingSubviews = NO;
1243 #endif
1244 }
1245 #endif // !PLATFORM(IOS)
1246
1247 @end
1248
1249 @implementation WebHTMLView (WebPrivate)
1250
1251 + (NSArray *)supportedMIMETypes
1252 {
1253     return [WebHTMLRepresentation supportedMIMETypes];
1254 }
1255
1256 + (NSArray *)supportedImageMIMETypes
1257 {
1258     return [WebHTMLRepresentation supportedImageMIMETypes];
1259 }
1260
1261 + (NSArray *)supportedNonImageMIMETypes
1262 {
1263     return [WebHTMLRepresentation supportedNonImageMIMETypes];
1264 }
1265
1266 + (NSArray *)unsupportedTextMIMETypes
1267 {
1268     return [WebHTMLRepresentation unsupportedTextMIMETypes];
1269 }
1270
1271 #if PLATFORM(IOS)
1272 - (void)mouseMoved:(WebEvent *)event
1273 {
1274     Frame* frame = core([self _frame]);
1275     if (frame)
1276         frame->eventHandler().mouseMoved(event);
1277 }
1278 #endif
1279
1280 #if !PLATFORM(IOS)
1281 + (void)_postFlagsChangedEvent:(NSEvent *)flagsChangedEvent
1282 {
1283     // This is obsolete SPI needed only for older versions of Safari
1284 }
1285
1286 - (id)_bridge
1287 {
1288     // This method exists to maintain compatibility with Leopard's Dictionary.app, since it
1289     // calls _bridge to get access to convertNSRangeToDOMRange: and convertDOMRangeToNSRange:.
1290     // Return the WebFrame, which implements the compatibility methods. <rdar://problem/6002160>
1291     return [self _frame];
1292 }
1293
1294 - (void)_updateMouseoverWithFakeEvent
1295 {
1296 #pragma clang diagnostic push
1297 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1298     NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved
1299         location:[[self window] convertScreenToBase:[NSEvent mouseLocation]]
1300         modifierFlags:[[NSApp currentEvent] modifierFlags]
1301         timestamp:[NSDate timeIntervalSinceReferenceDate]
1302         windowNumber:[[self window] windowNumber]
1303         context:[[NSApp currentEvent] context]
1304         eventNumber:0 clickCount:0 pressure:0];
1305 #pragma clang diagnostic pop
1306
1307     [self _updateMouseoverWithEvent:fakeEvent];
1308 }
1309 #endif // !PLATFORM(IOS)
1310
1311 - (void)_frameOrBoundsChanged
1312 {
1313     WebView *webView = [self _webView];
1314     WebDynamicScrollBarsView *scrollView = [[[webView mainFrame] frameView] _scrollView];
1315
1316     NSPoint origin = [[self superview] bounds].origin;
1317     if (!NSEqualPoints(_private->lastScrollPosition, origin) && ![scrollView inProgrammaticScroll]) {
1318         if (Frame* coreFrame = core([self _frame])) {
1319             if (FrameView* coreView = coreFrame->view()) {
1320                 _private->inScrollPositionChanged = YES;
1321                 coreView->scrollPositionChangedViaPlatformWidget(IntPoint(_private->lastScrollPosition), IntPoint(origin));
1322                 _private->inScrollPositionChanged = NO;
1323             }
1324         }
1325     
1326 #if !PLATFORM(IOS)
1327         [_private->completionController endRevertingChange:NO moveLeft:NO];
1328 #endif
1329         
1330         [[webView _UIDelegateForwarder] webView:webView didScrollDocumentInFrameView:[self _frameView]];
1331     }
1332     _private->lastScrollPosition = origin;
1333 }
1334
1335 - (void)_setAsideSubviews
1336 {
1337 #if !PLATFORM(IOS)
1338     ASSERT(!_private->subviewsSetAside);
1339     ASSERT(_private->savedSubviews == nil);
1340     _private->savedSubviews = _subviews;
1341     // We need to keep the layer-hosting view in the subviews, otherwise the layers flash.
1342     if (_private->layerHostingView) {
1343         NSArray* newSubviews = [[NSArray alloc] initWithObjects:_private->layerHostingView, nil];
1344         _subviews = newSubviews;
1345     } else
1346         _subviews = nil;
1347     _private->subviewsSetAside = YES;
1348 #endif
1349  }
1350  
1351  - (void)_restoreSubviews
1352  {
1353 #if !PLATFORM(IOS)
1354     ASSERT(_private->subviewsSetAside);
1355     if (_private->layerHostingView) {
1356         [_subviews release];
1357         _subviews = _private->savedSubviews;
1358     } else {
1359         ASSERT(_subviews == nil);
1360         _subviews = _private->savedSubviews;
1361     }
1362     _private->savedSubviews = nil;
1363     _private->subviewsSetAside = NO;
1364 #endif
1365 }
1366
1367 #ifndef NDEBUG
1368
1369 - (void)didAddSubview:(NSView *)subview
1370 {
1371     if (_private->enumeratingSubviews)
1372         LOG(View, "A view of class %s was added during subview enumeration for layout or printing mode change. This view might paint without first receiving layout.", object_getClassName([subview class]));
1373 }
1374 #endif
1375
1376
1377 - (void)viewWillDraw
1378 {
1379     // On window close we will be called when the datasource is nil, then hit an assert in _topHTMLView
1380     // So check if the dataSource is nil before calling [self _isTopHTMLView], this can be removed
1381     // once the FIXME in _isTopHTMLView is fixed.
1382     if (_private->dataSource && [self _isTopHTMLView]) {
1383         [self _web_updateLayoutAndStyleIfNeededRecursive];
1384         [[self _webView] _flushCompositingChanges];
1385     }
1386
1387     [super viewWillDraw];
1388 }
1389
1390
1391 #if !PLATFORM(IOS)
1392 // Don't let AppKit even draw subviews. We take care of that.
1393 - (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView
1394 {
1395     // This helps when we print as part of a larger print process.
1396     // If the WebHTMLView itself is what we're printing, then we will never have to do this.
1397     BOOL wasInPrintingMode = _private->printing;
1398     BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
1399     if (isPrinting) {
1400         if (!wasInPrintingMode)
1401             [self _web_setPrintingModeRecursive];
1402         else
1403             [self _web_updateLayoutAndStyleIfNeededRecursive];
1404     } else if (wasInPrintingMode)
1405         [self _web_clearPrintingModeRecursive];
1406
1407     // There are known cases where -viewWillDraw is not called on all views being drawn.
1408     // See <rdar://problem/6964278> for example. Performing layout at this point prevents us from
1409     // trying to paint without layout (which WebCore now refuses to do, instead bailing out without
1410     // drawing at all), but we may still fail to update any regions dirtied by the layout which are
1411     // not already dirty. 
1412     if ([self _needsLayout]) {
1413         NSInteger rectCount;
1414         [self getRectsBeingDrawn:0 count:&rectCount];
1415         if (rectCount) {
1416             LOG_ERROR("View needs layout. Either -viewWillDraw wasn't called or layout was invalidated during the display operation. Performing layout now.");
1417             [self _web_updateLayoutAndStyleIfNeededRecursive];
1418         }
1419     }
1420
1421     [self _setAsideSubviews];
1422     [super _recursiveDisplayRectIfNeededIgnoringOpacity:rect isVisibleRect:isVisibleRect rectIsVisibleRectForView:visibleView topView:topView];
1423     [self _restoreSubviews];
1424
1425     if (wasInPrintingMode != isPrinting) {
1426         if (wasInPrintingMode)
1427             [self _web_setPrintingModeRecursive];
1428         else
1429             [self _web_clearPrintingModeRecursive];
1430     }
1431 }
1432
1433 // Don't let AppKit even draw subviews. We take care of that.
1434 - (void)_recursiveDisplayAllDirtyWithLockFocus:(BOOL)needsLockFocus visRect:(NSRect)visRect
1435 {
1436     BOOL needToSetAsideSubviews = !_private->subviewsSetAside;
1437
1438     BOOL wasInPrintingMode = _private->printing;
1439     BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
1440
1441     if (needToSetAsideSubviews) {
1442         // This helps when we print as part of a larger print process.
1443         // If the WebHTMLView itself is what we're printing, then we will never have to do this.
1444         if (isPrinting) {
1445             if (!wasInPrintingMode)
1446                 [self _web_setPrintingModeRecursive];
1447             else
1448                 [self _web_updateLayoutAndStyleIfNeededRecursive];
1449         } else if (wasInPrintingMode)
1450             [self _web_clearPrintingModeRecursive];
1451
1452
1453         [self _setAsideSubviews];
1454     }
1455
1456     [super _recursiveDisplayAllDirtyWithLockFocus:needsLockFocus visRect:visRect];
1457
1458     if (needToSetAsideSubviews) {
1459         if (wasInPrintingMode != isPrinting) {
1460             if (wasInPrintingMode)
1461                 [self _web_setPrintingModeRecursive];
1462             else
1463                 [self _web_clearPrintingModeRecursive];
1464         }
1465
1466         [self _restoreSubviews];
1467     }
1468 }
1469
1470 // Don't let AppKit even draw subviews. We take care of that.
1471 - (void)_recursive:(BOOL)recurse displayRectIgnoringOpacity:(NSRect)displayRect inContext:(NSGraphicsContext *)context topView:(BOOL)topView
1472 {
1473     [self _setAsideSubviews];
1474     [super _recursive:recurse displayRectIgnoringOpacity:displayRect inContext:context topView:topView];
1475     [self _restoreSubviews];
1476 }
1477
1478 // Don't let AppKit even draw subviews. We take care of that.
1479 - (void)_recursive:(BOOL)recurseX displayRectIgnoringOpacity:(NSRect)displayRect inGraphicsContext:(NSGraphicsContext *)graphicsContext CGContext:(CGContextRef)ctx topView:(BOOL)isTopView shouldChangeFontReferenceColor:(BOOL)shouldChangeFontReferenceColor
1480 {
1481     BOOL didSetAsideSubviews = NO;
1482
1483     if (!_private->subviewsSetAside) {
1484         [self _setAsideSubviews];
1485         didSetAsideSubviews = YES;
1486     }
1487     
1488     [super _recursive:recurseX displayRectIgnoringOpacity:displayRect inGraphicsContext:graphicsContext CGContext:ctx topView:isTopView shouldChangeFontReferenceColor:shouldChangeFontReferenceColor];
1489
1490     if (didSetAsideSubviews)
1491         [self _restoreSubviews];
1492 }
1493 #endif // !PLATFORM(IOS)
1494
1495 - (BOOL)_insideAnotherHTMLView
1496 {
1497     return self != [self _topHTMLView];
1498 }
1499
1500 #if !PLATFORM(IOS)
1501 static BOOL isQuickLookEvent(NSEvent *event)
1502 {
1503 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
1504     const int kCGSEventSystemSubtypeHotKeyCombinationReleased = 9;
1505     return [event type] == NSSystemDefined && [event subtype] == kCGSEventSystemSubtypeHotKeyCombinationReleased && [event data1] == 'lkup';
1506 #else
1507     return NO;
1508 #endif
1509 }
1510 #endif
1511
1512 - (NSView *)hitTest:(NSPoint)point
1513 {
1514     // WebHTMLView objects handle all events for objects inside them.
1515     // To get those events, we prevent hit testing from AppKit.
1516
1517     // But there are three exceptions to this:
1518     //   1) For right mouse clicks and control clicks we don't yet have an implementation
1519     //      that works for nested views, so we let the hit testing go through the
1520     //      standard NSView code path (needs to be fixed, see bug 4361618).
1521     //   2) Java depends on doing a hit test inside it's mouse moved handling,
1522     //      so we let the hit testing go through the standard NSView code path
1523     //      when the current event is a mouse move (except when we are calling
1524     //      from _updateMouseoverWithEvent, so we have to use a global,
1525     //      forceWebHTMLViewHitTest, for that)
1526     //   3) The acceptsFirstMouse: and shouldDelayWindowOrderingForEvent: methods
1527     //      both need to figure out which view to check with inside the WebHTMLView.
1528     //      They use a global to change the behavior of hitTest: so they can get the
1529     //      right view. The global is forceNSViewHitTest and the method they use to
1530     //      do the hit testing is _hitViewForEvent:. (But this does not work correctly
1531     //      when there is HTML overlapping the view, see bug 4361626)
1532     //   4) NSAccessibilityHitTest relies on this for checking the cursor position.
1533     //      Our check for that is whether the event is NSFlagsChanged.  This works
1534     //      for VoiceOver's Control-Option-F5 command (move focus to item under cursor)
1535     //      and Dictionary's Command-Control-D (open dictionary popup for item under cursor).
1536     //      This is of course a hack.
1537
1538     if (_private->closed)
1539         return nil;
1540
1541 #if PLATFORM(IOS)
1542     // Preserve <rdar://problem/7992472> behavior for third party applications. See <rdar://problem/8463725>.
1543     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_MULTIPLE_IFRAME_TOUCH_EVENT_DISPATCH)) {
1544         WebEvent *event = [WAKWindow currentEvent];
1545         if (event != NULL && event.type == WebEventMouseDown && [self mouse:point inRect:[self frame]])
1546             return self;
1547         NSView *view = [super hitTest:point];
1548         
1549         // Find the clicked document view
1550         while (view && ![view conformsToProtocol:@protocol(WebDocumentView)])
1551             view = [view superview];
1552             
1553         return view;
1554     }
1555 #else
1556     BOOL captureHitsOnSubviews;
1557     if (forceNSViewHitTest)
1558         captureHitsOnSubviews = NO;
1559     else if (forceWebHTMLViewHitTest)
1560         captureHitsOnSubviews = YES;
1561     else {
1562         // FIXME: Why doesn't this include mouse entered/exited events, or other mouse button events?
1563         NSEvent *event = [[self window] currentEvent];
1564         captureHitsOnSubviews = !([event type] == NSMouseMoved
1565             || [event type] == NSRightMouseDown
1566             || ([event type] == NSLeftMouseDown && ([event modifierFlags] & NSControlKeyMask) != 0)
1567             || [event type] == NSFlagsChanged
1568             || isQuickLookEvent(event));
1569     }
1570
1571     if (!captureHitsOnSubviews) {
1572         NSView* hitView = [super hitTest:point];
1573         if (_private && hitView == _private->layerHostingView)
1574             hitView = self;
1575         return hitView;
1576     }
1577 #endif // !PLATFORM(IOS)
1578
1579     if ([[self superview] mouse:point inRect:[self frame]])
1580         return self;
1581     return nil;
1582 }
1583
1584 - (void)_clearLastHitViewIfSelf
1585 {
1586     if (lastHitView == self)
1587         lastHitView = nil;
1588 }
1589
1590 #if !PLATFORM(IOS)
1591 - (NSTrackingRectTag)addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside
1592 {
1593     ASSERT(_private->trackingRectOwner == nil);
1594     _private->trackingRectOwner = owner;
1595     _private->trackingRectUserData = data;
1596     return TRACKING_RECT_TAG;
1597 }
1598
1599 - (NSTrackingRectTag)_addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside useTrackingNum:(int)tag
1600 {
1601     ASSERT(tag == 0 || tag == TRACKING_RECT_TAG);
1602     ASSERT(_private->trackingRectOwner == nil);
1603     _private->trackingRectOwner = owner;
1604     _private->trackingRectUserData = data;
1605     return TRACKING_RECT_TAG;
1606 }
1607
1608 - (void)_addTrackingRects:(NSRect *)rects owner:(id)owner userDataList:(void **)userDataList assumeInsideList:(BOOL *)assumeInsideList trackingNums:(NSTrackingRectTag *)trackingNums count:(int)count
1609 {
1610     ASSERT(count == 1);
1611     ASSERT(trackingNums[0] == 0 || trackingNums[0] == TRACKING_RECT_TAG);
1612     ASSERT(_private->trackingRectOwner == nil);
1613     _private->trackingRectOwner = owner;
1614     _private->trackingRectUserData = userDataList[0];
1615     trackingNums[0] = TRACKING_RECT_TAG;
1616 }
1617
1618 - (void)removeTrackingRect:(NSTrackingRectTag)tag
1619 {
1620     if (tag == 0)
1621         return;
1622     
1623     if (_private && (tag == TRACKING_RECT_TAG)) {
1624         _private->trackingRectOwner = nil;
1625         return;
1626     }
1627     
1628     if (_private && (tag == _private->lastToolTipTag)) {
1629         [super removeTrackingRect:tag];
1630         _private->lastToolTipTag = 0;
1631         return;
1632     }
1633     
1634     // If any other tracking rect is being removed, we don't know how it was created
1635     // and it's possible there's a leak involved (see 3500217)
1636     ASSERT_NOT_REACHED();
1637 }
1638
1639 - (void)_removeTrackingRects:(NSTrackingRectTag *)tags count:(int)count
1640 {
1641     int i;
1642     for (i = 0; i < count; ++i) {
1643         int tag = tags[i];
1644         if (tag == 0)
1645             continue;
1646         ASSERT(tag == TRACKING_RECT_TAG);
1647         if (_private != nil) {
1648             _private->trackingRectOwner = nil;
1649         }
1650     }
1651 }
1652
1653 - (void)_sendToolTipMouseExited
1654 {
1655     // Nothing matters except window, trackingNumber, and userData.
1656     NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseExited
1657         location:NSMakePoint(0, 0)
1658         modifierFlags:0
1659         timestamp:0
1660         windowNumber:[[self window] windowNumber]
1661         context:NULL
1662         eventNumber:0
1663         trackingNumber:TRACKING_RECT_TAG
1664         userData:_private->trackingRectUserData];
1665     [_private->trackingRectOwner mouseExited:fakeEvent];
1666 }
1667
1668 - (void)_sendToolTipMouseEntered
1669 {
1670     // Nothing matters except window, trackingNumber, and userData.
1671     NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseEntered
1672         location:NSMakePoint(0, 0)
1673         modifierFlags:0
1674         timestamp:0
1675         windowNumber:[[self window] windowNumber]
1676         context:NULL
1677         eventNumber:0
1678         trackingNumber:TRACKING_RECT_TAG
1679         userData:_private->trackingRectUserData];
1680     [_private->trackingRectOwner mouseEntered:fakeEvent];
1681 }
1682 #endif // !PLATFORM(IOS)
1683
1684 - (void)_setToolTip:(NSString *)string
1685 {
1686 #if !PLATFORM(IOS)
1687     NSString *toolTip = [string length] == 0 ? nil : string;
1688     NSString *oldToolTip = _private->toolTip;
1689     if ((toolTip == nil || oldToolTip == nil) ? toolTip == oldToolTip : [toolTip isEqualToString:oldToolTip]) {
1690         return;
1691     }
1692     if (oldToolTip) {
1693         [self _sendToolTipMouseExited];
1694         [oldToolTip release];
1695     }
1696     _private->toolTip = [toolTip copy];
1697     if (toolTip) {
1698         // See radar 3500217 for why we remove all tooltips rather than just the single one we created.
1699         [self removeAllToolTips];
1700         NSRect wideOpenRect = NSMakeRect(-100000, -100000, 200000, 200000);
1701         _private->lastToolTipTag = [self addToolTipRect:wideOpenRect owner:self userData:NULL];
1702         [self _sendToolTipMouseEntered];
1703     }
1704 #endif
1705 }
1706
1707 #if !PLATFORM(IOS)
1708 - (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)data
1709 {
1710     return [[_private->toolTip copy] autorelease];
1711 }
1712
1713 static bool mouseEventIsPartOfClickOrDrag(NSEvent *event)
1714 {
1715     switch ([event type]) {
1716         case NSLeftMouseDown:
1717         case NSLeftMouseUp:
1718         case NSLeftMouseDragged:
1719         case NSRightMouseDown:
1720         case NSRightMouseUp:
1721         case NSRightMouseDragged:
1722         case NSOtherMouseDown:
1723         case NSOtherMouseUp:
1724         case NSOtherMouseDragged:
1725             return true;
1726         default:
1727             return false;
1728     }
1729 }
1730
1731 - (void)_updateMouseoverWithEvent:(NSEvent *)event
1732 {
1733     if (_private->closed)
1734         return;
1735
1736     NSView *contentView = [[event window] contentView];
1737     NSPoint locationForHitTest = [[contentView superview] convertPoint:[event locationInWindow] fromView:nil];
1738     
1739     forceWebHTMLViewHitTest = YES;
1740     NSView *hitView = [contentView hitTest:locationForHitTest];
1741     forceWebHTMLViewHitTest = NO;
1742     
1743     WebHTMLView *view = nil;
1744     if ([hitView isKindOfClass:[WebHTMLView class]])
1745         view = (WebHTMLView *)hitView;    
1746
1747     if (view)
1748         [view retain];
1749
1750     if (lastHitView != view && lastHitView && [lastHitView _frame]) {
1751         // If we are moving out of a view (or frame), let's pretend the mouse moved
1752         // all the way out of that view. But we have to account for scrolling, because
1753         // WebCore doesn't understand our clipping.
1754         NSRect visibleRect = [[[[lastHitView _frame] frameView] _scrollView] documentVisibleRect];
1755         float yScroll = visibleRect.origin.y;
1756         float xScroll = visibleRect.origin.x;
1757
1758         NSEvent *event = [NSEvent mouseEventWithType:NSMouseMoved
1759             location:NSMakePoint(-1 - xScroll, -1 - yScroll)
1760             modifierFlags:[[NSApp currentEvent] modifierFlags]
1761             timestamp:[NSDate timeIntervalSinceReferenceDate]
1762             windowNumber:[[view window] windowNumber]
1763             context:[[NSApp currentEvent] context]
1764             eventNumber:0 clickCount:0 pressure:0];
1765         if (Frame* lastHitCoreFrame = core([lastHitView _frame]))
1766             lastHitCoreFrame->eventHandler().mouseMoved(event);
1767     }
1768
1769     lastHitView = view;
1770
1771     if (view) {
1772         if (Frame* coreFrame = core([view _frame])) {
1773             // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
1774             // button is currently pressed. It is possible that neither of those things will be true on Lion and
1775             // newer when legacy scrollbars are enabled, because then WebKit receives mouse events all the time. 
1776             // If it is one of those cases where the page is not active and the mouse is not pressed, then we can
1777             // fire a much more restricted and efficient scrollbars-only version of the event.
1778
1779             if ([[self window] isKeyWindow] 
1780                 || mouseEventIsPartOfClickOrDrag(event)
1781 #if ENABLE(DASHBOARD_SUPPORT)
1782                 || [[self _webView] _dashboardBehavior:WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows]
1783 #endif
1784                 ) {
1785                 coreFrame->eventHandler().mouseMoved(event);
1786             } else
1787                 coreFrame->eventHandler().passMouseMovedEventToScrollbars(event);
1788         }
1789
1790         [view release];
1791     }
1792 }
1793
1794 + (NSArray *)_insertablePasteboardTypes
1795 {
1796     static NSArray *types = nil;
1797     if (!types) {
1798         types = [[NSArray alloc] initWithObjects:WebArchivePboardType, NSHTMLPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPDFPboardType,
1799             NSURLPboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, NSColorPboardType, kUTTypePNG, nil];
1800         CFRetain(types);
1801     }
1802     return types;
1803 }
1804
1805 + (NSArray *)_selectionPasteboardTypes
1806 {
1807     // FIXME: We should put data for NSHTMLPboardType on the pasteboard but Microsoft Excel doesn't like our format of HTML (3640423).
1808     return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
1809 }
1810
1811 - (void)pasteboardChangedOwner:(NSPasteboard *)pasteboard
1812 {
1813     [self setPromisedDragTIFFDataSource:0];
1814 }
1815
1816 - (void)pasteboard:(NSPasteboard *)pasteboard provideDataForType:(NSString *)type
1817 {
1818     if ([type isEqual:NSRTFDPboardType] && [[pasteboard types] containsObject:WebArchivePboardType]) {
1819         WebArchive *archive = [[WebArchive alloc] initWithData:[pasteboard dataForType:WebArchivePboardType]];
1820         [pasteboard _web_writePromisedRTFDFromArchive:archive containsImage:[[pasteboard types] containsObject:NSTIFFPboardType]];
1821         [archive release];
1822     } else if ([type isEqual:NSTIFFPboardType] && [self promisedDragTIFFDataSource]) {
1823         if (Image* image = [self promisedDragTIFFDataSource]->image())
1824             [pasteboard setData:(NSData *)image->getTIFFRepresentation() forType:NSTIFFPboardType];
1825         [self setPromisedDragTIFFDataSource:0];
1826     }
1827 }
1828
1829 - (void)_handleAutoscrollForMouseDragged:(NSEvent *)event 
1830
1831     [self autoscroll:event]; 
1832     [self _startAutoscrollTimer:event]; 
1833
1834 #endif // !PLATFORM(IOS)
1835
1836 - (WebPluginController *)_pluginController
1837 {
1838     return _private->pluginController;
1839 }
1840
1841 #if PLATFORM(IOS)
1842 // WAKView override.
1843 - (void)layoutIfNeeded
1844 {
1845     [self _layoutIfNeeded];
1846 }
1847
1848 // WAKView override.
1849 - (void)setScale:(float)scale
1850 {
1851     [super setScale:scale];
1852     Frame* coreFrame = core([self _frame]);
1853     if (!coreFrame)
1854         return;
1855
1856     if (Page* page = coreFrame->page())
1857         page->setPageScaleFactor(scale, IntPoint());
1858
1859     [[self _webView] _documentScaleChanged];
1860 }
1861
1862 #endif
1863
1864 #if !PLATFORM(IOS)
1865 - (void)_layoutForPrinting
1866 {
1867     // Set printing mode temporarily so we can adjust the size of the view. This will allow
1868     // AppKit's pagination code to use the correct height for the page content. Leaving printing
1869     // mode on indefinitely would interfere with Mail's printing mechanism (at least), so we just
1870     // turn it off again after adjusting the size.
1871     [self _web_setPrintingModeRecursiveAndAdjustViewSize];
1872     [self _web_clearPrintingModeRecursive];
1873 }
1874 #endif
1875
1876 #if !PLATFORM(IOS)
1877 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
1878 {
1879     if (!pasteString || !rangeToReplace || ![[self _webView] smartInsertDeleteEnabled]) {
1880         if (beforeString)
1881             *beforeString = nil;
1882         if (afterString)
1883             *afterString = nil;
1884         return;
1885     }
1886     
1887     [[self _frame] _smartInsertForString:pasteString replacingRange:rangeToReplace beforeString:beforeString afterString:afterString];
1888 }
1889
1890 - (BOOL)_canSmartReplaceWithPasteboard:(NSPasteboard *)pasteboard
1891 {
1892     return [[self _webView] smartInsertDeleteEnabled] && [[pasteboard types] containsObject:WebSmartPastePboardType];
1893 }
1894
1895 - (void)_startAutoscrollTimer:(NSEvent *)triggerEvent
1896 #else
1897 - (void)_startAutoscrollTimer: (WebEvent *)triggerEvent
1898 #endif
1899 {
1900     if (_private->autoscrollTimer == nil) {
1901         _private->autoscrollTimer = [[NSTimer scheduledTimerWithTimeInterval:AUTOSCROLL_INTERVAL
1902             target:self selector:@selector(_autoscroll) userInfo:nil repeats:YES] retain];
1903         _private->autoscrollTriggerEvent = [triggerEvent retain];
1904     }
1905 }
1906
1907 // FIXME: _selectionRect is deprecated in favor of selectionRect, which is in protocol WebDocumentSelection.
1908 // We can't remove this yet because it's still in use by Mail.
1909 - (NSRect)_selectionRect
1910 {
1911     return [self selectionRect];
1912 }
1913
1914 - (void)_stopAutoscrollTimer
1915 {
1916     NSTimer *timer = _private->autoscrollTimer;
1917     _private->autoscrollTimer = nil;
1918 #if !PLATFORM(IOS)
1919     [_private->autoscrollTriggerEvent release];
1920 #else
1921     if (_private->autoscrollTriggerEvent)
1922         CFRelease (_private->autoscrollTriggerEvent);
1923 #endif
1924     _private->autoscrollTriggerEvent = nil;
1925     [timer invalidate];
1926     [timer release];
1927 }
1928
1929 - (void)_autoscroll
1930 {
1931     // Guarantee that the autoscroll timer is invalidated, even if we don't receive
1932     // a mouse up event.
1933 #if !PLATFORM(IOS)
1934     BOOL isStillDown = CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState, kCGMouseButtonLeft);   
1935 #else
1936     BOOL isStillDown = NO;
1937 #endif
1938     if (!isStillDown){
1939         [self _stopAutoscrollTimer];
1940         return;
1941     }
1942
1943 #if !PLATFORM(IOS)
1944 #pragma clang diagnostic push
1945 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1946     NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
1947         location:[[self window] convertScreenToBase:[NSEvent mouseLocation]]
1948         modifierFlags:[[NSApp currentEvent] modifierFlags]
1949         timestamp:[NSDate timeIntervalSinceReferenceDate]
1950         windowNumber:[[self window] windowNumber]
1951         context:[[NSApp currentEvent] context]
1952         eventNumber:0 clickCount:0 pressure:0];
1953 #pragma clang diagnostic pop
1954     [self mouseDragged:fakeEvent];
1955 #endif
1956 }
1957
1958 - (BOOL)_canEdit
1959 {
1960     Frame* coreFrame = core([self _frame]);
1961     return coreFrame && coreFrame->editor().canEdit();
1962 }
1963
1964 - (BOOL)_canEditRichly
1965 {
1966     Frame* coreFrame = core([self _frame]);
1967     return coreFrame && coreFrame->editor().canEditRichly();
1968 }
1969
1970 - (BOOL)_canAlterCurrentSelection
1971 {
1972     return [self _hasSelectionOrInsertionPoint] && [self _isEditable];
1973 }
1974
1975 - (BOOL)_hasSelection
1976 {
1977     Frame* coreFrame = core([self _frame]);
1978     return coreFrame && coreFrame->selection().selection().isRange();
1979 }
1980
1981 - (BOOL)_hasSelectionOrInsertionPoint
1982 {
1983     Frame* coreFrame = core([self _frame]);
1984     return coreFrame && coreFrame->selection().selection().isCaretOrRange();
1985 }
1986
1987 - (BOOL)_hasInsertionPoint
1988 {
1989     Frame* coreFrame = core([self _frame]);
1990     return coreFrame && coreFrame->selection().selection().isCaret();
1991 }
1992
1993 - (BOOL)_isEditable
1994 {
1995     Frame* coreFrame = core([self _frame]);
1996     return coreFrame && coreFrame->selection().selection().isContentEditable();
1997 }
1998
1999 - (BOOL)_transparentBackground
2000 {
2001     return _private->transparentBackground;
2002 }
2003
2004 - (void)_setTransparentBackground:(BOOL)f
2005 {
2006     _private->transparentBackground = f;
2007 }
2008
2009 #if !PLATFORM(IOS)
2010 - (NSImage *)_selectionDraggingImage
2011 {
2012     if (![self _hasSelection])
2013         return nil;
2014
2015     Frame* coreFrame = core([self _frame]);
2016     if (!coreFrame)
2017         return nil;
2018
2019     auto dragImage = createDragImageForSelection(*coreFrame);
2020     [dragImage _web_dissolveToFraction:WebDragImageAlpha];
2021
2022     return dragImage.autorelease();
2023 }
2024
2025 - (NSRect)_selectionDraggingRect
2026 {
2027     // Mail currently calls this method. We can eliminate it when Mail no longer calls it.
2028     return [self selectionRect];
2029 }
2030 #endif
2031
2032 - (DOMNode *)_insertOrderedList
2033 {
2034     Frame* coreFrame = core([self _frame]);
2035     return coreFrame ? kit(coreFrame->editor().insertOrderedList().get()) : nil;
2036 }
2037
2038 - (DOMNode *)_insertUnorderedList
2039 {
2040     Frame* coreFrame = core([self _frame]);
2041     return coreFrame ? kit(coreFrame->editor().insertUnorderedList().get()) : nil;
2042 }
2043
2044 - (BOOL)_canIncreaseSelectionListLevel
2045 {
2046     Frame* coreFrame = core([self _frame]);
2047     return coreFrame && coreFrame->editor().canIncreaseSelectionListLevel();
2048 }
2049
2050 - (BOOL)_canDecreaseSelectionListLevel
2051 {
2052     Frame* coreFrame = core([self _frame]);
2053     return coreFrame && coreFrame->editor().canDecreaseSelectionListLevel();
2054 }
2055
2056 - (DOMNode *)_increaseSelectionListLevel
2057 {
2058     Frame* coreFrame = core([self _frame]);
2059     return coreFrame ? kit(coreFrame->editor().increaseSelectionListLevel().get()) : nil;
2060 }
2061
2062 - (DOMNode *)_increaseSelectionListLevelOrdered
2063 {
2064     Frame* coreFrame = core([self _frame]);
2065     return coreFrame ? kit(coreFrame->editor().increaseSelectionListLevelOrdered().get()) : nil;
2066 }
2067
2068 - (DOMNode *)_increaseSelectionListLevelUnordered
2069 {
2070     Frame* coreFrame = core([self _frame]);
2071     return coreFrame ? kit(coreFrame->editor().increaseSelectionListLevelUnordered().get()) : nil;
2072 }
2073
2074 - (void)_decreaseSelectionListLevel
2075 {
2076     Frame* coreFrame = core([self _frame]);
2077     if (coreFrame)
2078         coreFrame->editor().decreaseSelectionListLevel();
2079 }
2080
2081 #if !PLATFORM(IOS)
2082 - (void)_writeSelectionToPasteboard:(NSPasteboard *)pasteboard
2083 {
2084     ASSERT([self _hasSelection]);
2085     NSArray *types = [self pasteboardTypesForSelection];
2086
2087     // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
2088     NSAttributedString *attributedString = [self selectedAttributedString];
2089     NSMutableArray *mutableTypes = nil;
2090     if (![attributedString containsAttachments]) {
2091         mutableTypes = [types mutableCopy];
2092         [mutableTypes removeObject:NSRTFDPboardType];
2093         types = mutableTypes;
2094     }
2095
2096     [pasteboard declareTypes:types owner:[self _topHTMLView]];
2097     [self _writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard cachedAttributedString:attributedString];
2098     [mutableTypes release];
2099 }
2100 #endif
2101
2102 - (void)close
2103 {
2104     // Check for a nil _private here in case we were created with initWithCoder. In that case, the WebView is just throwing
2105     // out the archived WebHTMLView and recreating a new one if needed. So close doesn't need to do anything in that case.
2106     if (!_private || _private->closed)
2107         return;
2108
2109     _private->closed = YES;
2110
2111     [self _clearLastHitViewIfSelf];
2112 #if !PLATFORM(IOS)
2113     [self _removeWindowObservers];
2114     [self _removeSuperviewObservers];
2115 #endif
2116     [_private->pluginController destroyAllPlugins];
2117     [_private->pluginController setDataSource:nil];
2118 #if !PLATFORM(IOS)
2119     // remove tooltips before clearing _private so removeTrackingRect: will work correctly
2120     [self removeAllToolTips];
2121
2122     if (_private->isInSecureInputState) {
2123         DisableSecureEventInput();
2124         _private->isInSecureInputState = NO;
2125     }
2126 #endif
2127
2128     [_private clear];
2129 }
2130
2131 - (BOOL)_hasHTMLDocument
2132 {
2133     Frame* coreFrame = core([self _frame]);
2134     if (!coreFrame)
2135         return NO;
2136     Document* document = coreFrame->document();
2137     return document && document->isHTMLDocument();
2138 }
2139
2140 #if !PLATFORM(IOS)
2141 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
2142                                                  forType:(NSString *)pboardType
2143                                                inContext:(DOMRange *)context
2144                                             subresources:(NSArray **)subresources
2145 {
2146     if (pboardType == WebArchivePboardType) {
2147         WebArchive *archive = [[WebArchive alloc] initWithData:[pasteboard dataForType:WebArchivePboardType]];
2148         if (subresources)
2149             *subresources = [archive subresources];
2150         DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithArchive:archive];
2151         [archive release];
2152         return fragment;
2153     }
2154     if (pboardType == NSFilenamesPboardType)
2155         return [self _documentFragmentWithPaths:[pasteboard propertyListForType:NSFilenamesPboardType]];
2156         
2157     if (pboardType == NSHTMLPboardType) {
2158         NSString *HTMLString = [pasteboard stringForType:NSHTMLPboardType];
2159         // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
2160         if ([HTMLString hasPrefix:@"Version:"]) {
2161             NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
2162             if (range.location != NSNotFound)
2163                 HTMLString = [HTMLString substringFromIndex:range.location];
2164         }
2165         if ([HTMLString length] == 0)
2166             return nil;
2167         
2168         return [[self _frame] _documentFragmentWithMarkupString:HTMLString baseURLString:nil];
2169     }
2170
2171     // The _hasHTMLDocument clause here is a workaround for a bug in NSAttributedString: Radar 5052369.
2172     // If we call _documentFromRange on an XML document we'll get "setInnerHTML: method not found".
2173     // FIXME: Remove this once bug 5052369 is fixed.
2174     if ([self _hasHTMLDocument] && (pboardType == NSRTFPboardType || pboardType == NSRTFDPboardType)) {
2175         NSAttributedString *string = nil;
2176         if (pboardType == NSRTFDPboardType)
2177             string = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
2178         if (string == nil)
2179             string = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
2180         if (string == nil)
2181             return nil;
2182             
2183         NSDictionary *documentAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
2184             [[self class] _excludedElementsForAttributedStringConversion], NSExcludedElementsDocumentAttribute,
2185             self, @"WebResourceHandler", nil];
2186         NSArray *s;
2187         
2188         BOOL wasDeferringCallbacks = [[self _webView] defersCallbacks];
2189         if (!wasDeferringCallbacks)
2190             [[self _webView] setDefersCallbacks:YES];
2191             
2192         DOMDocumentFragment *fragment = [string _documentFromRange:NSMakeRange(0, [string length]) 
2193                                                           document:[[self _frame] DOMDocument] 
2194                                                 documentAttributes:documentAttributes
2195                                                       subresources:&s];
2196         if (subresources)
2197             *subresources = s;
2198         
2199         NSEnumerator *e = [s objectEnumerator];
2200         WebResource *r;
2201         while ((r = [e nextObject]))
2202             [[self _dataSource] addSubresource:r];
2203         
2204         if (!wasDeferringCallbacks)
2205             [[self _webView] setDefersCallbacks:NO];
2206         
2207         [documentAttributes release];
2208         [string release];
2209         return fragment;
2210     }
2211     if (pboardType == NSTIFFPboardType) {
2212         WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSTIFFPboardType]
2213                                                               URL:uniqueURLWithRelativePart(@"image.tiff")
2214                                                          MIMEType:@"image/tiff" 
2215                                                  textEncodingName:nil
2216                                                         frameName:nil];
2217         DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
2218         [resource release];
2219         return fragment;
2220     }
2221     if (pboardType == NSPDFPboardType) {
2222         WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSPDFPboardType]
2223                                                               URL:uniqueURLWithRelativePart(@"application.pdf")
2224                                                          MIMEType:@"application/pdf" 
2225                                                  textEncodingName:nil
2226                                                         frameName:nil];
2227         DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
2228         [resource release];
2229         return fragment;
2230     }
2231
2232     if ([pboardType isEqualToString:(NSString*)kUTTypePNG]) {
2233         WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:(NSString*)kUTTypePNG]
2234                                                               URL:uniqueURLWithRelativePart(@"image.png")
2235                                                          MIMEType:@"image/png" 
2236                                                  textEncodingName:nil
2237                                                         frameName:nil];
2238         DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
2239         [resource release];
2240         return fragment;
2241     }
2242     if (pboardType == NSURLPboardType) {
2243         NSURL *URL = [NSURL URLFromPasteboard:pasteboard];
2244         DOMDocument* document = [[self _frame] DOMDocument];
2245         ASSERT(document);
2246         if (!document)
2247             return nil;
2248         DOMHTMLAnchorElement *anchor = (DOMHTMLAnchorElement *)[document createElement:@"a"];
2249         NSString *URLString = [URL _web_originalDataAsString]; // Original data is ASCII-only, so there is no need to precompose.
2250         if ([URLString length] == 0)
2251             return nil;
2252         NSString *URLTitleString = [[pasteboard stringForType:WebURLNamePboardType] precomposedStringWithCanonicalMapping];
2253         DOMText *text = [document createTextNode:URLTitleString];
2254         [anchor setHref:URLString];
2255         [anchor appendChild:text];
2256         DOMDocumentFragment *fragment = [document createDocumentFragment];
2257         [fragment appendChild:anchor];
2258         return fragment;
2259     }
2260     if (pboardType == NSStringPboardType) {
2261         if (!context)
2262             return nil;
2263         return kit(createFragmentFromText(*core(context), [[pasteboard stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping]).get());
2264     }
2265     return nil;
2266 }
2267 #endif // !PLATFORM(IOS)
2268
2269 #if ENABLE(NETSCAPE_PLUGIN_API) 
2270 - (void)_pauseNullEventsForAllNetscapePlugins 
2271
2272     NSArray *subviews = [self subviews]; 
2273     unsigned int subviewCount = [subviews count]; 
2274     unsigned int subviewIndex; 
2275     
2276     for (subviewIndex = 0; subviewIndex < subviewCount; subviewIndex++) { 
2277         NSView *subview = [subviews objectAtIndex:subviewIndex]; 
2278         if ([subview isKindOfClass:[WebBaseNetscapePluginView class]]) 
2279             [(WebBaseNetscapePluginView *)subview stopTimers];
2280     } 
2281
2282 #endif 
2283
2284 #if ENABLE(NETSCAPE_PLUGIN_API) 
2285 - (void)_resumeNullEventsForAllNetscapePlugins 
2286
2287     NSArray *subviews = [self subviews]; 
2288     unsigned int subviewCount = [subviews count]; 
2289     unsigned int subviewIndex; 
2290     
2291     for (subviewIndex = 0; subviewIndex < subviewCount; subviewIndex++) { 
2292         NSView *subview = [subviews objectAtIndex:subviewIndex]; 
2293         if ([subview isKindOfClass:[WebBaseNetscapePluginView class]]) 
2294             [(WebBaseNetscapePluginView *)subview restartTimers]; 
2295     } 
2296
2297 #endif 
2298
2299 - (BOOL)_isUsingAcceleratedCompositing
2300 {
2301     return _private->layerHostingView != nil;
2302 }
2303
2304 - (NSView *)_compositingLayersHostingView
2305 {
2306     return _private->layerHostingView;
2307 }
2308
2309 - (BOOL)_isInPrintMode
2310 {
2311     return _private->printing;
2312 }
2313
2314 - (BOOL)_beginPrintModeWithMinimumPageWidth:(CGFloat)minimumPageWidth height:(CGFloat)minimumPageHeight maximumPageWidth:(CGFloat)maximumPageWidth
2315 {
2316     Frame* frame = core([self _frame]);
2317     if (!frame)
2318         return NO;
2319
2320     if (frame->document() && frame->document()->isFrameSet()) {
2321         minimumPageWidth = 0;
2322         minimumPageHeight = 0;
2323     }
2324
2325     float maximumShrinkRatio = 0;
2326     if (minimumPageWidth > 0.0)
2327         maximumShrinkRatio = maximumPageWidth / minimumPageWidth;
2328
2329     [self _setPrinting:YES minimumPageLogicalWidth:minimumPageWidth logicalHeight:minimumPageHeight originalPageWidth:minimumPageWidth originalPageHeight:minimumPageHeight maximumShrinkRatio:maximumShrinkRatio adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
2330     return YES;
2331 }
2332
2333 - (BOOL)_beginPrintModeWithPageWidth:(float)pageWidth height:(float)pageHeight shrinkToFit:(BOOL)shrinkToFit
2334 {
2335     Frame* frame = core([self _frame]);
2336     if (!frame)
2337         return NO;
2338
2339     Document* document = frame->document();
2340     bool isHorizontal = !document || !document->renderView() || document->renderView()->style().isHorizontalWritingMode();
2341
2342     float pageLogicalWidth = isHorizontal ? pageWidth : pageHeight;
2343     float pageLogicalHeight = isHorizontal ? pageHeight : pageWidth;
2344     FloatSize minLayoutSize(pageLogicalWidth, pageLogicalHeight);
2345     float maximumShrinkRatio = 1;
2346
2347     // If we are a frameset just print with the layout we have onscreen, otherwise relayout
2348     // according to the page width.
2349     if (shrinkToFit && (!frame->document() || !frame->document()->isFrameSet())) {
2350         minLayoutSize = frame->resizePageRectsKeepingRatio(FloatSize(pageLogicalWidth, pageLogicalHeight), FloatSize(pageLogicalWidth * _WebHTMLViewPrintingMinimumShrinkFactor, pageLogicalHeight * _WebHTMLViewPrintingMinimumShrinkFactor));
2351         maximumShrinkRatio = _WebHTMLViewPrintingMaximumShrinkFactor / _WebHTMLViewPrintingMinimumShrinkFactor;
2352     }
2353
2354     [self _setPrinting:YES minimumPageLogicalWidth:minLayoutSize.width() logicalHeight:minLayoutSize.height() originalPageWidth:pageLogicalWidth originalPageHeight:pageLogicalHeight maximumShrinkRatio:maximumShrinkRatio adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
2355
2356     return YES;
2357 }
2358
2359 - (void)_endPrintMode
2360 {
2361     [self _setPrinting:NO minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
2362 }
2363
2364 - (BOOL)_isInScreenPaginationMode
2365 {
2366     return _private->paginateScreenContent;
2367 }
2368
2369 - (BOOL)_beginScreenPaginationModeWithPageSize:(CGSize)pageSize shrinkToFit:(BOOL)shrinkToFit
2370 {
2371     Frame* frame = core([self _frame]);
2372     if (!frame)
2373         return NO;
2374
2375     Document* document = frame->document();
2376     bool isHorizontal = !document || !document->renderView() || document->renderView()->style().isHorizontalWritingMode();
2377
2378     float pageLogicalWidth = isHorizontal ? pageSize.width : pageSize.height;
2379     float pageLogicalHeight = isHorizontal ? pageSize.height : pageSize.width;
2380     FloatSize minLayoutSize(pageLogicalWidth, pageLogicalHeight);
2381     float maximumShrinkRatio = 1;
2382
2383     // If we are a frameset just print with the layout we have onscreen, otherwise relayout
2384     // according to the page width.
2385     if (shrinkToFit && (!frame->document() || !frame->document()->isFrameSet())) {
2386         minLayoutSize = frame->resizePageRectsKeepingRatio(FloatSize(pageLogicalWidth, pageLogicalHeight), FloatSize(pageLogicalWidth * _WebHTMLViewPrintingMinimumShrinkFactor, pageLogicalHeight * _WebHTMLViewPrintingMinimumShrinkFactor));
2387         maximumShrinkRatio = _WebHTMLViewPrintingMaximumShrinkFactor / _WebHTMLViewPrintingMinimumShrinkFactor;
2388     }
2389
2390     [self _setPrinting:[self _isInPrintMode] minimumPageLogicalWidth:minLayoutSize.width() logicalHeight:minLayoutSize.height() originalPageWidth:pageLogicalWidth originalPageHeight:pageLogicalHeight maximumShrinkRatio:maximumShrinkRatio adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
2391
2392     return YES;
2393 }
2394
2395 - (void)_endScreenPaginationMode
2396 {
2397     [self _setPrinting:[self _isInPrintMode] minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:YES paginateScreenContent:NO];
2398 }
2399
2400 - (CGFloat)_adjustedBottomOfPageWithTop:(CGFloat)top bottom:(CGFloat)bottom limit:(CGFloat)bottomLimit
2401 {
2402     Frame* frame = core([self _frame]);
2403     if (!frame)
2404         return bottom;
2405
2406     FrameView* view = frame->view();
2407     if (!view)
2408         return bottom;
2409
2410     float newBottom;
2411     view->adjustPageHeightDeprecated(&newBottom, top, bottom, bottomLimit);
2412
2413 #ifdef __LP64__
2414     // If the new bottom is equal to the old bottom (when both are treated as floats), we just return the original
2415     // bottom. This prevents rounding errors that can occur when converting newBottom to a double.
2416     if (WTF::areEssentiallyEqual(static_cast<float>(bottom), newBottom))
2417         return bottom;
2418     else
2419 #endif
2420         return newBottom;
2421 }
2422
2423 #if PLATFORM(IOS)
2424 - (id)accessibilityRootElement
2425 {
2426     return [[self _frame] accessibilityRoot];
2427 }
2428 #endif
2429
2430 @end
2431
2432 @implementation NSView (WebHTMLViewFileInternal)
2433
2434 - (void)_web_addDescendantWebHTMLViewsToArray:(NSMutableArray *)array
2435 {
2436 #if PLATFORM(IOS)
2437     NSArray* _subviews = [self subviews];
2438 #endif
2439     unsigned count = [_subviews count];
2440     for (unsigned i = 0; i < count; ++i) {
2441         NSView *child = [_subviews objectAtIndex:i];
2442         if ([child isKindOfClass:[WebHTMLView class]])
2443             [array addObject:child];
2444         [child _web_addDescendantWebHTMLViewsToArray:array];
2445     }
2446 }
2447
2448 @end
2449
2450 @implementation NSMutableDictionary (WebHTMLViewFileInternal)
2451
2452 - (void)_web_setObjectIfNotNil:(id)object forKey:(id)key
2453 {
2454     if (object == nil) {
2455         [self removeObjectForKey:key];
2456     } else {
2457         [self setObject:object forKey:key];
2458     }
2459 }
2460
2461 @end
2462
2463 @implementation WebHTMLView
2464
2465 + (void)initialize
2466 {
2467 #if !PLATFORM(IOS)
2468     [NSApp registerServicesMenuSendTypes:[[self class] _selectionPasteboardTypes] 
2469                              returnTypes:[[self class] _insertablePasteboardTypes]];
2470     JSC::initializeThreading();
2471     WTF::initializeMainThreadToProcessMainThread();
2472     RunLoop::initializeMainRunLoop();
2473 #endif
2474     WebCoreObjCFinalizeOnMainThread(self);
2475 }
2476
2477 - (id)initWithFrame:(NSRect)frame
2478 {
2479     self = [super initWithFrame:frame];
2480     if (!self)
2481         return nil;
2482     
2483 #if !PLATFORM(IOS)
2484     [self setFocusRingType:NSFocusRingTypeNone];
2485 #endif
2486     
2487     // Make all drawing go through us instead of subviews.
2488     [self _setDrawsOwnDescendants:YES];
2489     
2490     _private = [[WebHTMLViewPrivate alloc] init];
2491
2492     _private->pluginController = [[WebPluginController alloc] initWithDocumentView:self];
2493 #if PLATFORM(IOS)
2494     [[NSNotificationCenter defaultCenter] 
2495             addObserver:self selector:@selector(markedTextUpdate:) 
2496                    name:WebMarkedTextUpdatedNotification object:nil];
2497 #endif
2498     
2499     return self;
2500 }
2501
2502 - (void)dealloc
2503 {
2504     if (WebCoreObjCScheduleDeallocateOnMainThread([WebHTMLView class], self))
2505         return;
2506
2507 #if PLATFORM(IOS)
2508     [[NSNotificationCenter defaultCenter] removeObserver:self name:WebMarkedTextUpdatedNotification object:nil];
2509 #endif
2510
2511     // We can't assert that close has already been called because
2512     // this view can be removed from it's superview, even though
2513     // it could be needed later, so close if needed.
2514     [self close];
2515     [_private release];
2516     _private = nil;
2517     [super dealloc];
2518 }
2519
2520 - (void)finalize
2521 {
2522     ASSERT_MAIN_THREAD();
2523     // We can't assert that close has already been called because
2524     // this view can be removed from it's superview, even though
2525     // it could be needed later, so close if needed.
2526     [self close];
2527     [super finalize];
2528 }
2529
2530 // Returns YES if the delegate returns YES (so we should do no more work).
2531 - (BOOL)callDelegateDoCommandBySelectorIfNeeded:(SEL)selector
2532 {
2533     BOOL callerAlreadyCalledDelegate = _private->selectorForDoCommandBySelector == selector;
2534     _private->selectorForDoCommandBySelector = 0;
2535     if (callerAlreadyCalledDelegate)
2536         return NO;
2537     WebView *webView = [self _webView];
2538     return [[webView _editingDelegateForwarder] webView:webView doCommandBySelector:selector];
2539 }
2540
2541 typedef HashMap<SEL, String> SelectorNameMap;
2542
2543 // Map selectors into Editor command names.
2544 // This is not needed for any selectors that have the same name as the Editor command.
2545 static const SelectorNameMap* createSelectorExceptionMap()
2546 {
2547     SelectorNameMap* map = new HashMap<SEL, String>;
2548
2549     map->add(@selector(insertNewlineIgnoringFieldEditor:), "InsertNewline");
2550     map->add(@selector(insertParagraphSeparator:), "InsertNewline");
2551     map->add(@selector(insertTabIgnoringFieldEditor:), "InsertTab");
2552     map->add(@selector(pageDown:), "MovePageDown");
2553     map->add(@selector(pageDownAndModifySelection:), "MovePageDownAndModifySelection");
2554     map->add(@selector(pageUp:), "MovePageUp");
2555     map->add(@selector(pageUpAndModifySelection:), "MovePageUpAndModifySelection");
2556
2557     return map;
2558 }
2559
2560 static String commandNameForSelector(SEL selector)
2561 {
2562     // Check the exception map first.
2563     static const SelectorNameMap* exceptionMap = createSelectorExceptionMap();
2564     SelectorNameMap::const_iterator it = exceptionMap->find(selector);
2565     if (it != exceptionMap->end())
2566         return it->value;
2567
2568     // Remove the trailing colon.
2569     // No need to capitalize the command name since Editor command names are
2570     // not case sensitive.
2571     const char* selectorName = sel_getName(selector);
2572     size_t selectorNameLength = strlen(selectorName);
2573     if (selectorNameLength < 2 || selectorName[selectorNameLength - 1] != ':')
2574         return String();
2575     return String(selectorName, selectorNameLength - 1);
2576 }
2577
2578 - (Editor::Command)coreCommandBySelector:(SEL)selector
2579 {
2580     Frame* coreFrame = core([self _frame]);
2581     if (!coreFrame)
2582         return Editor::Command();
2583     return coreFrame->editor().command(commandNameForSelector(selector));
2584 }
2585
2586 - (Editor::Command)coreCommandByName:(const char*)name
2587 {
2588     Frame* coreFrame = core([self _frame]);
2589     if (!coreFrame)
2590         return Editor::Command();
2591     return coreFrame->editor().command(name);
2592 }
2593
2594 - (void)executeCoreCommandBySelector:(SEL)selector
2595 {
2596     if ([self callDelegateDoCommandBySelectorIfNeeded:selector])
2597         return;
2598     [self coreCommandBySelector:selector].execute();
2599 }
2600
2601 - (void)executeCoreCommandByName:(const char*)name
2602 {
2603     [self coreCommandByName:name].execute();
2604 }
2605
2606 // These commands are forwarded to the Editor object in WebCore.
2607 // Ideally we'd do this for all editing commands; more of the code
2608 // should be moved from here to there, and more commands should be
2609 // added to this list.
2610
2611 // FIXME: Maybe we should set things up so that all these share a single method implementation function.
2612 // The functions are identical.
2613
2614 #define WEBCORE_COMMAND(command) - (void)command:(id)sender { [self executeCoreCommandBySelector:_cmd]; }
2615
2616 WEBCORE_COMMAND(alignCenter)
2617 WEBCORE_COMMAND(alignJustified)
2618 WEBCORE_COMMAND(alignLeft)
2619 WEBCORE_COMMAND(alignRight)
2620 WEBCORE_COMMAND(copy)
2621 WEBCORE_COMMAND(cut)
2622 WEBCORE_COMMAND(paste)
2623 WEBCORE_COMMAND(delete)
2624 WEBCORE_COMMAND(deleteBackward)
2625 WEBCORE_COMMAND(deleteBackwardByDecomposingPreviousCharacter)
2626 WEBCORE_COMMAND(deleteForward)
2627 WEBCORE_COMMAND(deleteToBeginningOfLine)
2628 WEBCORE_COMMAND(deleteToBeginningOfParagraph)
2629 WEBCORE_COMMAND(deleteToEndOfLine)
2630 WEBCORE_COMMAND(deleteToEndOfParagraph)
2631 WEBCORE_COMMAND(deleteToMark)
2632 WEBCORE_COMMAND(deleteWordBackward)
2633 WEBCORE_COMMAND(deleteWordForward)
2634 WEBCORE_COMMAND(ignoreSpelling)
2635 WEBCORE_COMMAND(indent)
2636 WEBCORE_COMMAND(insertBacktab)
2637 WEBCORE_COMMAND(insertLineBreak)
2638 WEBCORE_COMMAND(insertNewline)
2639 WEBCORE_COMMAND(insertNewlineIgnoringFieldEditor)
2640 WEBCORE_COMMAND(insertParagraphSeparator)
2641 WEBCORE_COMMAND(insertTab)
2642 WEBCORE_COMMAND(insertTabIgnoringFieldEditor)
2643 WEBCORE_COMMAND(makeTextWritingDirectionLeftToRight)
2644 WEBCORE_COMMAND(makeTextWritingDirectionNatural)
2645 WEBCORE_COMMAND(makeTextWritingDirectionRightToLeft)
2646 WEBCORE_COMMAND(moveBackward)
2647 WEBCORE_COMMAND(moveBackwardAndModifySelection)
2648 WEBCORE_COMMAND(moveDown)
2649 WEBCORE_COMMAND(moveDownAndModifySelection)
2650 WEBCORE_COMMAND(moveForward)
2651 WEBCORE_COMMAND(moveForwardAndModifySelection)
2652 WEBCORE_COMMAND(moveLeft)
2653 WEBCORE_COMMAND(moveLeftAndModifySelection)
2654 WEBCORE_COMMAND(moveParagraphBackwardAndModifySelection)
2655 WEBCORE_COMMAND(moveParagraphForwardAndModifySelection)
2656 WEBCORE_COMMAND(moveRight)
2657 WEBCORE_COMMAND(moveRightAndModifySelection)
2658 WEBCORE_COMMAND(moveToBeginningOfDocument)
2659 WEBCORE_COMMAND(moveToBeginningOfDocumentAndModifySelection)
2660 WEBCORE_COMMAND(moveToBeginningOfLine)
2661 WEBCORE_COMMAND(moveToBeginningOfLineAndModifySelection)
2662 WEBCORE_COMMAND(moveToBeginningOfParagraph)
2663 WEBCORE_COMMAND(moveToBeginningOfParagraphAndModifySelection)
2664 WEBCORE_COMMAND(moveToBeginningOfSentence)
2665 WEBCORE_COMMAND(moveToBeginningOfSentenceAndModifySelection)
2666 WEBCORE_COMMAND(moveToEndOfDocument)
2667 WEBCORE_COMMAND(moveToEndOfDocumentAndModifySelection)
2668 WEBCORE_COMMAND(moveToEndOfLine)
2669 WEBCORE_COMMAND(moveToEndOfLineAndModifySelection)
2670 WEBCORE_COMMAND(moveToEndOfParagraph)
2671 WEBCORE_COMMAND(moveToEndOfParagraphAndModifySelection)
2672 WEBCORE_COMMAND(moveToEndOfSentence)
2673 WEBCORE_COMMAND(moveToEndOfSentenceAndModifySelection)
2674 WEBCORE_COMMAND(moveToLeftEndOfLine)
2675 WEBCORE_COMMAND(moveToLeftEndOfLineAndModifySelection)
2676 WEBCORE_COMMAND(moveToRightEndOfLine)
2677 WEBCORE_COMMAND(moveToRightEndOfLineAndModifySelection)
2678 WEBCORE_COMMAND(moveUp)
2679 WEBCORE_COMMAND(moveUpAndModifySelection)
2680 WEBCORE_COMMAND(moveWordBackward)
2681 WEBCORE_COMMAND(moveWordBackwardAndModifySelection)
2682 WEBCORE_COMMAND(moveWordForward)
2683 WEBCORE_COMMAND(moveWordForwardAndModifySelection)
2684 WEBCORE_COMMAND(moveWordLeft)
2685 WEBCORE_COMMAND(moveWordLeftAndModifySelection)
2686 WEBCORE_COMMAND(moveWordRight)
2687 WEBCORE_COMMAND(moveWordRightAndModifySelection)
2688 WEBCORE_COMMAND(outdent)
2689 WEBCORE_COMMAND(overWrite)
2690 WEBCORE_COMMAND(pageDown)
2691 WEBCORE_COMMAND(pageDownAndModifySelection)
2692 WEBCORE_COMMAND(pageUp)
2693 WEBCORE_COMMAND(pageUpAndModifySelection)
2694 WEBCORE_COMMAND(pasteAsPlainText)
2695 WEBCORE_COMMAND(selectAll)
2696 WEBCORE_COMMAND(selectLine)
2697 WEBCORE_COMMAND(selectParagraph)
2698 WEBCORE_COMMAND(selectSentence)
2699 WEBCORE_COMMAND(selectToMark)
2700 WEBCORE_COMMAND(selectWord)
2701 WEBCORE_COMMAND(setMark)
2702 WEBCORE_COMMAND(subscript)
2703 WEBCORE_COMMAND(superscript)
2704 WEBCORE_COMMAND(swapWithMark)
2705 WEBCORE_COMMAND(transpose)
2706 WEBCORE_COMMAND(underline)
2707 WEBCORE_COMMAND(unscript)
2708 WEBCORE_COMMAND(yank)
2709 WEBCORE_COMMAND(yankAndSelect)
2710
2711 #if PLATFORM(IOS)
2712 WEBCORE_COMMAND(clearText)
2713 WEBCORE_COMMAND(toggleBold)
2714 WEBCORE_COMMAND(toggleItalic)
2715 WEBCORE_COMMAND(toggleUnderline)
2716 #endif
2717
2718 #undef WEBCORE_COMMAND
2719
2720 #define COMMAND_PROLOGUE if ([self callDelegateDoCommandBySelectorIfNeeded:_cmd]) return;
2721
2722 #if !PLATFORM(IOS)
2723 - (IBAction)takeFindStringFromSelection:(id)sender
2724 {
2725     COMMAND_PROLOGUE
2726
2727     if (![self _hasSelection]) {
2728         NSBeep();
2729         return;
2730     }
2731
2732     [NSPasteboard _web_setFindPasteboardString:[self selectedString] withOwner:self];
2733 }
2734
2735 // This method is needed to support Mac OS X services.
2736 - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pasteboard types:(NSArray *)types
2737 {
2738     [pasteboard declareTypes:types owner:[self _topHTMLView]];
2739     [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
2740     return YES;
2741 }
2742
2743 - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType
2744 {
2745     BOOL isSendTypeOK = !sendType || ([[self pasteboardTypesForSelection] containsObject:sendType] && [self _hasSelection]);
2746     BOOL isReturnTypeOK = NO;
2747     if (!returnType)
2748         isReturnTypeOK = YES;
2749     else if ([[[self class] _insertablePasteboardTypes] containsObject:returnType] && [self _isEditable]) {
2750         // We can insert strings in any editable context.  We can insert other types, like images, only in rich edit contexts.
2751         isReturnTypeOK = [returnType isEqualToString:NSStringPboardType] || [self _canEditRichly];
2752     }
2753     if (isSendTypeOK && isReturnTypeOK)
2754         return self;
2755     return [[self nextResponder] validRequestorForSendType:sendType returnType:returnType];
2756 }
2757 #endif
2758
2759 // jumpToSelection is the old name for what AppKit now calls centerSelectionInVisibleArea. Safari
2760 // was using the old jumpToSelection selector in its menu. Newer versions of Safari will use the
2761 // selector centerSelectionInVisibleArea. We'll leave the old selector in place for two reasons:
2762 // (1) Compatibility between older Safari and newer WebKit; (2) other WebKit-based applications
2763 // might be using the selector, and we don't want to break them.
2764 - (void)jumpToSelection:(id)sender
2765 {
2766     COMMAND_PROLOGUE
2767
2768     if (Frame* coreFrame = core([self _frame]))
2769         coreFrame->selection().revealSelection(ScrollAlignment::alignCenterAlways);
2770 }
2771
2772 #if !PLATFORM(IOS)
2773 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
2774 {
2775     SEL action = [item action];
2776     RefPtr<Frame> frame = core([self _frame]);
2777
2778     if (!frame)
2779         return NO;
2780     
2781     if (Document* doc = frame->document()) {
2782         if (doc->isPluginDocument())
2783             return NO;
2784         if (doc->isImageDocument()) {            
2785             if (action == @selector(copy:))
2786                 return frame->loader().isComplete();
2787             return NO;
2788         }
2789     }
2790
2791     if (action == @selector(changeSpelling:)
2792             || action == @selector(_changeSpellingFromMenu:)
2793             || action == @selector(checkSpelling:)
2794             || action == @selector(complete:)
2795             || action == @selector(pasteFont:))
2796         return [self _canEdit];
2797
2798     if (action == @selector(showGuessPanel:)) {
2799         // Match OS X AppKit behavior for post-Tiger. Don't change Tiger behavior.
2800         NSMenuItem *menuItem = (NSMenuItem *)item;
2801         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
2802             BOOL panelShowing = [[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible];
2803             [menuItem setTitle:panelShowing
2804                 ? UI_STRING_INTERNAL("Hide Spelling and Grammar", "menu item title")
2805                 : UI_STRING_INTERNAL("Show Spelling and Grammar", "menu item title")];
2806         }
2807         return [self _canEdit];
2808     }
2809     
2810     if (action == @selector(changeBaseWritingDirection:)
2811             || action == @selector(makeBaseWritingDirectionLeftToRight:)
2812             || action == @selector(makeBaseWritingDirectionRightToLeft:)) {
2813         NSWritingDirection writingDirection;
2814
2815         if (action == @selector(changeBaseWritingDirection:)) {
2816             writingDirection = static_cast<NSWritingDirection>([item tag]);
2817             if (writingDirection == NSWritingDirectionNatural)
2818                 return NO;
2819         } else if (action == @selector(makeBaseWritingDirectionLeftToRight:))
2820             writingDirection = NSWritingDirectionLeftToRight;
2821         else
2822             writingDirection = NSWritingDirectionRightToLeft;
2823
2824         NSMenuItem *menuItem = (NSMenuItem *)item;
2825         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
2826             String direction = writingDirection == NSWritingDirectionLeftToRight ? "ltr" : "rtl";
2827             [menuItem setState:frame->editor().selectionHasStyle(CSSPropertyDirection, direction)];
2828         }
2829         return [self _canEdit];
2830     }
2831
2832     if (action == @selector(makeBaseWritingDirectionNatural:)) {
2833         NSMenuItem *menuItem = (NSMenuItem *)item;
2834         if ([menuItem isKindOfClass:[NSMenuItem class]])
2835             [menuItem setState:NSOffState];
2836         return NO;
2837     }
2838
2839     if (action == @selector(toggleBaseWritingDirection:)) {
2840         NSMenuItem *menuItem = (NSMenuItem *)item;
2841         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
2842             // Take control of the title of the menu item instead of just checking/unchecking it because
2843             // a check would be ambiguous.
2844             [menuItem setTitle:frame->editor().selectionHasStyle(CSSPropertyDirection, "rtl")
2845                 ? UI_STRING_INTERNAL("Left to Right", "Left to Right context menu item")
2846                 : UI_STRING_INTERNAL("Right to Left", "Right to Left context menu item")];
2847         }
2848         return [self _canEdit];
2849     } 
2850     
2851     if (action == @selector(changeAttributes:)
2852             || action == @selector(changeColor:)        
2853             || action == @selector(changeFont:))
2854         return [self _canEditRichly];
2855     
2856     if (action == @selector(capitalizeWord:)
2857                || action == @selector(lowercaseWord:)
2858                || action == @selector(uppercaseWord:))
2859         return [self _hasSelection] && [self _isEditable];
2860
2861     if (action == @selector(centerSelectionInVisibleArea:)
2862                || action == @selector(jumpToSelection:)
2863                || action == @selector(copyFont:))
2864         return [self _hasSelection] || ([self _isEditable] && [self _hasInsertionPoint]);
2865     
2866     if (action == @selector(changeDocumentBackgroundColor:))
2867         return [[self _webView] isEditable] && [self _canEditRichly];
2868     
2869     if (action == @selector(_ignoreSpellingFromMenu:)
2870             || action == @selector(_learnSpellingFromMenu:)
2871             || action == @selector(takeFindStringFromSelection:))
2872         return [self _hasSelection];
2873     
2874     if (action == @selector(paste:) || action == @selector(pasteAsPlainText:))
2875         return frame && (frame->editor().canDHTMLPaste() || frame->editor().canPaste());
2876     
2877     if (action == @selector(pasteAsRichText:))
2878         return frame && (frame->editor().canDHTMLPaste()
2879             || (frame->editor().canPaste() && frame->selection().selection().isContentRichlyEditable()));
2880     
2881     if (action == @selector(performFindPanelAction:))
2882         return NO;
2883     
2884     if (action == @selector(_lookUpInDictionaryFromMenu:))
2885         return [self _hasSelection];
2886
2887     if (action == @selector(stopSpeaking:))
2888         return [NSApp isSpeaking];
2889
2890     if (action == @selector(toggleGrammarChecking:)) {
2891         // FIXME 4799134: WebView is the bottleneck for this grammar-checking logic, but we must validate 
2892         // the selector here because we implement it here, and we must implement it here because the AppKit 
2893         // code checks the first responder.
2894         NSMenuItem *menuItem = (NSMenuItem *)item;
2895         if ([menuItem isKindOfClass:[NSMenuItem class]])
2896             [menuItem setState:[self isGrammarCheckingEnabled] ? NSOnState : NSOffState];
2897         return YES;
2898     }
2899
2900     if (action == @selector(orderFrontSubstitutionsPanel:)) {
2901         NSMenuItem *menuItem = (NSMenuItem *)item;
2902         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
2903             BOOL panelShowing = [[[NSSpellChecker sharedSpellChecker] substitutionsPanel] isVisible];
2904             [menuItem setTitle:panelShowing
2905                 ? UI_STRING_INTERNAL("Hide Substitutions", "menu item title")
2906                 : UI_STRING_INTERNAL("Show Substitutions", "menu item title")];
2907         }
2908         return [self _canEdit];
2909     }
2910     // FIXME 4799134: WebView is the bottleneck for this logic, but we must validate 
2911     // the selector here because we implement it here, and we must implement it here because the AppKit 
2912     // code checks the first responder.
2913     if (action == @selector(toggleSmartInsertDelete:)) {
2914         NSMenuItem *menuItem = (NSMenuItem *)item;
2915         if ([menuItem isKindOfClass:[NSMenuItem class]])
2916             [menuItem setState:[self smartInsertDeleteEnabled] ? NSOnState : NSOffState];
2917         return [self _canEdit];
2918     }
2919     if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
2920         NSMenuItem *menuItem = (NSMenuItem *)item;
2921         if ([menuItem isKindOfClass:[NSMenuItem class]])
2922             [menuItem setState:[self isAutomaticQuoteSubstitutionEnabled] ? NSOnState : NSOffState];
2923         return [self _canEdit];
2924     }
2925     if (action == @selector(toggleAutomaticLinkDetection:)) {
2926         NSMenuItem *menuItem = (NSMenuItem *)item;
2927         if ([menuItem isKindOfClass:[NSMenuItem class]])
2928             [menuItem setState:[self isAutomaticLinkDetectionEnabled] ? NSOnState : NSOffState];
2929         return [self _canEdit];
2930     }
2931     if (action == @selector(toggleAutomaticDashSubstitution:)) {
2932         NSMenuItem *menuItem = (NSMenuItem *)item;
2933         if ([menuItem isKindOfClass:[NSMenuItem class]])
2934             [menuItem setState:[self isAutomaticDashSubstitutionEnabled] ? NSOnState : NSOffState];
2935         return [self _canEdit];
2936     }
2937     if (action == @selector(toggleAutomaticTextReplacement:)) {
2938         NSMenuItem *menuItem = (NSMenuItem *)item;
2939         if ([menuItem isKindOfClass:[NSMenuItem class]])
2940             [menuItem setState:[self isAutomaticTextReplacementEnabled] ? NSOnState : NSOffState];
2941         return [self _canEdit];
2942     }
2943     if (action == @selector(toggleAutomaticSpellingCorrection:)) {
2944         NSMenuItem *menuItem = (NSMenuItem *)item;
2945         if ([menuItem isKindOfClass:[NSMenuItem class]])
2946             [menuItem setState:[self isAutomaticSpellingCorrectionEnabled] ? NSOnState : NSOffState];
2947         return [self _canEdit];
2948     }
2949
2950     Editor::Command command = [self coreCommandBySelector:action];
2951     if (command.isSupported()) {
2952         NSMenuItem *menuItem = (NSMenuItem *)item;
2953         if ([menuItem isKindOfClass:[NSMenuItem class]])
2954             [menuItem setState:kit(command.state())];
2955         return command.isEnabled();
2956     }
2957
2958     return YES;
2959 }
2960
2961 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
2962 {
2963     // This can be called during teardown when _webView is nil. Return NO when this happens, because CallUIDelegateReturningBoolean
2964     // assumes the WebVIew is non-nil.
2965     if (![self _webView])
2966         return NO;
2967     BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
2968     return CallUIDelegateReturningBoolean(result, [self _webView], @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
2969 }
2970 #endif // !PLATFORM(IOS)
2971
2972 - (BOOL)acceptsFirstResponder
2973 {
2974     // Don't accept first responder when we first click on this view.
2975     // We have to pass the event down through WebCore first to be sure we don't hit a subview.
2976     // Do accept first responder at any other time, for example from keyboard events,
2977     // or from calls back from WebCore once we begin mouse-down event handling.
2978 #if !PLATFORM(IOS)            
2979     NSEvent *event = [NSApp currentEvent];
2980     if ([event type] == NSLeftMouseDown
2981             && !_private->handlingMouseDownEvent
2982             && NSPointInRect([event locationInWindow], [self convertRect:[self visibleRect] toView:nil])) {
2983         return NO;
2984     }
2985 #else
2986     WebEvent *event = [WAKWindow currentEvent];
2987     if (event && event.type == WebEventMouseDown
2988             && !_private->handlingMouseDownEvent
2989             && NSPointInRect([event locationInWindow], [self convertRect:[self visibleRect] toView:nil]))
2990         return NO;
2991 #endif
2992     return YES;
2993 }
2994
2995 - (BOOL)maintainsInactiveSelection
2996 {
2997 #if USE(UIKIT_EDITING)
2998     // We want to maintain an inactive selection, when in editable content.
2999     if ([[self _webView] maintainsInactiveSelection])
3000         return YES;
3001
3002     if ([[self window] _newFirstResponderAfterResigning] == self)
3003         return YES;
3004     
3005     Frame* coreFrame = core([self _frame]);
3006     return coreFrame && coreFrame->selection().selection().isContentEditable();
3007 #else
3008     // This method helps to determine whether the WebHTMLView should maintain
3009     // an inactive selection when it's not first responder.
3010     // Traditionally, these views have not maintained such selections,
3011     // clearing them when the view was not first responder. However,
3012     // to fix bugs like this one:
3013     // <rdar://problem/3672088>: "Editable WebViews should maintain a selection even 
3014     //                            when they're not firstResponder"
3015     // it was decided to add a switch to act more like an NSTextView.
3016
3017     if ([[self _webView] maintainsInactiveSelection])
3018         return YES;
3019
3020     // Predict the case where we are losing first responder status only to
3021     // gain it back again. Want to keep the selection in that case.
3022     id nextResponder = [[self window] _newFirstResponderAfterResigning];
3023     if ([nextResponder isKindOfClass:[NSScrollView class]]) {
3024         id contentView = [nextResponder contentView];
3025         if (contentView)
3026             nextResponder = contentView;
3027     }
3028     if ([nextResponder isKindOfClass:[NSClipView class]]) {
3029         id documentView = [nextResponder documentView];
3030         if (documentView)
3031             nextResponder = documentView;
3032     }
3033     if (nextResponder == self)
3034         return YES;
3035
3036     Frame* coreFrame = core([self _frame]);
3037     bool selectionIsEditable = coreFrame && coreFrame->selection().selection().isContentEditable();
3038     bool nextResponderIsInWebView = [nextResponder isKindOfClass:[NSView class]]
3039         && [nextResponder isDescendantOf:[[[self _webView] mainFrame] frameView]];
3040
3041     return selectionIsEditable && nextResponderIsInWebView;
3042 #endif
3043 }
3044
3045 #if !PLATFORM(IOS)
3046 - (void)addSuperviewObservers
3047 {
3048     if (_private->observingSuperviewNotifications)
3049         return;
3050
3051     NSView *superview = [self superview];
3052     if (!superview || ![self window])
3053         return;
3054     
3055     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
3056     [notificationCenter addObserver:self selector:@selector(_frameOrBoundsChanged) name:NSViewFrameDidChangeNotification object:superview];
3057     [notificationCenter addObserver:self selector:@selector(_frameOrBoundsChanged) name:NSViewBoundsDidChangeNotification object:superview];
3058     
3059     // In addition to registering for frame/bounds change notifications, call -_frameOrBoundsChanged.
3060     // It will check the current scroll against the previous layout's scroll.  We need to
3061     // do this here to catch the case where the WebView is laid out at one size, removed from its
3062     // window, resized, and inserted into another window.  Our frame/bounds changed notifications
3063     // will not be sent in that situation, since we only watch for changes while in the view hierarchy.
3064     [self _frameOrBoundsChanged];
3065     
3066     _private->observingSuperviewNotifications = true;
3067 }
3068
3069 - (void)addWindowObservers
3070 {
3071     if (_private->observingWindowNotifications)
3072         return;
3073     
3074     NSWindow *window = [self window];
3075     if (!window)
3076         return;
3077     
3078     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
3079     [notificationCenter addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:nil];
3080     [notificationCenter addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:nil];
3081     [notificationCenter addObserver:self selector:@selector(windowWillOrderOnScreen:) name:WKWindowWillOrderOnScreenNotification() object:window];
3082     [notificationCenter addObserver:self selector:@selector(windowWillOrderOffScreen:) name:WKWindowWillOrderOffScreenNotification() object:window];
3083     [notificationCenter addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:window];
3084     
3085     _private->observingWindowNotifications = true;
3086 }
3087
3088 - (void)viewWillMoveToSuperview:(NSView *)newSuperview
3089 {
3090     [self _removeSuperviewObservers];
3091 }
3092
3093 - (void)viewDidMoveToSuperview
3094 {
3095     if ([self superview] != nil)
3096         [self addSuperviewObservers];
3097
3098     if ([self superview] && [self _isUsingAcceleratedCompositing]) {
3099         WebView *webView = [self _webView];
3100         if ([webView _postsAcceleratedCompositingNotifications])
3101             [[NSNotificationCenter defaultCenter] postNotificationName:_WebViewDidStartAcceleratedCompositingNotification object:webView userInfo:nil];
3102     }
3103 }
3104 #endif // !PLATFORM(IOS)
3105
3106 - (void)viewWillMoveToWindow:(NSWindow *)window
3107 {
3108     // Don't do anything if we aren't initialized.  This happens
3109     // when decoding a WebView.  When WebViews are decoded their subviews
3110     // are created by initWithCoder: and so won't be normally
3111     // initialized.  The stub views are discarded by WebView.
3112     if (!_private)
3113         return;
3114
3115 #if !PLATFORM(IOS)
3116     // FIXME: Some of these calls may not work because this view may be already removed from it's superview.
3117     [self _removeWindowObservers];
3118     [self _removeSuperviewObservers];
3119 #endif
3120
3121     // FIXME: This accomplishes the same thing as the call to setCanStartMedia(false) in
3122     // WebView. It would be nice to have a single mechanism instead of two.
3123     [[self _pluginController] stopAllPlugins];
3124 }
3125
3126 - (void)viewDidMoveToWindow
3127 {
3128     // Don't do anything if we aren't initialized.  This happens
3129     // when decoding a WebView.  When WebViews are decoded their subviews
3130     // are created by initWithCoder: and so won't be normally
3131     // initialized.  The stub views are discarded by WebView.
3132     if (!_private || _private->closed)
3133         return;
3134         
3135     [self _stopAutoscrollTimer];
3136     if ([self window]) {
3137         _private->lastScrollPosition = [[self superview] bounds].origin;
3138 #if !PLATFORM(IOS)
3139         [self addWindowObservers];
3140         [self addSuperviewObservers];
3141 #endif
3142
3143         // FIXME: This accomplishes the same thing as the call to setCanStartMedia(true) in
3144         // WebView. It would be nice to have a single mechanism instead of two.
3145         [[self _pluginController] startAllPlugins];
3146
3147         _private->lastScrollPosition = NSZeroPoint;
3148
3149 #if !PLATFORM(IOS)
3150         if (!_private->flagsChangedEventMonitor) {
3151             _private->flagsChangedEventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSFlagsChangedMask handler:^(NSEvent *flagsChangedEvent) {
3152                 [self _postFakeMouseMovedEventForFlagsChangedEvent:flagsChangedEvent];
3153                 return flagsChangedEvent;
3154             }];
3155         }
3156     } else {
3157         [NSEvent removeMonitor:_private->flagsChangedEventMonitor];
3158         _private->flagsChangedEventMonitor = nil;
3159 #endif
3160     }
3161 }
3162
3163 - (void)_web_makePluginSubviewsPerformSelector:(SEL)selector withObject:(id)object
3164 {
3165 #if ENABLE(NETSCAPE_PLUGIN_API)
3166     // Copy subviews because [self subviews] returns the view's mutable internal array,
3167     // and we must avoid mutating the array while enumerating it.
3168     NSArray *subviews = [[self subviews] copy];
3169     
3170     NSEnumerator *enumerator = [subviews objectEnumerator];
3171     WebNetscapePluginView *view;
3172     while ((view = [enumerator nextObject]) != nil)
3173         if ([view isKindOfClass:[WebBaseNetscapePluginView class]])
3174             [view performSelector:selector withObject:object];
3175     
3176     [subviews release];
3177 #endif
3178 }
3179
3180 - (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow
3181 {
3182 #if !PLATFORM(IOS)
3183     [self _web_makePluginSubviewsPerformSelector:@selector(viewWillMoveToHostWindow:) withObject:hostWindow];
3184 #endif
3185 }
3186
3187 - (void)viewDidMoveToHostWindow
3188 {
3189 #if !PLATFORM(IOS)
3190     [self _web_makePluginSubviewsPerformSelector:@selector(viewDidMoveToHostWindow) withObject:nil];
3191 #endif
3192 }
3193
3194
3195 - (void)addSubview:(NSView *)view
3196 {
3197     [super addSubview:view];
3198
3199     if ([WebPluginController isPlugInView:view]) {
3200
3201 #if PLATFORM(IOS)
3202         WebView *webView = [self _webView];
3203         [[webView _UIKitDelegateForwarder] webView:webView willAddPlugInView:view];
3204 #endif
3205
3206         [[self _pluginController] addPlugin:view];
3207     }
3208 }
3209
3210 - (void)willRemoveSubview:(NSView *)subview
3211 {
3212 #ifndef NDEBUG
3213     // Have to null-check _private, since this can be called via -dealloc when
3214     // cleaning up the the layerHostingView.
3215     if (_private && _private->enumeratingSubviews)
3216         LOG(View, "A view of class %s was removed during subview enumeration for layout or printing mode change. We will still do layout or the printing mode change even though this view is no longer in the view hierarchy.", object_getClassName([subview class]));
3217 #endif
3218
3219     if ([WebPluginController isPlugInView:subview])
3220         [[self _pluginController] destroyPlugin:subview];
3221
3222     [super willRemoveSubview:subview];
3223 }
3224
3225 - (void)reapplyStyles
3226 {
3227 #ifdef LOG_TIMES
3228     double start = CFAbsoluteTimeGetCurrent();
3229 #endif
3230
3231     if (Frame* coreFrame = core([self _frame]))
3232         coreFrame->document()->styleResolverChanged(RecalcStyleImmediately);
3233     
3234 #ifdef LOG_TIMES        
3235     double thisTime = CFAbsoluteTimeGetCurrent() - start;
3236     LOG(Timing, "%s apply style seconds = %f", [self URL], thisTime);
3237 #endif
3238 }
3239
3240 // Do a layout, but set up a new fixed width for the purposes of doing printing layout.
3241 // minPageWidth==0 implies a non-printing layout
3242 - (void)layoutToMinimumPageWidth:(float)minPageLogicalWidth height:(float)minPageLogicalHeight originalPageWidth:(float)originalPageWidth originalPageHeight:(float)originalPageHeight maximumShrinkRatio:(float)maximumShrinkRatio adjustingViewSize:(BOOL)adjustViewSize
3243 {
3244     Frame* coreFrame = core([self _frame]);
3245     if (!coreFrame)
3246         return;
3247     if (coreFrame->document()) {
3248         if (coreFrame->document()->inPageCache())
3249             return;
3250         coreFrame->document()->updateStyleIfNeeded();
3251     }
3252
3253     if (![self _needsLayout])
3254         return;
3255
3256 #ifdef LOG_TIMES        
3257     double start = CFAbsoluteTimeGetCurrent();
3258 #endif
3259
3260     LOG(View, "%@ doing layout", self);
3261
3262     if (FrameView* coreView = coreFrame->view()) {
3263         if (minPageLogicalWidth > 0.0) {
3264             FloatSize pageSize(minPageLogicalWidth, minPageLogicalHeight);
3265             FloatSize originalPageSize(originalPageWidth, originalPageHeight);
3266             if (coreFrame->document() && coreFrame->document()->renderView() && !coreFrame->document()->renderView()->style().isHorizontalWritingMode()) {
3267                 pageSize = FloatSize(minPageLogicalHeight, minPageLogicalWidth);
3268                 originalPageSize = FloatSize(originalPageHeight, originalPageWidth);
3269             }
3270             coreView->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, adjustViewSize ? AdjustViewSize : DoNotAdjustViewSize);
3271         } else {
3272             coreView->forceLayout(!adjustViewSize);
3273             if (adjustViewSize)
3274                 coreView->adjustViewSize();
3275         }
3276     }
3277     
3278 #ifdef LOG_TIMES        
3279     double thisTime = CFAbsoluteTimeGetCurrent() - start;
3280     LOG(Timing, "%s layout seconds = %f", [self URL], thisTime);
3281 #endif
3282 }
3283
3284 - (void)layout
3285 {
3286     [self layoutToMinimumPageWidth:0 height:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustingViewSize:NO];
3287 }
3288
3289 #if !PLATFORM(IOS)
3290 // Deliver mouseup events to the DOM for button 2.
3291 - (void)rightMouseUp:(NSEvent *)event
3292 {
3293     // There's a chance that if we run a nested event loop the event will be released.
3294     // Retaining and then autoreleasing prevents that from causing a problem later here or
3295     // inside AppKit code.
3296     [[event retain] autorelease];
3297
3298     [super rightMouseUp:event];
3299
3300     if (Frame* coreframe = core([self _frame]))
3301         coreframe->eventHandler().mouseUp(event);
3302 }
3303
3304 static void setMenuItemTarget(NSMenuItem* menuItem)
3305 {
3306     // Don't set the menu item's action to the context menu action forwarder if we already
3307     // have an action.
3308     if ([menuItem action])
3309         return;
3310
3311     [menuItem setTarget:[WebMenuTarget sharedMenuTarget]];
3312     [menuItem setAction:@selector(forwardContextMenuAction:)];
3313 }
3314
3315 static void setMenuTargets(NSMenu* menu)
3316 {
3317     NSInteger itemCount = [menu numberOfItems];
3318     for (NSInteger i = 0; i < itemCount; ++i) {
3319         NSMenuItem *item = [menu itemAtIndex:i];
3320         setMenuItemTarget(item);
3321         if ([item hasSubmenu])
3322             setMenuTargets([item submenu]);
3323     }
3324 }
3325
3326 - (NSMenu *)menuForEvent:(NSEvent *)event
3327 {
3328     // There's a chance that if we run a nested event loop the event will be released.
3329     // Retaining and then autoreleasing prevents that from causing a problem later here or
3330     // inside AppKit code.
3331     [[event retain] autorelease];
3332
3333     [_private->completionController endRevertingChange:NO moveLeft:NO];
3334
3335     RefPtr<Frame> coreFrame = core([self _frame]);
3336     if (!coreFrame)
3337         return nil;
3338
3339     Page* page = coreFrame->page();
3340     if (!page)
3341         return nil;
3342
3343     // Match behavior of other browsers by sending a mousedown event for right clicks.
3344     _private->handlingMouseDownEvent = YES;
3345     page->contextMenuController().clearContextMenu();
3346     coreFrame->eventHandler().mouseDown(event);
3347     BOOL handledEvent = coreFrame->eventHandler().sendContextMenuEvent(PlatformEventFactory::createPlatformMouseEvent(event, page->chrome().platformPageClient()));
3348     _private->handlingMouseDownEvent = NO;
3349
3350     if (!handledEvent)
3351         return nil;
3352
3353     // Re-get page, since it might have gone away during event handling.
3354     page = coreFrame->page();
3355     if (!page)
3356         return nil;
3357
3358     ContextMenu* coreMenu = page->contextMenuController().contextMenu();
3359     if (!coreMenu)
3360         return nil;
3361
3362     NSArray* menuItems = coreMenu->platformDescription();
3363     if (!menuItems)
3364         return nil;
3365
3366     NSUInteger count = [menuItems count];
3367     if (!count)
3368         return nil;
3369
3370     NSMenu* menu = [[[NSMenu alloc] init] autorelease];
3371     for (NSUInteger i = 0; i < count; i++)
3372         [menu addItem:[menuItems objectAtIndex:i]];
3373     setMenuTargets(menu);
3374     
3375     [[WebMenuTarget sharedMenuTarget] setMenuController:&page->contextMenuController()];
3376     
3377     return menu;
3378 }
3379 #endif // !PLATFORM(IOS)
3380
3381 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
3382 {
3383     return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
3384 }
3385
3386 - (void)clearFocus
3387 {
3388     Frame* coreFrame = core([self _frame]);
3389     if (!coreFrame)
3390         return;
3391     Document* document = coreFrame->document();
3392     if (!document)
3393         return;
3394     
3395     document->setFocusedElement(0);
3396 }
3397
3398 - (BOOL)isOpaque
3399 {
3400     return [[self _webView] drawsBackground];
3401 }
3402
3403 #if !PLATFORM(IOS)
3404 - (void)setLayer:(CALayer *)layer
3405 {
3406     if (Frame* frame = core([self _frame])) {
3407         if (FrameView* view = frame->view())
3408             view->setPaintsEntireContents(layer);
3409     }
3410
3411     [super setLayer:layer];
3412 }
3413 #endif
3414
3415 #if !LOG_DISABLED
3416 - (void)setNeedsDisplay:(BOOL)flag
3417 {
3418     LOG(View, "%@ setNeedsDisplay:%@", self, flag ? @"YES" : @"NO");
3419     [super setNeedsDisplay:flag];
3420 }
3421 #endif
3422
3423 - (void)setNeedsDisplayInRect:(NSRect)invalidRect
3424 {
3425     if (_private->inScrollPositionChanged) {
3426         // When scrolling, the dirty regions are adjusted for the scroll only
3427         // after NSViewBoundsDidChangeNotification is sent. Translate the invalid
3428         // rect to pre-scrolled coordinates in order to get the right dirty region
3429         // after adjustment. See <rdar://problem/7678927>.
3430         NSPoint origin = [[self superview] bounds].origin;
3431         invalidRect.origin.x -= _private->lastScrollPosition.x - origin.x;
3432         invalidRect.origin.y -= _private->lastScrollPosition.y - origin.y;
3433     }
3434     [super setNeedsDisplayInRect:invalidRect];
3435 }
3436
3437 - (void)setNeedsLayout: (BOOL)flag
3438 {
3439     LOG(View, "%@ setNeedsLayout:%@", self, flag ? @"YES" : @"NO");
3440     if (!flag)
3441         return; // There's no way to say you don't need a layout.
3442     if (Frame* frame = core([self _frame])) {
3443         if (frame->document() && frame->document()->inPageCache())
3444             return;
3445         if (FrameView* view = frame->view())
3446             view->setNeedsLayout();
3447     }
3448 }
3449
3450 - (void)setNeedsToApplyStyles: (BOOL)flag
3451 {
3452     LOG(View, "%@ setNeedsToApplyStyles:%@", self, flag ? @"YES" : @"NO");
3453     if (!flag)
3454         return; // There's no way to say you don't need a style recalc.
3455     if (Frame* frame = core([self _frame])) {
3456         if (frame->document() && frame->document()->inPageCache())
3457             return;
3458         frame->document()->scheduleForcedStyleRecalc();
3459     }
3460 }
3461
3462 - (void)drawSingleRect:(NSRect)rect
3463 {
3464 #if !PLATFORM(IOS)
3465     [NSGraphicsContext saveGraphicsState];
3466     NSRectClip(rect);
3467         
3468     ASSERT([[self superview] isKindOfClass:[WebClipView class]]);
3469
3470     [(WebClipView *)[self superview] setAdditionalClip:rect];
3471 #endif
3472
3473     @try {
3474 #if !PLATFORM(IOS)
3475         if ([self _transparentBackground]) {
3476             [[NSColor clearColor] set];
3477             NSRectFill (rect);
3478         }
3479 #endif
3480
3481         [[self _frame] _drawRect:rect contentsOnly:YES];
3482
3483 #if !PLATFORM(IOS)
3484         WebView *webView = [self _webView];
3485
3486         // This hack is needed for <rdar://problem/5023545>. We can hit a race condition where drawRect will be
3487         // called after the WebView has closed. If the client did not properly close the WebView and set the 
3488         // UIDelegate to nil, then the UIDelegate will be stale and this code will crash. 
3489         static BOOL version3OrLaterClient = WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_QUICKBOOKS_QUIRK);
3490         if (version3OrLaterClient)
3491    &n