summaryrefslogtreecommitdiffstats
path: root/WebKit/mac/WebView/WebView.mm
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/mac/WebView/WebView.mm')
-rw-r--r--WebKit/mac/WebView/WebView.mm1913
1 files changed, 921 insertions, 992 deletions
diff --git a/WebKit/mac/WebView/WebView.mm b/WebKit/mac/WebView/WebView.mm
index eabbc9d..20f2712 100644
--- a/WebKit/mac/WebView/WebView.mm
+++ b/WebKit/mac/WebView/WebView.mm
@@ -28,7 +28,10 @@
*/
#import "WebViewInternal.h"
+#import "WebViewData.h"
+#import "DOMCSSStyleDeclarationInternal.h"
+#import "DOMNodeInternal.h"
#import "DOMRangeInternal.h"
#import "WebBackForwardListInternal.h"
#import "WebCache.h"
@@ -40,6 +43,7 @@
#import "WebDefaultEditingDelegate.h"
#import "WebDefaultPolicyDelegate.h"
#import "WebDefaultUIDelegate.h"
+#import "WebDelegateImplementationCaching.h"
#import "WebDocument.h"
#import "WebDocumentInternal.h"
#import "WebDownload.h"
@@ -64,7 +68,6 @@
#import "WebKitSystemBits.h"
#import "WebKitVersionChecks.h"
#import "WebLocalizableStrings.h"
-#import "WebNodeHighlight.h"
#import "WebNSDataExtras.h"
#import "WebNSDataExtrasPrivate.h"
#import "WebNSDictionaryExtras.h"
@@ -76,6 +79,7 @@
#import "WebNSURLRequestExtras.h"
#import "WebNSUserDefaultsExtras.h"
#import "WebNSViewExtras.h"
+#import "WebNodeHighlight.h"
#import "WebPDFView.h"
#import "WebPanelAuthenticationHandler.h"
#import "WebPasteboardHelper.h"
@@ -84,6 +88,8 @@
#import "WebPreferenceKeysPrivate.h"
#import "WebPreferencesPrivate.h"
#import "WebScriptDebugDelegate.h"
+#import "WebSystemInterface.h"
+#import "WebTextCompletionController.h"
#import "WebTextIterator.h"
#import "WebUIDelegate.h"
#import "WebUIDelegatePrivate.h"
@@ -103,8 +109,8 @@
#import <WebCore/FocusController.h>
#import <WebCore/Frame.h>
#import <WebCore/FrameLoader.h>
-#import <WebCore/FrameView.h>
#import <WebCore/FrameTree.h>
+#import <WebCore/FrameView.h>
#import <WebCore/GCController.h>
#import <WebCore/HTMLNames.h>
#import <WebCore/HistoryItem.h>
@@ -116,15 +122,18 @@
#import <WebCore/PageGroup.h>
#import <WebCore/PlatformMouseEvent.h>
#import <WebCore/ProgressTracker.h>
+#import <WebCore/ResourceHandle.h>
+#import <WebCore/RuntimeApplicationChecks.h>
#import <WebCore/ScriptController.h>
#import <WebCore/ScriptValue.h>
+#import <WebCore/SecurityOrigin.h>
#import <WebCore/SelectionController.h>
#import <WebCore/Settings.h>
#import <WebCore/TextResourceDecoder.h>
#import <WebCore/ThreadCheck.h>
#import <WebCore/WebCoreObjCExtras.h>
-#import <WebCore/WebCoreTextRenderer.h>
#import <WebCore/WebCoreView.h>
+#import <WebCore/Widget.h>
#import <WebKit/DOM.h>
#import <WebKit/DOMExtensions.h>
#import <WebKit/DOMPrivate.h>
@@ -147,6 +156,26 @@
#import <WebKit/WebDashboardRegion.h>
#endif
+@class NSTextInputContext;
+
+@interface NSResponder (WebNSResponderDetails)
+- (NSTextInputContext *)inputContext;
+@end
+
+@interface NSSpellChecker (WebNSSpellCheckerDetails)
+- (void)_preflightChosenSpellServer;
+@end
+
+@interface NSView (WebNSViewDetails)
+- (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
+- (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
+- (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
+@end
+
+@interface NSWindow (WebNSWindowDetails)
+- (id)_oldFirstResponderBeforeBecoming;
+@end
+
using namespace WebCore;
using namespace JSC;
@@ -247,6 +276,7 @@ macro(moveWordLeftAndModifySelection) \
macro(moveWordRight) \
macro(moveWordRightAndModifySelection) \
macro(outdent) \
+macro(orderFrontSubstitutionsPanel) \
macro(pageDown) \
macro(pageDownAndModifySelection) \
macro(pageUp) \
@@ -295,32 +325,23 @@ macro(yankAndSelect) \
#define UsingAcceleratedCompositingProperty @"_isUsingAcceleratedCompositing"
#endif
-
static BOOL s_didSetCacheModel;
static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
-static BOOL applicationIsTerminating;
-static int pluginDatabaseClientCount = 0;
+static WebView *lastMouseoverView;
#ifndef NDEBUG
static const char webViewIsOpen[] = "At least one WebView is still open.";
#endif
-@interface NSSpellChecker (AppKitSecretsIKnow)
-- (void)_preflightChosenSpellServer;
-@end
-
-@interface NSView (AppKitSecretsIKnow)
-- (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
-- (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
-- (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
-@end
-
-@interface NSWindow (AppKitSecretsIKnow)
-- (id)_oldFirstResponderBeforeBecoming;
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+@interface NSObject (NSTextInputContextDetails)
+- (BOOL)wantsToHandleMouseEvents;
+- (BOOL)handleMouseEvent:(NSEvent *)event;
@end
+#endif
-@interface NSObject (ValidateWithoutDelegate)
+@interface NSObject (WebValidateWithoutDelegate)
- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
@end
@@ -333,99 +354,6 @@ static const char webViewIsOpen[] = "At least one WebView is still open.";
- (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
@end
-@interface WebViewPrivate : NSObject {
-@public
- Page* page;
-
- id UIDelegate;
- id UIDelegateForwarder;
- id resourceProgressDelegate;
- id downloadDelegate;
- id policyDelegate;
- id policyDelegateForwarder;
- id frameLoadDelegate;
- id frameLoadDelegateForwarder;
- id <WebFormDelegate> formDelegate;
- id editingDelegate;
- id editingDelegateForwarder;
- id scriptDebugDelegate;
-
- WebInspector *inspector;
- WebNodeHighlight *currentNodeHighlight;
-
- BOOL allowsUndo;
-
- float zoomMultiplier;
-
- NSString *applicationNameForUserAgent;
- String userAgent;
- BOOL userAgentOverridden;
-
- WebPreferences *preferences;
- BOOL useSiteSpecificSpoofing;
-
- NSWindow *hostWindow;
-
- int programmaticFocusCount;
-
- WebResourceDelegateImplementationCache resourceLoadDelegateImplementations;
- WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations;
- WebScriptDebugDelegateImplementationCache scriptDebugDelegateImplementations;
-
- void *observationInfo;
-
- BOOL closed;
- BOOL shouldCloseWithWindow;
- BOOL mainFrameDocumentReady;
- BOOL drawsBackground;
- BOOL editable;
- BOOL tabKeyCyclesThroughElementsChanged;
- BOOL becomingFirstResponder;
- BOOL becomingFirstResponderFromOutside;
- BOOL hoverFeedbackSuspended;
- BOOL usesPageCache;
- BOOL catchesDelegateExceptions;
-
- NSColor *backgroundColor;
-
- NSString *mediaStyle;
-
- BOOL hasSpellCheckerDocumentTag;
- NSInteger spellCheckerDocumentTag;
-
- BOOL smartInsertDeleteEnabled;
- BOOL selectTrailingWhitespaceEnabled;
-
-#if ENABLE(DASHBOARD_SUPPORT)
- BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
- BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
- BOOL dashboardBehaviorAlwaysAcceptsFirstMouse;
- BOOL dashboardBehaviorAllowWheelScrolling;
-#endif
-
- // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database.
- WebPluginDatabase *pluginDatabase;
-
- HashMap<unsigned long, RetainPtr<id> > identifierMap;
-
- BOOL _keyboardUIModeAccessed;
- KeyboardUIMode _keyboardUIMode;
-
- BOOL shouldUpdateWhileOffscreen;
-
- // When this flag is set, we will not make any subviews underneath this WebView. This means no WebFrameViews and no WebHTMLViews.
- BOOL useDocumentViews;
-
-#if USE(ACCELERATED_COMPOSITING)
- // When this flag is set, next time a WebHTMLView draws, it needs to temporarily disable screen updates
- // so that the NSView drawing is visually synchronized with CALayer updates.
- BOOL needsOneShotDrawingSynchronization;
- // Number of WebHTMLViews using accelerated compositing. Used to implement _isUsingAcceleratedCompositing.
- int acceleratedFramesCount;
-#endif
-}
-@end
-
@interface WebView (WebFileInternal)
- (WebFrame *)_selectedOrMainFrame;
- (BOOL)_isLoading;
@@ -434,9 +362,9 @@ static const char webViewIsOpen[] = "At least one WebView is still open.";
+ (void)_preflightSpellChecker;
- (BOOL)_continuousCheckingAllowed;
- (NSResponder *)_responderForResponderOperations;
-@end
-
-@interface WebView (WebCallDelegateFunctions)
+#if USE(ACCELERATED_COMPOSITING)
+- (void)_clearLayerSyncLoopObserver;
+#endif
@end
static void patchMailRemoveAttributesMethod();
@@ -497,75 +425,13 @@ static BOOL continuousSpellCheckingEnabled;
#ifndef BUILDING_ON_TIGER
static BOOL grammarCheckingEnabled;
#endif
-
-@implementation WebViewPrivate
-
-+ (void)initialize
-{
- JSC::initializeThreading();
-#ifndef BUILDING_ON_TIGER
- WebCoreObjCFinalizeOnMainThread(self);
-#endif
-}
-
-- init
-{
- self = [super init];
- if (!self)
- return nil;
- JSC::initializeThreading();
- allowsUndo = YES;
- zoomMultiplier = 1;
-#if ENABLE(DASHBOARD_SUPPORT)
- dashboardBehaviorAllowWheelScrolling = YES;
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+static BOOL automaticQuoteSubstitutionEnabled;
+static BOOL automaticLinkDetectionEnabled;
+static BOOL automaticDashSubstitutionEnabled;
+static BOOL automaticTextReplacementEnabled;
+static BOOL automaticSpellingCorrectionEnabled;
#endif
- shouldCloseWithWindow = objc_collecting_enabled();
- continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
-
-#ifndef BUILDING_ON_TIGER
- grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
-#endif
-
- usesPageCache = YES;
-
- pluginDatabaseClientCount++;
-
- shouldUpdateWhileOffscreen = YES;
-
- return self;
-}
-
-- (void)dealloc
-{
- ASSERT(applicationIsTerminating || !page);
- ASSERT(applicationIsTerminating || !preferences);
-
- [applicationNameForUserAgent release];
- [backgroundColor release];
-
- [inspector release];
- [currentNodeHighlight release];
-
- [hostWindow release];
-
- [policyDelegateForwarder release];
- [UIDelegateForwarder release];
- [frameLoadDelegateForwarder release];
- [editingDelegateForwarder release];
-
- [mediaStyle release];
-
- [super dealloc];
-}
-
-- (void)finalize
-{
- ASSERT_MAIN_THREAD();
-
- [super finalize];
-}
-
-@end
@implementation WebView (AllWebViews)
@@ -680,7 +546,7 @@ static void WebKitInitializeApplicationCachePathIfNecessary()
static bool runningLeopardMail()
{
#ifdef BUILDING_ON_LEOPARD
- return [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"];
+ return applicationIsAppleMail();
#endif
return NO;
}
@@ -688,11 +554,16 @@ static bool runningLeopardMail()
static bool runningTigerMail()
{
#ifdef BUILDING_ON_TIGER
- return [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"];
+ return applicationIsAppleMail();
#endif
return NO;
}
+- (void)_dispatchPendingLoadRequests
+{
+ cache()->loader()->servePendingRequests();
+}
+
- (void)_registerDraggedTypes
{
NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
@@ -705,7 +576,7 @@ static bool runningTigerMail()
- (BOOL)_usesDocumentViews
{
- return _private->useDocumentViews;
+ return _private->usesDocumentViews;
}
- (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
@@ -723,12 +594,11 @@ static bool runningTigerMail()
_private->catchesDelegateExceptions = YES;
_private->mainFrameDocumentReady = NO;
_private->drawsBackground = YES;
- _private->smartInsertDeleteEnabled = YES;
- _private->backgroundColor = [[NSColor whiteColor] retain];
- _private->useDocumentViews = usesDocumentViews;
+ _private->backgroundColor = [[NSColor colorWithDeviceWhite:1 alpha:1] retain];
+ _private->usesDocumentViews = usesDocumentViews;
WebFrameView *frameView = nil;
- if (_private->useDocumentViews) {
+ if (_private->usesDocumentViews) {
NSRect f = [self frame];
frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
[frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
@@ -797,6 +667,9 @@ static bool runningTigerMail()
// with substitute data.
FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForLocalAndSubstituteData);
}
+
+ if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS))
+ ResourceHandle::forceContentSniffing();
}
- (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews
@@ -823,15 +696,6 @@ static bool runningTigerMail()
return self;
}
-- (void)_boundsChanged
-{
- Frame* frame = core([self mainFrame]);
- IntSize oldSize = frame->view()->frameRect().size();
- frame->view()->resize([self bounds].size.width, [self bounds].size.height);
- if (oldSize != frame->view()->frameRect().size())
- [self setNeedsDisplay: YES];
-}
-
- (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count
{
// If count == 0 here, use the rect passed in for drawing. This is a workaround for:
@@ -858,7 +722,7 @@ static bool runningTigerMail()
- (void)drawSingleRect:(NSRect)rect
{
- ASSERT(!_private->useDocumentViews);
+ ASSERT(!_private->usesDocumentViews);
[NSGraphicsContext saveGraphicsState];
NSRectClip(rect);
@@ -882,18 +746,43 @@ static bool runningTigerMail()
- (BOOL)isFlipped
{
- return _private && !_private->useDocumentViews;
+ return _private && !_private->usesDocumentViews;
+}
+
+- (void)setFrameSize:(NSSize)size
+{
+ if (!_private->usesDocumentViews && !NSEqualSizes(_private->lastLayoutSize, size)) {
+ Frame* frame = [self _mainCoreFrame];
+ // FIXME: Viewless WebKit is broken with Safari banners (e.g., the Find banner). We'll have to figure out a way for
+ // Safari to communicate that this space is being consumed. For WebKit with document views, there's no
+ // need to do an explicit resize, since WebFrameViews have auto resizing turned on and will handle changing
+ // their bounds automatically. See <rdar://problem/6835573> for details.
+ frame->view()->resize(IntSize(size));
+ frame->view()->setNeedsLayout();
+ [self setNeedsDisplay:YES];
+ _private->lastLayoutSize = size;
+ }
+
+ [super setFrameSize:size];
+}
+
+#if USE(ACCELERATED_COMPOSITING) || !defined(BUILDING_ON_TIGER)
+
+- (void)_viewWillDrawInternal
+{
+ Frame* frame = [self _mainCoreFrame];
+ if (frame && frame->view())
+ frame->view()->layoutIfNeededRecursive();
}
+#endif
+
#ifndef BUILDING_ON_TIGER
- (void)viewWillDraw
{
- if (!_private->useDocumentViews) {
- Frame* frame = core([self mainFrame]);
- if (frame && frame->view())
- frame->view()->layoutIfNeededRecursive();
- }
+ if (!_private->usesDocumentViews)
+ [self _viewWillDrawInternal];
[super viewWillDraw];
}
@@ -902,7 +791,7 @@ static bool runningTigerMail()
- (void)drawRect:(NSRect)rect
{
- if (_private->useDocumentViews)
+ if (_private->usesDocumentViews)
return [super drawRect:rect];
ASSERT_MAIN_THREAD();
@@ -1002,7 +891,22 @@ static bool runningTigerMail()
+ (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f
{
- WebCoreSetAlwaysUsesComplexTextCodePath(f);
+ Font::setCodePath(f ? Font::Complex : Font::Auto);
+}
+
++ (BOOL)canCloseAllWebViews
+{
+ return DOMWindow::dispatchAllPendingBeforeUnloadEvents();
+}
+
++ (void)closeAllWebViews
+{
+ DOMWindow::dispatchAllPendingUnloadEvents();
+
+ // This will close the WebViews in a random order. Change this if close order is important.
+ NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator];
+ while (WebView *webView = [enumerator nextObject])
+ [webView close];
}
+ (BOOL)canShowFile:(NSString *)path
@@ -1045,18 +949,33 @@ static bool runningTigerMail()
WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");
#endif
- // Dispatch unload events.
- // FIXME: Shouldn't have to use a RefPtr here -- keeping the frame alive while stopping it
- // should be WebCore's responsibility -- but we do as of the time this comment was written.
- RefPtr<Frame> mainFrame = core([self mainFrame]);
- if (mainFrame && mainFrame->page() && mainFrame->page()->pendingUnloadEventCount())
- mainFrame->loader()->stopLoading(true);
-
_private->closed = YES;
+
+ [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
[self _closePluginDatabases];
}
+static bool fastDocumentTeardownEnabled()
+{
+#ifdef NDEBUG
+ static bool enabled = ![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
+#else
+ static bool initialized = false;
+ static bool enabled = false;
+ if (!initialized) {
+ // This allows debug builds to default to not have fast teardown, so leak checking still works.
+ // But still allow the WebKitEnableFullDocumentTeardown default to override it if present.
+ NSNumber *setting = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
+ if (setting)
+ enabled = ![setting boolValue];
+ initialized = true;
+ }
+#endif
+ return enabled;
+}
+
// _close is here only for backward compatibility; clients and subclasses should use
// public method -close instead.
- (void)_close
@@ -1064,22 +983,21 @@ static bool runningTigerMail()
if (!_private || _private->closed)
return;
+ if (lastMouseoverView == self)
+ lastMouseoverView = nil;
+
#ifndef NDEBUG
WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);
#endif
-
- WebPreferences *preferences = _private->preferences;
- BOOL fullDocumentTeardown = [preferences fullDocumentTeardownEnabled];
-
- // To quit the apps fast we skip document teardown. Two exceptions:
- // 1) plugins need to be destroyed and unloaded
- // 2) unload events need to be called
- if (applicationIsTerminating && !fullDocumentTeardown) {
+
+ // To quit the apps fast we skip document teardown, except plugins
+ // need to be destroyed and unloaded.
+ if (applicationIsTerminating && fastDocumentTeardownEnabled()) {
[self _closeWithFastTeardown];
return;
}
- if (Frame* mainFrame = core([self mainFrame]))
+ if (Frame* mainFrame = [self _mainCoreFrame])
mainFrame->loader()->detachFromParent();
[self _removeFromAllWebViewsSet];
@@ -1111,12 +1029,17 @@ static bool runningTigerMail()
[[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
_private->hasSpellCheckerDocumentTag = NO;
}
+
+#if USE(ACCELERATED_COMPOSITING)
+ [self _clearLayerSyncLoopObserver];
+#endif
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
+ WebPreferences *preferences = _private->preferences;
_private->preferences = nil;
[preferences didRemoveFromWebView];
[preferences release];
@@ -1132,6 +1055,13 @@ static bool runningTigerMail()
#endif
}
+// Indicates if the WebView is in the midst of a user gesture.
+- (BOOL)_isProcessingUserGesture
+{
+ WebFrame *frame = [self mainFrame];
+ return core(frame)->loader()->isProcessingUserGesture();
+}
+
+ (NSString *)_MIMETypeForFile:(NSString *)path
{
NSString *extension = [path pathExtension];
@@ -1277,13 +1207,7 @@ static bool runningTigerMail()
- (BOOL)_needsAdobeFrameReloadingQuirk
{
- static BOOL checked = NO;
- static BOOL needsQuirk = NO;
-
- if (checked)
- return needsQuirk;
-
- needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
+ static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
|| WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
|| WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
|| WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
@@ -1293,26 +1217,29 @@ static bool runningTigerMail()
|| WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
|| WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
|| WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
- checked = YES;
return needsQuirk;
}
-- (BOOL)_needsKeyboardEventDisambiguationQuirks
+- (BOOL)_needsLinkElementTextCSSQuirk
{
- static BOOL checked = NO;
- static BOOL needsQuirks = NO;
-
- if (checked)
- return needsQuirks;
-
- needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH)
- && ![[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"];
- checked = YES;
+ static BOOL needsQuirk = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_LINK_ELEMENT_TEXT_CSS_QUIRK)
+ && WKAppVersionCheckLessThan(@"com.e-frontier.shade10", -1, 10.6);
+ return needsQuirk;
+}
+- (BOOL)_needsKeyboardEventDisambiguationQuirks
+{
+ static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari();
return needsQuirks;
}
+- (BOOL)_needsFrameLoadDelegateRetainQuirk
+{
+ static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.equinux.iSale5", -1, 5.6);
+ return needsQuirk;
+}
+
- (void)_preferencesChangedNotification:(NSNotification *)notification
{
WebPreferences *preferences = (WebPreferences *)[notification object];
@@ -1372,14 +1299,18 @@ static bool runningTigerMail()
} else
settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
+ settings->setTreatsAnyTextCSSLinkAsStylesheet([self _needsLinkElementTextCSSQuirk]);
settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]);
settings->setNeedsLeopardMailQuirks(runningLeopardMail());
settings->setNeedsTigerMailQuirks(runningTigerMail());
settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing);
settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]);
+ settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]);
settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]);
settings->setZoomsTextOnly([preferences zoomsTextOnly]);
+ settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]);
settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));
+ settings->setAcceleratedCompositingEnabled([preferences acceleratedCompositingEnabled]);
}
static inline IMP getMethod(id o, SEL s)
@@ -1411,14 +1342,6 @@ static inline IMP getMethod(id o, SEL s)
cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));
}
-WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView)
-{
- static WebResourceDelegateImplementationCache empty;
- if (!webView)
- return &empty;
- return &webView->_private->resourceLoadDelegateImplementations;
-}
-
- (void)_cacheFrameLoadDelegateImplementations
{
WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
@@ -1432,6 +1355,7 @@ WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementa
cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
+ cache->didClearInspectorWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearInspectorWindowObject:forFrame:));
cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
@@ -1449,14 +1373,6 @@ WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementa
cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
}
-WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView)
-{
- static WebFrameLoadDelegateImplementationCache empty;
- if (!webView)
- return &empty;
- return &webView->_private->frameLoadDelegateImplementations;
-}
-
- (void)_cacheScriptDebugDelegateImplementations
{
WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations;
@@ -1480,14 +1396,6 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati
cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:));
}
-WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView)
-{
- static WebScriptDebugDelegateImplementationCache empty;
- if (!webView)
- return &empty;
- return &webView->_private->scriptDebugDelegateImplementations;
-}
-
- (id)_policyDelegateForwarder
{
if (!_private->policyDelegateForwarder)
@@ -1758,42 +1666,72 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
#define DASHBOARD_CONTROL_LABEL @"control"
+- (void)_addControlRect:(NSRect)bounds clip:(NSRect)clip fromView:(NSView *)view toDashboardRegions:(NSMutableDictionary *)regions
+{
+ NSRect adjustedBounds = bounds;
+ adjustedBounds.origin = [self convertPoint:bounds.origin fromView:view];
+ adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
+ adjustedBounds.size = bounds.size;
+
+ NSRect adjustedClip;
+ adjustedClip.origin = [self convertPoint:clip.origin fromView:view];
+ adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
+ adjustedClip.size = clip.size;
+
+ WebDashboardRegion *region = [[WebDashboardRegion alloc] initWithRect:adjustedBounds
+ clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle];
+ NSMutableArray *scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
+ if (!scrollerRegions) {
+ scrollerRegions = [[NSMutableArray alloc] init];
+ [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
+ [scrollerRegions release];
+ }
+ [scrollerRegions addObject:region];
+ [region release];
+}
+
+- (void)_addScrollerDashboardRegionsForFrameView:(FrameView*)frameView dashboardRegions:(NSMutableDictionary *)regions
+{
+ NSView *documentView = [[kit(frameView->frame()) frameView] documentView];
+
+ const HashSet<RefPtr<Widget> >* children = frameView->children();
+ HashSet<RefPtr<Widget> >::const_iterator end = children->end();
+ for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
+ Widget* widget = (*it).get();
+ if (widget->isFrameView()) {
+ [self _addScrollerDashboardRegionsForFrameView:static_cast<FrameView*>(widget) dashboardRegions:regions];
+ continue;
+ }
+
+ if (!widget->isScrollbar())
+ continue;
+
+ // FIXME: This should really pass an appropriate clip, but our first try got it wrong, and
+ // it's not common to need this to be correct in Dashboard widgets.
+ NSRect bounds = widget->frameRect();
+ [self _addControlRect:bounds clip:bounds fromView:documentView toDashboardRegions:regions];
+ }
+}
+
- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
{
- // Add scroller regions for NSScroller and KWQScrollBar
- int i, count = [views count];
-
- for (i = 0; i < count; i++) {
- NSView *aView = [views objectAtIndex:i];
+ // Add scroller regions for NSScroller and WebCore scrollbars
+ NSUInteger count = [views count];
+ for (NSUInteger i = 0; i < count; i++) {
+ NSView *view = [views objectAtIndex:i];
- if ([aView isKindOfClass:[NSScroller class]] ||
- [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) {
- NSRect bounds = [aView bounds];
- NSRect adjustedBounds;
- adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView];
- adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
-
- // AppKit has horrible hack of placing absent scrollers at -100,-100
- if (adjustedBounds.origin.y == -100)
- continue;
- adjustedBounds.size = bounds.size;
- NSRect clip = [aView visibleRect];
- NSRect adjustedClip;
- adjustedClip.origin = [self convertPoint:clip.origin fromView:aView];
- adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
- adjustedClip.size = clip.size;
- WebDashboardRegion *aRegion =
- [[[WebDashboardRegion alloc] initWithRect:adjustedBounds
- clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease];
- NSMutableArray *scrollerRegions;
- scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
- if (!scrollerRegions) {
- scrollerRegions = [NSMutableArray array];
- [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
+ if ([view isKindOfClass:[WebHTMLView class]]) {
+ if (Frame* coreFrame = core([(WebHTMLView*)view _frame])) {
+ if (FrameView* coreView = coreFrame->view())
+ [self _addScrollerDashboardRegionsForFrameView:coreView dashboardRegions:regions];
}
- [scrollerRegions addObject:aRegion];
+ } else if ([view isKindOfClass:[NSScroller class]]) {
+ // AppKit places absent scrollers at -100,-100
+ if ([view frame].origin.y < 0)
+ continue;
+ [self _addControlRect:[view bounds] clip:[view visibleRect] fromView:view toDashboardRegions:regions];
}
- [self _addScrollerDashboardRegions:regions from:[aView subviews]];
+ [self _addScrollerDashboardRegions:regions from:[view subviews]];
}
}
@@ -1805,7 +1743,7 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
- (NSDictionary *)_dashboardRegions
{
// Only return regions from main frame.
- Frame* mainFrame = core([self mainFrame]);
+ Frame* mainFrame = [self _mainCoreFrame];
if (!mainFrame)
return nil;
NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
@@ -1871,12 +1809,12 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
+ (void)_setShouldUseFontSmoothing:(BOOL)f
{
- WebCoreSetShouldUseFontSmoothing(f);
+ Font::setShouldUseSmoothing(f);
}
+ (BOOL)_shouldUseFontSmoothing
{
- return WebCoreShouldUseFontSmoothing();
+ return Font::shouldUseSmoothing();
}
+ (void)_setUsesTestModeFocusRingColor:(BOOL)f
@@ -1889,12 +1827,6 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
return usesTestModeFocusRingColor();
}
-// This is only used by versions of Safari up to and including 3.0 and should be removed in a future release.
-+ (NSString *)_minimumRequiredSafariBuildNumber
-{
- return @"420+";
-}
-
- (void)setAlwaysShowVerticalScroller:(BOOL)flag
{
WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
@@ -1925,8 +1857,7 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
- (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
{
- Frame* mainFrame = core([self mainFrame]);
- if (mainFrame)
+ if (Frame* mainFrame = [self _mainCoreFrame])
mainFrame->view()->setProhibitsScrolling(prohibits);
}
@@ -1938,14 +1869,13 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
- (void)_setInViewSourceMode:(BOOL)flag
{
- Frame* mainFrame = core([self mainFrame]);
- if (mainFrame)
+ if (Frame* mainFrame = [self _mainCoreFrame])
mainFrame->setInViewSourceMode(flag);
}
- (BOOL)_inViewSourceMode
{
- Frame* mainFrame = core([self mainFrame]);
+ Frame* mainFrame = [self _mainCoreFrame];
return mainFrame && mainFrame->inViewSourceMode();
}
@@ -1988,13 +1918,13 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
- (void)_attachScriptDebuggerToAllFrames
{
- for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
+ for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
[kit(frame) _attachScriptDebugger];
}
- (void)_detachScriptDebuggerFromAllFrames
{
- for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
+ for (Frame* frame = [self _mainCoreFrame]; frame; frame = frame->tree()->traverseNext())
[kit(frame) _detachScriptDebugger];
}
@@ -2057,13 +1987,13 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
IntPoint rectStart(rect.origin.x, rect.origin.y);
IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
- Frame* coreFrame = core([self mainFrame]);
+ Frame* coreFrame = [self _mainCoreFrame];
if (!coreFrame)
return nil;
VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
- return [[[WebTextIterator alloc] initWithRange:[DOMRange _wrapRange:selectionInsideRect.toNormalizedRange().get()]] autorelease];
+ return [[[WebTextIterator alloc] initWithRange:kit(selectionInsideRect.toNormalizedRange().get())] autorelease];
}
- (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
@@ -2091,7 +2021,7 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
- (void)_executeCoreCommandByName:(NSString *)name value:(NSString *)value
{
- Frame* coreFrame = core([self mainFrame]);
+ Frame* coreFrame = [self _mainCoreFrame];
if (!coreFrame)
return;
coreFrame->editor()->command(name).execute(value);
@@ -2148,47 +2078,25 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
return handCursor().impl();
}
-#if USE(ACCELERATED_COMPOSITING)
-- (BOOL)_needsOneShotDrawingSynchronization
-{
- return _private->needsOneShotDrawingSynchronization;
-}
-
-- (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization
+- (BOOL)_isUsingAcceleratedCompositing
{
- _private->needsOneShotDrawingSynchronization = needsSynchronization;
+#if USE(ACCELERATED_COMPOSITING)
+ return _private->acceleratedFramesCount > 0;
+#else
+ return NO;
+#endif
}
-- (void)_startedAcceleratedCompositingForFrame:(WebFrame*)webFrame
+- (NSPasteboard *)_insertionPasteboard
{
- BOOL entering = _private->acceleratedFramesCount == 0;
- if (entering)
- [self willChangeValueForKey:UsingAcceleratedCompositingProperty];
- ++_private->acceleratedFramesCount;
- if (entering)
- [self didChangeValueForKey:UsingAcceleratedCompositingProperty];
+ return _private ? _private->insertionPasteboard : nil;
}
-- (void)_stoppedAcceleratedCompositingForFrame:(WebFrame*)webFrame
-{
- BOOL leaving = _private->acceleratedFramesCount == 1;
- ASSERT(_private->acceleratedFramesCount > 0);
-
- if (leaving)
- [self willChangeValueForKey:UsingAcceleratedCompositingProperty];
- --_private->acceleratedFramesCount;
- if (leaving)
- [self didChangeValueForKey:UsingAcceleratedCompositingProperty];
-}
-#endif
-- (BOOL)_isUsingAcceleratedCompositing
+- (void)_updateActiveState
{
-#if USE(ACCELERATED_COMPOSITING)
- return _private->acceleratedFramesCount > 0;
-#else
- return NO;
-#endif
+ if (_private && _private->page)
+ _private->page->focusController()->setActive([[self window] isKeyWindow]);
}
@end
@@ -2244,14 +2152,33 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
return;
initialized = YES;
+ InitWebCoreSystemInterface();
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
+
+ continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
+#ifndef BUILDING_ON_TIGER
+ grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
+#endif
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ automaticQuoteSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticQuoteSubstitutionEnabled];
+ automaticLinkDetectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticLinkDetectionEnabled];
+ automaticDashSubstitutionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticDashSubstitutionEnabled];
+ automaticTextReplacementEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticTextReplacementEnabled];
+ automaticSpellingCorrectionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebAutomaticSpellingCorrectionEnabled];
+#endif
}
+ (void)_applicationWillTerminate
{
applicationIsTerminating = YES;
+
+ if (fastDocumentTeardownEnabled())
+ [self closeAllWebViews];
+
if (!pluginDatabaseClientCount)
[WebPluginDatabase closeSharedDatabase];
@@ -2368,7 +2295,7 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
+ (void)registerURLSchemeAsLocal:(NSString *)protocol
{
- FrameLoader::registerURLSchemeAsLocal(protocol);
+ SecurityOrigin::registerURLSchemeAsLocal(protocol);
}
- (id)_initWithArguments:(NSDictionary *) arguments
@@ -2388,11 +2315,41 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen
return self;
}
+static bool clientNeedsWebViewInitThreadWorkaround()
+{
+ if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND))
+ return false;
+
+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
+
+ // Installer.
+ if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.installer"])
+ return true;
+
+ // Automator.
+ if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Automator"])
+ return true;
+
+ // Automator Runner.
+ if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.AutomatorRunner"])
+ return true;
+
+ // Automator workflows.
+ if ([bundleIdentifier _webkit_hasCaseInsensitivePrefix:@"com.apple.Automator."])
+ return true;
+
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+ // Mail.
+ if ([bundleIdentifier _webkit_isCaseInsensitiveEqualToString:@"com.apple.Mail"])
+ return true;
+#endif
+
+ return false;
+}
+
static bool needsWebViewInitThreadWorkaround()
{
- static BOOL isOldClient = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND)
- && ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.installer"] ||
- [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Automator"]);
+ static bool isOldClient = clientNeedsWebViewInitThreadWorkaround();
return isOldClient && !pthread_main_np();
}
@@ -2517,6 +2474,9 @@ static bool needsWebViewInitThreadWorkaround()
--WebViewCount;
+ if ([self _needsFrameLoadDelegateRetainQuirk])
+ [_private->frameLoadDelegate release];
+
[_private release];
// [super dealloc] can end up dispatching against _private (3466082)
_private = nil;
@@ -2549,31 +2509,9 @@ static bool needsWebViewInitThreadWorkaround()
return _private->shouldCloseWithWindow;
}
-- (void)removeSizeObservers
-{
- if (!_private->useDocumentViews && [self window]) {
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:NSViewFrameDidChangeNotification object:self];
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:NSViewBoundsDidChangeNotification object:self];
- }
-}
-
-- (void)addSizeObservers
+- (void)addWindowObserversForWindow:(NSWindow *)window
{
- if (!_private->useDocumentViews && [self window]) {
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_boundsChanged)
- name:NSViewFrameDidChangeNotification object:self];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_boundsChanged)
- name:NSViewBoundsDidChangeNotification object:self];
- [self _boundsChanged];
- }
-}
-
-- (void)addWindowObservers
-{
- NSWindow *window = [self window];
- if (!_private->useDocumentViews && window) {
+ if (window) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:)
name:NSWindowDidBecomeKeyNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:)
@@ -2586,7 +2524,7 @@ static bool needsWebViewInitThreadWorkaround()
- (void)removeWindowObservers
{
NSWindow *window = [self window];
- if (!_private->useDocumentViews && window) {
+ if (window) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSWindowDidBecomeKeyNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
@@ -2601,10 +2539,7 @@ static bool needsWebViewInitThreadWorkaround()
// Don't do anything if the WebView isn't initialized.
// This happens when decoding a WebView in a nib.
// FIXME: What sets up the observer of NSWindowWillCloseNotification in this case?
- if (!_private)
- return;
-
- if (_private->closed)
+ if (!_private || _private->closed)
return;
if ([self window] && [self window] != [self hostWindow])
@@ -2618,11 +2553,13 @@ static bool needsWebViewInitThreadWorkaround()
// and over, so do them when we move into a window.
[window setAcceptsMouseMovedEvents:YES];
WKSetNSWindowShouldPostEventNotifications(window, YES);
-
- [self removeWindowObservers];
- [self removeSizeObservers];
} else
_private->page->willMoveOffscreen();
+
+ if (window != [self window]) {
+ [self removeWindowObservers];
+ [self addWindowObserversForWindow:window];
+ }
}
- (void)viewDidMoveToWindow
@@ -2633,66 +2570,29 @@ static bool needsWebViewInitThreadWorkaround()
// initialized. The stub views are discarded by WebView.
if (!_private || _private->closed)
return;
-
- if ([self window]) {
- [self addWindowObservers];
- [self addSizeObservers];
- _private->page->didMoveOnscreen();
- }
-}
-- (void)_updateFocusedAndActiveState
-{
- ASSERT(!_private->useDocumentViews);
- [self _updateFocusedAndActiveStateForFrame:[self mainFrame]];
-}
-
-- (void)_updateFocusedAndActiveStateForFrame:(WebFrame *)webFrame
-{
- Frame* frame = core(webFrame);
- if (!frame)
- return;
+ if ([self window])
+ _private->page->didMoveOnscreen();
- Page* page = frame->page();
- if (!page)
- return;
-
- NSWindow *window = [self window];
- BOOL windowIsKey = [window isKeyWindow];
- BOOL windowOrSheetIsKey = windowIsKey || [[window attachedSheet] isKeyWindow];
-
- WebFrameView *mainFrameView = [[self mainFrame] frameView];
- id <WebDocumentView> documentView = [mainFrameView documentView];
- BOOL documentViewIsResigningFirstResponder = [documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isResigningFirstResponder];
-
- NSResponder *firstResponder = [window firstResponder];
- if ([firstResponder isKindOfClass:[NSView class]]
- && [(NSView *)firstResponder isDescendantOf:mainFrameView])
- page->focusController()->setActive(windowIsKey && !documentViewIsResigningFirstResponder);
-
- Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
- frame->selection()->setFocused(frame == focusedFrame && windowOrSheetIsKey);
+ [self _updateActiveState];
}
- (void)_windowDidBecomeKey:(NSNotification *)notification
{
- ASSERT(!_private->useDocumentViews);
NSWindow *keyWindow = [notification object];
if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
- [self _updateFocusedAndActiveState];
+ [self _updateActiveState];
}
- (void)_windowDidResignKey:(NSNotification *)notification
{
- ASSERT(!_private->useDocumentViews);
NSWindow *formerKeyWindow = [notification object];
if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
- [self _updateFocusedAndActiveState];
+ [self _updateActiveState];
}
- (void)_windowWillOrderOnScreen:(NSNotification *)notification
{
- ASSERT(!_private->useDocumentViews);
if (![self shouldUpdateWhileOffscreen])
[self setNeedsDisplay:YES];
}
@@ -2797,12 +2697,23 @@ static bool needsWebViewInitThreadWorkaround()
- (void)setFrameLoadDelegate:delegate
{
+ // <rdar://problem/6950660> - Due to some subtle WebKit changes - presumably to delegate callback behavior - we've
+ // unconvered a latent bug in at least one WebKit app where the delegate wasn't properly retained by the app and
+ // was dealloc'ed before being cleared.
+ // This is an effort to keep such apps working for now.
+ if ([self _needsFrameLoadDelegateRetainQuirk]) {
+ [delegate retain];
+ [_private->frameLoadDelegate release];
+ }
+
_private->frameLoadDelegate = delegate;
[self _cacheFrameLoadDelegateImplementations];
+#if ENABLE(ICONDATABASE)
// If this delegate wants callbacks for icons, fire up the icon database.
if (_private->frameLoadDelegateImplementations.didReceiveIconForFrameFunc)
[WebIconDatabase sharedIconDatabase];
+#endif
}
- frameLoadDelegate
@@ -2813,21 +2724,21 @@ static bool needsWebViewInitThreadWorkaround()
- (WebFrame *)mainFrame
{
// This can be called in initialization, before _private has been set up (3465613)
- if (!_private)
- return nil;
- if (!_private->page)
+ if (!_private || !_private->page)
return nil;
return kit(_private->page->mainFrame());
}
- (WebFrame *)selectedFrame
{
- // If the first responder is a view in our tree, we get the frame containing the first responder.
- // This is faster than searching the frame hierarchy, and will give us a result even in the case
- // where the focused frame doesn't actually contain a selection.
- WebFrame *focusedFrame = [self _focusedFrame];
- if (focusedFrame)
- return focusedFrame;
+ if (_private->usesDocumentViews) {
+ // If the first responder is a view in our tree, we get the frame containing the first responder.
+ // This is faster than searching the frame hierarchy, and will give us a result even in the case
+ // where the focused frame doesn't actually contain a selection.
+ WebFrame *focusedFrame = [self _focusedFrame];
+ if (focusedFrame)
+ return focusedFrame;
+ }
// If the first responder is outside of our view tree, we search for a frame containing a selection.
// There should be at most only one of these.
@@ -2843,7 +2754,7 @@ static bool needsWebViewInitThreadWorkaround()
return kit(_private->page->backForwardList());
}
-- (void)setMaintainsBackForwardList: (BOOL)flag
+- (void)setMaintainsBackForwardList:(BOOL)flag
{
if (!_private->page)
return;
@@ -2895,7 +2806,7 @@ static bool needsWebViewInitThreadWorkaround()
// FIXME: it would be nice to rework this code so that _private->zoomMultiplier doesn't exist and callers
// all access _private->page->settings().
- Frame* coreFrame = core([self mainFrame]);
+ Frame* coreFrame = [self _mainCoreFrame];
if (coreFrame)
coreFrame->setZoomFactor(m, isTextOnly);
}
@@ -2990,17 +2901,6 @@ static bool needsWebViewInitThreadWorkaround()
[self _setZoomMultiplier:1.0f isTextOnly:isTextOnly];
}
-- (void)viewWillMoveToSuperview:(NSView *)newSuperview
-{
- [self removeSizeObservers];
-}
-
-- (void)viewDidMoveToSuperview
-{
- if ([self superview] != nil)
- [self addSizeObservers];
-}
-
- (void)setApplicationNameForUserAgent:(NSString *)applicationName
{
NSString *name = [applicationName copy];
@@ -3053,7 +2953,7 @@ static bool needsWebViewInitThreadWorkaround()
NSString *oldEncoding = [self customTextEncodingName];
if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
return;
- if (Frame* mainFrame = core([self mainFrame]))
+ if (Frame* mainFrame = [self _mainCoreFrame])
mainFrame->loader()->reloadWithOverrideEncoding(encoding);
}
@@ -3094,7 +2994,7 @@ static bool needsWebViewInitThreadWorkaround()
- (WebScriptObject *)windowScriptObject
{
- Frame* coreFrame = core([self mainFrame]);
+ Frame* coreFrame = [self _mainCoreFrame];
if (!coreFrame)
return nil;
return coreFrame->script()->windowScriptObject();
@@ -3113,17 +3013,21 @@ static bool needsWebViewInitThreadWorkaround()
if (hostWindow == _private->hostWindow)
return;
- Frame* coreFrame = core([self mainFrame]);
- for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
- [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
+ Frame* coreFrame = [self _mainCoreFrame];
+ if (_private->usesDocumentViews) {
+ for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
+ [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
+ }
if (_private->hostWindow && [self window] != _private->hostWindow)
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
if (hostWindow)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
[_private->hostWindow release];
_private->hostWindow = [hostWindow retain];
- for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
- [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
+ if (_private->usesDocumentViews) {
+ for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
+ [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
+ }
}
- (NSWindow *)hostWindow
@@ -3159,7 +3063,7 @@ static bool needsWebViewInitThreadWorkaround()
return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
}
-// The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
+// The following 2 internal NSView methods are called on the drag destination to make scrolling while dragging work.
// Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination.
// When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination.
// Forward these calls to the document subview to make its scroll view scroll.
@@ -3228,87 +3132,98 @@ static bool needsWebViewInitThreadWorkaround()
return core(self)->dragController()->performDrag(&dragData);
}
-- (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
+- (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
{
- NSView *hitView = [super _hitTest:aPoint dragTypes:types];
- if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
+ NSView *hitView = [super _hitTest:point dragTypes:types];
+ if (!hitView && [[self superview] mouse:*point inRect:[self frame]])
return self;
- } else {
- return hitView;
- }
+ return hitView;
}
- (BOOL)acceptsFirstResponder
{
- return [[[self mainFrame] frameView] acceptsFirstResponder];
+ if (_private->usesDocumentViews)
+ return [[[self mainFrame] frameView] acceptsFirstResponder];
+
+ // FIXME (Viewless): Need more code from WebHTMLView here.
+ return YES;
}
- (BOOL)becomeFirstResponder
{
- if (_private->becomingFirstResponder) {
- // Fix for unrepro infinite recursion reported in radar 4448181. If we hit this assert on
- // a debug build, we should figure out what causes the problem and do a better fix.
- ASSERT_NOT_REACHED();
- return NO;
- }
-
- // This works together with setNextKeyView to splice the WebView into
- // the key loop similar to the way NSScrollView does this. Note that
- // WebFrameView has very similar code.
- NSWindow *window = [self window];
- WebFrameView *mainFrameView = [[self mainFrame] frameView];
+ if (_private->usesDocumentViews) {
+ if (_private->becomingFirstResponder) {
+ // Fix for unrepro infinite recursion reported in Radar 4448181. If we hit this assert on
+ // a debug build, we should figure out what causes the problem and do a better fix.
+ ASSERT_NOT_REACHED();
+ return NO;
+ }
+
+ // This works together with setNextKeyView to splice the WebView into
+ // the key loop similar to the way NSScrollView does this. Note that
+ // WebFrameView has very similar code.
+ NSWindow *window = [self window];
+ WebFrameView *mainFrameView = [[self mainFrame] frameView];
+
+ NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
+ BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
+
+ if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
+ NSView *previousValidKeyView = [self previousValidKeyView];
+ if (previousValidKeyView != self && previousValidKeyView != mainFrameView) {
+ _private->becomingFirstResponder = YES;
+ _private->becomingFirstResponderFromOutside = fromOutside;
+ [window makeFirstResponder:previousValidKeyView];
+ _private->becomingFirstResponderFromOutside = NO;
+ _private->becomingFirstResponder = NO;
+ return YES;
+ }
+ return NO;
+ }
- NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
- BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
-
- if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
- NSView *previousValidKeyView = [self previousValidKeyView];
- if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
+ if ([mainFrameView acceptsFirstResponder]) {
_private->becomingFirstResponder = YES;
_private->becomingFirstResponderFromOutside = fromOutside;
- [window makeFirstResponder:previousValidKeyView];
+ [window makeFirstResponder:mainFrameView];
_private->becomingFirstResponderFromOutside = NO;
_private->becomingFirstResponder = NO;
return YES;
- } else {
- return NO;
- }
+ }
+
+ return NO;
}
-
- if ([mainFrameView acceptsFirstResponder]) {
- _private->becomingFirstResponder = YES;
- _private->becomingFirstResponderFromOutside = fromOutside;
- [window makeFirstResponder:mainFrameView];
- _private->becomingFirstResponderFromOutside = NO;
- _private->becomingFirstResponder = NO;
- return YES;
- }
-
- return NO;
+
+ // FIXME (Viewless): Need more code from WebHTMLView here.
+ return YES;
}
- (NSView *)_webcore_effectiveFirstResponder
{
- WebFrameView *frameView = [[self mainFrame] frameView];
- return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
+ if (_private && _private->usesDocumentViews) {
+ if (WebFrameView *frameView = [[self mainFrame] frameView])
+ return [frameView _webcore_effectiveFirstResponder];
+ }
+ return [super _webcore_effectiveFirstResponder];
}
-- (void)setNextKeyView:(NSView *)aView
+- (void)setNextKeyView:(NSView *)view
{
- // This works together with becomeFirstResponder to splice the WebView into
- // the key loop similar to the way NSScrollView does this. Note that
- // WebFrameView has very similar code.
- WebFrameView *mainFrameView = [[self mainFrame] frameView];
- if (mainFrameView != nil) {
- [mainFrameView setNextKeyView:aView];
- } else {
- [super setNextKeyView:aView];
+ if (_private && _private->usesDocumentViews) {
+ // This works together with becomeFirstResponder to splice the WebView into
+ // the key loop similar to the way NSScrollView does this. Note that
+ // WebFrameView has similar code.
+ if (WebFrameView *mainFrameView = [[self mainFrame] frameView]) {
+ [mainFrameView setNextKeyView:view];
+ return;
+ }
}
+
+ [super setNextKeyView:view];
}
-static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
+static WebFrame *incrementFrame(WebFrame *frame, BOOL forward, BOOL wrapFlag)
{
- Frame* coreFrame = core(curr);
+ Frame* coreFrame = core(frame);
return kit(forward
? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
: coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
@@ -3349,7 +3264,6 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
{
if (!_private->page)
return 0.0;
-
return _private->page->progress()->estimatedProgress();
}
@@ -3487,6 +3401,117 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
return _private->currentNodeHighlight;
}
+- (NSView *)previousValidKeyView
+{
+ NSView *result = [super previousValidKeyView];
+
+ // Work around AppKit bug 6905484. If the result is a view that's inside this one, it's
+ // possible it is the wrong answer, because the fact that it's a descendant causes the
+ // code that implements key view redirection to fail; this means we won't redirect to
+ // the toolbar, for example, when we hit the edge of a window. Since the bug is specific
+ // to cases where the receiver of previousValidKeyView is an ancestor of the last valid
+ // key view in the loop, we can sidestep it by walking along previous key views until
+ // we find one that is not a superview, then using that to call previousValidKeyView.
+
+ if (![result isDescendantOf:self])
+ return result;
+
+ // Use a visited set so we don't loop indefinitely when walking crazy key loops.
+ // AppKit uses such sets internally and we want our loop to be as robust as its loops.
+ RetainPtr<CFMutableSetRef> visitedViews = CFSetCreateMutable(0, 0, 0);
+ CFSetAddValue(visitedViews.get(), result);
+
+ NSView *previousView = self;
+ do {
+ CFSetAddValue(visitedViews.get(), previousView);
+ previousView = [previousView previousKeyView];
+ if (!previousView || CFSetGetValue(visitedViews.get(), previousView))
+ return result;
+ } while ([result isDescendantOf:previousView]);
+ return [previousView previousValidKeyView];
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+ // FIXME (Viewless): This method should be shared with WebHTMLView, which needs to
+ // do the same work in the usesDocumentViews case. We don't want to maintain two
+ // duplicate copies of this method.
+
+ if (_private->usesDocumentViews) {
+ [super mouseDown:event];
+ return;
+ }
+
+ // There's a chance that responding to this event will run a nested event loop, and
+ // fetching a new event might release the old one. Retaining and then autoreleasing
+ // the current event prevents that from causing a problem inside WebKit or AppKit code.
+ [[event retain] autorelease];
+
+ RetainPtr<WebView> protector = self;
+ if ([[self inputContext] wantsToHandleMouseEvents] && [[self inputContext] handleMouseEvent:event])
+ return;
+
+ _private->handlingMouseDownEvent = YES;
+
+ // Record the mouse down position so we can determine drag hysteresis.
+ [self _setMouseDownEvent:event];
+
+ NSInputManager *currentInputManager = [NSInputManager currentInputManager];
+ if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:event])
+ goto done;
+
+ [_private->completionController endRevertingChange:NO moveLeft:NO];
+
+ // If the web page handles the context menu event and menuForEvent: returns nil, we'll get control click events here.
+ // We don't want to pass them along to KHTML a second time.
+ if (!([event modifierFlags] & NSControlKeyMask)) {
+ _private->ignoringMouseDraggedEvents = NO;
+
+ // Don't do any mouseover while the mouse is down.
+ [self _cancelUpdateMouseoverTimer];
+
+ // Let WebCore get a chance to deal with the event. This will call back to us
+ // to start the autoscroll timer if appropriate.
+ if (Frame* frame = [self _mainCoreFrame])
+ frame->eventHandler()->mouseDown(event);
+ }
+
+done:
+ _private->handlingMouseDownEvent = NO;
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+ // FIXME (Viewless): This method should be shared with WebHTMLView, which needs to
+ // do the same work in the usesDocumentViews case. We don't want to maintain two
+ // duplicate copies of this method.
+
+ if (_private->usesDocumentViews) {
+ [super mouseUp:event];
+ return;
+ }
+
+ // There's a chance that responding to this event will run a nested event loop, and
+ // fetching a new event might release the old one. Retaining and then autoreleasing
+ // the current event prevents that from causing a problem inside WebKit or AppKit code.
+ [[event retain] autorelease];
+
+ [self _setMouseDownEvent:nil];
+
+ NSInputManager *currentInputManager = [NSInputManager currentInputManager];
+ if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:event])
+ return;
+
+ [self retain];
+
+ [self _stopAutoscrollTimer];
+ if (Frame* frame = [self _mainCoreFrame])
+ frame->eventHandler()->mouseUp(event);
+ [self _updateMouseoverWithFakeEvent];
+
+ [self release];
+}
+
@end
@implementation WebView (WebIBActions)
@@ -3627,6 +3652,13 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
[menuItem setState:checkMark ? NSOnState : NSOffState];
}
return retVal;
+ } else if (action == @selector(toggleSmartInsertDelete:)) {
+ BOOL checkMark = [self smartInsertDeleteEnabled];
+ if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ [menuItem setState:checkMark ? NSOnState : NSOffState];
+ }
+ return YES;
#ifndef BUILDING_ON_TIGER
} else if (action == @selector(toggleGrammarChecking:)) {
BOOL checkMark = [self isGrammarCheckingEnabled];
@@ -3636,6 +3668,43 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
}
return YES;
#endif
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ } else if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
+ BOOL checkMark = [self isAutomaticQuoteSubstitutionEnabled];
+ if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ [menuItem setState:checkMark ? NSOnState : NSOffState];
+ }
+ return YES;
+ } else if (action == @selector(toggleAutomaticLinkDetection:)) {
+ BOOL checkMark = [self isAutomaticLinkDetectionEnabled];
+ if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ [menuItem setState:checkMark ? NSOnState : NSOffState];
+ }
+ return YES;
+ } else if (action == @selector(toggleAutomaticDashSubstitution:)) {
+ BOOL checkMark = [self isAutomaticDashSubstitutionEnabled];
+ if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ [menuItem setState:checkMark ? NSOnState : NSOffState];
+ }
+ return YES;
+ } else if (action == @selector(toggleAutomaticTextReplacement:)) {
+ BOOL checkMark = [self isAutomaticTextReplacementEnabled];
+ if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ [menuItem setState:checkMark ? NSOnState : NSOffState];
+ }
+ return YES;
+ } else if (action == @selector(toggleAutomaticSpellingCorrection:)) {
+ BOOL checkMark = [self isAutomaticSpellingCorrectionEnabled];
+ if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ [menuItem setState:checkMark ? NSOnState : NSOffState];
+ }
+ return YES;
+#endif
}
FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
@@ -3737,15 +3806,21 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
return;
_private->hoverFeedbackSuspended = newValue;
- id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
- // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
- // such as by calling a protocol method or using respondsToSelector or sending a notification.
- // But until there is any need for these more general solutions, we'll just hardwire it to work
- // with WebHTMLView.
- // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
- // on each subframe separately.
- if ([documentView isKindOfClass:[WebHTMLView class]])
- [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
+
+ if (_private->usesDocumentViews) {
+ id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
+ // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
+ // such as by calling a protocol method or using respondsToSelector or sending a notification.
+ // But until there is any need for these more general solutions, we'll just hardwire it to work
+ // with WebHTMLView.
+ // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
+ // on each subframe separately.
+ if ([documentView isKindOfClass:[WebHTMLView class]])
+ [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
+ return;
+ }
+
+ [self _updateMouseoverWithFakeEvent];
}
- (BOOL)isHoverFeedbackSuspended
@@ -3803,13 +3878,13 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
- (BOOL)shouldClose
{
- Frame* coreFrame = core([self mainFrame]);
+ Frame* coreFrame = [self _mainCoreFrame];
if (!coreFrame)
return YES;
return coreFrame->shouldClose();
}
-static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsValue)
+static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue jsValue)
{
NSAppleEventDescriptor* aeDesc = 0;
if (jsValue.isBoolean())
@@ -3851,7 +3926,7 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV
return aeDesc;
}
}
- JSValuePtr primitive = object->toPrimitive(exec);
+ JSValue primitive = object->toPrimitive(exec);
if (exec->hadException()) {
exec->clearException();
return [NSAppleEventDescriptor nullDescriptor];
@@ -3866,15 +3941,15 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV
- (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
{
- Frame* coreFrame = core([self mainFrame]);
+ Frame* coreFrame = [self _mainCoreFrame];
if (!coreFrame)
return nil;
if (!coreFrame->document())
return nil;
- JSValuePtr result = coreFrame->loader()->executeScript(script, true).jsValue();
+ JSValue result = coreFrame->loader()->executeScript(script, true).jsValue();
if (!result) // FIXME: pass errors
return 0;
- JSLock lock(false);
+ JSLock lock(SilenceAssertionsOnly);
return aeDescFromJSValue(coreFrame->script()->globalObject()->globalExec(), result);
}
@@ -4215,7 +4290,7 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV
if (!coreFrame)
return;
- coreFrame->selection()->setSelectedRange([range _range], core(selectionAffinity), true);
+ coreFrame->selection()->setSelectedRange(core(range), core(selectionAffinity), true);
}
}
@@ -4241,7 +4316,7 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV
_private->editable = flag;
if (!_private->tabKeyCyclesThroughElementsChanged && _private->page)
_private->page->setTabKeyCyclesThroughElements(!flag);
- Frame* mainFrame = core([self mainFrame]);
+ Frame* mainFrame = [self _mainCoreFrame];
if (mainFrame) {
if (flag) {
mainFrame->applyEditingStyleToBodyElement();
@@ -4273,7 +4348,10 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV
- (void)setSmartInsertDeleteEnabled:(BOOL)flag
{
- _private->smartInsertDeleteEnabled = flag;
+ if (_private->smartInsertDeleteEnabled != flag) {
+ _private->smartInsertDeleteEnabled = flag;
+ [[NSUserDefaults standardUserDefaults] setBool:_private->smartInsertDeleteEnabled forKey:WebSmartInsertDeleteEnabled];
+ }
if (flag)
[self setSelectTrailingWhitespaceEnabled:false];
}
@@ -4393,10 +4471,13 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV
grammarCheckingEnabled = flag;
[[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled];
- // FIXME 4811447: workaround for lack of API
+#ifndef BUILDING_ON_LEOPARD
+ [[NSSpellChecker sharedSpellChecker] updatePanels];
+#else
NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
if ([spellChecker respondsToSelector:@selector(_updateGrammar)])
[spellChecker performSelector:@selector(_updateGrammar)];
+#endif
// We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
// because grammar checking only occurs on code paths that already preflight spell checking appropriately.
@@ -4414,6 +4495,129 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV
@end
+@implementation WebView (WebViewTextChecking)
+
+- (BOOL)isAutomaticQuoteSubstitutionEnabled
+{
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+ return NO;
+#else
+ return automaticQuoteSubstitutionEnabled;
+#endif
+}
+
+- (BOOL)isAutomaticLinkDetectionEnabled
+{
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+ return NO;
+#else
+ return automaticLinkDetectionEnabled;
+#endif
+}
+
+- (BOOL)isAutomaticDashSubstitutionEnabled
+{
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+ return NO;
+#else
+ return automaticDashSubstitutionEnabled;
+#endif
+}
+
+- (BOOL)isAutomaticTextReplacementEnabled
+{
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+ return NO;
+#else
+ return automaticTextReplacementEnabled;
+#endif
+}
+
+- (BOOL)isAutomaticSpellingCorrectionEnabled
+{
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+ return NO;
+#else
+ return automaticSpellingCorrectionEnabled;
+#endif
+}
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
+- (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag
+{
+ if (automaticQuoteSubstitutionEnabled == flag)
+ return;
+ automaticQuoteSubstitutionEnabled = flag;
+ [[NSUserDefaults standardUserDefaults] setBool:automaticQuoteSubstitutionEnabled forKey:WebAutomaticQuoteSubstitutionEnabled];
+ [[NSSpellChecker sharedSpellChecker] updatePanels];
+}
+
+- (void)toggleAutomaticQuoteSubstitution:(id)sender
+{
+ [self setAutomaticQuoteSubstitutionEnabled:![self isAutomaticQuoteSubstitutionEnabled]];
+}
+
+- (void)setAutomaticLinkDetectionEnabled:(BOOL)flag
+{
+ if (automaticLinkDetectionEnabled == flag)
+ return;
+ automaticLinkDetectionEnabled = flag;
+ [[NSUserDefaults standardUserDefaults] setBool:automaticLinkDetectionEnabled forKey:WebAutomaticLinkDetectionEnabled];
+ [[NSSpellChecker sharedSpellChecker] updatePanels];
+}
+
+- (void)toggleAutomaticLinkDetection:(id)sender
+{
+ [self setAutomaticLinkDetectionEnabled:![self isAutomaticLinkDetectionEnabled]];
+}
+
+- (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag
+{
+ if (automaticDashSubstitutionEnabled == flag)
+ return;
+ automaticDashSubstitutionEnabled = flag;
+ [[NSUserDefaults standardUserDefaults] setBool:automaticDashSubstitutionEnabled forKey:WebAutomaticDashSubstitutionEnabled];
+ [[NSSpellChecker sharedSpellChecker] updatePanels];
+}
+
+- (void)toggleAutomaticDashSubstitution:(id)sender
+{
+ [self setAutomaticDashSubstitutionEnabled:![self isAutomaticDashSubstitutionEnabled]];
+}
+
+- (void)setAutomaticTextReplacementEnabled:(BOOL)flag
+{
+ if (automaticTextReplacementEnabled == flag)
+ return;
+ automaticTextReplacementEnabled = flag;
+ [[NSUserDefaults standardUserDefaults] setBool:automaticTextReplacementEnabled forKey:WebAutomaticTextReplacementEnabled];
+ [[NSSpellChecker sharedSpellChecker] updatePanels];
+}
+
+- (void)toggleAutomaticTextReplacement:(id)sender
+{
+ [self setAutomaticTextReplacementEnabled:![self isAutomaticTextReplacementEnabled]];
+}
+
+- (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag
+{
+ if (automaticSpellingCorrectionEnabled == flag)
+ return;
+ automaticSpellingCorrectionEnabled = flag;
+ [[NSUserDefaults standardUserDefaults] setBool:automaticSpellingCorrectionEnabled forKey:WebAutomaticSpellingCorrectionEnabled];
+ [[NSSpellChecker sharedSpellChecker] updatePanels];
+}
+
+- (void)toggleAutomaticSpellingCorrection:(id)sender
+{
+ [self setAutomaticSpellingCorrectionEnabled:![self isAutomaticSpellingCorrectionEnabled]];
+}
+
+#endif
+
+@end
+
@implementation WebView (WebViewUndoableEditing)
- (void)replaceSelectionWithNode:(DOMNode *)node
@@ -4508,6 +4712,22 @@ FOR_EACH_RESPONDER_SELECTOR(FORWARD)
[[self _selectedOrMainFrame] _replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
}
+- (BOOL)_selectionIsCaret
+{
+ Frame* coreFrame = core([self _selectedOrMainFrame]);
+ if (!coreFrame)
+ return NO;
+ return coreFrame->selection()->isCaret();
+}
+
+- (BOOL)_selectionIsAll
+{
+ Frame* coreFrame = core([self _selectedOrMainFrame]);
+ if (!coreFrame)
+ return NO;
+ return coreFrame->selection()->isAll(MayLeaveEditableContent);
+}
+
@end
static WebFrameView *containingFrameView(NSView *view)
@@ -4524,7 +4744,7 @@ static WebFrameView *containingFrameView(NSView *view)
if (s_didSetCacheModel && cacheModel == s_cacheModel)
return;
- NSString *nsurlCacheDirectory = [(NSString *)WKCopyFoundationCacheDirectory() autorelease];
+ NSString *nsurlCacheDirectory = (NSString *)WebCFAutorelease(WKCopyFoundationCacheDirectory());
if (!nsurlCacheDirectory)
nsurlCacheDirectory = NSHomeDirectory();
@@ -4773,6 +4993,7 @@ static WebFrameView *containingFrameView(NSView *view)
{
if (_private->closed)
return nil;
+ ASSERT(_private->usesDocumentViews);
NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]];
if (![view isDescendantOf:[[self mainFrame] frameView]])
return nil;
@@ -4878,6 +5099,18 @@ static WebFrameView *containingFrameView(NSView *view)
(void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions);
}
+
+#if USE(ACCELERATED_COMPOSITING)
+- (void)_clearLayerSyncLoopObserver
+{
+ if (!_private->layerSyncRunLoopObserver)
+ return;
+
+ CFRunLoopObserverInvalidate(_private->layerSyncRunLoopObserver);
+ CFRelease(_private->layerSyncRunLoopObserver);
+ _private->layerSyncRunLoopObserver = 0;
+}
+#endif
@end
@implementation WebView (WebViewInternal)
@@ -4887,6 +5120,7 @@ static WebFrameView *containingFrameView(NSView *view)
return _private->becomingFirstResponderFromOutside;
}
+#if ENABLE(ICONDATABASE)
- (void)_receivedIconChangedNotification:(NSNotification *)notification
{
// Get the URL for this notification
@@ -4927,6 +5161,7 @@ static WebFrameView *containingFrameView(NSView *view)
[self _didChangeValueForKey:_WebMainFrameIconKey];
}
+#endif // ENABLE(ICONDATABASE)
// Get the appropriate user-agent string for a particular URL.
- (WebCore::String)_userAgentForURL:(const WebCore::KURL&)url
@@ -5009,536 +5244,230 @@ static WebFrameView *containingFrameView(NSView *view)
return _private->_keyboardUIMode;
}
-@end
-
-// We use these functions to call the delegates and block exceptions. These functions are
-// declared inside a WebView category to get direct access to the delegate data memebers,
-// preventing more ObjC message dispatch and compensating for the expense of the @try/@catch.
-
-@implementation WebView (WebCallDelegateFunctions)
-
-typedef float (*ObjCMsgSendFPRet)(id, SEL, ...);
-#if defined(__i386__)
-static const ObjCMsgSendFPRet objc_msgSend_float_return = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend_fpret);
-#else
-static const ObjCMsgSendFPRet objc_msgSend_float_return = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend);
-#endif
-
-static inline id CallDelegate(WebView *self, id delegate, SEL selector)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend(delegate, selector, self);
- @try {
- return objc_msgSend(delegate, selector, self);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
-
-static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend(delegate, selector, self, object);
- @try {
- return objc_msgSend(delegate, selector, self, object);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
-
-static inline id CallDelegate(WebView *self, id delegate, SEL selector, NSRect rect)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
- @try {
- return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
-
-static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend(delegate, selector, self, object1, object2);
- @try {
- return objc_msgSend(delegate, selector, self, object1, object2);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
-
-static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, BOOL boolean)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend(delegate, selector, self, object, boolean);
- @try {
- return objc_msgSend(delegate, selector, self, object, boolean);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
-
-static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend(delegate, selector, self, object1, object2, object3);
- @try {
- return objc_msgSend(delegate, selector, self, object1, object2, object3);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
-
-static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, NSUInteger integer)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend(delegate, selector, self, object, integer);
- @try {
- return objc_msgSend(delegate, selector, self, object, integer);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
-
-static inline float CallDelegateReturningFloat(WebView *self, id delegate, SEL selector)
+- (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard
{
- if (!delegate || ![delegate respondsToSelector:selector])
- return 0.0f;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend_float_return(delegate, selector, self);
- @try {
- return objc_msgSend_float_return(delegate, selector, self);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return 0.0f;
+ _private->insertionPasteboard = pasteboard;
}
-static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector)
+- (void)_setMouseDownEvent:(NSEvent *)event
{
- if (!delegate || ![delegate respondsToSelector:selector])
- return result;
- if (!self->_private->catchesDelegateExceptions)
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
- @try {
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return result;
-}
+ ASSERT(!event || [event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown);
-static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return result;
- if (!self->_private->catchesDelegateExceptions)
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
- @try {
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return result;
-}
+ if (event == _private->mouseDownEvent)
+ return;
-static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object, BOOL boolean)
-{
- if (!delegate || ![delegate respondsToSelector:selector])
- return result;
- if (!self->_private->catchesDelegateExceptions)
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
- @try {
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return result;
+ [event retain];
+ [_private->mouseDownEvent release];
+ _private->mouseDownEvent = event;
}
-static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object1, id object2)
+- (void)_cancelUpdateMouseoverTimer
{
- if (!delegate || ![delegate respondsToSelector:selector])
- return result;
- if (!self->_private->catchesDelegateExceptions)
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
- @try {
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
+ if (_private->updateMouseoverTimer) {
+ CFRunLoopTimerInvalidate(_private->updateMouseoverTimer);
+ CFRelease(_private->updateMouseoverTimer);
+ _private->updateMouseoverTimer = NULL;
}
- return result;
}
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector)
+- (void)_stopAutoscrollTimer
{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self);
- @try {
- return implementation(delegate, selector, self);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
+ NSTimer *timer = _private->autoscrollTimer;
+ _private->autoscrollTimer = nil;
+ [_private->autoscrollTriggerEvent release];
+ _private->autoscrollTriggerEvent = nil;
+ [timer invalidate];
+ [timer release];
}
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object)
++ (void)_updateMouseoverWithEvent:(NSEvent *)event
{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object);
- @try {
- return implementation(delegate, selector, self, object);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
+ WebView *oldView = lastMouseoverView;
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2)
-{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, object2);
- @try {
- return implementation(delegate, selector, self, object1, object2);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
+ lastMouseoverView = nil;
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
-{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, object2, object3);
- @try {
- return implementation(delegate, selector, self, object1, object2, object3);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
+ NSView *contentView = [[event window] contentView];
+ NSPoint locationForHitTest = [[contentView superview] convertPoint:[event locationInWindow] fromView:nil];
+ for (NSView *hitView = [contentView hitTest:locationForHitTest]; hitView; hitView = [hitView superview]) {
+ if ([hitView isKindOfClass:[WebView class]]) {
+ lastMouseoverView = static_cast<WebView *>(hitView);
+ break;
+ }
}
- return nil;
-}
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3, id object4)
-{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, object2, object3, object4);
- @try {
- return implementation(delegate, selector, self, object1, object2, object3, object4);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
+ if (lastMouseoverView && lastMouseoverView->_private->hoverFeedbackSuspended)
+ lastMouseoverView = nil;
+
+ if (lastMouseoverView != oldView) {
+ if (Frame* oldCoreFrame = [oldView _mainCoreFrame]) {
+ NSEvent *oldViewEvent = [NSEvent mouseEventWithType:NSMouseMoved
+ location:NSMakePoint(-1, -1)
+ modifierFlags:[[NSApp currentEvent] modifierFlags]
+ timestamp:[NSDate timeIntervalSinceReferenceDate]
+ windowNumber:[[oldView window] windowNumber]
+ context:[[NSApp currentEvent] context]
+ eventNumber:0 clickCount:0 pressure:0];
+ oldCoreFrame->eventHandler()->mouseMoved(oldViewEvent);
+ }
}
- return nil;
-}
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2)
-{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, integer, object2);
- @try {
- return implementation(delegate, selector, self, object1, integer, object2);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
+ if (!lastMouseoverView)
+ return;
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, NSInteger integer2, id object2)
-{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, integer1, integer2, object2);
- @try {
- return implementation(delegate, selector, self, object1, integer1, integer2, object2);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
+ if (Frame* coreFrame = core([lastMouseoverView mainFrame]))
+ coreFrame->eventHandler()->mouseMoved(event);
}
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, NSInteger integer, id object3)
+- (void)_updateMouseoverWithFakeEvent
{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, object2, integer, object3);
- @try {
- return implementation(delegate, selector, self, object1, object2, integer, object3);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
+ [self _cancelUpdateMouseoverTimer];
+
+ NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved
+ location:[[self window] convertScreenToBase:[NSEvent mouseLocation]]
+ modifierFlags:[[NSApp currentEvent] modifierFlags]
+ timestamp:[NSDate timeIntervalSinceReferenceDate]
+ windowNumber:[[self window] windowNumber]
+ context:[[NSApp currentEvent] context]
+ eventNumber:0 clickCount:0 pressure:0];
+
+ [[self class] _updateMouseoverWithEvent:fakeEvent];
}
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
+- (void)_setToolTip:(NSString *)toolTip
{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3);
- @try {
- return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
+ if (_private->usesDocumentViews) {
+ id documentView = [[[self _selectedOrMainFrame] frameView] documentView];
+ if ([documentView isKindOfClass:[WebHTMLView class]])
+ [documentView _setToolTip:toolTip];
+ return;
}
- return nil;
-}
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4)
-{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, integer, object2, object3, object4);
- @try {
- return implementation(delegate, selector, self, object1, integer, object2, object3, object4);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
+ // FIXME (Viewless): Code to handle tooltips needs to move into WebView.
}
-static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
+- (void)_selectionChanged
{
- if (!delegate)
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return implementation(delegate, selector, self, object1, interval, object2, object3);
- @try {
- return implementation(delegate, selector, self, object1, interval, object2, object3);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
+ if (_private->usesDocumentViews) {
+ id documentView = [[[self _selectedOrMainFrame] frameView] documentView];
+ if ([documentView isKindOfClass:[WebHTMLView class]])
+ [documentView _selectionChanged];
+ return;
}
- return nil;
-}
-id CallUIDelegate(WebView *self, SEL selector)
-{
- return CallDelegate(self, self->_private->UIDelegate, selector);
-}
-
-id CallUIDelegate(WebView *self, SEL selector, id object)
-{
- return CallDelegate(self, self->_private->UIDelegate, selector, object);
+ // FIXME (Viewless): We'll need code here.
}
-id CallUIDelegate(WebView *self, SEL selector, id object, BOOL boolean)
+- (Frame*)_mainCoreFrame
{
- return CallDelegate(self, self->_private->UIDelegate, selector, object, boolean);
+ return (_private && _private->page) ? _private->page->mainFrame() : 0;
}
-id CallUIDelegate(WebView *self, SEL selector, NSRect rect)
-{
- return CallDelegate(self, self->_private->UIDelegate, selector, rect);
-}
-
-id CallUIDelegate(WebView *self, SEL selector, id object1, id object2)
-{
- return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2);
-}
-
-id CallUIDelegate(WebView *self, SEL selector, id object1, id object2, id object3)
-{
- return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2, object3);
-}
-
-id CallUIDelegate(WebView *self, SEL selector, id object, NSUInteger integer)
-{
- return CallDelegate(self, self->_private->UIDelegate, selector, object, integer);
-}
-
-float CallUIDelegateReturningFloat(WebView *self, SEL selector)
-{
- return CallDelegateReturningFloat(self, self->_private->UIDelegate, selector);
-}
-
-BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector)
-{
- return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector);
-}
-
-BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object)
-{
- return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object);
-}
-
-BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean)
-{
- return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean);
-}
-
-BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, id object2)
-{
- return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object1, object2);
-}
-
-id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector)
-{
- return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector);
-}
-
-id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object)
-{
- return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object);
-}
-
-id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
-{
- return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2);
-}
-
-id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
-{
- return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3);
-}
-
-id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
-{
- return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3, object4);
-}
-
-id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
-{
- return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, interval, object2, object3);
-}
+#if USE(ACCELERATED_COMPOSITING)
-id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
+- (BOOL)_needsOneShotDrawingSynchronization
{
- return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2);
+ return _private->needsOneShotDrawingSynchronization;
}
-id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
+- (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization
{
- return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3);
+ _private->needsOneShotDrawingSynchronization = needsSynchronization;
}
-id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
+- (void)_startedAcceleratedCompositingForFrame:(WebFrame*)webFrame
{
- return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3, object4);
+ BOOL entering = _private->acceleratedFramesCount == 0;
+ if (entering)
+ [self willChangeValueForKey:UsingAcceleratedCompositingProperty];
+ ++_private->acceleratedFramesCount;
+ if (entering)
+ [self didChangeValueForKey:UsingAcceleratedCompositingProperty];
}
-id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2)
+- (void)_stoppedAcceleratedCompositingForFrame:(WebFrame*)webFrame
{
- return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, integer, object2);
+ BOOL leaving = _private->acceleratedFramesCount == 1;
+ ASSERT(_private->acceleratedFramesCount > 0);
+
+ if (leaving)
+ [self willChangeValueForKey:UsingAcceleratedCompositingProperty];
+ --_private->acceleratedFramesCount;
+ if (leaving)
+ [self didChangeValueForKey:UsingAcceleratedCompositingProperty];
}
-id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
+- (BOOL)_syncCompositingChanges
{
- return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, integer, object3);
-}
+ Frame* frame = [self _mainCoreFrame];
+ if (frame && frame->view())
+ return frame->view()->syncCompositingStateRecursive();
-BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, WebView *self, SEL selector, id object1, id object2)
-{
- if (!self->_private->catchesDelegateExceptions)
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2);
- @try {
- return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return result;
+ return YES;
}
-id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
-{
- return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, object2, integer, object3);
-}
+/*
+ The order of events with compositing updates is this:
+
+ Start of runloop End of runloop
+ | |
+ --|-------------------------------------------------------|--
+ ^ ^ ^
+ | | |
+ NSWindow update, | CA commit
+ NSView drawing |
+ flush |
+ layerSyncRunLoopObserverCallBack
+
+ To avoid flashing, we have to ensure that compositing changes (rendered via
+ the CoreAnimation rendering display link) appear on screen at the same time
+ as content painted into the window via the normal WebCore rendering path.
+
+ CoreAnimation will commit any layer changes at the end of the runloop via
+ its "CA commit" observer. Those changes can then appear onscreen at any time
+ when the display link fires, which can result in unsynchronized rendering.
+
+ To fix this, the GraphicsLayerCA code in WebCore does not change the CA
+ layer tree during style changes and layout; it stores up all changes and
+ commits them via syncCompositingState(). There are then two situations in
+ which we can call syncCompositingState():
+
+ 1. When painting. FrameView::paintContents() makes a call to syncCompositingState().
+
+ 2. When style changes/layout have made changes to the layer tree which do not
+ result in painting. In this case we need a run loop observer to do a
+ syncCompositingState() at an appropriate time. The observer will keep firing
+ until the time is right (essentially when there are no more pending layouts).
+
+*/
-id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
+static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActivity, void* info)
{
- return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, object2, integer2, object3);
+ WebView* webView = reinterpret_cast<WebView*>(info);
+ if ([webView _syncCompositingChanges])
+ [webView _clearLayerSyncLoopObserver];
}
-id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4)
+- (void)_scheduleCompositingLayerSync
{
- return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer, object2, object3, object4);
-}
+ if (_private->layerSyncRunLoopObserver)
+ return;
-id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, NSInteger integer2, id object2)
-{
- return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, integer2, object2);
-}
+ // Run after AppKit does its window update. If we do any painting, we'll commit
+ // layer changes from FrameView::paintContents(), otherwise we'll commit via
+ // _syncCompositingChanges when this observer fires.
+ const CFIndex runLoopOrder = NSDisplayWindowRunLoopOrdering + 1;
-// The form delegate needs to have it's own implementation, because the first argument is never the WebView
+ // The WebView always outlives the observer, so no need to retain/release.
+ CFRunLoopObserverContext context = { 0, self, 0, 0, 0 };
-id CallFormDelegate(WebView *self, SEL selector, id object1, id object2)
-{
- id delegate = self->_private->formDelegate;
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend(delegate, selector, object1, object2);
- @try {
- return objc_msgSend(delegate, selector, object1, object2);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
-}
+ _private->layerSyncRunLoopObserver = CFRunLoopObserverCreate(NULL,
+ kCFRunLoopBeforeWaiting | kCFRunLoopExit, true /* repeats */,
+ runLoopOrder, layerSyncRunLoopObserverCallBack, &context);
-id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5)
-{
- id delegate = self->_private->formDelegate;
- if (!delegate || ![delegate respondsToSelector:selector])
- return nil;
- if (!self->_private->catchesDelegateExceptions)
- return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
- @try {
- return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return nil;
+ CFRunLoopAddObserver(CFRunLoopGetCurrent(), _private->layerSyncRunLoopObserver, kCFRunLoopCommonModes);
}
-BOOL CallFormDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, SEL selectorArg, id object2)
-{
- id delegate = self->_private->formDelegate;
- if (!delegate || ![delegate respondsToSelector:selector])
- return result;
- if (!self->_private->catchesDelegateExceptions)
- return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
- @try {
- return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
- } @catch(id exception) {
- ReportDiscardedDelegateException(selector, exception);
- }
- return result;
-}
+#endif
@end