summaryrefslogtreecommitdiffstats
path: root/WebKit/mac/WebView
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-11 17:01:47 +0100
committerBen Murdoch <benm@google.com>2009-08-11 18:21:02 +0100
commit0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch)
tree2943df35f62d885c89d01063cc528dd73b480fea /WebKit/mac/WebView
parent7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff)
downloadexternal_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2
Merge in WebKit r47029.
Diffstat (limited to 'WebKit/mac/WebView')
-rw-r--r--WebKit/mac/WebView/WebDataSource.mm18
-rw-r--r--WebKit/mac/WebView/WebDelegateImplementationCaching.h121
-rw-r--r--WebKit/mac/WebView/WebDelegateImplementationCaching.mm590
-rw-r--r--WebKit/mac/WebView/WebDynamicScrollBarsView.h1
-rw-r--r--WebKit/mac/WebView/WebDynamicScrollBarsView.mm (renamed from WebKit/mac/WebView/WebDynamicScrollBarsView.m)165
-rw-r--r--WebKit/mac/WebView/WebFrame.mm281
-rw-r--r--WebKit/mac/WebView/WebFrameInternal.h21
-rw-r--r--WebKit/mac/WebView/WebFramePrivate.h12
-rw-r--r--WebKit/mac/WebView/WebFrameView.mm77
-rw-r--r--WebKit/mac/WebView/WebHTMLRepresentation.mm13
-rw-r--r--WebKit/mac/WebView/WebHTMLView.mm1133
-rw-r--r--WebKit/mac/WebView/WebHTMLViewInternal.h6
-rw-r--r--WebKit/mac/WebView/WebHTMLViewPrivate.h1
-rw-r--r--WebKit/mac/WebView/WebPDFView.h2
-rw-r--r--WebKit/mac/WebView/WebPDFView.mm30
-rw-r--r--WebKit/mac/WebView/WebPreferenceKeysPrivate.h9
-rw-r--r--WebKit/mac/WebView/WebPreferences.mm72
-rw-r--r--WebKit/mac/WebView/WebPreferencesPrivate.h15
-rw-r--r--WebKit/mac/WebView/WebRenderNode.h4
-rw-r--r--WebKit/mac/WebView/WebRenderNode.mm54
-rw-r--r--WebKit/mac/WebView/WebResource.mm6
-rw-r--r--WebKit/mac/WebView/WebScriptDebugDelegate.mm18
-rw-r--r--WebKit/mac/WebView/WebScriptDebugger.mm7
-rw-r--r--WebKit/mac/WebView/WebTextCompletionController.h45
-rw-r--r--WebKit/mac/WebView/WebTextCompletionController.mm325
-rw-r--r--WebKit/mac/WebView/WebTextIterator.mm8
-rw-r--r--WebKit/mac/WebView/WebUIDelegatePrivate.h26
-rw-r--r--WebKit/mac/WebView/WebView.mm1913
-rw-r--r--WebKit/mac/WebView/WebViewData.h161
-rw-r--r--WebKit/mac/WebView/WebViewData.mm106
-rw-r--r--WebKit/mac/WebView/WebViewInternal.h160
-rw-r--r--WebKit/mac/WebView/WebViewPrivate.h74
32 files changed, 3464 insertions, 2010 deletions
diff --git a/WebKit/mac/WebView/WebDataSource.mm b/WebKit/mac/WebView/WebDataSource.mm
index 57347d3..b83139d 100644
--- a/WebKit/mac/WebView/WebDataSource.mm
+++ b/WebKit/mac/WebView/WebDataSource.mm
@@ -189,7 +189,7 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
- (NSString *)_responseMIMEType
{
- return [[self response] _webcore_MIMEType];
+ return [[self response] MIMEType];
}
- (BOOL)_transferApplicationCache:(NSString*)destinationBundleIdentifier
@@ -198,14 +198,10 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
if (!loader)
return NO;
-
- ApplicationCache* cache = loader->applicationCache();
- if (!cache)
- return YES;
-
+
NSString *cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:destinationBundleIdentifier];
- return ApplicationCacheStorage::storeCopyOfCache(cacheDir, cache);
+ return ApplicationCacheStorage::storeCopyOfCache(cacheDir, loader->applicationCacheHost());
}
@end
@@ -224,7 +220,9 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
RetainPtr<WebDataSource*> protect(self);
[[self representation] receivedData:data withDataSource:self];
- [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
+
+ if ([[self _webView] _usesDocumentViews])
+ [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
}
- (void)_setMainDocumentError:(NSError *)error
@@ -340,7 +338,7 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
return [WebView canShowMIMETypeAsHTML:MIMEType];
}
--(void)_makeRepresentation
+- (void)_makeRepresentation
{
Class repClass = [[self class] _representationClassForMIMEType:[self _responseMIMEType]];
@@ -350,7 +348,7 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
[self _setRepresentation:(id <WebDocumentRepresentation>)newRep];
[newRep release];
}
-
+
[_private->representation setDataSource:self];
}
diff --git a/WebKit/mac/WebView/WebDelegateImplementationCaching.h b/WebKit/mac/WebView/WebDelegateImplementationCaching.h
new file mode 100644
index 0000000..41e44e0
--- /dev/null
+++ b/WebKit/mac/WebView/WebDelegateImplementationCaching.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This header contains WebView declarations that can be used anywhere in WebKit, but are neither SPI nor API.
+
+#import "WebTypesInternal.h"
+
+@class WebView;
+
+struct WebResourceDelegateImplementationCache {
+ IMP didCancelAuthenticationChallengeFunc;
+ IMP didReceiveAuthenticationChallengeFunc;
+ IMP identifierForRequestFunc;
+ IMP willSendRequestFunc;
+ IMP didReceiveResponseFunc;
+ IMP didReceiveContentLengthFunc;
+ IMP didFinishLoadingFromDataSourceFunc;
+ IMP didFailLoadingWithErrorFromDataSourceFunc;
+ IMP didLoadResourceFromMemoryCacheFunc;
+ IMP willCacheResponseFunc;
+ IMP plugInFailedWithErrorFunc;
+ IMP shouldUseCredentialStorageFunc;
+};
+
+struct WebFrameLoadDelegateImplementationCache {
+ IMP didClearWindowObjectForFrameFunc;
+ IMP didClearInspectorWindowObjectForFrameFunc;
+ IMP windowScriptObjectAvailableFunc;
+ IMP didHandleOnloadEventsForFrameFunc;
+ IMP didReceiveServerRedirectForProvisionalLoadForFrameFunc;
+ IMP didCancelClientRedirectForFrameFunc;
+ IMP willPerformClientRedirectToURLDelayFireDateForFrameFunc;
+ IMP didChangeLocationWithinPageForFrameFunc;
+ IMP willCloseFrameFunc;
+ IMP didStartProvisionalLoadForFrameFunc;
+ IMP didReceiveTitleForFrameFunc;
+ IMP didCommitLoadForFrameFunc;
+ IMP didFailProvisionalLoadWithErrorForFrameFunc;
+ IMP didFailLoadWithErrorForFrameFunc;
+ IMP didFinishLoadForFrameFunc;
+ IMP didFirstLayoutInFrameFunc;
+ IMP didFirstVisuallyNonEmptyLayoutInFrameFunc;
+ IMP didReceiveIconForFrameFunc;
+ IMP didFinishDocumentLoadForFrameFunc;
+};
+
+struct WebScriptDebugDelegateImplementationCache {
+ BOOL didParseSourceExpectsBaseLineNumber;
+ IMP didParseSourceFunc;
+ IMP failedToParseSourceFunc;
+ IMP didEnterCallFrameFunc;
+ IMP willExecuteStatementFunc;
+ IMP willLeaveCallFrameFunc;
+ IMP exceptionWasRaisedFunc;
+};
+
+WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *);
+WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *);
+WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *);
+
+id CallFormDelegate(WebView *, SEL, id, id);
+id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5);
+BOOL CallFormDelegateReturningBoolean(BOOL, WebView *, SEL, id, SEL, id);
+
+id CallUIDelegate(WebView *, SEL);
+id CallUIDelegate(WebView *, SEL, id);
+id CallUIDelegate(WebView *, SEL, NSRect);
+id CallUIDelegate(WebView *, SEL, id, id);
+id CallUIDelegate(WebView *, SEL, id, BOOL);
+id CallUIDelegate(WebView *, SEL, id, id, id);
+id CallUIDelegate(WebView *, SEL, id, NSUInteger);
+float CallUIDelegateReturningFloat(WebView *, SEL);
+BOOL CallUIDelegateReturningBoolean(BOOL, WebView *, SEL);
+BOOL CallUIDelegateReturningBoolean(BOOL, WebView *, SEL, id);
+BOOL CallUIDelegateReturningBoolean(BOOL, WebView *, SEL, id, id);
+BOOL CallUIDelegateReturningBoolean(BOOL, WebView *, SEL, id, BOOL);
+
+id CallFrameLoadDelegate(IMP, WebView *, SEL);
+id CallFrameLoadDelegate(IMP, WebView *, SEL, id);
+id CallFrameLoadDelegate(IMP, WebView *, SEL, id, id);
+id CallFrameLoadDelegate(IMP, WebView *, SEL, id, id, id);
+id CallFrameLoadDelegate(IMP, WebView *, SEL, id, id, id, id);
+id CallFrameLoadDelegate(IMP, WebView *, SEL, id, NSTimeInterval, id, id);
+
+id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id);
+id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id, id);
+id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id, id, id);
+id CallResourceLoadDelegate(IMP, WebView *, SEL, id, NSInteger, id);
+id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id, NSInteger, id);
+
+BOOL CallResourceLoadDelegateReturningBoolean(BOOL, IMP, WebView *, SEL, id, id);
+
+id CallScriptDebugDelegate(IMP, WebView *, SEL, id, id, NSInteger, id);
+id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, NSInteger, id);
+id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, id, id);
+id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, NSInteger, id);
diff --git a/WebKit/mac/WebView/WebDelegateImplementationCaching.mm b/WebKit/mac/WebView/WebDelegateImplementationCaching.mm
new file mode 100644
index 0000000..441df92
--- /dev/null
+++ b/WebKit/mac/WebView/WebDelegateImplementationCaching.mm
@@ -0,0 +1,590 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebDelegateImplementationCaching.h"
+
+#import "WebKitLogging.h"
+#import "WebView.h"
+#import "WebViewData.h"
+#import <objc/objc-runtime.h>
+
+@implementation WebView (WebDelegateImplementationCaching)
+
+WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView)
+{
+ static WebResourceDelegateImplementationCache empty;
+ if (!webView)
+ return &empty;
+ return &webView->_private->resourceLoadDelegateImplementations;
+}
+
+WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView)
+{
+ static WebFrameLoadDelegateImplementationCache empty;
+ if (!webView)
+ return &empty;
+ return &webView->_private->frameLoadDelegateImplementations;
+}
+
+WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView)
+{
+ static WebScriptDebugDelegateImplementationCache empty;
+ if (!webView)
+ return &empty;
+ return &webView->_private->scriptDebugDelegateImplementations;
+}
+
+// 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.
+
+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)
+{
+ 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;
+}
+
+static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector)
+{
+ 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;
+}
+
+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;
+}
+
+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;
+}
+
+static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object1, id object2)
+{
+ 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);
+ }
+ return result;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector)
+{
+ 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;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object)
+{
+ 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;
+}
+
+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;
+}
+
+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);
+ }
+ 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);
+ }
+ 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;
+}
+
+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;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, NSInteger integer, id object3)
+{
+ 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;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
+{
+ 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);
+ }
+ 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;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
+{
+ 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);
+ }
+ 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);
+}
+
+id CallUIDelegate(WebView *self, SEL selector, id object, BOOL boolean)
+{
+ return CallDelegate(self, self->_private->UIDelegate, selector, object, boolean);
+}
+
+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);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
+{
+ return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
+{
+ return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
+{
+ return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3, object4);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2)
+{
+ return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, integer, object2);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
+{
+ return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, integer, object3);
+}
+
+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;
+}
+
+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);
+}
+
+id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
+{
+ return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, object2, integer2, object3);
+}
+
+id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4)
+{
+ return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer, object2, object3, object4);
+}
+
+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);
+}
+
+// The form delegate needs to have it's own implementation, because the first argument is never the WebView
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+@end
diff --git a/WebKit/mac/WebView/WebDynamicScrollBarsView.h b/WebKit/mac/WebView/WebDynamicScrollBarsView.h
index a0f8006..ce92b33 100644
--- a/WebKit/mac/WebView/WebDynamicScrollBarsView.h
+++ b/WebKit/mac/WebView/WebDynamicScrollBarsView.h
@@ -43,6 +43,7 @@ extern const int WebCoreScrollbarAlwaysOn;
BOOL suppressLayout;
BOOL suppressScrollers;
BOOL inUpdateScrollers;
+ unsigned inUpdateScrollersLayoutPass;
}
- (void)setAllowsHorizontalScrolling:(BOOL)flag; // This method is used by Safari, so it cannot be removed.
@end
diff --git a/WebKit/mac/WebView/WebDynamicScrollBarsView.m b/WebKit/mac/WebView/WebDynamicScrollBarsView.mm
index de19ef6..0cf2a98 100644
--- a/WebKit/mac/WebView/WebDynamicScrollBarsView.m
+++ b/WebKit/mac/WebView/WebDynamicScrollBarsView.mm
@@ -29,7 +29,11 @@
#import "WebDynamicScrollBarsViewInternal.h"
#import "WebDocument.h"
+#import "WebFrameInternal.h"
#import "WebFrameView.h"
+#import "WebHTMLViewInternal.h"
+#import <WebCore/Frame.h>
+#import <WebCore/FrameView.h>
#import <WebKitSystemInterface.h>
using namespace WebCore;
@@ -81,80 +85,108 @@ const int WebCoreScrollbarAlwaysOn = ScrollbarAlwaysOn;
#endif
}
+static const unsigned cMaxUpdateScrollbarsPass = 2;
+
- (void)updateScrollers
{
- // We need to do the work below twice in the case where a scroll bar disappears,
- // making the second layout have a wider width than the first. Doing it more than
- // twice would indicate some kind of infinite loop, so we do it at most twice.
- // It's quite efficient to do this work twice in the normal case, so we don't bother
- // trying to figure out of the second pass is needed or not.
- if (inUpdateScrollers)
- return;
-
- inUpdateScrollers = true;
-
- int pass;
BOOL hasVerticalScroller = [self hasVerticalScroller];
BOOL hasHorizontalScroller = [self hasHorizontalScroller];
- BOOL oldHasVertical = hasVerticalScroller;
- BOOL oldHasHorizontal = hasHorizontalScroller;
-
- for (pass = 0; pass < 2; pass++) {
- BOOL scrollsVertically;
- BOOL scrollsHorizontally;
-
- if (!suppressLayout && !suppressScrollers && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
- // Do a layout if pending, before checking if scrollbars are needed.
- // This fixes 2969367, although may introduce a slowdown in live resize performance.
- NSView *documentView = [self documentView];
- if (!documentView) {
- scrollsHorizontally = NO;
- scrollsVertically = NO;
- } else {
- if ((hasVerticalScroller != oldHasVertical ||
- hasHorizontalScroller != oldHasHorizontal || [documentView inLiveResize]) && [documentView conformsToProtocol:@protocol(WebDocumentView)]) {
- [(id <WebDocumentView>)documentView setNeedsLayout: YES];
- [(id <WebDocumentView>)documentView layout];
- }
-
- NSSize documentSize = [documentView frame].size;
- NSSize frameSize = [self frame].size;
-
- scrollsVertically = (vScroll == ScrollbarAlwaysOn) ||
- (vScroll == ScrollbarAuto && documentSize.height > frameSize.height);
- if (scrollsVertically)
- scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) ||
- (hScroll == ScrollbarAuto && documentSize.width + [NSScroller scrollerWidth] > frameSize.width);
- else {
- scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) ||
- (hScroll == ScrollbarAuto && documentSize.width > frameSize.width);
- if (scrollsHorizontally)
- scrollsVertically = (vScroll == ScrollbarAlwaysOn) ||
- (vScroll == ScrollbarAuto && documentSize.height + [NSScroller scrollerWidth] > frameSize.height);
- }
- }
- } else {
- scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScroller : (hScroll == ScrollbarAlwaysOn);
- scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScroller : (vScroll == ScrollbarAlwaysOn);
+
+ BOOL newHasHorizontalScroller = hasHorizontalScroller;
+ BOOL newHasVerticalScroller = hasVerticalScroller;
+
+ BOOL needsLayout = NO;
+
+ NSView *documentView = [self documentView];
+ if (!documentView) {
+ newHasHorizontalScroller = NO;
+ newHasVerticalScroller = NO;
+ }
+
+ if (hScroll != ScrollbarAuto)
+ newHasHorizontalScroller = (hScroll == ScrollbarAlwaysOn);
+ if (vScroll != ScrollbarAuto)
+ newHasVerticalScroller = (vScroll == ScrollbarAlwaysOn);
+
+ if (!documentView || suppressLayout || suppressScrollers || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
+ inUpdateScrollers = YES;
+ if (hasHorizontalScroller != newHasHorizontalScroller)
+ [self setHasHorizontalScroller:newHasHorizontalScroller];
+ if (hasVerticalScroller != newHasVerticalScroller)
+ [self setHasVerticalScroller:newHasVerticalScroller];
+ if (suppressScrollers) {
+ [[self verticalScroller] setNeedsDisplay:NO];
+ [[self horizontalScroller] setNeedsDisplay:NO];
}
+ inUpdateScrollers = NO;
+ return;
+ }
- if (hasVerticalScroller != scrollsVertically) {
- [self setHasVerticalScroller:scrollsVertically];
- hasVerticalScroller = scrollsVertically;
+ needsLayout = NO;
+
+ // If we came in here with the view already needing a layout, then go ahead and do that
+ // first. (This will be the common case, e.g., when the page changes due to window resizing for example).
+ // This layout will not re-enter updateScrollers and does not count towards our max layout pass total.
+ if ([documentView isKindOfClass:[WebHTMLView class]]) {
+ WebHTMLView* htmlView = (WebHTMLView*)documentView;
+ if ([htmlView _needsLayout]) {
+ inUpdateScrollers = YES;
+ [(id <WebDocumentView>)documentView layout];
+ inUpdateScrollers = NO;
}
+ }
- if (hasHorizontalScroller != scrollsHorizontally) {
- [self setHasHorizontalScroller:scrollsHorizontally];
- hasHorizontalScroller = scrollsHorizontally;
- }
+ NSSize documentSize = [documentView frame].size;
+ NSSize visibleSize = [self documentVisibleRect].size;
+ NSSize frameSize = [self frame].size;
+
+ if (hScroll == ScrollbarAuto) {
+ newHasHorizontalScroller = documentSize.width > visibleSize.width;
+ if (newHasHorizontalScroller && !inUpdateScrollersLayoutPass && documentSize.height <= frameSize.height && documentSize.width <= frameSize.width)
+ newHasHorizontalScroller = NO;
+ }
+
+ if (vScroll == ScrollbarAuto) {
+ newHasVerticalScroller = documentSize.height > visibleSize.height;
+ if (newHasVerticalScroller && !inUpdateScrollersLayoutPass && documentSize.height <= frameSize.height && documentSize.width <= frameSize.width)
+ newHasVerticalScroller = NO;
}
- if (suppressScrollers) {
- [[self verticalScroller] setNeedsDisplay: NO];
- [[self horizontalScroller] setNeedsDisplay: NO];
+ // Unless in ScrollbarsAlwaysOn mode, if we ever turn one scrollbar off, always turn the other one off too.
+ // Never ever try to both gain/lose a scrollbar in the same pass.
+ if (!newHasHorizontalScroller && hasHorizontalScroller && vScroll != ScrollbarAlwaysOn)
+ newHasVerticalScroller = NO;
+ if (!newHasVerticalScroller && hasVerticalScroller && hScroll != ScrollbarAlwaysOn)
+ newHasHorizontalScroller = NO;
+
+ if (hasHorizontalScroller != newHasHorizontalScroller) {
+ inUpdateScrollers = YES;
+ [self setHasHorizontalScroller:newHasHorizontalScroller];
+ inUpdateScrollers = NO;
+ needsLayout = YES;
}
- inUpdateScrollers = false;
+ if (hasVerticalScroller != newHasVerticalScroller) {
+ inUpdateScrollers = YES;
+ [self setHasVerticalScroller:newHasVerticalScroller];
+ inUpdateScrollers = NO;
+ needsLayout = YES;
+ }
+
+ if (needsLayout && inUpdateScrollersLayoutPass < cMaxUpdateScrollbarsPass &&
+ [documentView conformsToProtocol:@protocol(WebDocumentView)]) {
+ inUpdateScrollersLayoutPass++;
+ [(id <WebDocumentView>)documentView setNeedsLayout:YES];
+ [(id <WebDocumentView>)documentView layout];
+ NSSize newDocumentSize = [documentView frame].size;
+ if (NSEqualSizes(documentSize, newDocumentSize)) {
+ // The layout with the new scroll state had no impact on
+ // the document's overall size, so updateScrollers didn't get called.
+ // Recur manually.
+ [self updateScrollers];
+ }
+ inUpdateScrollersLayoutPass--;
+ }
}
// Make the horizontal and vertical scroll bars come and go as needed.
@@ -186,6 +218,15 @@ const int WebCoreScrollbarAlwaysOn = ScrollbarAlwaysOn;
[[self horizontalScroller] setNeedsDisplay: NO];
}
#endif
+
+#if USE(ACCELERATED_COMPOSITING) && defined(BUILDING_ON_LEOPARD)
+ NSView *documentView = [self documentView];
+ if ([documentView isKindOfClass:[WebHTMLView class]]) {
+ WebHTMLView *htmlView = (WebHTMLView *)documentView;
+ if ([htmlView _isUsingAcceleratedCompositing])
+ [htmlView _updateLayerHostingViewPosition];
+ }
+#endif
}
- (BOOL)allowsHorizontalScrolling
diff --git a/WebKit/mac/WebView/WebFrame.mm b/WebKit/mac/WebView/WebFrame.mm
index 2aa5fab..c03ef58 100644
--- a/WebKit/mac/WebView/WebFrame.mm
+++ b/WebKit/mac/WebView/WebFrame.mm
@@ -46,18 +46,21 @@
#import "WebIconFetcherInternal.h"
#import "WebKitStatisticsPrivate.h"
#import "WebKitVersionChecks.h"
+#import "WebNSObjectExtras.h"
#import "WebNSURLExtras.h"
#import "WebScriptDebugger.h"
#import "WebViewInternal.h"
#import <JavaScriptCore/APICast.h>
+#import <WebCore/AXObjectCache.h>
#import <WebCore/AccessibilityObject.h>
#import <WebCore/AnimationController.h>
-#import <WebCore/AXObjectCache.h>
+#import <WebCore/CSSMutableStyleDeclaration.h>
#import <WebCore/ColorMac.h>
#import <WebCore/DOMImplementation.h>
#import <WebCore/DocLoader.h>
#import <WebCore/DocumentFragment.h>
#import <WebCore/EventHandler.h>
+#import <WebCore/EventNames.h>
#import <WebCore/Frame.h>
#import <WebCore/FrameLoader.h>
#import <WebCore/FrameTree.h>
@@ -68,21 +71,22 @@
#import <WebCore/LegacyWebArchive.h>
#import <WebCore/Page.h>
#import <WebCore/PluginData.h>
+#import <WebCore/RenderLayer.h>
#import <WebCore/RenderPart.h>
#import <WebCore/RenderView.h>
-#import <WebCore/RenderLayer.h>
#import <WebCore/ReplaceSelectionCommand.h>
+#import <WebCore/RuntimeApplicationChecks.h>
+#import <WebCore/ScriptValue.h>
#import <WebCore/SmartReplace.h>
#import <WebCore/TextIterator.h>
+#import <WebCore/ThreadCheck.h>
#import <WebCore/TypingCommand.h>
#import <WebCore/htmlediting.h>
-#import <WebCore/ScriptController.h>
-#import <WebCore/ScriptValue.h>
#import <WebCore/markup.h>
#import <WebCore/visible_units.h>
#import <runtime/JSLock.h>
#import <runtime/JSValue.h>
-#include <wtf/CurrentTime.h>
+#import <wtf/CurrentTime.h>
using namespace std;
using namespace WebCore;
@@ -90,7 +94,8 @@ using namespace HTMLNames;
using JSC::JSGlobalObject;
using JSC::JSLock;
-using JSC::JSValuePtr;
+using JSC::JSValue;
+using JSC::SilenceAssertionsOnly;
/*
Here is the current behavior matrix for four types of navigations:
@@ -128,6 +133,14 @@ NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
+NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey";
+NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey";
+NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey";
+NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey";
+NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey";
+NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey";
+NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey";
+
// FIXME: Remove when this key becomes publicly defined
NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface";
@@ -158,76 +171,6 @@ NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterf
@end
-CSSStyleDeclaration* core(DOMCSSStyleDeclaration *declaration)
-{
- return [declaration _CSSStyleDeclaration];
-}
-
-DOMCSSStyleDeclaration *kit(WebCore::CSSStyleDeclaration* declaration)
-{
- return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:declaration];
-}
-
-Element* core(DOMElement *element)
-{
- return [element _element];
-}
-
-DOMElement *kit(Element* element)
-{
- return [DOMElement _wrapElement:element];
-}
-
-Node* core(DOMNode *node)
-{
- return [node _node];
-}
-
-DOMNode *kit(Node* node)
-{
- return [DOMNode _wrapNode:node];
-}
-
-Document* core(DOMDocument *document)
-{
- return [document _document];
-}
-
-DOMDocument *kit(Document* document)
-{
- return [DOMDocument _wrapDocument:document];
-}
-
-DocumentFragment* core(DOMDocumentFragment *fragment)
-{
- return [fragment _documentFragment];
-}
-
-DOMDocumentFragment *kit(DocumentFragment* fragment)
-{
- return [DOMDocumentFragment _wrapDocumentFragment:fragment];
-}
-
-HTMLElement* core(DOMHTMLElement *element)
-{
- return [element _HTMLElement];
-}
-
-DOMHTMLElement *kit(HTMLElement *element)
-{
- return [DOMHTMLElement _wrapHTMLElement:element];
-}
-
-Range* core(DOMRange *range)
-{
- return [range _range];
-}
-
-DOMRange *kit(Range* range)
-{
- return [DOMRange _wrapRange:range];
-}
-
EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
{
switch (editableLinkBehavior) {
@@ -385,22 +328,24 @@ WebView *getWebView(WebFrame *webFrame)
Frame* coreFrame = _private->coreFrame;
for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
- WebFrame *webFrame = kit(frame);
- // Don't call setDrawsBackground:YES here because it may be NO because of a load
- // in progress; WebFrameLoaderClient keeps it set to NO during the load process.
- if (!drawsBackground)
- [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
- [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
- id documentView = [[webFrame frameView] documentView];
- if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
- [documentView setDrawsBackground:drawsBackground];
- if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
- [documentView setBackgroundColor:backgroundColor];
- if (frame && frame->view()) {
- frame->view()->setTransparent(!drawsBackground);
- Color color = colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
- frame->view()->setBaseBackgroundColor(color);
- frame->view()->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
+ if ([webView _usesDocumentViews]) {
+ // Don't call setDrawsBackground:YES here because it may be NO because of a load
+ // in progress; WebFrameLoaderClient keeps it set to NO during the load process.
+ WebFrame *webFrame = kit(frame);
+ if (!drawsBackground)
+ [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
+ [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
+ id documentView = [[webFrame frameView] documentView];
+ if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
+ [documentView setDrawsBackground:drawsBackground];
+ if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
+ [documentView setBackgroundColor:backgroundColor];
+ }
+
+ if (FrameView* view = frame->view()) {
+ view->setTransparent(!drawsBackground);
+ view->setBaseBackgroundColor(colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]));
+ view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
}
}
}
@@ -437,21 +382,27 @@ WebView *getWebView(WebFrame *webFrame)
- (BOOL)_hasSelection
{
- id documentView = [_private->webFrameView documentView];
+ if ([getWebView(self) _usesDocumentViews]) {
+ id documentView = [_private->webFrameView documentView];
- // optimization for common case to avoid creating potentially large selection string
- if ([documentView isKindOfClass:[WebHTMLView class]])
- if (Frame* coreFrame = _private->coreFrame)
- return coreFrame->selection()->isRange();
+ // optimization for common case to avoid creating potentially large selection string
+ if ([documentView isKindOfClass:[WebHTMLView class]])
+ if (Frame* coreFrame = _private->coreFrame)
+ return coreFrame->selection()->isRange();
- if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
- return [[documentView selectedString] length] > 0;
-
- return NO;
+ if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
+ return [[documentView selectedString] length] > 0;
+
+ return NO;
+ }
+
+ Frame* coreFrame = _private->coreFrame;
+ return coreFrame && coreFrame->selection()->isRange();
}
- (void)_clearSelection
{
+ ASSERT([getWebView(self) _usesDocumentViews]);
id documentView = [_private->webFrameView documentView];
if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
[documentView deselectAll];
@@ -532,7 +483,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
size_t size = nodesVector->size();
NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
for (size_t i = 0; i < size; ++i)
- [nodes addObject:[DOMNode _wrapNode:(*nodesVector)[i]]];
+ [nodes addObject:kit((*nodesVector)[i])];
return nodes;
}
@@ -540,7 +491,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
{
// FIXME: This is always "for interchange". Is that right? See the previous method.
Vector<Node*> nodeList;
- NSString *markupString = createMarkup([range _range], nodes ? &nodeList : 0, AnnotateForInterchange);
+ NSString *markupString = createMarkup(core(range), nodes ? &nodeList : 0, AnnotateForInterchange);
if (nodes)
*nodes = [self _nodesFromList:&nodeList];
@@ -556,7 +507,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
{
// This will give a system malloc'd buffer that can be turned directly into an NSString
unsigned length;
- UChar* buf = plainTextToMallocAllocatedBuffer([range _range], length, true);
+ UChar* buf = plainTextToMallocAllocatedBuffer(core(range), length, true);
if (!buf)
return [NSString string];
@@ -592,7 +543,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
}
if (!_private->coreFrame || !_private->coreFrame->document() || !_private->coreFrame->view()) return pages;
- RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer());
+ RenderView* root = toRenderView(_private->coreFrame->document()->renderer());
if (!root) return pages;
FrameView* view = _private->coreFrame->view();
@@ -644,7 +595,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
{
ASSERT(_private->coreFrame->document());
- JSValuePtr result = _private->coreFrame->loader()->executeScript(string, forceUserGesture).jsValue();
+ JSValue result = _private->coreFrame->loader()->executeScript(string, forceUserGesture).jsValue();
if (!_private->coreFrame) // In case the script removed our frame from the page.
return @"";
@@ -655,25 +606,25 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
if (!result || !result.isBoolean() && !result.isString() && !result.isNumber())
return @"";
- JSLock lock(false);
+ JSLock lock(SilenceAssertionsOnly);
return String(result.toString(_private->coreFrame->script()->globalObject()->globalExec()));
}
- (NSRect)_caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
{
- VisiblePosition visiblePosition([node _node], offset, static_cast<EAffinity>(affinity));
+ VisiblePosition visiblePosition(core(node), offset, static_cast<EAffinity>(affinity));
return visiblePosition.absoluteCaretBounds();
}
- (NSRect)_firstRectForDOMRange:(DOMRange *)range
{
- return _private->coreFrame->firstRectForRange([range _range]);
+ return _private->coreFrame->firstRectForRange(core(range));
}
- (void)_scrollDOMRangeToVisible:(DOMRange *)range
{
NSRect rangeRect = [self _firstRectForDOMRange:range];
- Node *startNode = [[range startContainer] _node];
+ Node *startNode = core([range startContainer]);
if (startNode && startNode->renderer()) {
RenderLayer *layer = startNode->renderer()->enclosingLayer();
@@ -698,7 +649,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
if (!_private->coreFrame || !_private->coreFrame->document())
return nil;
- RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer());
+ RenderView* root = toRenderView(_private->coreFrame->document()->renderer());
if (!root)
return nil;
return _private->coreFrame->document()->axObjectCache()->getOrCreate(root)->wrapper();
@@ -715,7 +666,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
SelectionController selection;
selection.setSelection(_private->coreFrame->selection()->selection());
selection.modify(alteration, direction, granularity);
- return [DOMRange _wrapRange:selection.toNormalizedRange().get()];
+ return kit(selection.toNormalizedRange().get());
}
- (TextGranularity)_selectionGranularity
@@ -777,7 +728,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
- (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
{
- return [DOMRange _wrapRange:[self _convertToDOMRange:nsrange].get()];
+ return kit([self _convertToDOMRange:nsrange].get());
}
- (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
@@ -788,12 +739,12 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
- (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
{
- return [self _convertToNSRange:[range _range]];
+ return [self _convertToNSRange:core(range)];
}
- (DOMRange *)_markDOMRange
{
- return [DOMRange _wrapRange:_private->coreFrame->mark().toNormalizedRange().get()];
+ return kit(_private->coreFrame->mark().toNormalizedRange().get());
}
// Given proposedRange, returns an extended range that includes adjacent whitespace that should
@@ -801,8 +752,8 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
// the text surrounding the deletion.
- (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
{
- Node *startContainer = [[proposedRange startContainer] _node];
- Node *endContainer = [[proposedRange endContainer] _node];
+ Node* startContainer = core([proposedRange startContainer]);
+ Node* endContainer = core([proposedRange endContainer]);
if (startContainer == nil || endContainer == nil)
return nil;
@@ -824,9 +775,9 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
RefPtr<Range> range = _private->coreFrame->document()->createRange();
int exception = 0;
- range->setStart(newStart.node(), newStart.m_offset, exception);
- range->setEnd(newStart.node(), newStart.m_offset, exception);
- return [DOMRange _wrapRange:range.get()];
+ range->setStart(newStart.node(), newStart.deprecatedEditingOffset(), exception);
+ range->setEnd(newStart.node(), newStart.deprecatedEditingOffset(), exception);
+ return kit(range.get());
}
// Determines whether whitespace needs to be added around aString to preserve proper spacing and
@@ -842,8 +793,8 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
*afterString = nil;
// inspect destination
- Node *startContainer = [[rangeToReplace startContainer] _node];
- Node *endContainer = [[rangeToReplace endContainer] _node];
+ Node *startContainer = core([rangeToReplace startContainer]);
+ Node *endContainer = core([rangeToReplace endContainer]);
Position startPos(startContainer, [rangeToReplace startOffset]);
Position endPos(endContainer, [rangeToReplace endOffset]);
@@ -890,28 +841,28 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
- (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
{
if (!_private->coreFrame || !_private->coreFrame->document())
- return 0;
+ return nil;
- return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString).get()];
+ return kit(createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString).get());
}
- (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
{
if (!_private->coreFrame || !_private->coreFrame->document())
- return 0;
+ return nil;
NSEnumerator *nodeEnum = [nodes objectEnumerator];
Vector<Node*> nodesVector;
DOMNode *node;
while ((node = [nodeEnum nextObject]))
- nodesVector.append([node _node]);
+ nodesVector.append(core(node));
- return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get()];
+ return kit(createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get());
}
- (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
{
- DOMDocumentFragment *fragment = [DOMDocumentFragment _wrapDocumentFragment:_private->coreFrame->document()->createDocumentFragment().get()];
+ DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().get());
[fragment appendChild:node];
[self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
}
@@ -939,7 +890,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
VisiblePosition previous = position.previous();
if (previous.isNotNull()) {
- DOMRange *previousCharacterRange = [DOMRange _wrapRange:makeRange(previous, position).get()];
+ DOMRange *previousCharacterRange = kit(makeRange(previous, position).get());
NSRect rect = [self _firstRectForDOMRange:previousCharacterRange];
if (NSPointInRect(point, rect))
return previousCharacterRange;
@@ -947,7 +898,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
VisiblePosition next = position.next();
if (next.isNotNull()) {
- DOMRange *nextCharacterRange = [DOMRange _wrapRange:makeRange(position, next).get()];
+ DOMRange *nextCharacterRange = kit(makeRange(position, next).get());
NSRect rect = [self _firstRectForDOMRange:nextCharacterRange];
if (NSPointInRect(point, rect))
return nextCharacterRange;
@@ -960,14 +911,14 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
{
if (!_private->coreFrame || !_private->coreFrame->typingStyle())
return nil;
- return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:_private->coreFrame->typingStyle()->copy().get()];
+ return kit(_private->coreFrame->typingStyle()->copy().get());
}
- (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
{
if (!_private->coreFrame)
return;
- _private->coreFrame->computeAndSetTypingStyle([style _CSSStyleDeclaration], undoAction);
+ _private->coreFrame->computeAndSetTypingStyle(core(style), undoAction);
}
- (void)_dragSourceMovedTo:(NSPoint)windowLoc
@@ -977,6 +928,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
FrameView* view = _private->coreFrame->view();
if (!view)
return;
+ ASSERT([getWebView(self) _usesDocumentViews]);
// FIXME: These are fake modifier keys here, but they should be real ones instead.
PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]),
LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
@@ -990,6 +942,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
FrameView* view = _private->coreFrame->view();
if (!view)
return;
+ ASSERT([getWebView(self) _usesDocumentViews]);
// FIXME: These are fake modifier keys here, but they should be real ones instead.
PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]),
LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
@@ -1097,7 +1050,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
- (unsigned)_pendingFrameUnloadEventCount
{
- return _private->coreFrame->eventHandler()->pendingFrameUnloadEventCount();
+ return _private->coreFrame->domWindow()->pendingUnloadEventListeners();
}
- (WebIconFetcher *)fetchApplicationIcon:(id)target
@@ -1150,7 +1103,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
if (!controller)
return false;
- Node* coreNode = [node _node];
+ Node* coreNode = core(node);
if (!coreNode || !coreNode->renderer())
return false;
@@ -1167,7 +1120,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
if (!controller)
return false;
- Node* coreNode = [node _node];
+ Node* coreNode = core(node);
if (!coreNode || !coreNode->renderer())
return false;
@@ -1192,7 +1145,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
if (_private->coreFrame->selection()->isNone() || !fragment)
return;
- applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle));
+ applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), core(fragment), selectReplacement, smartReplace, matchStyle));
_private->coreFrame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
}
@@ -1208,6 +1161,40 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
[self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
}
+- (NSMutableDictionary *)_cacheabilityDictionary
+{
+ NSMutableDictionary *result = [NSMutableDictionary dictionary];
+
+ FrameLoader* frameLoader = _private->coreFrame->loader();
+ DocumentLoader* documentLoader = frameLoader->documentLoader();
+ if (documentLoader && !documentLoader->mainDocumentError().isNull())
+ [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError];
+
+ if (frameLoader->containsPlugins())
+ [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins];
+
+ if (DOMWindow* domWindow = _private->coreFrame->domWindow()) {
+ if (domWindow->hasEventListener(eventNames().unloadEvent))
+ [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener];
+
+ if (domWindow->optionalApplicationCache())
+ [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache];
+ }
+
+ if (Document* document = _private->coreFrame->document()) {
+ if (document->hasOpenDatabases())
+ [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases];
+
+ if (document->usingGeolocation())
+ [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesGeolocation];
+
+ if (!document->canSuspendActiveDOMObjects())
+ [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects];
+ }
+
+ return result;
+}
+
@end
@implementation WebFrame
@@ -1246,6 +1233,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
- (WebFrameView *)frameView
{
+ ASSERT(!getWebView(self) || [getWebView(self) _usesDocumentViews]);
return _private->webFrameView;
}
@@ -1254,8 +1242,17 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
return getWebView(self);
}
+static bool needsMicrosoftMessengerDOMDocumentWorkaround()
+{
+ static bool needsWorkaround = applicationIsMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending;
+ return needsWorkaround;
+}
+
- (DOMDocument *)DOMDocument
{
+ if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np())
+ return nil;
+
Frame* coreFrame = _private->coreFrame;
if (!coreFrame)
return nil;
@@ -1314,6 +1311,9 @@ static NSURL *createUniqueWebDataURL()
- (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
{
+ if (!pthread_main_np())
+ return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL];
+
KURL responseURL;
if (!baseURL) {
baseURL = blankURL();
@@ -1333,6 +1333,8 @@ static NSURL *createUniqueWebDataURL()
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
{
+ WebCoreThreadViolationCheckRoundTwo();
+
if (!MIMEType)
MIMEType = @"text/html";
[self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil];
@@ -1346,11 +1348,15 @@ static NSURL *createUniqueWebDataURL()
- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
{
+ WebCoreThreadViolationCheckRoundTwo();
+
[self _loadHTMLString:string baseURL:baseURL unreachableURL:nil];
}
- (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
{
+ WebCoreThreadViolationCheckRoundTwo();
+
[self _loadHTMLString:string baseURL:baseURL unreachableURL:unreachableURL];
}
@@ -1369,8 +1375,7 @@ static NSURL *createUniqueWebDataURL()
- (void)reload
{
- if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) &&
- [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"])
+ if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) && applicationIsSafari())
_private->coreFrame->loader()->reload(GetCurrentKeyModifiers() & shiftKey);
else
_private->coreFrame->loader()->reload(false);
diff --git a/WebKit/mac/WebView/WebFrameInternal.h b/WebKit/mac/WebView/WebFrameInternal.h
index 473e691..10a3015 100644
--- a/WebKit/mac/WebView/WebFrameInternal.h
+++ b/WebKit/mac/WebView/WebFrameInternal.h
@@ -63,30 +63,9 @@ namespace WebCore {
typedef WebCore::HistoryItem WebCoreHistoryItem;
-WebCore::CSSStyleDeclaration* core(DOMCSSStyleDeclaration *);
-DOMCSSStyleDeclaration *kit(WebCore::CSSStyleDeclaration*);
-
WebCore::Frame* core(WebFrame *);
WebFrame *kit(WebCore::Frame *);
-WebCore::Element* core(DOMElement *);
-DOMElement *kit(WebCore::Element*);
-
-WebCore::Node* core(DOMNode *);
-DOMNode *kit(WebCore::Node*);
-
-WebCore::Document* core(DOMDocument *);
-DOMDocument *kit(WebCore::Document*);
-
-WebCore::DocumentFragment* core(DOMDocumentFragment *);
-DOMDocumentFragment *kit(WebCore::DocumentFragment*);
-
-WebCore::HTMLElement* core(DOMHTMLElement *);
-DOMHTMLElement *kit(WebCore::HTMLElement*);
-
-WebCore::Range* core(DOMRange *);
-DOMRange *kit(WebCore::Range*);
-
WebCore::Page* core(WebView *);
WebView *kit(WebCore::Page*);
diff --git a/WebKit/mac/WebView/WebFramePrivate.h b/WebKit/mac/WebView/WebFramePrivate.h
index e3e3540..8e7a2ef 100644
--- a/WebKit/mac/WebView/WebFramePrivate.h
+++ b/WebKit/mac/WebView/WebFramePrivate.h
@@ -45,6 +45,14 @@ extern NSString *WebPageCacheEntryDateKey;
extern NSString *WebPageCacheDataSourceKey;
extern NSString *WebPageCacheDocumentViewKey;
+extern NSString *WebFrameMainDocumentError;
+extern NSString *WebFrameHasPlugins;
+extern NSString *WebFrameHasUnloadListener;
+extern NSString *WebFrameUsesDatabases;
+extern NSString *WebFrameUsesGeolocation;
+extern NSString *WebFrameUsesApplicationCache;
+extern NSString *WebFrameCanSuspendActiveDOMObjects;
+
typedef enum {
WebFrameLoadTypeStandard,
WebFrameLoadTypeBack,
@@ -55,7 +63,8 @@ typedef enum {
WebFrameLoadTypeSame, // user loads same URL again (but not reload button)
WebFrameLoadTypeInternal, // maps to WebCore::FrameLoadTypeRedirectWithLockedBackForwardList
WebFrameLoadTypeReplace,
- WebFrameLoadTypeReloadFromOrigin
+ WebFrameLoadTypeReloadFromOrigin,
+ WebFrameLoadTypeBackWMLDeckNotAccessible
} WebFrameLoadType;
@interface WebFrame (WebPrivate)
@@ -100,4 +109,5 @@ typedef enum {
- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace;
- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace;
+- (NSMutableDictionary *)_cacheabilityDictionary;
@end
diff --git a/WebKit/mac/WebView/WebFrameView.mm b/WebKit/mac/WebView/WebFrameView.mm
index bc51bb5..1a460ea 100644
--- a/WebKit/mac/WebView/WebFrameView.mm
+++ b/WebKit/mac/WebView/WebFrameView.mm
@@ -307,20 +307,21 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
[WebViewFactory createSharedFactory];
[WebKeyGenerator createSharedGenerator];
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-
+// FIXME: Remove the NSAppKitVersionNumberWithDeferredWindowDisplaySupport check once
+// once AppKit's Deferred Window Display support is available.
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) || !defined(NSAppKitVersionNumberWithDeferredWindowDisplaySupport)
// CoreGraphics deferred updates are disabled if WebKitEnableCoalescedUpdatesPreferenceKey is NO
- // or has no value. For compatibility with Mac OS X 10.4.6, deferred updates are off by default.
- if (![defaults boolForKey:WebKitEnableDeferredUpdatesPreferenceKey])
+ // or has no value. For compatibility with Mac OS X 10.5 and lower, deferred updates are off by default.
+ if (![[NSUserDefaults standardUserDefaults] boolForKey:WebKitEnableDeferredUpdatesPreferenceKey])
WKDisableCGDeferredUpdates();
-
+#endif
if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MAIN_THREAD_EXCEPTIONS))
setDefaultThreadViolationBehavior(LogOnFirstThreadViolation, ThreadViolationRoundOne);
bool throwExceptionsForRoundTwo = WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_ROUND_TWO_MAIN_THREAD_EXCEPTIONS);
#ifdef MAIL_THREAD_WORKAROUND
// Even if old Mail is linked with new WebKit, don't throw exceptions.
- if (needMailThreadWorkaround())
+ if ([WebResource _needMailThreadWorkaroundIfCalledOffMainThread])
throwExceptionsForRoundTwo = false;
#endif
if (!throwExceptionsForRoundTwo)
@@ -492,9 +493,15 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
- (void)setFrameSize:(NSSize)size
{
- // See WebFrameLoaderClient::provisionalLoadStarted.
- if (!NSEqualSizes(size, [self frame].size) && [[[self webFrame] webView] drawsBackground])
- [[self _scrollView] setDrawsBackground:YES];
+ if (!NSEqualSizes(size, [self frame].size)) {
+ // See WebFrameLoaderClient::provisionalLoadStarted.
+ if ([[[self webFrame] webView] drawsBackground])
+ [[self _scrollView] setDrawsBackground:YES];
+ if (Frame* coreFrame = [self _web_frame]) {
+ if (FrameView* coreFrameView = coreFrame->view())
+ coreFrameView->setNeedsLayout();
+ }
+ }
[super setFrameSize:size];
}
@@ -518,31 +525,49 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
return frame->eventHandler()->scrollOverflow(direction, granularity);
}
-- (void)scrollToBeginningOfDocument:(id)sender
+- (BOOL)_scrollToBeginningOfDocument
{
- if (![self _scrollOverflowInDirection:ScrollUp granularity:ScrollByDocument]) {
+ if ([self _scrollOverflowInDirection:ScrollUp granularity:ScrollByDocument])
+ return YES;
+ if (![self _hasScrollBars])
+ return NO;
+ NSPoint point = [[[self _scrollView] documentView] frame].origin;
+ return [[self _contentView] _scrollTo:&point animate:YES];
+}
- if (![self _hasScrollBars]) {
- [[self _largestChildWithScrollBars] scrollToBeginningOfDocument:sender];
- return;
- }
+- (BOOL)_scrollToEndOfDocument
+{
+ if ([self _scrollOverflowInDirection:ScrollDown granularity:ScrollByDocument])
+ return YES;
+ if (![self _hasScrollBars])
+ return NO;
+ NSRect frame = [[[self _scrollView] documentView] frame];
+ NSPoint point = NSMakePoint(frame.origin.x, NSMaxY(frame));
+ return [[self _contentView] _scrollTo:&point animate:YES];
+}
- [[self _contentView] scrollPoint:[[[self _scrollView] documentView] frame].origin];
+- (void)scrollToBeginningOfDocument:(id)sender
+{
+ if ([self _scrollToBeginningOfDocument])
+ return;
+
+ if (WebFrameView *child = [self _largestChildWithScrollBars]) {
+ if ([child _scrollToBeginningOfDocument])
+ return;
}
+ [[self nextResponder] tryToPerform:@selector(scrollToBeginningOfDocument:) with:sender];
}
- (void)scrollToEndOfDocument:(id)sender
{
- if (![self _scrollOverflowInDirection:ScrollDown granularity:ScrollByDocument]) {
+ if ([self _scrollToEndOfDocument])
+ return;
- if (![self _hasScrollBars]) {
- [[self _largestChildWithScrollBars] scrollToEndOfDocument:sender];
+ if (WebFrameView *child = [self _largestChildWithScrollBars]) {
+ if ([child _scrollToEndOfDocument])
return;
- }
-
- NSRect frame = [[[self _scrollView] documentView] frame];
- [[self _contentView] scrollPoint:NSMakePoint(frame.origin.x, NSMaxY(frame))];
}
+ [[self nextResponder] tryToPerform:@selector(scrollToEndOfDocument:) with:sender];
}
- (void)_goBack
@@ -653,12 +678,14 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
- (void)scrollLineUp:(id)sender
{
- [self _scrollLineVertically:YES];
+ if (![self _scrollLineVertically:YES])
+ [[self nextResponder] tryToPerform:@selector(scrollLineUp:) with:sender];
}
- (void)scrollLineDown:(id)sender
{
- [self _scrollLineVertically:NO];
+ if (![self _scrollLineVertically:NO])
+ [[self nextResponder] tryToPerform:@selector(scrollLineDown:) with:sender];
}
- (BOOL)_firstResponderIsFormControl
diff --git a/WebKit/mac/WebView/WebHTMLRepresentation.mm b/WebKit/mac/WebView/WebHTMLRepresentation.mm
index 3f69870..39489e8 100644
--- a/WebKit/mac/WebView/WebHTMLRepresentation.mm
+++ b/WebKit/mac/WebView/WebHTMLRepresentation.mm
@@ -28,7 +28,7 @@
#import "WebHTMLRepresentation.h"
-#import "DOMNodeInternal.h"
+#import "DOMElementInternal.h"
#import "DOMRangeInternal.h"
#import "WebArchive.h"
#import "WebBasePluginPackage.h"
@@ -47,6 +47,7 @@
#import <WebCore/FrameLoader.h>
#import <WebCore/FrameLoaderClient.h>
#import <WebCore/HTMLFormControlElement.h>
+#import <WebCore/HTMLFormElement.h>
#import <WebCore/HTMLInputElement.h>
#import <WebCore/HTMLNames.h>
#import <WebCore/MIMETypeRegistry.h>
@@ -259,13 +260,13 @@ static NSArray *concatenateArrays(NSArray *first, NSArray *second)
- (NSAttributedString *)attributedStringFrom:(DOMNode *)startNode startOffset:(int)startOffset to:(DOMNode *)endNode endOffset:(int)endOffset
{
- return [NSAttributedString _web_attributedStringFromRange:Range::create([startNode _node]->document(), [startNode _node], startOffset, [endNode _node], endOffset).get()];
+ return [NSAttributedString _web_attributedStringFromRange:Range::create(core(startNode)->document(), core(startNode), startOffset, core(endNode), endOffset).get()];
}
static HTMLFormElement* formElementFromDOMElement(DOMElement *element)
{
- Node* node = [element _node];
- return node && node->hasTagName(formTag) ? static_cast<HTMLFormElement *>(node) : 0;
+ Element* node = core(element);
+ return node && node->hasTagName(formTag) ? static_cast<HTMLFormElement*>(node) : 0;
}
- (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
@@ -277,7 +278,7 @@ static HTMLFormElement* formElementFromDOMElement(DOMElement *element)
AtomicString targetName = name;
for (unsigned i = 0; i < elements.size(); i++) {
HTMLFormControlElement* elt = elements[i];
- if (elt->name() == targetName)
+ if (elt->formControlName() == targetName)
return kit(elt);
}
return nil;
@@ -285,7 +286,7 @@ static HTMLFormElement* formElementFromDOMElement(DOMElement *element)
static HTMLInputElement* inputElementFromDOMElement(DOMElement* element)
{
- Node* node = [element _node];
+ Element* node = core(element);
return node && node->hasTagName(inputTag) ? static_cast<HTMLInputElement*>(node) : 0;
}
diff --git a/WebKit/mac/WebView/WebHTMLView.mm b/WebKit/mac/WebView/WebHTMLView.mm
index c4ca174..d58c765 100644
--- a/WebKit/mac/WebView/WebHTMLView.mm
+++ b/WebKit/mac/WebView/WebHTMLView.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* (C) 2006, 2007 Graham Dennis (graham.dennis@gmail.com)
*
* Redistribution and use in source and binary forms, with or without
@@ -29,14 +29,17 @@
#import "WebHTMLView.h"
+#import "DOMCSSStyleDeclarationInternal.h"
+#import "DOMDocumentFragmentInternal.h"
+#import "DOMDocumentInternal.h"
#import "DOMNodeInternal.h"
#import "DOMRangeInternal.h"
#import "WebArchive.h"
-#import "WebNetscapePluginView.h"
#import "WebClipView.h"
-#import "WebDOMOperationsPrivate.h"
+#import "WebDOMOperationsInternal.h"
#import "WebDataSourceInternal.h"
#import "WebDefaultUIDelegate.h"
+#import "WebDelegateImplementationCaching.h"
#import "WebDocumentInternal.h"
#import "WebDynamicScrollBarsView.h"
#import "WebEditingDelegate.h"
@@ -50,7 +53,6 @@
#import "WebKitNSStringExtras.h"
#import "WebKitVersionChecks.h"
#import "WebLocalizableStrings.h"
-#import "WebNodeHighlight.h"
#import "WebNSAttributedStringExtras.h"
#import "WebNSEventExtras.h"
#import "WebNSFileManagerExtras.h"
@@ -60,17 +62,20 @@
#import "WebNSPrintOperationExtras.h"
#import "WebNSURLExtras.h"
#import "WebNSViewExtras.h"
+#import "WebNetscapePluginView.h"
+#import "WebNodeHighlight.h"
#import "WebPluginController.h"
#import "WebPreferences.h"
#import "WebPreferencesPrivate.h"
#import "WebResourcePrivate.h"
#import "WebStringTruncator.h"
+#import "WebTextCompletionController.h"
#import "WebTypesInternal.h"
#import "WebUIDelegatePrivate.h"
#import "WebViewInternal.h"
#import <AppKit/NSAccessibility.h>
#import <ApplicationServices/ApplicationServices.h>
-#import <dlfcn.h>
+#import <WebCore/CSSMutableStyleDeclaration.h>
#import <WebCore/CachedImage.h>
#import <WebCore/CachedResourceClient.h>
#import <WebCore/ColorMac.h>
@@ -78,38 +83,38 @@
#import <WebCore/ContextMenuController.h>
#import <WebCore/Document.h>
#import <WebCore/DocumentFragment.h>
+#import <WebCore/DragController.h>
#import <WebCore/Editor.h>
#import <WebCore/EditorDeleteAction.h>
#import <WebCore/Element.h>
#import <WebCore/EventHandler.h>
#import <WebCore/ExceptionHandlers.h>
-#import <WebCore/DragController.h>
#import <WebCore/FloatRect.h>
#import <WebCore/FocusController.h>
#import <WebCore/Frame.h>
#import <WebCore/FrameLoader.h>
#import <WebCore/FrameView.h>
-#import <WebCore/HitTestResult.h>
#import <WebCore/HTMLNames.h>
+#import <WebCore/HitTestResult.h>
#import <WebCore/Image.h>
#import <WebCore/KeyboardEvent.h>
#import <WebCore/LegacyWebArchive.h>
#import <WebCore/MIMETypeRegistry.h>
#import <WebCore/Page.h>
#import <WebCore/PlatformKeyboardEvent.h>
-#import <WebCore/PlatformMouseEvent.h>
#import <WebCore/Range.h>
#import <WebCore/SelectionController.h>
#import <WebCore/SharedBuffer.h>
#import <WebCore/SimpleFontData.h>
#import <WebCore/Text.h>
#import <WebCore/WebCoreObjCExtras.h>
-#import <WebCore/WebCoreTextRenderer.h>
+#import <WebCore/WebFontCache.h>
#import <WebCore/markup.h>
#import <WebKit/DOM.h>
#import <WebKit/DOMExtensions.h>
#import <WebKit/DOMPrivate.h>
#import <WebKitSystemInterface.h>
+#import <dlfcn.h>
#import <limits>
#import <runtime/InitializeThreading.h>
@@ -144,6 +149,7 @@ using namespace WTF;
static IMP oldSetCursorIMP = NULL;
#ifdef BUILDING_ON_TIGER
+
static IMP oldResetCursorRectsIMP = NULL;
static BOOL canSetCursor = YES;
@@ -169,7 +175,9 @@ static void setCursor(NSCursor* self, SEL cmd)
if (canSetCursor)
oldSetCursorIMP(self, cmd);
}
+
#else
+
static void setCursor(NSWindow* self, SEL cmd, NSPoint point)
{
NSView* view = [[self _web_borderView] hitTest:point];
@@ -184,21 +192,8 @@ static void setCursor(NSWindow* self, SEL cmd, NSPoint point)
}
oldSetCursorIMP(self, cmd, point);
}
-#endif
-#if USE(ACCELERATED_COMPOSITING)
-@interface WebLayerHostingView : NSView
-@end
-
-@implementation WebLayerHostingView
-// Empty NSViews intercept rightMouseDown: to do context menu handling, but we need the WebLayerHostingView to
-// let right mouse clicks through.
-- (void)rightMouseDown:(NSEvent *)theEvent
-{
- [[self nextResponder] performSelector:_cmd withObject:theEvent];
-}
-@end
-#endif // USE(ACCELERATED_COMPOSITING)
+#endif
extern "C" {
@@ -206,6 +201,7 @@ extern "C" {
extern NSString *NSMarkedClauseSegmentAttributeName;
extern NSString *NSTextInputReplacementRangeAttributeName;
+
}
@interface NSView (WebNSViewDetails)
@@ -224,7 +220,6 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
@interface NSWindow (WebNSWindowDetails)
- (id)_newFirstResponderAfterResigning;
-- (void)_setForceActiveControls:(BOOL)flag;
@end
@interface NSAttributedString (WebNSAttributedStringDetails)
@@ -335,6 +330,32 @@ static CachedResourceClient* promisedDataClient()
- (void)_web_clearPrintingModeRecursive;
@end
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
+@interface WebHTMLView (WebHTMLViewTextCheckingInternal)
+- (void)orderFrontSubstitutionsPanel:(id)sender;
+- (BOOL)smartInsertDeleteEnabled;
+- (void)setSmartInsertDeleteEnabled:(BOOL)flag;
+- (void)toggleSmartInsertDelete:(id)sender;
+- (BOOL)isAutomaticQuoteSubstitutionEnabled;
+- (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag;
+- (void)toggleAutomaticQuoteSubstitution:(id)sender;
+- (BOOL)isAutomaticLinkDetectionEnabled;
+- (void)setAutomaticLinkDetectionEnabled:(BOOL)flag;
+- (void)toggleAutomaticLinkDetection:(id)sender;
+- (BOOL)isAutomaticDashSubstitutionEnabled;
+- (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag;
+- (void)toggleAutomaticDashSubstitution:(id)sender;
+- (BOOL)isAutomaticTextReplacementEnabled;
+- (void)setAutomaticTextReplacementEnabled:(BOOL)flag;
+- (void)toggleAutomaticTextReplacement:(id)sender;
+- (BOOL)isAutomaticSpellingCorrectionEnabled;
+- (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag;
+- (void)toggleAutomaticSpellingCorrection:(id)sender;
+@end
+
+#endif
+
@interface WebHTMLView (WebForwardDeclaration) // FIXME: Put this in a normal category and stop doing the forward declaration trick.
- (void)_setPrinting:(BOOL)printing minimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustViewSize:(BOOL)adjustViewSize;
@end
@@ -366,24 +387,6 @@ static CachedResourceClient* promisedDataClient()
- (void)_web_setObjectIfNotNil:(id)object forKey:(id)key;
@end
-// Handles the complete: text command
-@interface WebTextCompleteController : NSObject <NSTableViewDelegate, NSTableViewDataSource> {
-@private
- WebHTMLView *_view;
- NSWindow *_popupWindow;
- NSTableView *_tableView;
- NSArray *_completions;
- NSString *_originalString;
- int prefixLength;
-}
-- (id)initWithHTMLView:(WebHTMLView *)view;
-- (void)doCompletion;
-- (void)endRevertingChange:(BOOL)revertChange moveLeft:(BOOL)goLeft;
-- (BOOL)popupWindowIsOpen;
-- (BOOL)filterKeyDown:(NSEvent *)event;
-- (void)_reflectSelection;
-@end
-
struct WebHTMLViewInterpretKeyEventsParameters {
KeyboardEvent* event;
BOOL eventWasHandled;
@@ -396,7 +399,6 @@ struct WebHTMLViewInterpretKeyEventsParameters {
@interface WebHTMLViewPrivate : NSObject {
@public
BOOL closed;
- BOOL needsLayout;
BOOL needsToApplyStyles;
BOOL ignoringMouseDraggedEvents;
BOOL printing;
@@ -404,7 +406,6 @@ struct WebHTMLViewInterpretKeyEventsParameters {
BOOL observingMouseMovedNotifications;
BOOL observingSuperviewNotifications;
BOOL observingWindowNotifications;
- BOOL resigningFirstResponder;
id savedSubviews;
BOOL subviewsSetAside;
@@ -416,8 +417,10 @@ struct WebHTMLViewInterpretKeyEventsParameters {
NSEvent *mouseDownEvent; // Kept after handling the event.
BOOL handlingMouseDownEvent;
NSEvent *keyDownEvent; // Kept after handling the event.
-
- NSSize lastLayoutSize;
+
+ // A WebHTMLView has a single input context, but we return nil when in non-editable content to avoid making input methods do their work.
+ // This state is saved each time selection changes, because computing it causes style recalc, which is not always safe to do.
+ BOOL exposeInputContext;
NSPoint lastScrollPosition;
@@ -439,7 +442,7 @@ struct WebHTMLViewInterpretKeyEventsParameters {
BOOL nextResponderDisabledOnce;
#endif
- WebTextCompleteController *compController;
+ WebTextCompletionController *completionController;
BOOL transparentBackground;
@@ -449,7 +452,6 @@ struct WebHTMLViewInterpretKeyEventsParameters {
WebDataSource *dataSource;
WebCore::CachedImage* promisedDragTIFFDataSource;
- CFRunLoopTimerRef updateFocusedAndActiveStateTimer;
CFRunLoopTimerRef updateMouseoverTimer;
SEL selectorForDoCommandBySelector;
@@ -514,14 +516,13 @@ static NSCellStateValue kit(TriState state)
ASSERT(!autoscrollTimer);
ASSERT(!autoscrollTriggerEvent);
- ASSERT(!updateFocusedAndActiveStateTimer);
ASSERT(!updateMouseoverTimer);
[mouseDownEvent release];
[keyDownEvent release];
[pluginController release];
[toolTip release];
- [compController release];
+ [completionController release];
[dataSource release];
[highlighters release];
if (promisedDragTIFFDataSource)
@@ -546,7 +547,7 @@ static NSCellStateValue kit(TriState state)
[keyDownEvent release];
[pluginController release];
[toolTip release];
- [compController release];
+ [completionController release];
[dataSource release];
[highlighters release];
if (promisedDragTIFFDataSource)
@@ -556,7 +557,7 @@ static NSCellStateValue kit(TriState state)
keyDownEvent = nil;
pluginController = nil;
toolTip = nil;
- compController = nil;
+ completionController = nil;
dataSource = nil;
highlighters = nil;
promisedDragTIFFDataSource = 0;
@@ -684,6 +685,13 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
subresources:0]))
return fragment;
+ if ([types containsObject:NSRTFDPboardType] &&
+ (fragment = [self _documentFragmentFromPasteboard:pasteboard
+ forType:NSRTFDPboardType
+ inContext:context
+ subresources:0]))
+ return fragment;
+
if ([types containsObject:NSRTFPboardType] &&
(fragment = [self _documentFragmentFromPasteboard:pasteboard
forType:NSRTFPboardType
@@ -691,16 +699,16 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
subresources:0]))
return fragment;
- if ([types containsObject:NSRTFDPboardType] &&
+ if ([types containsObject:NSTIFFPboardType] &&
(fragment = [self _documentFragmentFromPasteboard:pasteboard
- forType:NSRTFDPboardType
+ forType:NSTIFFPboardType
inContext:context
subresources:0]))
return fragment;
- if ([types containsObject:NSTIFFPboardType] &&
+ if ([types containsObject:NSPDFPboardType] &&
(fragment = [self _documentFragmentFromPasteboard:pasteboard
- forType:NSTIFFPboardType
+ forType:NSPDFPboardType
inContext:context
subresources:0]))
return fragment;
@@ -746,7 +754,7 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
NSArray *types = [pasteboard types];
if ([types containsObject:NSStringPboardType])
- return [pasteboard stringForType:NSStringPboardType];
+ return [[pasteboard stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping];
NSAttributedString *attributedString = nil;
NSString *string;
@@ -780,20 +788,29 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
- (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText
{
+ WebView *webView = [[self _webView] retain];
+ [webView _setInsertionPasteboard:pasteboard];
+
DOMRange *range = [self _selectedRange];
- DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard
- inContext:range allowPlainText:allowPlainText];
- WebFrame *frame = [self _frame];
- if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:[self _selectedRange] givenAction:WebViewInsertActionPasted]) {
- [frame _replaceSelectionWithFragment:fragment selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard] matchStyle:NO];
- }
+ DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard inContext:range allowPlainText:allowPlainText];
+ if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:range givenAction:WebViewInsertActionPasted])
+ [[self _frame] _replaceSelectionWithFragment:fragment selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard] matchStyle:NO];
+
+ [webView _setInsertionPasteboard:nil];
+ [webView release];
}
- (void)_pasteAsPlainTextWithPasteboard:(NSPasteboard *)pasteboard
{
+ WebView *webView = [[self _webView] retain];
+ [webView _setInsertionPasteboard:pasteboard];
+
NSString *text = [self _plainTextFromPasteboard:pasteboard];
if ([self _shouldReplaceSelectionWithText:text givenAction:WebViewInsertActionPasted])
[[self _frame] _replaceSelectionWithText:text selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard]];
+
+ [webView _setInsertionPasteboard:nil];
+ [webView release];
}
- (void)_removeMouseMovedObserverUnconditionally
@@ -834,7 +851,6 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
[notificationCenter removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil];
[notificationCenter removeObserver:self name:NSWindowDidResignKeyNotification object:nil];
[notificationCenter removeObserver:self name:NSWindowWillCloseNotification object:window];
- [notificationCenter removeObserver:self name:WKWindowWillOrderOnScreenNotification() object:window];
_private->observingWindowNotifications = false;
}
@@ -950,15 +966,6 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
_private->mouseDownEvent = event;
}
-- (void)_cancelUpdateFocusedAndActiveStateTimer
-{
- if (_private->updateFocusedAndActiveStateTimer) {
- CFRunLoopTimerInvalidate(_private->updateFocusedAndActiveStateTimer);
- CFRelease(_private->updateFocusedAndActiveStateTimer);
- _private->updateFocusedAndActiveStateTimer = NULL;
- }
-}
-
- (void)_cancelUpdateMouseoverTimer
{
if (_private->updateMouseoverTimer) {
@@ -1139,17 +1146,11 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
- (void)_frameOrBoundsChanged
{
- if (!NSEqualSizes(_private->lastLayoutSize, [(NSClipView *)[self superview] documentVisibleRect].size)) {
- [self setNeedsLayout:YES];
- [self setNeedsDisplay:YES];
- [_private->compController endRevertingChange:NO moveLeft:NO];
- }
-
NSPoint origin = [[self superview] bounds].origin;
if (!NSEqualPoints(_private->lastScrollPosition, origin)) {
if (Frame* coreFrame = core([self _frame]))
coreFrame->eventHandler()->sendScrollEvent();
- [_private->compController endRevertingChange:NO moveLeft:NO];
+ [_private->completionController endRevertingChange:NO moveLeft:NO];
WebView *webView = [self _webView];
[[webView _UIDelegateForwarder] webView:webView didScrollDocumentInFrameView:[self _frameView]];
@@ -1165,6 +1166,10 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
_updateMouseoverTimerCallback, &context);
CFRunLoopAddTimer(CFRunLoopGetCurrent(), _private->updateMouseoverTimer, kCFRunLoopDefaultMode);
}
+
+#if USE(ACCELERATED_COMPOSITING) && defined(BUILDING_ON_LEOPARD)
+ [self _updateLayerHostingViewPosition];
+#endif
}
- (void)_setAsideSubviews
@@ -1267,12 +1272,20 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
} else if (wasInPrintingMode)
[self _web_clearPrintingModeRecursive];
-#ifdef BUILDING_ON_TIGER
-
+#ifndef BUILDING_ON_TIGER
+ // There are known cases where -viewWillDraw is not called on all views being drawn.
+ // See <rdar://problem/6964278> for example. Performing layout at this point prevents us from
+ // trying to paint without layout (which WebCore now refuses to do, instead bailing out without
+ // drawing at all), but we may still fail to update and regions dirtied by the layout which are
+ // not already dirty.
+ if ([self _needsLayout]) {
+ LOG_ERROR("View needs layout. Either -viewWillDraw wasn't called or layout was invalidated during the display operation. Performing layout now.");
+ [self _web_layoutIfNeededRecursive];
+ }
+#else
// Because Tiger does not have viewWillDraw we need to do layout here.
[self _web_layoutIfNeededRecursive];
[_subviews makeObjectsPerformSelector:@selector(_propagateDirtyRectsToOpaqueAncestors)];
-
#endif
[self _setAsideSubviews];
@@ -1381,10 +1394,13 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
// when there is HTML overlapping the view, see bug 4361626)
// 4) NSAccessibilityHitTest relies on this for checking the cursor position.
// Our check for that is whether the event is NSFlagsChanged. This works
- // for VoiceOver's cntl-opt-f5 command (move focus to item under cursor)
- // and Dictionary's cmd-cntl-D (open dictionary popup for item under cursor).
+ // for VoiceOver's Control-Option-F5 command (move focus to item under cursor)
+ // and Dictionary's Command-Control-D (open dictionary popup for item under cursor).
// This is of course a hack.
+ if (_private->closed)
+ return nil;
+
BOOL captureHitsOnSubviews;
if (forceNSViewHitTest)
captureHitsOnSubviews = NO;
@@ -1398,8 +1414,14 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
|| [event type] == NSFlagsChanged);
}
- if (!captureHitsOnSubviews)
- return [super hitTest:point];
+ if (!captureHitsOnSubviews) {
+ NSView* hitView = [super hitTest:point];
+#if USE(ACCELERATED_COMPOSITING)
+ if (_private && hitView == _private->layerHostingView)
+ hitView = self;
+#endif
+ return hitView;
+ }
if ([[self superview] mouse:point inRect:[self frame]])
return self;
return nil;
@@ -1551,18 +1573,18 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
if (lastHitView != view && lastHitView && [lastHitView _frame]) {
// If we are moving out of a view (or frame), let's pretend the mouse moved
// all the way out of that view. But we have to account for scrolling, because
- // khtml doesn't understand our clipping.
+ // WebCore doesn't understand our clipping.
NSRect visibleRect = [[[[lastHitView _frame] frameView] _scrollView] documentVisibleRect];
float yScroll = visibleRect.origin.y;
float xScroll = visibleRect.origin.x;
- event = [NSEvent mouseEventWithType:NSMouseMoved
- location:NSMakePoint(-1 - xScroll, -1 - yScroll )
- modifierFlags:[[NSApp currentEvent] modifierFlags]
- timestamp:[NSDate timeIntervalSinceReferenceDate]
- windowNumber:[[view window] windowNumber]
- context:[[NSApp currentEvent] context]
- eventNumber:0 clickCount:0 pressure:0];
+ NSEvent *event = [NSEvent mouseEventWithType:NSMouseMoved
+ location:NSMakePoint(-1 - xScroll, -1 - yScroll)
+ modifierFlags:[[NSApp currentEvent] modifierFlags]
+ timestamp:[NSDate timeIntervalSinceReferenceDate]
+ windowNumber:[[view window] windowNumber]
+ context:[[NSApp currentEvent] context]
+ eventNumber:0 clickCount:0 pressure:0];
if (Frame* lastHitCoreFrame = core([lastHitView _frame]))
lastHitCoreFrame->eventHandler()->mouseMoved(event);
}
@@ -1582,7 +1604,7 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
{
static NSArray *types = nil;
if (!types) {
- types = [[NSArray alloc] initWithObjects:WebArchivePboardType, NSHTMLPboardType, NSFilenamesPboardType, NSTIFFPboardType,
+ types = [[NSArray alloc] initWithObjects:WebArchivePboardType, NSHTMLPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPDFPboardType,
#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
NSPICTPboardType,
#endif
@@ -1736,7 +1758,7 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
return [[self _webView] smartInsertDeleteEnabled] && [[pasteboard types] containsObject:WebSmartPastePboardType];
}
-- (void)_startAutoscrollTimer: (NSEvent *)triggerEvent
+- (void)_startAutoscrollTimer:(NSEvent *)triggerEvent
{
if (_private->autoscrollTimer == nil) {
_private->autoscrollTimer = [[NSTimer scheduledTimerWithTimeInterval:AUTOSCROLL_INTERVAL
@@ -1910,13 +1932,6 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
[_private->highlighters removeObjectForKey:type];
}
-- (void)_updateFocusedAndActiveState
-{
- [self _cancelUpdateFocusedAndActiveStateTimer];
-
- [[self _webView] _updateFocusedAndActiveStateForFrame:[self _frame]];
-}
-
- (void)_writeSelectionToPasteboard:(NSPasteboard *)pasteboard
{
ASSERT([self _hasSelection]);
@@ -1946,7 +1961,6 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
_private->closed = YES;
[self _cancelUpdateMouseoverTimer];
- [self _cancelUpdateFocusedAndActiveStateTimer];
[self _clearLastHitViewIfSelf];
[self _removeMouseMovedObserverUnconditionally];
[self _removeWindowObservers];
@@ -2057,6 +2071,16 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
[resource release];
return fragment;
}
+ if (pboardType == NSPDFPboardType) {
+ WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSPDFPboardType]
+ URL:uniqueURLWithRelativePart(@"application.pdf")
+ MIMEType:@"application/pdf"
+ textEncodingName:nil
+ frameName:nil];
+ DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
+ [resource release];
+ return fragment;
+ }
#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
if (pboardType == NSPICTPboardType) {
WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSPICTPboardType]
@@ -2173,23 +2197,14 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
@end
-@interface NSString (WebHTMLViewFileInternal)
-- (BOOL)matchesExtensionEquivalent:(NSString *)extension;
-@end
-
-@implementation NSString (WebHTMLViewFileInternal)
-
-- (BOOL)matchesExtensionEquivalent:(NSString *)extension
+static bool matchesExtensionOrEquivalent(NSString *filename, NSString *extension)
{
- if ([self hasSuffix:extension])
- return YES;
- else if ([extension isEqualToString:@"jpeg"] && [self hasSuffix:@"jpg"])
- return YES;
- return NO;
+ NSString *extensionAsSuffix = [@"." stringByAppendingString:extension];
+ return [filename _webkit_hasCaseInsensitiveSuffix:extensionAsSuffix]
+ || ([extension _webkit_isCaseInsensitiveEqualToString:@"jpeg"]
+ && [filename _webkit_hasCaseInsensitiveSuffix:@".jpg"]);
}
-@end
-
#ifdef BUILDING_ON_TIGER
// The following is a workaround for
@@ -2245,7 +2260,6 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info)
_private = [[WebHTMLViewPrivate alloc] init];
_private->pluginController = [[WebPluginController alloc] initWithDocumentView:self];
- _private->needsLayout = YES;
return self;
}
@@ -2637,6 +2651,58 @@ WEBCORE_COMMAND(yankAndSelect)
return YES;
}
#endif
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ if (action == @selector(orderFrontSubstitutionsPanel:)) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ if ([menuItem isKindOfClass:[NSMenuItem class]]) {
+ BOOL panelShowing = [[[NSSpellChecker sharedSpellChecker] substitutionsPanel] isVisible];
+ [menuItem setTitle:panelShowing
+ ? UI_STRING("Hide Substitutions", "menu item title")
+ : UI_STRING("Show Substitutions", "menu item title")];
+ }
+ return [self _canEdit];
+ }
+ // FIXME 4799134: WebView is the bottleneck for this logic, but we must validate
+ // the selector here because we implement it here, and we must implement it here because the AppKit
+ // code checks the first responder.
+ if (action == @selector(toggleSmartInsertDelete:)) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ if ([menuItem isKindOfClass:[NSMenuItem class]])
+ [menuItem setState:[self smartInsertDeleteEnabled] ? NSOnState : NSOffState];
+ return [self _canEdit];
+ }
+ if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ if ([menuItem isKindOfClass:[NSMenuItem class]])
+ [menuItem setState:[self isAutomaticQuoteSubstitutionEnabled] ? NSOnState : NSOffState];
+ return [self _canEdit];
+ }
+ if (action == @selector(toggleAutomaticLinkDetection:)) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ if ([menuItem isKindOfClass:[NSMenuItem class]])
+ [menuItem setState:[self isAutomaticLinkDetectionEnabled] ? NSOnState : NSOffState];
+ return [self _canEdit];
+ }
+ if (action == @selector(toggleAutomaticDashSubstitution:)) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ if ([menuItem isKindOfClass:[NSMenuItem class]])
+ [menuItem setState:[self isAutomaticDashSubstitutionEnabled] ? NSOnState : NSOffState];
+ return [self _canEdit];
+ }
+ if (action == @selector(toggleAutomaticTextReplacement:)) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ if ([menuItem isKindOfClass:[NSMenuItem class]])
+ [menuItem setState:[self isAutomaticTextReplacementEnabled] ? NSOnState : NSOffState];
+ return [self _canEdit];
+ }
+ if (action == @selector(toggleAutomaticSpellingCorrection:)) {
+ NSMenuItem *menuItem = (NSMenuItem *)item;
+ if ([menuItem isKindOfClass:[NSMenuItem class]])
+ [menuItem setState:[self isAutomaticSpellingCorrectionEnabled] ? NSOnState : NSOffState];
+ return [self _canEdit];
+ }
+#endif
Editor::Command command = [self coreCommandBySelector:action];
if (command.isSupported()) {
@@ -2745,14 +2811,6 @@ WEBCORE_COMMAND(yankAndSelect)
- (void)addSuperviewObservers
{
- // We watch the bounds of our superview, so that we can do a layout when the size
- // of the superview changes. This is different from other scrollable things that don't
- // need this kind of thing because their layout doesn't change.
-
- // We need to pay attention to both height and width because our "layout" has to change
- // to extend the background the full height of the space and because some elements have
- // sizes that are based on the total size of the view.
-
if (_private->observingSuperviewNotifications)
return;
@@ -2765,7 +2823,7 @@ WEBCORE_COMMAND(yankAndSelect)
[notificationCenter addObserver:self selector:@selector(_frameOrBoundsChanged) name:NSViewBoundsDidChangeNotification object:superview];
// In addition to registering for frame/bounds change notifications, call -_frameOrBoundsChanged.
- // It will check the current size/scroll against the previous layout's size/scroll. We need to
+ // It will check the current scroll against the previous layout's scroll. We need to
// do this here to catch the case where the WebView is laid out at one size, removed from its
// window, resized, and inserted into another window. Our frame/bounds changed notifications
// will not be sent in that situation, since we only watch for changes while in the view hierarchy.
@@ -2787,7 +2845,6 @@ WEBCORE_COMMAND(yankAndSelect)
[notificationCenter addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:nil];
[notificationCenter addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:nil];
[notificationCenter addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:window];
- [notificationCenter addObserver:self selector:@selector(windowWillOrderOnScreen:) name:WKWindowWillOrderOnScreenNotification() object:window];
_private->observingWindowNotifications = true;
}
@@ -2803,12 +2860,6 @@ WEBCORE_COMMAND(yankAndSelect)
[self addSuperviewObservers];
}
-static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, void *info)
-{
- WebHTMLView *view = (WebHTMLView *)info;
- [view _updateFocusedAndActiveState];
-}
-
- (void)viewWillMoveToWindow:(NSWindow *)window
{
// Don't do anything if we aren't initialized. This happens
@@ -2823,7 +2874,6 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
[self _removeWindowObservers];
[self _removeSuperviewObservers];
[self _cancelUpdateMouseoverTimer];
- [self _cancelUpdateFocusedAndActiveStateTimer];
[[self _pluginController] stopAllPlugins];
}
@@ -2844,19 +2894,6 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
[self addSuperviewObservers];
[self addMouseMovedObserver];
- // Schedule this update, rather than making the call right now.
- // The reason is that placing the caret in the just-installed view requires
- // the HTML/XML document to be available on the WebCore side, but it is not
- // at the time this code is running. However, it will be there on the next
- // crank of the run loop. Doing this helps to make a blinking caret appear
- // in a new, empty window "automatic".
- if (!_private->updateFocusedAndActiveStateTimer) {
- CFRunLoopTimerContext context = { 0, self, NULL, NULL, NULL };
- _private->updateFocusedAndActiveStateTimer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 0, 0, 0,
- _updateFocusedAndActiveStateTimerCallback, &context);
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), _private->updateFocusedAndActiveStateTimer, kCFRunLoopDefaultMode);
- }
-
[[self _pluginController] startAllPlugins];
_private->lastScrollPosition = NSZeroPoint;
@@ -2921,7 +2958,7 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
{
[self reapplyStyles];
- if (!_private->needsLayout && ![[self _frame] _needsLayout])
+ if (![self _needsLayout])
return;
#ifdef LOG_TIMES
@@ -2931,10 +2968,8 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
LOG(View, "%@ doing layout", self);
Frame* coreFrame = core([self _frame]);
- if (!coreFrame) {
- _private->needsLayout = NO;
+ if (!coreFrame)
return;
- }
if (FrameView* coreView = coreFrame->view()) {
if (minPageWidth > 0.0)
@@ -2945,11 +2980,7 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
coreView->adjustViewSize();
}
}
- _private->needsLayout = NO;
- if (!_private->printing)
- _private->lastLayoutSize = [(NSClipView *)[self superview] documentVisibleRect].size;
-
#ifdef LOG_TIMES
double thisTime = CFAbsoluteTimeGetCurrent() - start;
LOG(Timing, "%s layout seconds = %f", [self URL], thisTime);
@@ -2964,49 +2995,64 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
// Deliver mouseup events to the DOM for button 2.
- (void)rightMouseUp:(NSEvent *)event
{
+ // There's a chance that if we run a nested event loop the event will be released.
+ // Retaining and then autoreleasing prevents that from causing a problem later here or
+ // inside AppKit code.
+ [[event retain] autorelease];
+
[super rightMouseUp:event];
+
if (Frame* coreframe = core([self _frame]))
coreframe->eventHandler()->mouseUp(event);
}
- (NSMenu *)menuForEvent:(NSEvent *)event
{
- [_private->compController endRevertingChange:NO moveLeft:NO];
+ // There's a chance that if we run a nested event loop the event will be released.
+ // Retaining and then autoreleasing prevents that from causing a problem later here or
+ // inside AppKit code.
+ [[event retain] autorelease];
- _private->handlingMouseDownEvent = YES;
- BOOL handledEvent = NO;
- Frame* coreFrame = core([self _frame]);
+ [_private->completionController endRevertingChange:NO moveLeft:NO];
- if (!coreFrame) {
- _private->handlingMouseDownEvent = NO;
+ RefPtr<Frame> coreFrame = core([self _frame]);
+ if (!coreFrame)
return nil;
- }
Page* page = coreFrame->page();
if (!page)
return nil;
+ // Match behavior of other browsers by sending a mousedown event for right clicks.
+ _private->handlingMouseDownEvent = YES;
page->contextMenuController()->clearContextMenu();
- // Match behavior of other browsers by sending an onmousedown event for right clicks.
coreFrame->eventHandler()->mouseDown(event);
- handledEvent = coreFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event));
+ BOOL handledEvent = coreFrame->eventHandler()->sendContextMenuEvent(event);
_private->handlingMouseDownEvent = NO;
if (!handledEvent)
return nil;
+ // Re-get page, since it might have gone away during event handling.
+ page = coreFrame->page();
+ if (!page)
+ return nil;
+
ContextMenu* coreMenu = page->contextMenuController()->contextMenu();
if (!coreMenu)
return nil;
NSArray* menuItems = coreMenu->platformDescription();
- NSMenu* menu = nil;
- if (menuItems && [menuItems count] > 0) {
- menu = [[[NSMenu alloc] init] autorelease];
- for (unsigned i = 0; i < [menuItems count]; i++)
- [menu addItem:[menuItems objectAtIndex:i]];
- }
+ if (!menuItems)
+ return nil;
+ NSUInteger count = [menuItems count];
+ if (!count)
+ return nil;
+
+ NSMenu* menu = [[[NSMenu alloc] init] autorelease];
+ for (NSUInteger i = 0; i < count; i++)
+ [menu addItem:[menuItems objectAtIndex:i]];
return menu;
}
@@ -3041,7 +3087,14 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
- (void)setNeedsLayout: (BOOL)flag
{
LOG(View, "%@ setNeedsLayout:%@", self, flag ? @"YES" : @"NO");
- _private->needsLayout = flag;
+ if (!flag)
+ return; // There's no way to say you don't need a layout.
+ if (Frame* frame = core([self _frame])) {
+ if (frame->document() && frame->document()->inPageCache())
+ return;
+ if (FrameView* view = frame->view())
+ view->setNeedsLayout();
+ }
}
- (void)setNeedsToApplyStyles: (BOOL)flag
@@ -3123,9 +3176,13 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
#if USE(ACCELERATED_COMPOSITING)
if ([[self _webView] _needsOneShotDrawingSynchronization]) {
- // Disable screen updates so that drawing into the NSView and
- // CALayer updates appear on the screen at the same time.
+ // Disable screen updates so that any layer changes committed here
+ // don't show up on the screen before the window flush at the end
+ // of the current window display.
[[self window] disableScreenUpdatesUntilFlush];
+
+ // Make sure any layer changes that happened as a result of layout
+ // via -viewWillDraw are committed.
[CATransaction flush];
[[self _webView] _setNeedsOneShotDrawingSynchronization:NO];
}
@@ -3159,47 +3216,54 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
- (void)windowDidBecomeKey:(NSNotification *)notification
{
+ if (!pthread_main_np()) {
+ [self performSelectorOnMainThread:_cmd withObject:notification waitUntilDone:NO];
+ return;
+ }
+
NSWindow *keyWindow = [notification object];
if (keyWindow == [self window])
[self addMouseMovedObserver];
-
- if (keyWindow == [self window] || keyWindow == [[self window] attachedSheet])
- [self _updateFocusedAndActiveState];
}
- (void)windowDidResignKey:(NSNotification *)notification
{
+ if (!pthread_main_np()) {
+ [self performSelectorOnMainThread:_cmd withObject:notification waitUntilDone:NO];
+ return;
+ }
+
NSWindow *formerKeyWindow = [notification object];
if (formerKeyWindow == [self window])
[self removeMouseMovedObserver];
- if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet]) {
- [self _updateFocusedAndActiveState];
- [_private->compController endRevertingChange:NO moveLeft:NO];
- }
+ if (formerKeyWindow == [self window] || formerKeyWindow == [[self window] attachedSheet])
+ [_private->completionController endRevertingChange:NO moveLeft:NO];
}
- (void)windowWillClose:(NSNotification *)notification
{
- [_private->compController endRevertingChange:NO moveLeft:NO];
- [[self _pluginController] destroyAllPlugins];
-}
+ if (!pthread_main_np()) {
+ [self performSelectorOnMainThread:_cmd withObject:notification waitUntilDone:NO];
+ return;
+ }
-- (void)windowWillOrderOnScreen:(NSNotification *)notification
-{
- if (![[self _webView] shouldUpdateWhileOffscreen])
- [self setNeedsDisplay:YES];
+ [_private->completionController endRevertingChange:NO moveLeft:NO];
+ [[self _pluginController] destroyAllPlugins];
}
- (void)scrollWheel:(NSEvent *)event
{
- [self retain];
+ // 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];
+
Frame* frame = core([self _frame]);
if (!frame || !frame->eventHandler()->wheelEvent(event))
[super scrollWheel:event];
- [self release];
}
- (BOOL)_isSelectionEvent:(NSEvent *)event
@@ -3210,6 +3274,11 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
- (BOOL)acceptsFirstMouse:(NSEvent *)event
{
+ // 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];
+
NSView *hitView = [self _hitViewForEvent:event];
WebHTMLView *hitHTMLView = [hitView isKindOfClass:[self class]] ? (WebHTMLView *)hitView : nil;
@@ -3234,16 +3303,22 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)event
{
+ // 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];
+
NSView *hitView = [self _hitViewForEvent:event];
WebHTMLView *hitHTMLView = [hitView isKindOfClass:[self class]] ? (WebHTMLView *)hitView : nil;
if (hitHTMLView) {
bool result = false;
- if ([hitHTMLView _isSelectionEvent:event])
+ if ([hitHTMLView _isSelectionEvent:event]) {
if (Frame* coreFrame = core([hitHTMLView _frame])) {
[hitHTMLView _setMouseDownEvent:event];
result = coreFrame->eventHandler()->eventMayStartDrag(event);
[hitHTMLView _setMouseDownEvent:nil];
}
+ }
return result;
}
return [hitView shouldDelayWindowOrderingForEvent:event];
@@ -3251,6 +3326,11 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
- (void)mouseDown:(NSEvent *)event
{
+ // 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<WebHTMLView> protector = self;
if ([[self inputContext] wantsToHandleMouseEvents] && [[self inputContext] handleMouseEvent:event])
return;
@@ -3264,7 +3344,7 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v
if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:event])
goto done;
- [_private->compController endRevertingChange:NO moveLeft:NO];
+ [_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.
@@ -3298,15 +3378,23 @@ done:
- (void)mouseDragged:(NSEvent *)event
{
+ // 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];
+
NSInputManager *currentInputManager = [NSInputManager currentInputManager];
if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:event])
return;
[self retain];
- if (!_private->ignoringMouseDraggedEvents)
- if (Frame* coreframe = core([self _frame]))
- coreframe->eventHandler()->mouseDragged(event);
+ if (!_private->ignoringMouseDraggedEvents) {
+ if (Frame* frame = core([self _frame])) {
+ if (Page* page = frame->page())
+ page->mainFrame()->eventHandler()->mouseDragged(event);
+ }
+ }
[self release];
}
@@ -3315,15 +3403,15 @@ done:
{
ASSERT(![self _webView] || [self _isTopHTMLView]);
- Page *page = core([self _webView]);
-
+ Page* page = core([self _webView]);
if (!page)
return NSDragOperationNone;
-
- if (page->dragController()->dragOperation() == DragOperationNone)
+
+ // FIXME: Why do we override the source provided operation here? Why not in DragController::startDrag
+ if (page->dragController()->sourceDragOperation() == DragOperationNone)
return NSDragOperationGeneric | NSDragOperationCopy;
-
- return (NSDragOperation)page->dragController()->dragOperation();
+
+ return (NSDragOperation)page->dragController()->sourceDragOperation();
}
- (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenLoc
@@ -3388,7 +3476,7 @@ done:
wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease];
NSString* filename = [response suggestedFilename];
NSString* trueExtension(tiffResource->image()->filenameExtension());
- if (![filename matchesExtensionEquivalent:trueExtension])
+ if (!matchesExtensionOrEquivalent(filename, trueExtension))
filename = [[filename stringByAppendingString:@"."] stringByAppendingString:trueExtension];
[wrapper setPreferredFilename:filename];
}
@@ -3431,6 +3519,11 @@ noPromisedData:
- (void)mouseUp:(NSEvent *)event
{
+ // 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];
@@ -3440,8 +3533,10 @@ noPromisedData:
[self retain];
[self _stopAutoscrollTimer];
- if (Frame* coreframe = core([self _frame]))
- coreframe->eventHandler()->mouseUp(event);
+ if (Frame* frame = core([self _frame])) {
+ if (Page* page = frame->page())
+ page->mainFrame()->eventHandler()->mouseUp(event);
+ }
[self _updateMouseoverWithFakeEvent];
[self release];
@@ -3459,29 +3554,50 @@ noPromisedData:
return YES;
}
+// Utility function to make sure we don't return anything through the NSTextInput
+// API when an editable region is not currently focused.
+static BOOL isTextInput(Frame* coreFrame)
+{
+ return coreFrame && !coreFrame->selection()->isNone() && coreFrame->selection()->isContentEditable();
+}
+
+static BOOL isInPasswordField(Frame* coreFrame)
+{
+ return coreFrame && coreFrame->selection()->isInPasswordField();
+}
+
- (BOOL)becomeFirstResponder
{
NSSelectionDirection direction = NSDirectSelection;
if (![[self _webView] _isPerformingProgrammaticFocus])
direction = [[self window] keyViewSelectionDirection];
- [self _updateFocusedAndActiveState];
[self _updateFontPanel];
Frame* frame = core([self _frame]);
if (!frame)
return YES;
-
- frame->editor()->setStartNewKillRingSequence(true);
- if (direction == NSDirectSelection)
- return YES;
+ BOOL exposeInputContext = isTextInput(frame) && !isInPasswordField(frame);
+ if (exposeInputContext != _private->exposeInputContext) {
+ _private->exposeInputContext = exposeInputContext;
+ [NSApp updateWindows];
+ }
+
+ frame->editor()->setStartNewKillRingSequence(true);
Page* page = frame->page();
if (!page)
return YES;
- page->focusController()->setFocusedFrame(frame);
+ if (![[self _webView] _isPerformingProgrammaticFocus])
+ page->focusController()->setFocusedFrame(frame);
+
+ page->focusController()->setFocused(true);
+
+ if (direction == NSDirectSelection)
+ return YES;
+
if (Document* document = frame->document())
document->setFocusedNode(0);
page->focusController()->setInitialFocus(direction == NSSelectingNext ? FocusDirectionForward : FocusDirectionBackward,
@@ -3493,15 +3609,24 @@ noPromisedData:
{
BOOL resign = [super resignFirstResponder];
if (resign) {
- _private->resigningFirstResponder = YES;
- [_private->compController endRevertingChange:NO moveLeft:NO];
+ [_private->completionController endRevertingChange:NO moveLeft:NO];
+ Frame* coreFrame = core([self _frame]);
+ if (!coreFrame)
+ return resign;
+ Page* page = coreFrame->page();
+ if (!page)
+ return resign;
if (![self maintainsInactiveSelection]) {
[self deselectAll];
if (![[self _webView] _isPerformingProgrammaticFocus])
[self clearFocus];
}
- [self _updateFocusedAndActiveState];
- _private->resigningFirstResponder = NO;
+
+ id nextResponder = [[self window] _newFirstResponderAfterResigning];
+ bool nextResponderIsInWebView = [nextResponder isKindOfClass:[NSView class]]
+ && [nextResponder isDescendantOf:[[[self _webView] mainFrame] frameView]];
+ if (!nextResponderIsInWebView)
+ page->focusController()->setFocused(false);
}
return resign;
}
@@ -3582,8 +3707,10 @@ noPromisedData:
[self _setPrinting:YES minimumPageWidth:0.0f maximumPageWidth:0.0f adjustViewSize:NO];
float newBottomFloat = *newBottom;
- if (FrameView* view = core([self _frame])->view())
- view->adjustPageHeight(&newBottomFloat, oldTop, oldBottom, bottomLimit);
+ if (Frame* frame = core([self _frame])) {
+ if (FrameView* view = frame->view())
+ view->adjustPageHeight(&newBottomFloat, oldTop, oldBottom, bottomLimit);
+ }
#ifdef __LP64__
// If the new bottom is equal to the old bottom (when both are treated as floats), we just copy
@@ -3781,6 +3908,11 @@ noPromisedData:
- (void)keyDown:(NSEvent *)event
{
+ // 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<WebHTMLView> selfProtector = self;
BOOL eventWasSentToWebCore = (_private->keyDownEvent == event);
@@ -3789,15 +3921,15 @@ noPromisedData:
[_private->keyDownEvent release];
_private->keyDownEvent = [event retain];
- BOOL completionPopupWasOpen = _private->compController && [_private->compController popupWindowIsOpen];
+ BOOL completionPopupWasOpen = _private->completionController && [_private->completionController popupWindowIsOpen];
Frame* coreFrame = core([self _frame]);
if (!eventWasSentToWebCore && coreFrame && coreFrame->eventHandler()->keyEvent(event)) {
// WebCore processed a key event, bail on any preexisting complete: UI
if (completionPopupWasOpen)
- [_private->compController endRevertingChange:YES moveLeft:NO];
- } else if (!_private->compController || ![_private->compController filterKeyDown:event]) {
+ [_private->completionController endRevertingChange:YES moveLeft:NO];
+ } else if (!_private->completionController || ![_private->completionController filterKeyDown:event]) {
// Not consumed by complete: popup window
- [_private->compController endRevertingChange:YES moveLeft:NO];
+ [_private->completionController endRevertingChange:YES moveLeft:NO];
callSuper = YES;
}
if (callSuper)
@@ -3808,6 +3940,11 @@ noPromisedData:
- (void)keyUp:(NSEvent *)event
{
+ // 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];
+
BOOL eventWasSentToWebCore = (_private->keyDownEvent == event);
RetainPtr<WebHTMLView> selfProtector = self;
@@ -3820,6 +3957,11 @@ noPromisedData:
- (void)flagsChanged:(NSEvent *)event
{
+ // 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];
+
Frame* coreFrame = core([self _frame]);
if (coreFrame)
coreFrame->eventHandler()->capsLockStateMayHaveChanged();
@@ -4052,6 +4194,11 @@ noPromisedData:
- (BOOL)performKeyEquivalent:(NSEvent *)event
{
+ // 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];
+
if ([self _handleStyleKeyEquivalent:event])
return YES;
@@ -4144,6 +4291,8 @@ noPromisedData:
BOOL aIsItalic = ([fm traitsOfFont:a] & NSItalicFontMask) != 0;
BOOL bIsItalic = ([fm traitsOfFont:b] & NSItalicFontMask) != 0;
+ BOOL aIsBold = aWeight > MIN_BOLD_WEIGHT;
+
if ([aFamilyName isEqualToString:bFamilyName]) {
NSString *familyNameForCSS = aFamilyName;
@@ -4153,7 +4302,8 @@ noPromisedData:
// Find the font the same way the rendering code would later if it encountered this CSS.
NSFontTraitMask traits = aIsItalic ? NSFontItalicTrait : 0;
- NSFont *foundFont = WebCoreFindFont(aFamilyName, traits, aWeight, aPointSize);
+ int weight = aIsBold ? STANDARD_BOLD_WEIGHT : STANDARD_WEIGHT;
+ NSFont *foundFont = [WebFontCache fontWithFamily:aFamilyName traits:traits weight:weight size:aPointSize];
// If we don't find a font with the same Postscript name, then we'll have to use the
// Postscript name to make the CSS specific enough.
@@ -4173,8 +4323,9 @@ noPromisedData:
else if (aPointSize > soa)
[style _setFontSizeDelta:@"1px"];
+ // FIXME: Map to the entire range of CSS weight values.
if (aWeight == bWeight)
- [style setFontWeight:aWeight > MIN_BOLD_WEIGHT ? @"bold" : @"normal"];
+ [style setFontWeight:aIsBold ? @"bold" : @"normal"];
if (aIsItalic == bIsItalic)
[style setFontStyle:aIsItalic ? @"italic" : @"normal"];
@@ -4408,9 +4559,9 @@ NSStrokeColorAttributeName /* NSColor, default nil: same as foreground co
if (![self _canEdit])
return;
- if (!_private->compController)
- _private->compController = [[WebTextCompleteController alloc] initWithHTMLView:self];
- [_private->compController doCompletion];
+ if (!_private->completionController)
+ _private->completionController = [[WebTextCompletionController alloc] initWithWebView:[self _webView] HTMLView:self];
+ [_private->completionController doCompletion];
}
- (void)checkSpelling:(id)sender
@@ -4630,7 +4781,13 @@ static BOOL writingDirectionKeyBindingsEnabled()
// support them via the key bindings mechanism.
- (BOOL)_wantsKeyDownForEvent:(NSEvent *)event
{
- return YES;
+ bool haveWebCoreFrame = core([self _frame]);
+
+ // If we have a frame, our keyDown method will handle key bindings after sending
+ // the event through the DOM, so ask AppKit not to do its early special key binding
+ // mapping. If we don't have a frame, just let things work the normal way without
+ // a keyDown.
+ return haveWebCoreFrame;
}
#else
@@ -4704,15 +4861,28 @@ static BOOL writingDirectionKeyBindingsEnabled()
#endif
+- (void)_updateControlTints
+{
+ Frame* frame = core([self _frame]);
+ if (!frame)
+ return;
+ FrameView* view = frame->view();
+ if (!view)
+ return;
+ view->updateControlTints();
+}
+
// Despite its name, this is called at different times than windowDidBecomeKey is.
// It takes into account all the other factors that determine when NSCell draws
// with different tints, so it's the right call to use for control tints. We'd prefer
// to do this with API. <rdar://problem/5136760>
- (void)_windowChangedKeyState
{
- if (Frame* frame = core([self _frame]))
- if (FrameView* view = frame->view())
- view->updateControlTints();
+ if (pthread_main_np())
+ [self _updateControlTints];
+ else
+ [self performSelectorOnMainThread:@selector(_updateControlTints) withObject:nil waitUntilDone:NO];
+
[super _windowChangedKeyState];
}
@@ -4902,6 +5072,121 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
#endif
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
+- (void)orderFrontSubstitutionsPanel:(id)sender
+{
+ COMMAND_PROLOGUE
+
+ NSSpellChecker *checker = [NSSpellChecker sharedSpellChecker];
+ if (!checker) {
+ LOG_ERROR("No NSSpellChecker");
+ return;
+ }
+
+ NSPanel *substitutionsPanel = [checker substitutionsPanel];
+ if ([substitutionsPanel isVisible]) {
+ [substitutionsPanel orderOut:sender];
+ return;
+ }
+ [substitutionsPanel orderFront:sender];
+}
+
+// FIXME 4799134: WebView is the bottleneck for this logic, but we must implement these methods here because
+// the AppKit code checks the first responder.
+
+- (BOOL)smartInsertDeleteEnabled
+{
+ return [[self _webView] smartInsertDeleteEnabled];
+}
+
+- (void)setSmartInsertDeleteEnabled:(BOOL)flag
+{
+ [[self _webView] setSmartInsertDeleteEnabled:flag];
+}
+
+- (void)toggleSmartInsertDelete:(id)sender
+{
+ [[self _webView] toggleSmartInsertDelete:sender];
+}
+
+- (BOOL)isAutomaticQuoteSubstitutionEnabled
+{
+ return [[self _webView] isAutomaticQuoteSubstitutionEnabled];
+}
+
+- (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag
+{
+ [[self _webView] setAutomaticQuoteSubstitutionEnabled:flag];
+}
+
+- (void)toggleAutomaticQuoteSubstitution:(id)sender
+{
+ [[self _webView] toggleAutomaticQuoteSubstitution:sender];
+}
+
+- (BOOL)isAutomaticLinkDetectionEnabled
+{
+ return [[self _webView] isAutomaticLinkDetectionEnabled];
+}
+
+- (void)setAutomaticLinkDetectionEnabled:(BOOL)flag
+{
+ [[self _webView] setAutomaticLinkDetectionEnabled:flag];
+}
+
+- (void)toggleAutomaticLinkDetection:(id)sender
+{
+ [[self _webView] toggleAutomaticLinkDetection:sender];
+}
+
+- (BOOL)isAutomaticDashSubstitutionEnabled
+{
+ return [[self _webView] isAutomaticDashSubstitutionEnabled];
+}
+
+- (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag
+{
+ [[self _webView] setAutomaticDashSubstitutionEnabled:flag];
+}
+
+- (void)toggleAutomaticDashSubstitution:(id)sender
+{
+ [[self _webView] toggleAutomaticDashSubstitution:sender];
+}
+
+- (BOOL)isAutomaticTextReplacementEnabled
+{
+ return [[self _webView] isAutomaticTextReplacementEnabled];
+}
+
+- (void)setAutomaticTextReplacementEnabled:(BOOL)flag
+{
+ [[self _webView] setAutomaticTextReplacementEnabled:flag];
+}
+
+- (void)toggleAutomaticTextReplacement:(id)sender
+{
+ [[self _webView] toggleAutomaticTextReplacement:sender];
+}
+
+- (BOOL)isAutomaticSpellingCorrectionEnabled
+{
+ return [[self _webView] isAutomaticSpellingCorrectionEnabled];
+}
+
+- (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag
+{
+ [[self _webView] setAutomaticSpellingCorrectionEnabled:flag];
+}
+
+- (void)toggleAutomaticSpellingCorrection:(id)sender
+{
+ [[self _webView] toggleAutomaticSpellingCorrection:sender];
+}
+
+#endif
+
- (void)_lookUpInDictionaryFromMenu:(id)sender
{
// Dictionary API will accept a whitespace-only string and display UI as if it were real text,
@@ -4929,7 +5214,6 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
return;
#endif
-
// We soft link to get the function that displays the dictionary (either pop-up window or app) to avoid the performance
// penalty of linking to another framework. This function changed signature as well as framework between Tiger and Leopard,
// so the two cases are handled separately.
@@ -5002,7 +5286,7 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
if (const PlatformKeyboardEvent* platformEvent = event->keyEvent()) {
NSEvent *macEvent = platformEvent->macEvent();
- if ([macEvent type] == NSKeyDown && [_private->compController filterKeyDown:macEvent])
+ if ([macEvent type] == NSKeyDown && [_private->completionController filterKeyDown:macEvent])
return true;
if ([macEvent type] == NSFlagsChanged)
@@ -5065,9 +5349,7 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
{
ASSERT(!_private->subviewsSetAside);
- if ([[self _frame] _needsLayout])
- _private->needsLayout = YES;
- if (_private->needsToApplyStyles || _private->needsLayout)
+ if (_private->needsToApplyStyles || [self _needsLayout])
[self layout];
}
@@ -5099,17 +5381,19 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
[[self _pluginController] destroyAllPlugins];
}
-- (BOOL)_isResigningFirstResponder
+- (BOOL)_needsLayout
{
- return _private->resigningFirstResponder;
+ return [[self _frame] _needsLayout];
}
#if USE(ACCELERATED_COMPOSITING)
- (void)attachRootLayer:(CALayer*)layer
{
if (!_private->layerHostingView) {
- WebLayerHostingView* hostingView = [[WebLayerHostingView alloc] initWithFrame:[self bounds]];
+ NSView* hostingView = [[NSView alloc] initWithFrame:[self bounds]];
+#if !defined(BUILDING_ON_LEOPARD)
[hostingView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+#endif
[self addSubview:hostingView];
[hostingView release];
// hostingView is owned by being a subview of self
@@ -5117,13 +5401,35 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
[[self _webView] _startedAcceleratedCompositingForFrame:[self _frame]];
}
- // Make a container layer, which will get sized/positioned by AppKit and CA
+ // Make a container layer, which will get sized/positioned by AppKit and CA.
CALayer* viewLayer = [CALayer layer];
+
+#if defined(BUILDING_ON_LEOPARD)
+ // Turn off default animations.
+ NSNull *nullValue = [NSNull null];
+ NSDictionary *actions = [NSDictionary dictionaryWithObjectsAndKeys:
+ nullValue, @"anchorPoint",
+ nullValue, @"bounds",
+ nullValue, @"contents",
+ nullValue, @"contentsRect",
+ nullValue, @"opacity",
+ nullValue, @"position",
+ nullValue, @"sublayerTransform",
+ nullValue, @"sublayers",
+ nullValue, @"transform",
+ nil];
+ [viewLayer setStyle:[NSDictionary dictionaryWithObject:actions forKey:@"actions"]];
+#endif
+
[_private->layerHostingView setLayer:viewLayer];
[_private->layerHostingView setWantsLayer:YES];
// Parent our root layer in the container layer
[viewLayer addSublayer:layer];
+
+#if defined(BUILDING_ON_LEOPARD)
+ [self _updateLayerHostingViewPosition];
+#endif
}
- (void)detachRootLayer
@@ -5136,7 +5442,37 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
[[self _webView] _stoppedAcceleratedCompositingForFrame:[self _frame]];
}
}
-#endif
+
+#if defined(BUILDING_ON_LEOPARD)
+// This method is necessary on Leopard to work around <rdar://problem/7067892>.
+- (void)_updateLayerHostingViewPosition
+{
+ if (!_private->layerHostingView)
+ return;
+
+ const CGFloat maxHeight = 4096;
+ NSRect layerViewFrame = [self bounds];
+
+ if (layerViewFrame.size.height > maxHeight) {
+ CGFloat documentHeight = layerViewFrame.size.height;
+
+ // Clamp the size of the view to <= 4096px to avoid the bug.
+ layerViewFrame.size.height = maxHeight;
+ NSRect visibleRect = [[self enclosingScrollView] documentVisibleRect];
+
+ // Place the top of the layer-hosting view at the top of the visibleRect.
+ CGFloat topOffset = NSMinY(visibleRect);
+ layerViewFrame.origin.y = topOffset;
+
+ // Compensate for the moved view by adjusting the sublayer transform on the view's layer (using flipped coords).
+ CGFloat bottomOffset = documentHeight - layerViewFrame.size.height - topOffset;
+ [[_private->layerHostingView layer] setSublayerTransform:CATransform3DMakeTranslation(0, -bottomOffset, 0)];
+ }
+
+ [_private->layerHostingView setFrame:layerViewFrame];
+}
+#endif // defined(BUILDING_ON_LEOPARD)
+#endif // USE(ACCELERATED_COMPOSITING)
@end
@@ -5160,22 +5496,14 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
return validAttributes;
}
-// Utility function to make sure we don't return anything through the NSTextInput
-// API when an editable region is not currently focused.
-static BOOL isTextInput(Frame* coreFrame)
-{
- return coreFrame && !coreFrame->selection()->isNone() && coreFrame->selection()->isContentEditable();
-}
-
-static BOOL isInPasswordField(Frame* coreFrame)
+- (NSTextInputContext *)inputContext
{
- return coreFrame && coreFrame->selection()->isInPasswordField();
+ return _private->exposeInputContext ? [super inputContext] : nil;
}
- (NSAttributedString *)textStorage
{
- Frame* coreFrame = core([self _frame]);
- if (!isTextInput(coreFrame) || isInPasswordField(coreFrame)) {
+ if (!_private->exposeInputContext) {
LOG(TextInput, "textStorage -> nil");
return nil;
}
@@ -5524,6 +5852,15 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
if (!coreFrame)
return;
+ BOOL exposeInputContext = isTextInput(coreFrame) && !isInPasswordField(coreFrame);
+ if (exposeInputContext != _private->exposeInputContext) {
+ _private->exposeInputContext = exposeInputContext;
+ // Let AppKit cache a potentially changed input context.
+ // WebCore routinely sets the selection to None when editing, and IMs become unhappy when an input context suddenly turns nil, see bug 26009.
+ if (!coreFrame->selection()->isNone())
+ [NSApp updateWindows];
+ }
+
if (!coreFrame->editor()->hasComposition())
return;
@@ -5542,292 +5879,6 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
@end
-/*
- This class runs the show for handing the complete: NSTextView operation. It counts on its HTML view
- to call endRevertingChange: whenever the current completion needs to be aborted.
-
- The class is in one of two modes: PopupWindow showing, or not. It is shown when a completion yields
- more than one match. If a completion yields one or zero matches, it is not shown, and **there is no
- state carried across to the next completion**.
- */
-
-@implementation WebTextCompleteController
-
-- (id)initWithHTMLView:(WebHTMLView *)view
-{
- self = [super init];
- if (!self)
- return nil;
- _view = view;
- return self;
-}
-
-- (void)dealloc
-{
- [_popupWindow release];
- [_completions release];
- [_originalString release];
-
- [super dealloc];
-}
-
-- (void)_insertMatch:(NSString *)match
-{
- // FIXME: 3769654 - We should preserve case of string being inserted, even in prefix (but then also be
- // able to revert that). Mimic NSText.
- WebFrame *frame = [_view _frame];
- NSString *newText = [match substringFromIndex:prefixLength];
- [frame _replaceSelectionWithText:newText selectReplacement:YES smartReplace:NO];
-}
-
-// mostly lifted from NSTextView_KeyBinding.m
-- (void)_buildUI
-{
- NSRect scrollFrame = NSMakeRect(0, 0, 100, 100);
- NSRect tableFrame = NSZeroRect;
- tableFrame.size = [NSScrollView contentSizeForFrameSize:scrollFrame.size hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder];
- // Added cast to work around problem with multiple Foundation initWithIdentifier: methods with different parameter types.
- NSTableColumn *column = [(NSTableColumn *)[NSTableColumn alloc] initWithIdentifier:[NSNumber numberWithInt:0]];
- [column setWidth:tableFrame.size.width];
- [column setEditable:NO];
-
- _tableView = [[NSTableView alloc] initWithFrame:tableFrame];
- [_tableView setAutoresizingMask:NSViewWidthSizable];
- [_tableView addTableColumn:column];
- [column release];
- [_tableView setGridStyleMask:NSTableViewGridNone];
- [_tableView setCornerView:nil];
- [_tableView setHeaderView:nil];
- [_tableView setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
- [_tableView setDelegate:self];
- [_tableView setDataSource:self];
- [_tableView setTarget:self];
- [_tableView setDoubleAction:@selector(tableAction:)];
-
- NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:scrollFrame];
- [scrollView setBorderType:NSNoBorder];
- [scrollView setHasVerticalScroller:YES];
- [scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- [scrollView setDocumentView:_tableView];
- [_tableView release];
-
- _popupWindow = [[NSWindow alloc] initWithContentRect:scrollFrame styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
- [_popupWindow setAlphaValue:0.88f];
- [_popupWindow setContentView:scrollView];
- [scrollView release];
- [_popupWindow setHasShadow:YES];
- [_popupWindow setOneShot:YES];
- [_popupWindow _setForceActiveControls:YES];
- [_popupWindow setReleasedWhenClosed:NO];
-}
-
-// mostly lifted from NSTextView_KeyBinding.m
-- (void)_placePopupWindow:(NSPoint)topLeft
-{
- int numberToShow = [_completions count];
- if (numberToShow > 20) {
- numberToShow = 20;
- }
-
- NSRect windowFrame;
- NSPoint wordStart = topLeft;
- windowFrame.origin = [[_view window] convertBaseToScreen:[_view convertPoint:wordStart toView:nil]];
- windowFrame.size.height = numberToShow * [_tableView rowHeight] + (numberToShow + 1) * [_tableView intercellSpacing].height;
- windowFrame.origin.y -= windowFrame.size.height;
- NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont systemFontOfSize:12.0f], NSFontAttributeName, nil];
- float maxWidth = 0.0f;
- int maxIndex = -1;
- int i;
- for (i = 0; i < numberToShow; i++) {
- float width = ceilf([[_completions objectAtIndex:i] sizeWithAttributes:attributes].width);
- if (width > maxWidth) {
- maxWidth = width;
- maxIndex = i;
- }
- }
- windowFrame.size.width = 100;
- if (maxIndex >= 0) {
- maxWidth = ceilf([NSScrollView frameSizeForContentSize:NSMakeSize(maxWidth, 100.0f) hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder].width);
- maxWidth = ceilf([NSWindow frameRectForContentRect:NSMakeRect(0.0f, 0.0f, maxWidth, 100.0f) styleMask:NSBorderlessWindowMask].size.width);
- maxWidth += 5.0f;
- windowFrame.size.width = MAX(maxWidth, windowFrame.size.width);
- maxWidth = MIN(400.0f, windowFrame.size.width);
- }
- [_popupWindow setFrame:windowFrame display:NO];
-
- [_tableView reloadData];
- [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
- [_tableView scrollRowToVisible:0];
- [self _reflectSelection];
- [_popupWindow setLevel:NSPopUpMenuWindowLevel];
- [_popupWindow orderFront:nil];
- [[_view window] addChildWindow:_popupWindow ordered:NSWindowAbove];
-}
-
-- (void)doCompletion
-{
- if (!_popupWindow) {
- NSSpellChecker *checker = [NSSpellChecker sharedSpellChecker];
- if (!checker) {
- LOG_ERROR("No NSSpellChecker");
- return;
- }
-
- // Get preceeding word stem
- WebFrame *frame = [_view _frame];
- DOMRange *selection = kit(core(frame)->selection()->toNormalizedRange().get());
- DOMRange *wholeWord = [frame _rangeByAlteringCurrentSelection:SelectionController::EXTEND
- direction:SelectionController::BACKWARD granularity:WordGranularity];
- DOMRange *prefix = [wholeWord cloneRange];
- [prefix setEnd:[selection startContainer] offset:[selection startOffset]];
-
- // Reject some NOP cases
- if ([prefix collapsed]) {
- NSBeep();
- return;
- }
- NSString *prefixStr = [frame _stringForRange:prefix];
- NSString *trimmedPrefix = [prefixStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
- if ([trimmedPrefix length] == 0) {
- NSBeep();
- return;
- }
- prefixLength = [prefixStr length];
-
- // Lookup matches
- [_completions release];
- _completions = [checker completionsForPartialWordRange:NSMakeRange(0, [prefixStr length]) inString:prefixStr language:nil inSpellDocumentWithTag:[[_view _webView] spellCheckerDocumentTag]];
- [_completions retain];
-
- if (!_completions || [_completions count] == 0) {
- NSBeep();
- } else if ([_completions count] == 1) {
- [self _insertMatch:[_completions objectAtIndex:0]];
- } else {
- ASSERT(!_originalString); // this should only be set IFF we have a popup window
- _originalString = [[frame _stringForRange:selection] retain];
- [self _buildUI];
- NSRect wordRect = [frame _caretRectAtNode:[wholeWord startContainer] offset:[wholeWord startOffset] affinity:NSSelectionAffinityDownstream];
- // +1 to be under the word, not the caret
- // FIXME - 3769652 - Wrong positioning for right to left languages. We should line up the upper
- // right corner with the caret instead of upper left, and the +1 would be a -1.
- NSPoint wordLowerLeft = { NSMinX(wordRect)+1, NSMaxY(wordRect) };
- [self _placePopupWindow:wordLowerLeft];
- }
- } else {
- [self endRevertingChange:YES moveLeft:NO];
- }
-}
-
-- (void)endRevertingChange:(BOOL)revertChange moveLeft:(BOOL)goLeft
-{
- if (_popupWindow) {
- // tear down UI
- [[_view window] removeChildWindow:_popupWindow];
- [_popupWindow orderOut:self];
- // Must autorelease because event tracking code may be on the stack touching UI
- [_popupWindow autorelease];
- _popupWindow = nil;
-
- if (revertChange) {
- WebFrame *frame = [_view _frame];
- [frame _replaceSelectionWithText:_originalString selectReplacement:YES smartReplace:NO];
- } else if ([_view _hasSelection]) {
- if (goLeft)
- [_view moveBackward:nil];
- else
- [_view moveForward:nil];
- }
- [_originalString release];
- _originalString = nil;
- }
- // else there is no state to abort if the window was not up
-}
-
-- (BOOL)popupWindowIsOpen
-{
- return _popupWindow != nil;
-}
-
-// WebHTMLView gives us a crack at key events it sees. Return whether we consumed the event.
-// The features for the various keys mimic NSTextView.
-- (BOOL)filterKeyDown:(NSEvent *)event
-{
- if (!_popupWindow)
- return NO;
- NSString *string = [event charactersIgnoringModifiers];
- if (![string length])
- return NO;
- unichar c = [string characterAtIndex:0];
- if (c == NSUpArrowFunctionKey) {
- int selectedRow = [_tableView selectedRow];
- if (0 < selectedRow) {
- [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow - 1] byExtendingSelection:NO];
- [_tableView scrollRowToVisible:selectedRow - 1];
- }
- return YES;
- }
- if (c == NSDownArrowFunctionKey) {
- int selectedRow = [_tableView selectedRow];
- if (selectedRow < (int)[_completions count] - 1) {
- [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow + 1] byExtendingSelection:NO];
- [_tableView scrollRowToVisible:selectedRow + 1];
- }
- return YES;
- }
- if (c == NSRightArrowFunctionKey || c == '\n' || c == '\r' || c == '\t') {
- // FIXME: What about backtab?
- [self endRevertingChange:NO moveLeft:NO];
- return YES;
- }
- if (c == NSLeftArrowFunctionKey) {
- [self endRevertingChange:NO moveLeft:YES];
- return YES;
- }
- if (c == 0x1B || c == NSF5FunctionKey) {
- // FIXME: F5?
- [self endRevertingChange:YES moveLeft:NO];
- return YES;
- }
- if (c == ' ' || c >= 0x21 && c <= 0x2F || c >= 0x3A && c <= 0x40 || c >= 0x5B && c <= 0x60 || c >= 0x7B && c <= 0x7D) {
- // FIXME: Is the above list of keys really definitive?
- // Originally this code called ispunct; aren't there other punctuation keys on international keyboards?
- [self endRevertingChange:NO moveLeft:NO];
- return NO; // let the char get inserted
- }
- return NO;
-}
-
-- (void)_reflectSelection
-{
- int selectedRow = [_tableView selectedRow];
- ASSERT(selectedRow >= 0 && selectedRow < (int)[_completions count]);
- [self _insertMatch:[_completions objectAtIndex:selectedRow]];
-}
-
-- (void)tableAction:(id)sender
-{
- [self _reflectSelection];
- [self endRevertingChange:NO moveLeft:NO];
-}
-
-- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
-{
- return [_completions count];
-}
-
-- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
-{
- return [_completions objectAtIndex:row];
-}
-
-- (void)tableViewSelectionDidChange:(NSNotification *)notification
-{
- [self _reflectSelection];
-}
-
-@end
-
@implementation WebHTMLView (WebDocumentPrivateProtocols)
- (NSRect)selectionRect
@@ -6082,4 +6133,10 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
_receivedUnhandledCommand = YES;
}
+- (BOOL)tryToPerform:(SEL)action with:(id)object
+{
+ _receivedUnhandledCommand = YES;
+ return YES;
+}
+
@end
diff --git a/WebKit/mac/WebView/WebHTMLViewInternal.h b/WebKit/mac/WebView/WebHTMLViewInternal.h
index a32df02..b5ec1c0 100644
--- a/WebKit/mac/WebView/WebHTMLViewInternal.h
+++ b/WebKit/mac/WebView/WebHTMLViewInternal.h
@@ -58,11 +58,15 @@ namespace WebCore {
- (void)setPromisedDragTIFFDataSource:(WebCore::CachedImage*)source;
- (void)_web_layoutIfNeededRecursive;
- (void)_destroyAllWebPlugins;
-- (BOOL)_isResigningFirstResponder;
+- (BOOL)_needsLayout;
#if USE(ACCELERATED_COMPOSITING)
- (void)attachRootLayer:(CALayer*)layer;
- (void)detachRootLayer;
#endif
+#if USE(ACCELERATED_COMPOSITING) && defined(BUILDING_ON_LEOPARD)
+- (void)_updateLayerHostingViewPosition;
+#endif
+
@end
diff --git a/WebKit/mac/WebView/WebHTMLViewPrivate.h b/WebKit/mac/WebView/WebHTMLViewPrivate.h
index 0d73884..bb59a7b 100644
--- a/WebKit/mac/WebView/WebHTMLViewPrivate.h
+++ b/WebKit/mac/WebView/WebHTMLViewPrivate.h
@@ -118,7 +118,6 @@
#endif
// SPI for DumpRenderTree
-- (void)_updateFocusedAndActiveState;
- (BOOL)_isUsingAcceleratedCompositing;
// SPI for printing (should be converted to API someday). When the WebHTMLView isn't being printed
diff --git a/WebKit/mac/WebView/WebPDFView.h b/WebKit/mac/WebView/WebPDFView.h
index 55d2a08..bdd2a6e 100644
--- a/WebKit/mac/WebView/WebPDFView.h
+++ b/WebKit/mac/WebView/WebPDFView.h
@@ -37,7 +37,7 @@
NSView *previewView;
PDFView *PDFSubview;
NSString *path;
- id trackedFirstResponder;
+ BOOL firstResponderIsPDFDocumentView;
BOOL written;
BOOL _ignoreScaleAndDisplayModeAndPageNotifications;
BOOL _willUpdatePreferencesSoon;
diff --git a/WebKit/mac/WebView/WebPDFView.mm b/WebKit/mac/WebView/WebPDFView.mm
index 0c872b9..dea3819 100644
--- a/WebKit/mac/WebView/WebPDFView.mm
+++ b/WebKit/mac/WebView/WebPDFView.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
#import "WebPDFView.h"
#import "WebDataSourceInternal.h"
+#import "WebDelegateImplementationCaching.h"
#import "WebDocumentInternal.h"
#import "WebDocumentPrivate.h"
#import "WebFrame.h"
@@ -47,13 +48,16 @@
#import "WebViewInternal.h"
#import <PDFKit/PDFKit.h>
#import <WebCore/EventNames.h>
+#import <WebCore/FormState.h>
#import <WebCore/Frame.h>
-#import <WebCore/FrameLoader.h>
#import <WebCore/FrameLoadRequest.h>
+#import <WebCore/FrameLoader.h>
+#import <WebCore/HTMLFormElement.h>
#import <WebCore/KURL.h>
#import <WebCore/KeyboardEvent.h>
#import <WebCore/MouseEvent.h>
#import <WebCore/PlatformKeyboardEvent.h>
+#import <WebCore/RuntimeApplicationChecks.h>
#import <wtf/Assertions.h>
using namespace WebCore;
@@ -182,7 +186,6 @@ static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selec
- (void)dealloc
{
- ASSERT(!trackedFirstResponder);
[dataSource release];
[previewView release];
[PDFSubview release];
@@ -373,7 +376,7 @@ static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selec
// (1) the symptom is fairly minor, and (2) we suspect that non-Safari clients are probably using the entire
// set of default items, rather than manually choosing from them. We can remove this code entirely when we
// ship a version of Safari that includes the fix for radar 3796579.
- if (![self _anyPDFTagsFoundInMenu:menu] && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"]) {
+ if (![self _anyPDFTagsFoundInMenu:menu] && applicationIsSafari()) {
[menu addItem:[NSMenuItem separatorItem]];
NSEnumerator *e = [items objectEnumerator];
NSMenuItem *menuItem;
@@ -468,8 +471,7 @@ static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selec
name:NSViewBoundsDidChangeNotification
object:[self _clipViewForPDFDocumentView]];
- [trackedFirstResponder release];
- trackedFirstResponder = nil;
+ firstResponderIsPDFDocumentView = NO;
}
#pragma mark NSUserInterfaceValidations PROTOCOL IMPLEMENTATION
@@ -941,16 +943,17 @@ static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selec
default:
break;
}
- if (button != noButton)
+ if (button != noButton) {
event = MouseEvent::create(eventNames().clickEvent, true, true, 0, [nsEvent clickCount], 0, 0, 0, 0,
[nsEvent modifierFlags] & NSControlKeyMask,
[nsEvent modifierFlags] & NSAlternateKeyMask,
[nsEvent modifierFlags] & NSShiftKeyMask,
[nsEvent modifierFlags] & NSCommandKeyMask,
button, 0, 0, true);
+ }
// Call to the frame loader because this is where our security checks are made.
- core([dataSource webFrame])->loader()->loadFrameRequestWithFormAndValues(ResourceRequest(URL), false, false, event.get(), 0, HashMap<String, String>());
+ core([dataSource webFrame])->loader()->loadFrameRequest(ResourceRequest(URL), false, false, event.get(), 0);
}
- (void)PDFViewOpenPDFInNativeApplication:(PDFView *)sender
@@ -1385,20 +1388,17 @@ static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selec
- (void)_trackFirstResponder
{
ASSERT([self window]);
-
- id newFirstResponder = [[self window] firstResponder];
- if (newFirstResponder == trackedFirstResponder)
+ BOOL newFirstResponderIsPDFDocumentView = [[self window] firstResponder] == [PDFSubview documentView];
+ if (newFirstResponderIsPDFDocumentView == firstResponderIsPDFDocumentView)
return;
// This next clause is the entire purpose of _trackFirstResponder. In other WebDocument
// view classes this is done in a resignFirstResponder override, but in this case the
// first responder view is a PDFKit class that we can't subclass.
- if (trackedFirstResponder == [PDFSubview documentView] && ![[dataSource _webView] maintainsInactiveSelection])
+ if (newFirstResponderIsPDFDocumentView && ![[dataSource _webView] maintainsInactiveSelection])
[self deselectAll];
-
- [trackedFirstResponder release];
- trackedFirstResponder = [newFirstResponder retain];
+ firstResponderIsPDFDocumentView = newFirstResponderIsPDFDocumentView;
}
- (void)_updatePreferences:(WebPreferences *)prefs
diff --git a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h
index e22113c..6565c09 100644
--- a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h
+++ b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h
@@ -61,8 +61,14 @@
#define WebKitBackForwardCacheExpirationIntervalKey @"WebKitBackForwardCacheExpirationIntervalKey"
#define WebKitTabToLinksPreferenceKey @"WebKitTabToLinksPreferenceKey"
#define WebKitPrivateBrowsingEnabledPreferenceKey @"WebKitPrivateBrowsingEnabled"
+#define WebSmartInsertDeleteEnabled @"WebSmartInsertDeleteEnabled"
#define WebContinuousSpellCheckingEnabled @"WebContinuousSpellCheckingEnabled"
#define WebGrammarCheckingEnabled @"WebGrammarCheckingEnabled"
+#define WebAutomaticQuoteSubstitutionEnabled @"WebAutomaticQuoteSubstitutionEnabled"
+#define WebAutomaticLinkDetectionEnabled @"WebAutomaticLinkDetectionEnabled"
+#define WebAutomaticDashSubstitutionEnabled @"WebAutomaticDashSubstitutionEnabled"
+#define WebAutomaticTextReplacementEnabled @"WebAutomaticTextReplacementEnabled"
+#define WebAutomaticSpellingCorrectionEnabled @"WebAutomaticSpellingCorrectionEnabled"
#define WebKitDOMPasteAllowedPreferenceKey @"WebKitDOMPasteAllowedPreferenceKey"
#define WebKitUsesPageCachePreferenceKey @"WebKitUsesPageCachePreferenceKey"
#define WebKitFTPDirectoryTemplatePath @"WebKitFTPDirectoryTemplatePath"
@@ -71,10 +77,13 @@
#define WebKitAuthorAndUserStylesEnabledPreferenceKey @"WebKitAuthorAndUserStylesEnabledPreferenceKey"
#define WebKitApplicationChromeModeEnabledPreferenceKey @"WebKitApplicationChromeModeEnabledPreferenceKey"
#define WebKitWebArchiveDebugModeEnabledPreferenceKey @"WebKitWebArchiveDebugModeEnabledPreferenceKey"
+#define WebKitLocalFileContentSniffingEnabledPreferenceKey @"WebKitLocalFileContentSniffingEnabledPreferenceKey"
#define WebKitLocalStorageDatabasePathPreferenceKey @"WebKitLocalStorageDatabasePathPreferenceKey"
#define WebKitEnableFullDocumentTeardownPreferenceKey @"WebKitEnableFullDocumentTeardown"
#define WebKitOfflineWebApplicationCacheEnabledPreferenceKey @"WebKitOfflineWebApplicationCacheEnabled"
#define WebKitZoomsTextOnlyPreferenceKey @"WebKitZoomsTextOnly"
+#define WebKitXSSAuditorEnabledPreferenceKey @"WebKitXSSAuditorEnabled"
+#define WebKitAcceleratedCompositingEnabledPreferenceKey @"WebKitAcceleratedCompositingEnabled"
// These are private both because callers should be using the cover methods and because the
// cover methods themselves are private.
diff --git a/WebKit/mac/WebView/WebPreferences.mm b/WebKit/mac/WebView/WebPreferences.mm
index 6db14bd..378b280 100644
--- a/WebKit/mac/WebView/WebPreferences.mm
+++ b/WebKit/mac/WebView/WebPreferences.mm
@@ -345,13 +345,11 @@ static WebCacheModel cacheModelForMainBundle(void)
[NSNumber numberWithBool:YES], WebKitAuthorAndUserStylesEnabledPreferenceKey,
[NSNumber numberWithBool:NO], WebKitApplicationChromeModeEnabledPreferenceKey,
[NSNumber numberWithBool:NO], WebKitWebArchiveDebugModeEnabledPreferenceKey,
+ [NSNumber numberWithBool:NO], WebKitLocalFileContentSniffingEnabledPreferenceKey,
[NSNumber numberWithBool:NO], WebKitOfflineWebApplicationCacheEnabledPreferenceKey,
[NSNumber numberWithBool:YES], WebKitZoomsTextOnlyPreferenceKey,
-#ifndef NDEBUG
- // In Release and Production we skip a lot of object teardown during quit to speed up shutdown time. This breaks
- // our RefCount Leak tracking, and so for Debug we will use the full document teardown.
- [NSNumber numberWithBool:YES], WebKitEnableFullDocumentTeardownPreferenceKey,
-#endif
+ [NSNumber numberWithBool:YES], WebKitXSSAuditorEnabledPreferenceKey,
+ [NSNumber numberWithBool:YES], WebKitAcceleratedCompositingEnabledPreferenceKey,
nil];
// This value shouldn't ever change, which is assumed in the initialization of WebKitPDFDisplayModePreferenceKey above
@@ -795,6 +793,16 @@ static WebCacheModel cacheModelForMainBundle(void)
[self _setBoolValue:flag forKey:WebKitWebArchiveDebugModeEnabledPreferenceKey];
}
+- (BOOL)localFileContentSniffingEnabled
+{
+ return [self _boolValueForKey:WebKitLocalFileContentSniffingEnabledPreferenceKey];
+}
+
+- (void)setLocalFileContentSniffingEnabled:(BOOL)flag
+{
+ [self _setBoolValue:flag forKey:WebKitLocalFileContentSniffingEnabledPreferenceKey];
+}
+
- (BOOL)offlineWebApplicationCacheEnabled
{
return [self _boolValueForKey:WebKitOfflineWebApplicationCacheEnabledPreferenceKey];
@@ -815,6 +823,16 @@ static WebCacheModel cacheModelForMainBundle(void)
[self _setBoolValue:flag forKey:WebKitZoomsTextOnlyPreferenceKey];
}
+- (BOOL)isXSSAuditorEnabled
+{
+ return [self _boolValueForKey:WebKitXSSAuditorEnabledPreferenceKey];
+}
+
+- (void)setXSSAuditorEnabled:(BOOL)flag
+{
+ [self _setBoolValue:flag forKey:WebKitXSSAuditorEnabledPreferenceKey];
+}
+
- (BOOL)respectStandardStyleKeyEquivalents
{
return [self _boolValueForKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
@@ -1032,6 +1050,11 @@ static WebCacheModel cacheModelForMainBundle(void)
- (void)_postPreferencesChangesNotification
{
+ if (!pthread_main_np()) {
+ [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
+ return;
+ }
+
[[NSNotificationCenter defaultCenter]
postNotificationName:WebPreferencesChangedNotification object:self
userInfo:nil];
@@ -1046,10 +1069,11 @@ static WebCacheModel cacheModelForMainBundle(void)
{
NSString *systemEncodingName = (NSString *)CFStringConvertEncodingToIANACharSetName([self _systemCFStringEncoding]);
- // CFStringConvertEncodingToIANACharSetName() returns CP949 for kTextEncodingDOSKorean AKA "extended EUC-KR" AKA windows-939.
+ // CFStringConvertEncodingToIANACharSetName() returns cp949 for kTextEncodingDOSKorean AKA "extended EUC-KR" AKA windows-939.
// ICU uses this name for a different encoding, so we need to change the name to a value that actually gives us windows-939.
// In addition, this value must match what is used in Safari, see <rdar://problem/5579292>.
- if ([systemEncodingName isEqualToString:@"CP949"])
+ // On some OS versions, the result is CP949 (uppercase).
+ if ([systemEncodingName _webkit_isCaseInsensitiveEqualToString:@"cp949"])
systemEncodingName = @"ks_c_5601-1987";
[[NSUserDefaults standardUserDefaults] registerDefaults:
[NSDictionary dictionaryWithObject:systemEncodingName forKey:WebKitDefaultTextEncodingNamePreferenceKey]];
@@ -1074,11 +1098,6 @@ static NSString *classIBCreatorID = nil;
[self _setBoolValue:DOMPasteAllowed forKey:WebKitDOMPasteAllowedPreferenceKey];
}
-- (void)_setFTPDirectoryTemplatePath:(NSString *)path
-{
- [self _setStringValue:[path stringByStandardizingPath] forKey:WebKitFTPDirectoryTemplatePath];
-}
-
- (NSString *)_localStorageDatabasePath
{
return [[self _stringValueForKey:WebKitLocalStorageDatabasePathPreferenceKey] stringByStandardizingPath];
@@ -1094,9 +1113,9 @@ static NSString *classIBCreatorID = nil;
return [[self _stringValueForKey:WebKitFTPDirectoryTemplatePath] stringByStandardizingPath];
}
-- (void)_setForceFTPDirectoryListings:(BOOL)force
+- (void)_setFTPDirectoryTemplatePath:(NSString *)path
{
- [self _setBoolValue:force forKey:WebKitForceFTPDirectoryListings];
+ [self _setStringValue:[path stringByStandardizingPath] forKey:WebKitFTPDirectoryTemplatePath];
}
- (BOOL)_forceFTPDirectoryListings
@@ -1104,6 +1123,21 @@ static NSString *classIBCreatorID = nil;
return [self _boolValueForKey:WebKitForceFTPDirectoryListings];
}
+- (void)_setForceFTPDirectoryListings:(BOOL)force
+{
+ [self _setBoolValue:force forKey:WebKitForceFTPDirectoryListings];
+}
+
+- (BOOL)acceleratedCompositingEnabled
+{
+ return [self _boolValueForKey:WebKitAcceleratedCompositingEnabledPreferenceKey];
+}
+
+- (void)setAcceleratedCompositingEnabled:(BOOL)enabled
+{
+ [self _setBoolValue:enabled forKey:WebKitAcceleratedCompositingEnabledPreferenceKey];
+}
+
- (void)didRemoveFromWebView
{
ASSERT(_private->numWebViews);
@@ -1118,16 +1152,6 @@ static NSString *classIBCreatorID = nil;
{
++_private->numWebViews;
}
-
-- (void)setFullDocumentTeardownEnabled:(BOOL)fullDocumentTeardownEnabled
-{
- [self _setBoolValue:fullDocumentTeardownEnabled forKey:WebKitEnableFullDocumentTeardownPreferenceKey];
-}
-
-- (BOOL)fullDocumentTeardownEnabled
-{
- return [self _boolValueForKey:WebKitEnableFullDocumentTeardownPreferenceKey];
-}
@end
@implementation WebPreferences (WebInternal)
diff --git a/WebKit/mac/WebView/WebPreferencesPrivate.h b/WebKit/mac/WebView/WebPreferencesPrivate.h
index ae94cce..d571869 100644
--- a/WebKit/mac/WebView/WebPreferencesPrivate.h
+++ b/WebKit/mac/WebView/WebPreferencesPrivate.h
@@ -83,6 +83,9 @@ extern NSString *WebPreferencesRemovedNotification;
- (BOOL)webArchiveDebugModeEnabled;
- (void)setWebArchiveDebugModeEnabled:(BOOL)webArchiveDebugModeEnabled;
+- (BOOL)localFileContentSniffingEnabled;
+- (void)setLocalFileContentSniffingEnabled:(BOOL)localFileContentSniffingEnabled;
+
- (BOOL)offlineWebApplicationCacheEnabled;
- (void)setOfflineWebApplicationCacheEnabled:(BOOL)offlineWebApplicationCacheEnabled;
@@ -101,6 +104,9 @@ extern NSString *WebPreferencesRemovedNotification;
- (BOOL)zoomsTextOnly;
- (void)setZoomsTextOnly:(BOOL)zoomsTextOnly;
+- (BOOL)isXSSAuditorEnabled;
+- (void)setXSSAuditorEnabled:(BOOL)flag;
+
// zero means do AutoScale
- (float)PDFScaleFactor;
- (void)setPDFScaleFactor:(float)scale;
@@ -123,11 +129,16 @@ extern NSString *WebPreferencesRemovedNotification;
- (NSString *)_ftpDirectoryTemplatePath;
- (void)_setFTPDirectoryTemplatePath:(NSString *)path;
+
- (void)_setForceFTPDirectoryListings:(BOOL)force;
- (BOOL)_forceFTPDirectoryListings;
+
- (NSString *)_localStorageDatabasePath;
- (void)_setLocalStorageDatabasePath:(NSString *)path;
+- (BOOL)acceleratedCompositingEnabled;
+- (void)setAcceleratedCompositingEnabled:(BOOL)enabled;
+
// Other private methods
- (void)_postPreferencesChangesNotification;
+ (WebPreferences *)_getInstanceForIdentifier:(NSString *)identifier;
@@ -141,8 +152,4 @@ extern NSString *WebPreferencesRemovedNotification;
// For WebView's use only.
- (void)willAddToWebView;
- (void)didRemoveFromWebView;
-
-// Force document tear down at application quit
-- (void)setFullDocumentTeardownEnabled:(BOOL)fullDocumentTeardownEnabled;
-- (BOOL)fullDocumentTeardownEnabled;
@end
diff --git a/WebKit/mac/WebView/WebRenderNode.h b/WebKit/mac/WebView/WebRenderNode.h
index 8e6b40f..901b2cc 100644
--- a/WebKit/mac/WebView/WebRenderNode.h
+++ b/WebKit/mac/WebView/WebRenderNode.h
@@ -28,7 +28,7 @@
#import <Foundation/Foundation.h>
-@class WebFrameView;
+@class WebFrame;
@interface WebRenderNode : NSObject
{
@@ -38,7 +38,7 @@
NSPoint absolutePosition;
}
-- (id)initWithWebFrameView:(WebFrameView *)view;
+- (id)initWithWebFrame:(WebFrame *)frame;
- (NSArray *)children;
diff --git a/WebKit/mac/WebView/WebRenderNode.mm b/WebKit/mac/WebView/WebRenderNode.mm
index 65ee13c..4a839a5 100644
--- a/WebKit/mac/WebView/WebRenderNode.mm
+++ b/WebKit/mac/WebView/WebRenderNode.mm
@@ -29,9 +29,8 @@
#import "WebRenderNode.h"
#import "WebFrameInternal.h"
-#import "WebFrameView.h"
-#import "WebHTMLView.h"
#import <WebCore/Frame.h>
+#import <WebCore/FrameLoaderClient.h>
#import <WebCore/RenderText.h>
#import <WebCore/RenderWidget.h>
#import <WebCore/RenderView.h>
@@ -39,9 +38,25 @@
using namespace WebCore;
+static WebRenderNode *copyRenderNode(RenderObject*);
+
@implementation WebRenderNode
-- (id)initWithName:(NSString *)n position:(NSPoint)p rect:(NSRect)r view:(NSView *)view children:(NSArray *)c
+- (id)_initWithCoreFrame:(Frame *)frame
+{
+ [self release];
+
+ if (!frame->loader()->client()->hasHTMLView())
+ return nil;
+
+ RenderObject* renderer = frame->contentRenderer();
+ if (!renderer)
+ return nil;
+
+ return copyRenderNode(renderer);
+}
+
+- (id)_initWithName:(NSString *)n position:(NSPoint)p rect:(NSRect)r coreFrame:(Frame*)coreFrame children:(NSArray *)c
{
NSMutableArray *collectChildren;
@@ -55,13 +70,8 @@ using namespace WebCore;
rect = r;
absolutePosition = p;
- if ([view isKindOfClass:[NSScrollView class]]) {
- NSScrollView *scrollView = (NSScrollView *)view;
- view = [scrollView superview];
- }
- if ([view isKindOfClass:[WebFrameView class]]) {
- WebFrameView *webFrameView = (WebFrameView *)view;
- WebRenderNode *node = [[WebRenderNode alloc] initWithWebFrameView:webFrameView];
+ if (coreFrame) {
+ WebRenderNode *node = [[WebRenderNode alloc] _initWithCoreFrame:coreFrame];
[collectChildren addObject:node];
[node release];
}
@@ -83,9 +93,10 @@ static WebRenderNode *copyRenderNode(RenderObject* node)
NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
- RenderWidget* renderWidget = node->isWidget() ? static_cast<RenderWidget*>(node) : 0;
+ RenderWidget* renderWidget = node->isWidget() ? toRenderWidget(node) : 0;
Widget* widget = renderWidget ? renderWidget->widget() : 0;
- NSView *view = widget ? widget->platformWidget() : nil;
+ FrameView* frameView = widget && widget->isFrameView() ? static_cast<FrameView*>(widget) : 0;
+ Frame* frame = frameView ? frameView->frame() : 0;
// FIXME: broken with transforms
FloatPoint absPos = node->localToAbsolute(FloatPoint());
@@ -109,9 +120,9 @@ static WebRenderNode *copyRenderNode(RenderObject* node)
height = box.height();
}
- WebRenderNode *result = [[WebRenderNode alloc] initWithName:name
- position:absPos rect:NSMakeRect(x, y, width, height)
- view:view children:children];
+ WebRenderNode *result = [[WebRenderNode alloc] _initWithName:name
+ position:absPos rect:NSMakeRect(x, y, width, height)
+ coreFrame:frame children:children];
[name release];
[children release];
@@ -119,18 +130,9 @@ static WebRenderNode *copyRenderNode(RenderObject* node)
return result;
}
-- (id)initWithWebFrameView:(WebFrameView *)view
+- (id)initWithWebFrame:(WebFrame *)frame
{
- [self release];
-
- if (![[view documentView] isMemberOfClass:[WebHTMLView class]])
- return nil;
-
- RenderObject* renderer = core([view webFrame])->contentRenderer();
- if (!renderer)
- return nil;
-
- return copyRenderNode(renderer);
+ return [self _initWithCoreFrame:core(frame)];
}
- (void)dealloc
diff --git a/WebKit/mac/WebView/WebResource.mm b/WebKit/mac/WebView/WebResource.mm
index e62ed1e..735e213 100644
--- a/WebKit/mac/WebView/WebResource.mm
+++ b/WebKit/mac/WebView/WebResource.mm
@@ -38,6 +38,7 @@
#import <JavaScriptCore/PassRefPtr.h>
#import <WebCore/ArchiveResource.h>
#import <WebCore/LegacyWebArchive.h>
+#import <WebCore/RuntimeApplicationChecks.h>
#import <WebCore/TextEncoding.h>
#import <WebCore/ThreadCheck.h>
#import <WebCore/WebCoreObjCExtras.h>
@@ -365,7 +366,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse"
// Copying it will also cause a performance regression.
return [self _initWithData:data
URL:URL
- MIMEType:[response _webcore_MIMEType]
+ MIMEType:[response MIMEType]
textEncodingName:[response textEncodingName]
frameName:nil
response:response
@@ -441,8 +442,7 @@ static const double newMailBundleVersion = 1050.0;
+ (BOOL)_needMailThreadWorkaroundIfCalledOffMainThread
{
- static BOOL isOldMail = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"]
- && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue] < newMailBundleVersion;
+ static BOOL isOldMail = applicationIsAppleMail() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue] < newMailBundleVersion;
return isOldMail;
}
diff --git a/WebKit/mac/WebView/WebScriptDebugDelegate.mm b/WebKit/mac/WebView/WebScriptDebugDelegate.mm
index 0b47e26..8489c9b 100644
--- a/WebKit/mac/WebView/WebScriptDebugDelegate.mm
+++ b/WebKit/mac/WebView/WebScriptDebugDelegate.mm
@@ -55,7 +55,7 @@ NSString * const WebScriptErrorLineNumberKey = @"WebScriptErrorLineNumber";
@interface WebScriptCallFrame (WebScriptDebugDelegateInternal)
-- (id)_convertValueToObjcValue:(JSValuePtr)value;
+- (id)_convertValueToObjcValue:(JSValue)value;
@end
@@ -113,7 +113,7 @@ NSString * const WebScriptErrorLineNumberKey = @"WebScriptErrorLineNumber";
_private->debuggerCallFrame = 0;
}
-- (id)_convertValueToObjcValue:(JSValuePtr)value
+- (id)_convertValueToObjcValue:(JSValue)value
{
if (!value)
return nil;
@@ -174,6 +174,8 @@ NSString * const WebScriptErrorLineNumberKey = @"WebScriptErrorLineNumber";
if (!_private->debuggerCallFrame)
return [NSArray array];
+ JSLock lock(SilenceAssertionsOnly);
+
const ScopeChainNode* scopeChain = _private->debuggerCallFrame->scopeChain();
if (!scopeChain->next) // global frame
return [NSArray arrayWithObject:_private->globalObject];
@@ -212,7 +214,7 @@ NSString * const WebScriptErrorLineNumberKey = @"WebScriptErrorLineNumber";
if (!_private->debuggerCallFrame)
return nil;
- JSValuePtr exception = _private->debuggerCallFrame->exception();
+ JSValue exception = _private->debuggerCallFrame->exception();
return exception ? [self _convertValueToObjcValue:exception] : nil;
}
@@ -227,7 +229,7 @@ NSString * const WebScriptErrorLineNumberKey = @"WebScriptErrorLineNumber";
if (!_private->debuggerCallFrame)
return nil;
- JSLock lock(false);
+ JSLock lock(SilenceAssertionsOnly);
// If this is the global call frame and there is no dynamic global object,
// Dashcode is attempting to execute JS in the evaluator using a stale
@@ -239,15 +241,15 @@ NSString * const WebScriptErrorLineNumberKey = @"WebScriptErrorLineNumber";
DynamicGlobalObjectScope globalObjectScope(globalObject->globalExec(), globalObject);
- JSValuePtr exception = noValue();
- JSValuePtr result = evaluateInGlobalCallFrame(String(script), exception, globalObject);
+ JSValue exception;
+ JSValue result = evaluateInGlobalCallFrame(String(script), exception, globalObject);
if (exception)
return [self _convertValueToObjcValue:exception];
return result ? [self _convertValueToObjcValue:result] : nil;
}
- JSValuePtr exception = noValue();
- JSValuePtr result = _private->debuggerCallFrame->evaluate(String(script), exception);
+ JSValue exception;
+ JSValue result = _private->debuggerCallFrame->evaluate(String(script), exception);
if (exception)
return [self _convertValueToObjcValue:exception];
return result ? [self _convertValueToObjcValue:result] : nil;
diff --git a/WebKit/mac/WebView/WebScriptDebugger.mm b/WebKit/mac/WebView/WebScriptDebugger.mm
index 384f826..76bdf58 100644
--- a/WebKit/mac/WebView/WebScriptDebugger.mm
+++ b/WebKit/mac/WebView/WebScriptDebugger.mm
@@ -28,16 +28,17 @@
#import "WebScriptDebugger.h"
+#import "WebDelegateImplementationCaching.h"
#import "WebFrameInternal.h"
-#import "WebViewInternal.h"
#import "WebScriptDebugDelegate.h"
-#import <runtime/JSGlobalObject.h>
-#import <debugger/DebuggerCallFrame.h>
+#import "WebViewInternal.h"
#import <WebCore/DOMWindow.h>
#import <WebCore/Frame.h>
#import <WebCore/JSDOMWindow.h>
#import <WebCore/KURL.h>
#import <WebCore/ScriptController.h>
+#import <debugger/DebuggerCallFrame.h>
+#import <runtime/JSGlobalObject.h>
using namespace JSC;
using namespace WebCore;
diff --git a/WebKit/mac/WebView/WebTextCompletionController.h b/WebKit/mac/WebView/WebTextCompletionController.h
new file mode 100644
index 0000000..158e9b8
--- /dev/null
+++ b/WebKit/mac/WebView/WebTextCompletionController.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+@class WebView;
+@class WebHTMLView;
+
+@interface WebTextCompletionController : NSObject <NSTableViewDelegate, NSTableViewDataSource> {
+@private
+ WebView *_view;
+ WebHTMLView *_htmlView;
+ NSWindow *_popupWindow;
+ NSTableView *_tableView;
+ NSArray *_completions;
+ NSString *_originalString;
+ int prefixLength;
+}
+- (id)initWithWebView:(WebView *)view HTMLView:(WebHTMLView *)htmlView;
+- (void)doCompletion;
+- (void)endRevertingChange:(BOOL)revertChange moveLeft:(BOOL)goLeft;
+- (BOOL)popupWindowIsOpen;
+- (BOOL)filterKeyDown:(NSEvent *)event;
+- (void)_reflectSelection;
+@end
diff --git a/WebKit/mac/WebView/WebTextCompletionController.mm b/WebKit/mac/WebView/WebTextCompletionController.mm
new file mode 100644
index 0000000..f7c172f
--- /dev/null
+++ b/WebKit/mac/WebView/WebTextCompletionController.mm
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebTextCompletionController.h"
+
+#import "DOMRangeInternal.h"
+#import "WebFrameInternal.h"
+#import "WebHTMLViewInternal.h"
+#import "WebTypesInternal.h"
+#import <WebCore/Frame.h>
+
+@interface NSWindow (WebNSWindowDetails)
+- (void)_setForceActiveControls:(BOOL)flag;
+@end
+
+using namespace WebCore;
+
+// This class handles the complete: operation.
+// It counts on its host view to call endRevertingChange: whenever the current completion needs to be aborted.
+
+// The class is in one of two modes: Popup window showing, or not.
+// It is shown when a completion yields more than one match.
+// If a completion yields one or zero matches, it is not shown, and there is no state carried across to the next completion.
+
+@implementation WebTextCompletionController
+
+- (id)initWithWebView:(WebView *)view HTMLView:(WebHTMLView *)htmlView
+{
+ self = [super init];
+ if (!self)
+ return nil;
+ _view = view;
+ _htmlView = htmlView;
+ return self;
+}
+
+- (void)dealloc
+{
+ [_popupWindow release];
+ [_completions release];
+ [_originalString release];
+
+ [super dealloc];
+}
+
+- (void)_insertMatch:(NSString *)match
+{
+ // FIXME: 3769654 - We should preserve case of string being inserted, even in prefix (but then also be
+ // able to revert that). Mimic NSText.
+ WebFrame *frame = [_htmlView _frame];
+ NSString *newText = [match substringFromIndex:prefixLength];
+ [frame _replaceSelectionWithText:newText selectReplacement:YES smartReplace:NO];
+}
+
+// mostly lifted from NSTextView_KeyBinding.m
+- (void)_buildUI
+{
+ NSRect scrollFrame = NSMakeRect(0, 0, 100, 100);
+ NSRect tableFrame = NSZeroRect;
+ tableFrame.size = [NSScrollView contentSizeForFrameSize:scrollFrame.size hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder];
+ // Added cast to work around problem with multiple Foundation initWithIdentifier: methods with different parameter types.
+ NSTableColumn *column = [(NSTableColumn *)[NSTableColumn alloc] initWithIdentifier:[NSNumber numberWithInt:0]];
+ [column setWidth:tableFrame.size.width];
+ [column setEditable:NO];
+
+ _tableView = [[NSTableView alloc] initWithFrame:tableFrame];
+ [_tableView setAutoresizingMask:NSViewWidthSizable];
+ [_tableView addTableColumn:column];
+ [column release];
+ [_tableView setGridStyleMask:NSTableViewGridNone];
+ [_tableView setCornerView:nil];
+ [_tableView setHeaderView:nil];
+ [_tableView setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
+ [_tableView setDelegate:self];
+ [_tableView setDataSource:self];
+ [_tableView setTarget:self];
+ [_tableView setDoubleAction:@selector(tableAction:)];
+
+ NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:scrollFrame];
+ [scrollView setBorderType:NSNoBorder];
+ [scrollView setHasVerticalScroller:YES];
+ [scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ [scrollView setDocumentView:_tableView];
+ [_tableView release];
+
+ _popupWindow = [[NSWindow alloc] initWithContentRect:scrollFrame styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
+ [_popupWindow setAlphaValue:0.88f];
+ [_popupWindow setContentView:scrollView];
+ [scrollView release];
+ [_popupWindow setHasShadow:YES];
+ [_popupWindow setOneShot:YES];
+ [_popupWindow _setForceActiveControls:YES];
+ [_popupWindow setReleasedWhenClosed:NO];
+}
+
+// mostly lifted from NSTextView_KeyBinding.m
+- (void)_placePopupWindow:(NSPoint)topLeft
+{
+ int numberToShow = [_completions count];
+ if (numberToShow > 20)
+ numberToShow = 20;
+
+ NSRect windowFrame;
+ NSPoint wordStart = topLeft;
+ windowFrame.origin = [[_view window] convertBaseToScreen:[_htmlView convertPoint:wordStart toView:nil]];
+ windowFrame.size.height = numberToShow * [_tableView rowHeight] + (numberToShow + 1) * [_tableView intercellSpacing].height;
+ windowFrame.origin.y -= windowFrame.size.height;
+ NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont systemFontOfSize:12.0f], NSFontAttributeName, nil];
+ float maxWidth = 0.0f;
+ int maxIndex = -1;
+ int i;
+ for (i = 0; i < numberToShow; i++) {
+ float width = ceilf([[_completions objectAtIndex:i] sizeWithAttributes:attributes].width);
+ if (width > maxWidth) {
+ maxWidth = width;
+ maxIndex = i;
+ }
+ }
+ windowFrame.size.width = 100;
+ if (maxIndex >= 0) {
+ maxWidth = ceilf([NSScrollView frameSizeForContentSize:NSMakeSize(maxWidth, 100.0f) hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder].width);
+ maxWidth = ceilf([NSWindow frameRectForContentRect:NSMakeRect(0.0f, 0.0f, maxWidth, 100.0f) styleMask:NSBorderlessWindowMask].size.width);
+ maxWidth += 5.0f;
+ windowFrame.size.width = MAX(maxWidth, windowFrame.size.width);
+ maxWidth = MIN(400.0f, windowFrame.size.width);
+ }
+ [_popupWindow setFrame:windowFrame display:NO];
+
+ [_tableView reloadData];
+ [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
+ [_tableView scrollRowToVisible:0];
+ [self _reflectSelection];
+ [_popupWindow setLevel:NSPopUpMenuWindowLevel];
+ [_popupWindow orderFront:nil];
+ [[_view window] addChildWindow:_popupWindow ordered:NSWindowAbove];
+}
+
+- (void)doCompletion
+{
+ if (!_popupWindow) {
+ NSSpellChecker *checker = [NSSpellChecker sharedSpellChecker];
+ if (!checker) {
+ LOG_ERROR("No NSSpellChecker");
+ return;
+ }
+
+ // Get preceeding word stem
+ WebFrame *frame = [_htmlView _frame];
+ DOMRange *selection = kit(core(frame)->selection()->toNormalizedRange().get());
+ DOMRange *wholeWord = [frame _rangeByAlteringCurrentSelection:SelectionController::EXTEND
+ direction:SelectionController::BACKWARD granularity:WordGranularity];
+ DOMRange *prefix = [wholeWord cloneRange];
+ [prefix setEnd:[selection startContainer] offset:[selection startOffset]];
+
+ // Reject some NOP cases
+ if ([prefix collapsed]) {
+ NSBeep();
+ return;
+ }
+ NSString *prefixStr = [frame _stringForRange:prefix];
+ NSString *trimmedPrefix = [prefixStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ if ([trimmedPrefix length] == 0) {
+ NSBeep();
+ return;
+ }
+ prefixLength = [prefixStr length];
+
+ // Lookup matches
+ [_completions release];
+ _completions = [checker completionsForPartialWordRange:NSMakeRange(0, [prefixStr length]) inString:prefixStr language:nil inSpellDocumentWithTag:[_view spellCheckerDocumentTag]];
+ [_completions retain];
+
+ if (!_completions || [_completions count] == 0) {
+ NSBeep();
+ } else if ([_completions count] == 1) {
+ [self _insertMatch:[_completions objectAtIndex:0]];
+ } else {
+ ASSERT(!_originalString); // this should only be set IFF we have a popup window
+ _originalString = [[frame _stringForRange:selection] retain];
+ [self _buildUI];
+ NSRect wordRect = [frame _caretRectAtNode:[wholeWord startContainer] offset:[wholeWord startOffset] affinity:NSSelectionAffinityDownstream];
+ // +1 to be under the word, not the caret
+ // FIXME - 3769652 - Wrong positioning for right to left languages. We should line up the upper
+ // right corner with the caret instead of upper left, and the +1 would be a -1.
+ NSPoint wordLowerLeft = { NSMinX(wordRect)+1, NSMaxY(wordRect) };
+ [self _placePopupWindow:wordLowerLeft];
+ }
+ } else {
+ [self endRevertingChange:YES moveLeft:NO];
+ }
+}
+
+- (void)endRevertingChange:(BOOL)revertChange moveLeft:(BOOL)goLeft
+{
+ if (_popupWindow) {
+ // tear down UI
+ [[_view window] removeChildWindow:_popupWindow];
+ [_popupWindow orderOut:self];
+ // Must autorelease because event tracking code may be on the stack touching UI
+ [_popupWindow autorelease];
+ _popupWindow = nil;
+
+ if (revertChange) {
+ WebFrame *frame = [_htmlView _frame];
+ [frame _replaceSelectionWithText:_originalString selectReplacement:YES smartReplace:NO];
+ } else if ([_htmlView _hasSelection]) {
+ if (goLeft)
+ [_htmlView moveBackward:nil];
+ else
+ [_htmlView moveForward:nil];
+ }
+ [_originalString release];
+ _originalString = nil;
+ }
+ // else there is no state to abort if the window was not up
+}
+
+- (BOOL)popupWindowIsOpen
+{
+ return _popupWindow != nil;
+}
+
+// WebHTMLView gives us a crack at key events it sees. Return whether we consumed the event.
+// The features for the various keys mimic NSTextView.
+- (BOOL)filterKeyDown:(NSEvent *)event
+{
+ if (!_popupWindow)
+ return NO;
+ NSString *string = [event charactersIgnoringModifiers];
+ if (![string length])
+ return NO;
+ unichar c = [string characterAtIndex:0];
+ if (c == NSUpArrowFunctionKey) {
+ int selectedRow = [_tableView selectedRow];
+ if (0 < selectedRow) {
+ [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow - 1] byExtendingSelection:NO];
+ [_tableView scrollRowToVisible:selectedRow - 1];
+ }
+ return YES;
+ }
+ if (c == NSDownArrowFunctionKey) {
+ int selectedRow = [_tableView selectedRow];
+ if (selectedRow < (int)[_completions count] - 1) {
+ [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow + 1] byExtendingSelection:NO];
+ [_tableView scrollRowToVisible:selectedRow + 1];
+ }
+ return YES;
+ }
+ if (c == NSRightArrowFunctionKey || c == '\n' || c == '\r' || c == '\t') {
+ // FIXME: What about backtab?
+ [self endRevertingChange:NO moveLeft:NO];
+ return YES;
+ }
+ if (c == NSLeftArrowFunctionKey) {
+ [self endRevertingChange:NO moveLeft:YES];
+ return YES;
+ }
+ if (c == 0x1B || c == NSF5FunctionKey) {
+ // FIXME: F5?
+ [self endRevertingChange:YES moveLeft:NO];
+ return YES;
+ }
+ if (c == ' ' || c >= 0x21 && c <= 0x2F || c >= 0x3A && c <= 0x40 || c >= 0x5B && c <= 0x60 || c >= 0x7B && c <= 0x7D) {
+ // FIXME: Is the above list of keys really definitive?
+ // Originally this code called ispunct; aren't there other punctuation keys on international keyboards?
+ [self endRevertingChange:NO moveLeft:NO];
+ return NO; // let the char get inserted
+ }
+ return NO;
+}
+
+- (void)_reflectSelection
+{
+ int selectedRow = [_tableView selectedRow];
+ ASSERT(selectedRow >= 0 && selectedRow < (int)[_completions count]);
+ [self _insertMatch:[_completions objectAtIndex:selectedRow]];
+}
+
+- (void)tableAction:(id)sender
+{
+ [self _reflectSelection];
+ [self endRevertingChange:NO moveLeft:NO];
+}
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
+{
+ return [_completions count];
+}
+
+- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
+{
+ return [_completions objectAtIndex:row];
+}
+
+- (void)tableViewSelectionDidChange:(NSNotification *)notification
+{
+ [self _reflectSelection];
+}
+
+@end
diff --git a/WebKit/mac/WebView/WebTextIterator.mm b/WebKit/mac/WebView/WebTextIterator.mm
index 15eeb5f..457bece 100644
--- a/WebKit/mac/WebView/WebTextIterator.mm
+++ b/WebKit/mac/WebView/WebTextIterator.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -67,7 +67,7 @@ using namespace WebCore;
return self;
_private = [[WebTextIteratorPrivate alloc] init];
- _private->_textIterator.set(new TextIterator([range _range], true, false));
+ _private->_textIterator.set(new TextIterator(core(range)));
return self;
}
@@ -83,7 +83,7 @@ using namespace WebCore;
- (DOMRange *)currentRange
{
- return [DOMRange _wrapRange:_private->_textIterator->range().get()];
+ return kit(_private->_textIterator->range().get());
}
- (const unichar *)currentTextPointer
@@ -102,7 +102,7 @@ using namespace WebCore;
- (DOMNode *)currentNode
{
- return [DOMNode _wrapNode:_private->_textIterator->node()];
+ return kit(_private->_textIterator->node());
}
- (NSString *)currentText
diff --git a/WebKit/mac/WebView/WebUIDelegatePrivate.h b/WebKit/mac/WebView/WebUIDelegatePrivate.h
index 8e67963..717cf01 100644
--- a/WebKit/mac/WebView/WebUIDelegatePrivate.h
+++ b/WebKit/mac/WebView/WebUIDelegatePrivate.h
@@ -72,6 +72,19 @@ enum {
WebMenuItemTagTextDirectionDefault,
WebMenuItemTagTextDirectionLeftToRight,
WebMenuItemTagTextDirectionRightToLeft,
+ WebMenuItemTagCorrectSpellingAutomatically,
+ WebMenuItemTagSubstitutionsMenu,
+ WebMenuItemTagShowSubstitutions,
+ WebMenuItemTagSmartCopyPaste,
+ WebMenuItemTagSmartQuotes,
+ WebMenuItemTagSmartDashes,
+ WebMenuItemTagSmartLinks,
+ WebMenuItemTagTextReplacement,
+ WebMenuItemTagTransformationsMenu,
+ WebMenuItemTagMakeUpperCase,
+ WebMenuItemTagMakeLowerCase,
+ WebMenuItemTagCapitalize,
+ WebMenuItemTagChangeBack,
WebMenuItemTagBaseApplication = 10000
};
@class WebGeolocation;
@@ -113,4 +126,17 @@ enum {
- (BOOL)webView:(WebView *)sender frame:(WebFrame *)frame requestGeolocationPermission:(WebGeolocation *)geolocation securityOrigin:(WebSecurityOrigin *)origin;
+- (void)webView:(WebView *)sender formStateDidChangeForNode:(DOMNode *)node;
+- (void)webView:(WebView *)sender formStateDidFocusNode:(DOMNode *)node;
+- (void)webView:(WebView *)sender formStateDidBlurNode:(DOMNode *)node;
+
+/*!
+ @method webView:printFrame:
+ @abstract Informs that a WebFrame needs to be printed
+ @param webView The WebView sending the delegate method
+ @param frameView The WebFrame needing to be printed
+ @discussion This method is called when a script or user requests the page to be printed.
+*/
+- (void)webView:(WebView *)sender printFrame:(WebFrame *)frame;
+
@end
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
diff --git a/WebKit/mac/WebView/WebViewData.h b/WebKit/mac/WebView/WebViewData.h
new file mode 100644
index 0000000..91d83a7
--- /dev/null
+++ b/WebKit/mac/WebView/WebViewData.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebTypesInternal.h"
+#import "WebDelegateImplementationCaching.h"
+#import <WebCore/PlatformString.h>
+#import <WebCore/WebCoreKeyboardUIMode.h>
+#import <wtf/HashMap.h>
+#import <wtf/RetainPtr.h>
+
+namespace WebCore {
+ class Page;
+}
+
+@class WebInspector;
+@class WebNodeHighlight;
+@class WebPluginDatabase;
+@class WebPreferences;
+@class WebTextCompletionController;
+@protocol WebFormDelegate;
+
+extern BOOL applicationIsTerminating;
+extern int pluginDatabaseClientCount;
+
+// FIXME: This should be renamed to WebViewData.
+@interface WebViewPrivate : NSObject {
+@public
+ WebCore::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;
+ WebCore::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;
+ WebCore::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 usesDocumentViews;
+
+#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;
+ // Run loop observer used to implement the compositing equivalent of -viewWillDraw
+ CFRunLoopObserverRef layerSyncRunLoopObserver;
+#endif
+
+ NSPasteboard *insertionPasteboard;
+
+ NSSize lastLayoutSize;
+
+ BOOL ignoringMouseDraggedEvents;
+
+ NSEvent *mouseDownEvent; // Kept after handling the event.
+ BOOL handlingMouseDownEvent;
+ NSEvent *keyDownEvent; // Kept after handling the event.
+
+ WebTextCompletionController *completionController;
+
+ NSTimer *autoscrollTimer;
+ NSEvent *autoscrollTriggerEvent;
+
+ CFRunLoopTimerRef updateMouseoverTimer;
+}
+@end
diff --git a/WebKit/mac/WebView/WebViewData.mm b/WebKit/mac/WebView/WebViewData.mm
new file mode 100644
index 0000000..48e7f6c
--- /dev/null
+++ b/WebKit/mac/WebView/WebViewData.mm
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebViewData.h"
+
+#import "WebKitLogging.h"
+#import "WebPreferenceKeysPrivate.h"
+#import <WebCore/WebCoreObjCExtras.h>
+#import <objc/objc-auto.h>
+#import <runtime/InitializeThreading.h>
+
+BOOL applicationIsTerminating = NO;
+int pluginDatabaseClientCount = 0;
+
+@implementation WebViewPrivate
+
++ (void)initialize
+{
+ JSC::initializeThreading();
+#ifndef BUILDING_ON_TIGER
+ WebCoreObjCFinalizeOnMainThread(self);
+#endif
+}
+
+- (id)init
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ allowsUndo = YES;
+ usesPageCache = YES;
+ shouldUpdateWhileOffscreen = YES;
+
+ zoomMultiplier = 1;
+
+#if ENABLE(DASHBOARD_SUPPORT)
+ dashboardBehaviorAllowWheelScrolling = YES;
+#endif
+
+ shouldCloseWithWindow = objc_collecting_enabled();
+
+ smartInsertDeleteEnabled = ![[NSUserDefaults standardUserDefaults] objectForKey:WebSmartInsertDeleteEnabled]
+ || [[NSUserDefaults standardUserDefaults] boolForKey:WebSmartInsertDeleteEnabled];
+
+
+ pluginDatabaseClientCount++;
+
+ return self;
+}
+
+- (void)dealloc
+{
+ ASSERT(applicationIsTerminating || !page);
+ ASSERT(applicationIsTerminating || !preferences);
+ ASSERT(!insertionPasteboard);
+
+ [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();
+ ASSERT(!insertionPasteboard);
+
+ [super finalize];
+}
+
+@end
diff --git a/WebKit/mac/WebView/WebViewInternal.h b/WebKit/mac/WebView/WebViewInternal.h
index ad4f19c..b8266c5 100644
--- a/WebKit/mac/WebView/WebViewInternal.h
+++ b/WebKit/mac/WebView/WebViewInternal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,28 +34,24 @@
#ifdef __cplusplus
#import <WebCore/WebCoreKeyboardUIMode.h>
-#endif
-#ifdef __cplusplus
namespace WebCore {
- class KeyboardEvent;
+ class String;
+ class Frame;
class KURL;
+ class KeyboardEvent;
class Page;
- class String;
}
-typedef WebCore::KeyboardEvent WebCoreKeyboardEvent;
-typedef WebCore::Page WebCorePage;
-#else
-@class WebCoreKeyboardEvent;
-@class WebCorePage;
#endif
@class WebBasePluginPackage;
@class WebDownload;
@class WebNodeHighlight;
+#ifdef __cplusplus
+
@interface WebView (WebViewEditingExtras)
-- (BOOL)_interceptEditingKeyEvent:(WebCoreKeyboardEvent *)event shouldSaveCommand:(BOOL)shouldSave;
+- (BOOL)_interceptEditingKeyEvent:(WebCore::KeyboardEvent*)event shouldSaveCommand:(BOOL)shouldSave;
- (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag;
@end
@@ -66,17 +62,48 @@ typedef WebCore::Page WebCorePage;
@end
@interface WebView (WebViewInternal)
-#ifdef __cplusplus
+
+- (WebCore::Frame*)_mainCoreFrame;
+
- (WebCore::String)_userAgentForURL:(const WebCore::KURL&)url;
- (WebCore::KeyboardUIMode)_keyboardUIMode;
+
+- (BOOL)_becomingFirstResponderFromOutside;
+
+#if ENABLE(ICONDATABASE)
+- (void)_registerForIconNotification:(BOOL)listen;
+- (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame;
+#endif
+
+- (void)_setMouseDownEvent:(NSEvent *)event;
+- (void)_cancelUpdateMouseoverTimer;
+- (void)_stopAutoscrollTimer;
+- (void)_updateMouseoverWithFakeEvent;
+- (void)_selectionChanged;
+- (void)_setToolTip:(NSString *)toolTip;
+
+#if USE(ACCELERATED_COMPOSITING)
+- (BOOL)_needsOneShotDrawingSynchronization;
+- (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization;
+- (void)_startedAcceleratedCompositingForFrame:(WebFrame*)webFrame;
+- (void)_stoppedAcceleratedCompositingForFrame:(WebFrame*)webFrame;
+- (void)_scheduleCompositingLayerSync;
#endif
+
@end
-@interface WebView (WebViewMiscInternal)
+#endif
+
+// FIXME: Temporary way to expose methods that are in the wrong category inside WebView.
+@interface WebView (WebViewOtherInternal)
+ (void)_setCacheModel:(WebCacheModel)cacheModel;
+ (WebCacheModel)_cacheModel;
-- (WebCorePage*)page;
+
+#ifdef __cplusplus
+- (WebCore::Page*)page;
+#endif
+
- (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items;
- (id)_UIDelegateForwarder;
- (id)_editingDelegateForwarder;
@@ -123,12 +150,8 @@ typedef WebCore::Page WebCorePage;
- (void)_addObject:(id)object forIdentifier:(unsigned long)identifier;
- (id)_objectForIdentifier:(unsigned long)identifier;
- (void)_removeObjectForIdentifier:(unsigned long)identifier;
-- (BOOL)_becomingFirstResponderFromOutside;
-
-- (void)_registerForIconNotification:(BOOL)listen;
-- (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame;
-- (void)_setZoomMultiplier:(float)m isTextOnly:(BOOL)isTextOnly;
+- (void)_setZoomMultiplier:(float)multiplier isTextOnly:(BOOL)isTextOnly;
- (float)_zoomMultiplier:(BOOL)isTextOnly;
- (float)_realZoomMultiplier;
- (BOOL)_realZoomMultiplierIsTextOnly;
@@ -140,106 +163,9 @@ typedef WebCore::Page WebCorePage;
- (IBAction)_resetZoom:(id)sender isTextOnly:(BOOL)isTextOnly;
- (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count;
-- (void)_updateFocusedAndActiveStateForFrame:(WebFrame *)webFrame;
+ (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame;
-#if USE(ACCELERATED_COMPOSITING)
-- (BOOL)_needsOneShotDrawingSynchronization;
-- (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization;
-- (void)_startedAcceleratedCompositingForFrame:(WebFrame*)webFrame;
-- (void)_stoppedAcceleratedCompositingForFrame:(WebFrame*)webFrame;
-#endif
+- (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard;
@end
-
-typedef struct _WebResourceDelegateImplementationCache {
- IMP didCancelAuthenticationChallengeFunc;
- IMP didReceiveAuthenticationChallengeFunc;
- IMP identifierForRequestFunc;
- IMP willSendRequestFunc;
- IMP didReceiveResponseFunc;
- IMP didReceiveContentLengthFunc;
- IMP didFinishLoadingFromDataSourceFunc;
- IMP didFailLoadingWithErrorFromDataSourceFunc;
- IMP didLoadResourceFromMemoryCacheFunc;
- IMP willCacheResponseFunc;
- IMP plugInFailedWithErrorFunc;
- IMP shouldUseCredentialStorageFunc;
-} WebResourceDelegateImplementationCache;
-
-typedef struct _WebFrameLoadDelegateImplementationCache {
- IMP didClearWindowObjectForFrameFunc;
- IMP windowScriptObjectAvailableFunc;
- IMP didHandleOnloadEventsForFrameFunc;
- IMP didReceiveServerRedirectForProvisionalLoadForFrameFunc;
- IMP didCancelClientRedirectForFrameFunc;
- IMP willPerformClientRedirectToURLDelayFireDateForFrameFunc;
- IMP didChangeLocationWithinPageForFrameFunc;
- IMP willCloseFrameFunc;
- IMP didStartProvisionalLoadForFrameFunc;
- IMP didReceiveTitleForFrameFunc;
- IMP didCommitLoadForFrameFunc;
- IMP didFailProvisionalLoadWithErrorForFrameFunc;
- IMP didFailLoadWithErrorForFrameFunc;
- IMP didFinishLoadForFrameFunc;
- IMP didFirstLayoutInFrameFunc;
- IMP didFirstVisuallyNonEmptyLayoutInFrameFunc;
- IMP didReceiveIconForFrameFunc;
- IMP didFinishDocumentLoadForFrameFunc;
-} WebFrameLoadDelegateImplementationCache;
-
-typedef struct _WebScriptDebugDelegateImplementationCache {
- BOOL didParseSourceExpectsBaseLineNumber;
- IMP didParseSourceFunc;
- IMP failedToParseSourceFunc;
- IMP didEnterCallFrameFunc;
- IMP willExecuteStatementFunc;
- IMP willLeaveCallFrameFunc;
- IMP exceptionWasRaisedFunc;
-} WebScriptDebugDelegateImplementationCache;
-
-WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView);
-WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView);
-WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView);
-
-#ifdef __cplusplus
-
-id CallFormDelegate(WebView *, SEL, id, id);
-id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5);
-BOOL CallFormDelegateReturningBoolean(BOOL, WebView *, SEL, id, SEL, id);
-
-id CallUIDelegate(WebView *, SEL);
-id CallUIDelegate(WebView *, SEL, id);
-id CallUIDelegate(WebView *, SEL, NSRect);
-id CallUIDelegate(WebView *, SEL, id, id);
-id CallUIDelegate(WebView *, SEL, id, BOOL);
-id CallUIDelegate(WebView *, SEL, id, id, id);
-id CallUIDelegate(WebView *, SEL, id, NSUInteger);
-float CallUIDelegateReturningFloat(WebView *, SEL);
-BOOL CallUIDelegateReturningBoolean(BOOL, WebView *, SEL);
-BOOL CallUIDelegateReturningBoolean(BOOL, WebView *, SEL, id);
-BOOL CallUIDelegateReturningBoolean(BOOL, WebView *, SEL, id, id);
-BOOL CallUIDelegateReturningBoolean(BOOL, WebView *, SEL, id, BOOL);
-
-id CallFrameLoadDelegate(IMP, WebView *, SEL);
-id CallFrameLoadDelegate(IMP, WebView *, SEL, id);
-id CallFrameLoadDelegate(IMP, WebView *, SEL, id, id);
-id CallFrameLoadDelegate(IMP, WebView *, SEL, id, id, id);
-id CallFrameLoadDelegate(IMP, WebView *, SEL, id, id, id, id);
-id CallFrameLoadDelegate(IMP, WebView *, SEL, id, NSTimeInterval, id, id);
-
-id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id);
-id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id, id);
-id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id, id, id);
-id CallResourceLoadDelegate(IMP, WebView *, SEL, id, NSInteger, id);
-id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id, NSInteger, id);
-
-BOOL CallResourceLoadDelegateReturningBoolean(BOOL, IMP, WebView *, SEL, id, id);
-
-id CallScriptDebugDelegate(IMP, WebView *, SEL, id, id, NSInteger, id);
-id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, NSInteger, id);
-id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, id, id);
-id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, NSInteger, id);
-
-#endif
diff --git a/WebKit/mac/WebView/WebViewPrivate.h b/WebKit/mac/WebView/WebViewPrivate.h
index ada0e01..362b2e6 100644
--- a/WebKit/mac/WebView/WebViewPrivate.h
+++ b/WebKit/mac/WebView/WebViewPrivate.h
@@ -206,12 +206,21 @@ typedef enum {
/*!
Could be worth adding to the API.
- @method loadItemsFromOtherView:
+ @method _loadBackForwardListFromOtherView:
@abstract Loads the view with the contents of the other view, including its backforward list.
@param otherView The WebView from which to copy contents.
*/
- (void)_loadBackForwardListFromOtherView:(WebView *)otherView;
+
+/*!
+ @method _dispatchPendingLoadRequests:
+ @abstract Dispatches any pending load requests that have been scheduled because of recent DOM additions or style changes.
+ @discussion You only need to call this method if you require synchronous notification of loads through the resource load delegate.
+ Otherwise the resource load delegate will be notified about loads during a future run loop iteration.
+ */
+- (void)_dispatchPendingLoadRequests;
+
+ (NSArray *)_supportedFileExtensions;
/*!
@@ -231,6 +240,13 @@ Could be worth adding to the API.
+ (NSString *)_standardUserAgentWithApplicationName:(NSString *)applicationName;
+/*!
+ @method canCloseAllWebViews
+ @abstract Checks if all the open WebViews can be closed (by dispatching the beforeUnload event to the pages).
+ @result YES if all the WebViews can be closed.
+*/
++ (BOOL)canCloseAllWebViews;
+
// May well become public
- (void)_setFormDelegate:(id<WebFormDelegate>)delegate;
- (id<WebFormDelegate>)_formDelegate;
@@ -241,6 +257,12 @@ Could be worth adding to the API.
// until callers can be weaned off of it.
- (void)_close;
+// Indicates if the WebView is in the midst of a user gesture.
+- (BOOL)_isProcessingUserGesture;
+
+// SPI for DumpRenderTree
+- (void)_updateActiveState;
+
/*!
@method _registerViewClass:representationClass:forURLScheme:
@discussion Register classes that implement WebDocumentView and WebDocumentRepresentation respectively.
@@ -295,8 +317,6 @@ Could be worth adding to the API.
+ (void)_setUsesTestModeFocusRingColor:(BOOL)f;
+ (BOOL)_usesTestModeFocusRingColor;
-+ (NSString *)_minimumRequiredSafariBuildNumber;
-
/*!
@method setAlwaysShowVerticalScroller:
@result Forces the vertical scroller to be visible if flag is YES, otherwise
@@ -369,15 +389,22 @@ Could be worth adding to the API.
- (WebHistoryItem *)_globalHistoryItem;
/*!
- @method textIteratorForRect:
- @param rectangle from which we want the WebTextIterator to load text from
- @result a WebtextIterator object.
+ @method textIteratorForRect:
+ @param rect The rectangle of the document that we're interested in text from.
+ @result WebTextIterator object, initialized with a range that corresponds to
+ the passed-in rectangle.
+ @abstract This method gives the text for the approximate range of the document
+ corresponding to the rectangle. The range is determined by using hit testing at
+ the top left and bottom right of the rectangle. Because of that, there can be
+ text visible in the rectangle that is not included in the iterator. If you need
+ a guarantee of iterating all text that is visible, then you need to instead make
+ a WebTextIterator with a DOMRange that covers the entire document.
*/
- (WebTextIterator *)textIteratorForRect:(NSRect)rect;
#if ENABLE_DASHBOARD_SUPPORT
-// <rdar://problem/5217124> Clients other than dashboard, don't use this.
-// Do not remove until Dashboard has moved off it
+// <rdar://problem/5217124> Clients other than Dashboard, don't use this.
+// As of this writing, Dashboard uses this on Tiger, but not on Leopard or newer.
- (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource;
#endif
@@ -413,6 +440,9 @@ Could be worth adding to the API.
// SPI for DumpRenderTree
- (BOOL)_isUsingAcceleratedCompositing;
+// Which pasteboard text is coming from in editing delegate methods such as shouldInsertNode.
+- (NSPasteboard *)_insertionPasteboard;
+
@end
@interface WebView (WebViewPrintingPrivate)
@@ -447,11 +477,36 @@ Could be worth adding to the API.
// FIXME: This method should be merged into WebIBActions when we're not in API freeze
- (void)toggleGrammarChecking:(id)sender;
#endif
+
+@end
+
+@interface WebView (WebViewTextChecking)
+
+- (BOOL)isAutomaticQuoteSubstitutionEnabled;
+- (BOOL)isAutomaticLinkDetectionEnabled;
+- (BOOL)isAutomaticDashSubstitutionEnabled;
+- (BOOL)isAutomaticTextReplacementEnabled;
+- (BOOL)isAutomaticSpellingCorrectionEnabled;
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+- (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag;
+- (void)toggleAutomaticQuoteSubstitution:(id)sender;
+- (void)setAutomaticLinkDetectionEnabled:(BOOL)flag;
+- (void)toggleAutomaticLinkDetection:(id)sender;
+- (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag;
+- (void)toggleAutomaticDashSubstitution:(id)sender;
+- (void)setAutomaticTextReplacementEnabled:(BOOL)flag;
+- (void)toggleAutomaticTextReplacement:(id)sender;
+- (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag;
+- (void)toggleAutomaticSpellingCorrection:(id)sender;
+#endif
+
@end
@interface WebView (WebViewEditingInMail)
- (void)_insertNewlineInQuotedContent;
- (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle;
+- (BOOL)_selectionIsCaret;
+- (BOOL)_selectionIsAll;
@end
@interface NSObject (WebFrameLoadDelegatePrivate)
@@ -467,6 +522,9 @@ Could be worth adding to the API.
- (void)webView:(WebView *)sender didFirstVisuallyNonEmptyLayoutInFrame:(WebFrame *)frame;
+// For implementing the WebInspector's test harness
+- (void)webView:(WebView *)webView didClearInspectorWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame;
+
@end
@interface NSObject (WebResourceLoadDelegatePrivate)