[iOS] Upstream WebCore/page changes
https://bugs.webkit.org/show_bug.cgi?id=126180
Reviewed by Darin Adler.
Source/WebCore:
* WebCore.xcodeproj/project.pbxproj:
* dom/EventNames.h:
(WebCore::EventNames::isGestureEventType): Added.
* page/AlternativeTextClient.h: Do not define WTF_USE_DICTATION_ALTERNATIVES when building for iOS.
* page/Chrome.cpp:
(WebCore::Chrome::Chrome):
(WebCore::Chrome::dispatchViewportPropertiesDidChange): Added; guarded by PLATFORM(IOS).
(WebCore::Chrome::setCursor): Make this an empty function when building for iOS.
(WebCore::Chrome::setCursorHiddenUntilMouseMoves): Ditto.
(WebCore::Chrome::didReceiveDocType): Added; iOS-specific.
* page/Chrome.h:
(WebCore::Chrome::setDispatchViewportDataDidChangeSuppressed): Added; guarded by PLATFORM(IOS).
* page/ChromeClient.h:
(WebCore::ChromeClient::didFlushCompositingLayers): Added; guarded by PLATFORM(IOS).
(WebCore::ChromeClient::fetchCustomFixedPositionLayoutRect): Added; guarded by PLATFORM(IOS).
(WebCore::ChromeClient::updateViewportConstrainedLayers): Added; guarded by PLATFORM(IOS).
* page/DOMTimer.cpp:
(WebCore::DOMTimer::install): Added iOS-specific code.
(WebCore::DOMTimer::fired): Ditto.
* page/DOMWindow.cpp:
(WebCore::DOMWindow::DOMWindow): Ditto.
(WebCore::DOMWindow::innerHeight): Ditto.
(WebCore::DOMWindow::innerWidth): Ditto.
(WebCore::DOMWindow::scrollX): Ditto.
(WebCore::DOMWindow::scrollY): Ditto.
(WebCore::DOMWindow::scrollBy): Ditto.
(WebCore::DOMWindow::scrollTo): Ditto.
(WebCore::DOMWindow::clearTimeout): Ditto.
(WebCore::DOMWindow::addEventListener): Ditto.
(WebCore::DOMWindow::incrementScrollEventListenersCount): Added; guarded by PLATFORM(IOS).
(WebCore::DOMWindow::decrementScrollEventListenersCount): Added; guarded by PLATFORM(IOS).
(WebCore::DOMWindow::resetAllGeolocationPermission): Added; Also added FIXME comment.
(WebCore::DOMWindow::removeEventListener): Added iOS-specific code.
(WebCore::DOMWindow::dispatchEvent): Modified to prevent dispatching duplicate pageshow and pagehide
events per <http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-pageshow>.
(WebCore::DOMWindow::removeAllEventListeners): Added iOS-specific code.
* page/DOMWindow.h:
* page/DOMWindow.idl: Added IOS_GESTURE_EVENTS-guarded attributes: ongesture{change, end, start}. Also
added IOS_TOUCH_EVENTS-guarded attributes: {Touch, TouchList}Constructor.
* page/EditorClient.h:
* page/EventHandler.cpp:
(WebCore::EventHandler::EventHandler): Added iOS-specific code.
(WebCore::EventHandler::clear): Ditto.
(WebCore::EventHandler::startPanScrolling): Make this an empty function when building for iOS.
(WebCore::EventHandler::handleMousePressEvent): Modified to invalidate a click when the clicked node is
null. Also, opt out of code for updating the scrollbars as UIKit manages scrollbars on iOS.
(WebCore::EventHandler::handleMouseMoveEvent): Opt of code for updating the scrollbars and cursor when building on iOS.
(WebCore::hitTestResultInFrame): Made this a file-local static function since it's only used in EventHandler.cpp.
(WebCore::EventHandler::dispatchSyntheticTouchEventIfEnabled): Added iOS-specific code.
* page/EventHandler.h:
* page/FocusController.h:
* page/Frame.cpp:
(WebCore::Frame::Frame): Added iOS-specific code.
(WebCore::Frame::scrollOverflowLayer): Added; iOS-specific.
(WebCore::Frame::overflowAutoScrollTimerFired): Added; iOS-specific.
(WebCore::Frame::startOverflowAutoScroll): Added; iOS-specific.
(WebCore::Frame::checkOverflowScroll): Added; iOS-specific.
(WebCore::Frame::willDetachPage): Added iOS-specific code.
(WebCore::Frame::createView): Ditto.
(WebCore::Frame::setSelectionChangeCallbacksDisabled): Added; iOS-specific.
(WebCore::Frame::selectionChangeCallbacksDisabled): Added; iOS-specific.
* page/Frame.h:
(WebCore::Frame::timersPaused): Added; guarded by PLATFORM(IOS).
* page/FrameView.cpp:
(WebCore::FrameView::FrameView): Added iOS-specific code.
(WebCore::FrameView::clear): Ditto.
(WebCore::FrameView::flushCompositingStateForThisFrame): Ditto.
(WebCore::FrameView::graphicsLayerForPlatformWidget): Added.
(WebCore::FrameView::scheduleLayerFlushAllowingThrottling): Added.
(WebCore::FrameView::layout): Added iOS-specific code.
(WebCore::countRenderedCharactersInRenderObjectWithThreshold): Added; helper function used by FrameView::renderedCharactersExceed().
Also added FIXME comment.
(WebCore::FrameView::renderedCharactersExceed): Added.
(WebCore::FrameView::visibleContentsResized): Added iOS-specific code.
(WebCore::FrameView::adjustTiledBackingCoverage): Ditto.
(WebCore::FrameView::performPostLayoutTasks): Ditto.
(WebCore::FrameView::sendResizeEventIfNeeded): Ditto.
(WebCore::FrameView::paintContents): Added iOS-specific code. Also added FIXME comments.
(WebCore::FrameView::setUseCustomFixedPositionLayoutRect): Added; iOS-specific.
(WebCore::FrameView::setCustomFixedPositionLayoutRect): Added; iOS-specific.
(WebCore::FrameView::updateFixedPositionLayoutRect): Added; iOS-specific.
* page/FrameView.h:
* page/Navigator.cpp:
(WebCore::Navigator::standalone): Added; iOS-specific.
* page/Navigator.h:
* page/Navigator.idl: Added WTF_PLATFORM_IOS-guarded attribute: standalone. Also added FIXME comment.
* page/NavigatorBase.cpp:
(WebCore::NavigatorBase::platform): Added iOS-specific code.
* page/Page.h:
(WebCore::Page::hasCustomHTMLTokenizerTimeDelay): Added; guarded by PLATFORM(IOS). Also added FIXME comment
to remove this method.
(WebCore::Page::customHTMLTokenizerTimeDelay): Added; guarded by PLATFORM(IOS). Also added FIXME comment
to remove this method.
* page/PageGroup.cpp:
(WebCore::PageGroup::removeVisitedLink): Added.
* page/PageGroup.h:
* page/Settings.cpp:
(WebCore::Settings::Settings):
(WebCore::Settings::setScriptEnabled): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setStandalone): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setAudioSessionCategoryOverride): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::audioSessionCategoryOverride): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setNetworkDataUsageTrackingEnabled): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::networkDataUsageTrackingEnabled): Added; guarded by PLATFORM(IOS).
(WebCore::sharedNetworkInterfaceNameGlobal): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setNetworkInterfaceName): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::networkInterfaceName): Added; guarded by PLATFORM(IOS).
* page/Settings.h:
(WebCore::Settings::setMaxParseDuration): Added; guarded by PLATFORM(IOS). Also added FIXME comment.
(WebCore::Settings::maxParseDuration): Added; guarded by PLATFORM(IOS). Also added FIXME comment.
(WebCore::Settings::standalone): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setTelephoneNumberParsingEnabled): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::telephoneNumberParsingEnabled): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setMediaDataLoadsAutomatically): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::mediaDataLoadsAutomatically): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setShouldTransformsAffectOverflow): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::shouldTransformsAffectOverflow): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setShouldDispatchJavaScriptWindowOnErrorEvents): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::shouldDispatchJavaScriptWindowOnErrorEvents): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setAlwaysUseBaselineOfPrimaryFont): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::alwaysUseBaselineOfPrimaryFont): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::setAlwaysUseAcceleratedOverflowScroll): Added; guarded by PLATFORM(IOS).
(WebCore::Settings::alwaysUseAcceleratedOverflowScroll): Added; guarded by PLATFORM(IOS).
* page/Settings.in: Added IOS_AIRPLAY-guarded setting: mediaPlaybackAllowsAirPlay.
* page/animation/CSSPropertyAnimation.cpp:
(WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap): Added iOS-specific code and FIXME comment.
* page/ios/EventHandlerIOS.mm: Added.
* page/ios/FrameIOS.mm: Added.
* page/mac/ChromeMac.mm:
* page/mac/PageMac.cpp:
(WebCore::Page::addSchedulePair): Opt out of code when building for iOS.
(WebCore::Page::removeSchedulePair): Ditto.
* page/mac/SettingsMac.mm:
(WebCore::Settings::shouldEnableScreenFontSubstitutionByDefault): Added iOS-specific code.
* page/mac/WebCoreFrameView.h:
Source/WebKit/ios:
* WebCoreSupport/WebChromeClientIOS.mm: Substitute ENABLE(IOS_TOUCH_EVENTS) for ENABLE(TOUCH_EVENTS).
Source/WebKit2:
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm: Added.
* WebProcess/WebPage/WebPage.cpp: Include header <WebCore/HitTestResult.h>.
Source/WTF:
* wtf/FeatureDefines.h: Define ENABLE_IOS_TOUCH_EVENTS to be enabled by default
when building iOS with ENABLE(TOUCH_EVENTS).
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@161106 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog
index fe42280..fe85b05 100644
--- a/Source/WTF/ChangeLog
+++ b/Source/WTF/ChangeLog
@@ -1,3 +1,13 @@
+2013-12-27 Daniel Bates <dabates@apple.com>
+
+ [iOS] Upstream WebCore/page changes
+ https://bugs.webkit.org/show_bug.cgi?id=126180
+
+ Reviewed by Darin Adler.
+
+ * wtf/FeatureDefines.h: Define ENABLE_IOS_TOUCH_EVENTS to be enabled by default
+ when building iOS with ENABLE(TOUCH_EVENTS).
+
2013-12-25 Thiago de Barros Lacerda <thiago.lacerda@openbossa.org>
[Nix] Building with DRAG_SUPPORT enabled
diff --git a/Source/WTF/wtf/FeatureDefines.h b/Source/WTF/wtf/FeatureDefines.h
index 8a6fa53..f8532aa 100644
--- a/Source/WTF/wtf/FeatureDefines.h
+++ b/Source/WTF/wtf/FeatureDefines.h
@@ -68,6 +68,10 @@
#define ENABLE_CSS_IMAGE_SET 1
#endif
+#if !defined(ENABLE_CURSOR_SUPPORT)
+#define ENABLE_CURSOR_SUPPORT 0
+#endif
+
#if !defined(ENABLE_DISK_IMAGE_CACHE)
#define ENABLE_DISK_IMAGE_CACHE 1
#endif
@@ -84,6 +88,10 @@
#define ENABLE_ICONDATABASE 0
#endif
+#if !defined(ENABLE_LETTERPRESS)
+#define ENABLE_LETTERPRESS 1
+#endif
+
#if !defined(ENABLE_IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
#define ENABLE_IOS_AUTOCORRECT_AND_AUTOCAPITALIZE 1
#endif
@@ -92,14 +100,14 @@
#define ENABLE_IOS_GESTURE_EVENTS 1
#endif
-#if !defined(ENABLE_LETTERPRESS)
-#define ENABLE_LETTERPRESS 1
-#endif
-
#if !defined(ENABLE_IOS_TEXT_AUTOSIZING)
#define ENABLE_IOS_TEXT_AUTOSIZING 1
#endif
+#if !defined(ENABLE_IOS_TOUCH_EVENTS)
+#define ENABLE_IOS_TOUCH_EVENTS 1
+#endif
+
#if !defined(ENABLE_METER_ELEMENT)
#define ENABLE_METER_ELEMENT 0
#endif
@@ -430,6 +438,10 @@
#define ENABLE_CSS_TRANSFORMS_ANIMATIONS_TRANSITIONS_UNPREFIXED 0
#endif
+#if !defined(ENABLE_CURSOR_SUPPORT)
+#define ENABLE_CURSOR_SUPPORT 1
+#endif
+
#if !defined(ENABLE_CUSTOM_SCHEME_HANDLER)
#define ENABLE_CUSTOM_SCHEME_HANDLER 0
#endif
@@ -894,4 +906,8 @@
#error "ENABLE(REMOTE_INSPECTOR) requires ENABLE(INSPECTOR)"
#endif
+#if ENABLE(IOS_TOUCH_EVENTS) && !ENABLE(TOUCH_EVENTS)
+#error "ENABLE(IOS_TOUCH_EVENTS) requires ENABLE(TOUCH_EVENTS)"
+#endif
+
#endif /* WTF_FeatureDefines_h */
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index b0a3ca3..db5b0a8 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,146 @@
+2013-12-27 Daniel Bates <dabates@apple.com>
+
+ [iOS] Upstream WebCore/page changes
+ https://bugs.webkit.org/show_bug.cgi?id=126180
+
+ Reviewed by Darin Adler.
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/EventNames.h:
+ (WebCore::EventNames::isGestureEventType): Added.
+ * page/AlternativeTextClient.h: Do not define WTF_USE_DICTATION_ALTERNATIVES when building for iOS.
+ * page/Chrome.cpp:
+ (WebCore::Chrome::Chrome):
+ (WebCore::Chrome::dispatchViewportPropertiesDidChange): Added; guarded by PLATFORM(IOS).
+ (WebCore::Chrome::setCursor): Make this an empty function when building for iOS.
+ (WebCore::Chrome::setCursorHiddenUntilMouseMoves): Ditto.
+ (WebCore::Chrome::didReceiveDocType): Added; iOS-specific.
+ * page/Chrome.h:
+ (WebCore::Chrome::setDispatchViewportDataDidChangeSuppressed): Added; guarded by PLATFORM(IOS).
+ * page/ChromeClient.h:
+ (WebCore::ChromeClient::didFlushCompositingLayers): Added; guarded by PLATFORM(IOS).
+ (WebCore::ChromeClient::fetchCustomFixedPositionLayoutRect): Added; guarded by PLATFORM(IOS).
+ (WebCore::ChromeClient::updateViewportConstrainedLayers): Added; guarded by PLATFORM(IOS).
+ * page/DOMTimer.cpp:
+ (WebCore::DOMTimer::install): Added iOS-specific code.
+ (WebCore::DOMTimer::fired): Ditto.
+ * page/DOMWindow.cpp:
+ (WebCore::DOMWindow::DOMWindow): Ditto.
+ (WebCore::DOMWindow::innerHeight): Ditto.
+ (WebCore::DOMWindow::innerWidth): Ditto.
+ (WebCore::DOMWindow::scrollX): Ditto.
+ (WebCore::DOMWindow::scrollY): Ditto.
+ (WebCore::DOMWindow::scrollBy): Ditto.
+ (WebCore::DOMWindow::scrollTo): Ditto.
+ (WebCore::DOMWindow::clearTimeout): Ditto.
+ (WebCore::DOMWindow::addEventListener): Ditto.
+ (WebCore::DOMWindow::incrementScrollEventListenersCount): Added; guarded by PLATFORM(IOS).
+ (WebCore::DOMWindow::decrementScrollEventListenersCount): Added; guarded by PLATFORM(IOS).
+ (WebCore::DOMWindow::resetAllGeolocationPermission): Added; Also added FIXME comment.
+ (WebCore::DOMWindow::removeEventListener): Added iOS-specific code.
+ (WebCore::DOMWindow::dispatchEvent): Modified to prevent dispatching duplicate pageshow and pagehide
+ events per <http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-pageshow>.
+ (WebCore::DOMWindow::removeAllEventListeners): Added iOS-specific code.
+ * page/DOMWindow.h:
+ * page/DOMWindow.idl: Added IOS_GESTURE_EVENTS-guarded attributes: ongesture{change, end, start}. Also
+ added IOS_TOUCH_EVENTS-guarded attributes: {Touch, TouchList}Constructor.
+ * page/EditorClient.h:
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::EventHandler): Added iOS-specific code.
+ (WebCore::EventHandler::clear): Ditto.
+ (WebCore::EventHandler::startPanScrolling): Make this an empty function when building for iOS.
+ (WebCore::EventHandler::handleMousePressEvent): Modified to invalidate a click when the clicked node is
+ null. Also, opt out of code for updating the scrollbars as UIKit manages scrollbars on iOS.
+ (WebCore::EventHandler::handleMouseMoveEvent): Opt of code for updating the scrollbars and cursor when building on iOS.
+ (WebCore::hitTestResultInFrame): Made this a file-local static function since it's only used in EventHandler.cpp.
+ (WebCore::EventHandler::dispatchSyntheticTouchEventIfEnabled): Added iOS-specific code.
+ * page/EventHandler.h:
+ * page/FocusController.h:
+ * page/Frame.cpp:
+ (WebCore::Frame::Frame): Added iOS-specific code.
+ (WebCore::Frame::scrollOverflowLayer): Added; iOS-specific.
+ (WebCore::Frame::overflowAutoScrollTimerFired): Added; iOS-specific.
+ (WebCore::Frame::startOverflowAutoScroll): Added; iOS-specific.
+ (WebCore::Frame::checkOverflowScroll): Added; iOS-specific.
+ (WebCore::Frame::willDetachPage): Added iOS-specific code.
+ (WebCore::Frame::createView): Ditto.
+ (WebCore::Frame::setSelectionChangeCallbacksDisabled): Added; iOS-specific.
+ (WebCore::Frame::selectionChangeCallbacksDisabled): Added; iOS-specific.
+ * page/Frame.h:
+ (WebCore::Frame::timersPaused): Added; guarded by PLATFORM(IOS).
+ * page/FrameView.cpp:
+ (WebCore::FrameView::FrameView): Added iOS-specific code.
+ (WebCore::FrameView::clear): Ditto.
+ (WebCore::FrameView::flushCompositingStateForThisFrame): Ditto.
+ (WebCore::FrameView::graphicsLayerForPlatformWidget): Added.
+ (WebCore::FrameView::scheduleLayerFlushAllowingThrottling): Added.
+ (WebCore::FrameView::layout): Added iOS-specific code.
+ (WebCore::countRenderedCharactersInRenderObjectWithThreshold): Added; helper function used by FrameView::renderedCharactersExceed().
+ Also added FIXME comment.
+ (WebCore::FrameView::renderedCharactersExceed): Added.
+ (WebCore::FrameView::visibleContentsResized): Added iOS-specific code.
+ (WebCore::FrameView::adjustTiledBackingCoverage): Ditto.
+ (WebCore::FrameView::performPostLayoutTasks): Ditto.
+ (WebCore::FrameView::sendResizeEventIfNeeded): Ditto.
+ (WebCore::FrameView::paintContents): Added iOS-specific code. Also added FIXME comments.
+ (WebCore::FrameView::setUseCustomFixedPositionLayoutRect): Added; iOS-specific.
+ (WebCore::FrameView::setCustomFixedPositionLayoutRect): Added; iOS-specific.
+ (WebCore::FrameView::updateFixedPositionLayoutRect): Added; iOS-specific.
+ * page/FrameView.h:
+ * page/Navigator.cpp:
+ (WebCore::Navigator::standalone): Added; iOS-specific.
+ * page/Navigator.h:
+ * page/Navigator.idl: Added WTF_PLATFORM_IOS-guarded attribute: standalone. Also added FIXME comment.
+ * page/NavigatorBase.cpp:
+ (WebCore::NavigatorBase::platform): Added iOS-specific code.
+ * page/Page.h:
+ (WebCore::Page::hasCustomHTMLTokenizerTimeDelay): Added; guarded by PLATFORM(IOS). Also added FIXME comment
+ to remove this method.
+ (WebCore::Page::customHTMLTokenizerTimeDelay): Added; guarded by PLATFORM(IOS). Also added FIXME comment
+ to remove this method.
+ * page/PageGroup.cpp:
+ (WebCore::PageGroup::removeVisitedLink): Added.
+ * page/PageGroup.h:
+ * page/Settings.cpp:
+ (WebCore::Settings::Settings):
+ (WebCore::Settings::setScriptEnabled): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setStandalone): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setAudioSessionCategoryOverride): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::audioSessionCategoryOverride): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setNetworkDataUsageTrackingEnabled): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::networkDataUsageTrackingEnabled): Added; guarded by PLATFORM(IOS).
+ (WebCore::sharedNetworkInterfaceNameGlobal): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setNetworkInterfaceName): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::networkInterfaceName): Added; guarded by PLATFORM(IOS).
+ * page/Settings.h:
+ (WebCore::Settings::setMaxParseDuration): Added; guarded by PLATFORM(IOS). Also added FIXME comment.
+ (WebCore::Settings::maxParseDuration): Added; guarded by PLATFORM(IOS). Also added FIXME comment.
+ (WebCore::Settings::standalone): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setTelephoneNumberParsingEnabled): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::telephoneNumberParsingEnabled): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setMediaDataLoadsAutomatically): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::mediaDataLoadsAutomatically): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setShouldTransformsAffectOverflow): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::shouldTransformsAffectOverflow): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setShouldDispatchJavaScriptWindowOnErrorEvents): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::shouldDispatchJavaScriptWindowOnErrorEvents): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setAlwaysUseBaselineOfPrimaryFont): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::alwaysUseBaselineOfPrimaryFont): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::setAlwaysUseAcceleratedOverflowScroll): Added; guarded by PLATFORM(IOS).
+ (WebCore::Settings::alwaysUseAcceleratedOverflowScroll): Added; guarded by PLATFORM(IOS).
+ * page/Settings.in: Added IOS_AIRPLAY-guarded setting: mediaPlaybackAllowsAirPlay.
+ * page/animation/CSSPropertyAnimation.cpp:
+ (WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap): Added iOS-specific code and FIXME comment.
+ * page/ios/EventHandlerIOS.mm: Added.
+ * page/ios/FrameIOS.mm: Added.
+ * page/mac/ChromeMac.mm:
+ * page/mac/PageMac.cpp:
+ (WebCore::Page::addSchedulePair): Opt out of code when building for iOS.
+ (WebCore::Page::removeSchedulePair): Ditto.
+ * page/mac/SettingsMac.mm:
+ (WebCore::Settings::shouldEnableScreenFontSubstitutionByDefault): Added iOS-specific code.
+ * page/mac/WebCoreFrameView.h:
+
2013-12-27 Gavin Barraclough <barraclough@apple.com>
Merge PageVisibilityState & ViewState::IsVisible in WebKit2
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index da88ff9..4a73693 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -5466,6 +5466,8 @@
CE057FA61220731100A476D5 /* DocumentMarkerController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE057FA41220731100A476D5 /* DocumentMarkerController.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE08C3D1152B599A0021B8C2 /* AlternativeTextController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE08C3CF152B599A0021B8C2 /* AlternativeTextController.cpp */; };
CE08C3D2152B599A0021B8C2 /* AlternativeTextController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE08C3D0152B599A0021B8C2 /* AlternativeTextController.h */; settings = {ATTRIBUTES = (); }; };
+ FE6938B61045D67E008EABB6 /* EventHandlerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = FE6938B51045D67E008EABB6 /* EventHandlerIOS.mm */; };
+ FED13D3D0CEA936A00D89466 /* FrameIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = FED13D3B0CEA936A00D89466 /* FrameIOS.mm */; };
CE7B2DB31586ABAD0098B3FA /* AlternativeTextUIController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE7B2DB41586ABAD0098B3FA /* AlternativeTextUIController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */; };
CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -12621,6 +12623,8 @@
CE057FA41220731100A476D5 /* DocumentMarkerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentMarkerController.h; sourceTree = "<group>"; };
CE08C3CF152B599A0021B8C2 /* AlternativeTextController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlternativeTextController.cpp; sourceTree = "<group>"; };
CE08C3D0152B599A0021B8C2 /* AlternativeTextController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlternativeTextController.h; sourceTree = "<group>"; };
+ FE6938B51045D67E008EABB6 /* EventHandlerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EventHandlerIOS.mm; sourceTree = "<group>"; };
+ FED13D3B0CEA936A00D89466 /* FrameIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FrameIOS.mm; sourceTree = "<group>"; };
CE5CB1B314EDAB6F00BB2795 /* EventSender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventSender.h; sourceTree = "<group>"; };
CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AlternativeTextUIController.h; path = mac/AlternativeTextUIController.h; sourceTree = "<group>"; };
CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AlternativeTextUIController.mm; path = mac/AlternativeTextUIController.mm; sourceTree = "<group>"; };
@@ -15731,6 +15735,7 @@
isa = PBXGroup;
children = (
316FE1060E6E1D8400BF6088 /* animation */,
+ 18A6CD6F0D8F2025001DC3CE /* ios */,
93C09A820B064F05005ABD4D /* mac */,
1AF62EE114DA22A70041556C /* scrolling */,
8538F0000AD71770006A81D1 /* AbstractView.idl */,
@@ -20538,6 +20543,15 @@
path = mediasource;
sourceTree = "<group>";
};
+ 18A6CD6F0D8F2025001DC3CE /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ FE6938B51045D67E008EABB6 /* EventHandlerIOS.mm */,
+ FED13D3B0CEA936A00D89466 /* FrameIOS.mm */,
+ );
+ path = ios;
+ sourceTree = "<group>";
+ };
CE79D68617F220ED00815C00 /* ios */ = {
isa = PBXGroup;
children = (
@@ -26350,6 +26364,7 @@
850657010AAB4763002D15C0 /* DOMStyleSheet.mm in Sources */,
850657030AAB4763002D15C0 /* DOMStyleSheetList.mm in Sources */,
85ACA99D0A9B575900671E90 /* DOMText.mm in Sources */,
+ FED13D3D0CEA936A00D89466 /* FrameIOS.mm in Sources */,
933A14AA0B7D1D0900A53FFD /* DOMTextEvent.mm in Sources */,
188604B30F2E654A000B6443 /* DOMTimer.cpp in Sources */,
76FC2B0B12370DA0006A991A /* DOMTokenList.cpp in Sources */,
@@ -28461,6 +28476,7 @@
49C7B9E51042D32F0009D447 /* WebGLTexture.cpp in Sources */,
0C3F1F5A10C8871200D72CE1 /* WebGLUniformLocation.cpp in Sources */,
77A17A7712F28642004E02F6 /* WebGLVertexArrayObjectOES.cpp in Sources */,
+ FE6938B61045D67E008EABB6 /* EventHandlerIOS.mm in Sources */,
31C0FF210E4CEB6E007D6FE5 /* WebKitAnimationEvent.cpp in Sources */,
976D6C7B122B8A3D001FD1F7 /* WebKitBlobBuilder.cpp in Sources */,
150B923915F08DC400E10986 /* WebKitCSSArrayFunctionValue.cpp in Sources */,
diff --git a/Source/WebCore/dom/EventNames.h b/Source/WebCore/dom/EventNames.h
index 048839a..294f239 100644
--- a/Source/WebCore/dom/EventNames.h
+++ b/Source/WebCore/dom/EventNames.h
@@ -290,6 +290,11 @@
DOM_EVENT_NAMES_FOR_EACH(DOM_EVENT_NAMES_DECLARE)
#undef DOM_EVENT_NAMES_DECLARE
+ inline bool isGestureEventType(const AtomicString& eventType) const
+ {
+ return eventType == gesturestartEvent || eventType == gesturechangeEvent || eventType == gestureendEvent;
+ }
+
inline bool isTouchEventType(const AtomicString& eventType) const
{
return eventType == touchstartEvent
diff --git a/Source/WebCore/page/AlternativeTextClient.h b/Source/WebCore/page/AlternativeTextClient.h
index 54477b6..a7e991d 100644
--- a/Source/WebCore/page/AlternativeTextClient.h
+++ b/Source/WebCore/page/AlternativeTextClient.h
@@ -31,10 +31,10 @@
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
-#if PLATFORM(MAC) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
+#if !PLATFORM(IOS) && PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
// Some platforms provide UI for suggesting alternative dictation text.
#define WTF_USE_DICTATION_ALTERNATIVES 1
-#endif // PLATFORM(MAC) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
+#endif // !PLATFORM(IOS) && PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
namespace WebCore {
diff --git a/Source/WebCore/page/Chrome.cpp b/Source/WebCore/page/Chrome.cpp
index 6fc9adff..493fdad 100644
--- a/Source/WebCore/page/Chrome.cpp
+++ b/Source/WebCore/page/Chrome.cpp
@@ -26,6 +26,7 @@
#include "DNS.h"
#include "DateTimeChooser.h"
#include "Document.h"
+#include "DocumentType.h"
#include "FileIconLoader.h"
#include "FileChooser.h"
#include "FileList.h"
@@ -65,6 +66,9 @@
: m_page(page)
, m_client(client)
, m_displayID(0)
+#if PLATFORM(IOS)
+ , m_isDispatchViewportDataDidChangeSuppressed(false)
+#endif
{
}
@@ -477,7 +481,7 @@
}
#endif
-#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES) && !PLATFORM(IOS)
PassRefPtr<DateTimeChooser> Chrome::openDateTimeChooser(DateTimeChooserClient* client, const DateTimeChooserParameters& parameters)
{
notifyPopupOpeningObservers();
@@ -498,17 +502,29 @@
void Chrome::dispatchViewportPropertiesDidChange(const ViewportArguments& arguments) const
{
+#if PLATFORM(IOS)
+ if (m_isDispatchViewportDataDidChangeSuppressed)
+ return;
+#endif
m_client.dispatchViewportPropertiesDidChange(arguments);
}
void Chrome::setCursor(const Cursor& cursor)
{
+#if ENABLE(CURSOR_SUPPORT)
m_client.setCursor(cursor);
+#else
+ UNUSED_PARAM(cursor);
+#endif
}
void Chrome::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
{
+#if ENABLE(CURSOR_SUPPORT)
m_client.setCursorHiddenUntilMouseMoves(hiddenUntilMouseMoves);
+#else
+ UNUSED_PARAM(hiddenUntilMouseMoves);
+#endif
}
#if ENABLE(REQUEST_ANIMATION_FRAME)
@@ -602,6 +618,26 @@
return m_client.requiresFullscreenForVideoPlayback();
}
+#if PLATFORM(IOS)
+// FIXME: Make argument, frame, a reference.
+void Chrome::didReceiveDocType(Frame* frame)
+{
+ ASSERT(frame);
+ if (!frame->isMainFrame())
+ return;
+
+ DocumentType* documentType = frame->document()->doctype();
+ if (!documentType) {
+ // FIXME: We should notify the client when <!DOCTYPE> is removed so that
+ // it can adjust the viewport accordingly. See <rdar://problem/15417894>.
+ return;
+ }
+
+ if (documentType->publicId().contains("xhtml mobile", false))
+ m_client.didReceiveMobileDocType();
+}
+#endif
+
void Chrome::registerPopupOpeningObserver(PopupOpeningObserver* observer)
{
ASSERT(observer);
diff --git a/Source/WebCore/page/Chrome.h b/Source/WebCore/page/Chrome.h
index 464400f..529c152 100644
--- a/Source/WebCore/page/Chrome.h
+++ b/Source/WebCore/page/Chrome.h
@@ -155,8 +155,9 @@
#if ENABLE(INPUT_TYPE_COLOR)
PassOwnPtr<ColorChooser> createColorChooser(ColorChooserClient*, const Color& initialColor);
#endif
-#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
- PassRefPtr<DateTimeChooser> openDateTimeChooser(DateTimeChooserClient*, const DateTimeChooserParameters&);
+
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES) && !PLATFORM(IOS)
+ PassRefPtr<DateTimeChooser> openDateTimeChooser(DateTimeChooserClient*, const DateTimeChooserParameters&)
#endif
void runOpenPanel(Frame*, PassRefPtr<FileChooser>);
@@ -179,6 +180,13 @@
PassRefPtr<PopupMenu> createPopupMenu(PopupMenuClient*) const;
PassRefPtr<SearchPopupMenu> createSearchPopupMenu(PopupMenuClient*) const;
+#if PLATFORM(IOS)
+ // FIXME: Can we come up with a better name for this setter?
+ void setDispatchViewportDataDidChangeSuppressed(bool dispatchViewportDataDidChangeSuppressed) { m_isDispatchViewportDataDidChangeSuppressed = dispatchViewportDataDidChangeSuppressed; }
+
+ void didReceiveDocType(Frame*);
+#endif
+
void registerPopupOpeningObserver(PopupOpeningObserver*);
void unregisterPopupOpeningObserver(PopupOpeningObserver*);
@@ -189,6 +197,9 @@
ChromeClient& m_client;
PlatformDisplayID m_displayID;
Vector<PopupOpeningObserver*> m_popupOpeningObservers;
+#if PLATFORM(IOS)
+ bool m_isDispatchViewportDataDidChangeSuppressed;
+#endif
};
}
diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h
index ee94476..ba87c70 100644
--- a/Source/WebCore/page/ChromeClient.h
+++ b/Source/WebCore/page/ChromeClient.h
@@ -40,6 +40,16 @@
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
+#if PLATFORM(IOS)
+#include "PlatformLayer.h"
+#define NSResponder WAKResponder
+#ifndef __OBJC__
+class WAKResponder;
+#else
+@class WAKResponder;
+#endif
+#endif
+
#if ENABLE(SQL_DATABASE)
#include "DatabaseDetails.h"
#endif
@@ -62,14 +72,15 @@
class GraphicsContext3D;
class GraphicsLayer;
class GraphicsLayerFactory;
-class HitTestResult;
class HTMLInputElement;
+class HitTestResult;
class IntRect;
class NavigationAction;
class Node;
class Page;
class PopupMenuClient;
class SecurityOrigin;
+class ViewportConstraints;
class Widget;
struct DateTimeChooserParameters;
@@ -156,8 +167,10 @@
virtual IntRect rootViewToScreen(const IntRect&) const = 0;
virtual PlatformPageClient platformPageClient() const = 0;
virtual void scrollbarsModeDidChange() const = 0;
+#if ENABLE(CURSOR_SUPPORT)
virtual void setCursor(const Cursor&) = 0;
virtual void setCursorHiddenUntilMouseMoves(bool) = 0;
+#endif
#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER)
virtual void scheduleAnimation() = 0;
#endif
@@ -212,11 +225,46 @@
virtual bool shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename);
virtual String generateReplacementFile(const String& path);
+#if ENABLE(IOS_TOUCH_EVENTS)
+ virtual void didPreventDefaultForEvent() = 0;
+#endif
+
+#if PLATFORM(IOS)
+ virtual void didReceiveMobileDocType() = 0;
+ virtual void setNeedsScrollNotifications(Frame*, bool) = 0;
+ virtual void observedContentChange(Frame*) = 0;
+ virtual void clearContentChangeObservers(Frame*) = 0;
+ virtual void notifyRevealedSelectionByScrollingFrame(Frame*) = 0;
+
+ enum LayoutType { NormalLayout, Scroll };
+ virtual void didLayout(LayoutType = NormalLayout) = 0;
+ virtual void didStartOverflowScroll() = 0;
+ virtual void didEndOverflowScroll() = 0;
+
+ // FIXME: Remove this functionality. This functionality was added to workaround an issue (<rdar://problem/5973875>)
+ // where the unconfirmed text in a text area would be removed when a person clicks in the text area before a
+ // suggestion is shown. We should fix this issue in <rdar://problem/5975559>.
+ virtual void suppressFormNotifications() = 0;
+ virtual void restoreFormNotifications() = 0;
+
+ virtual void didFlushCompositingLayers() { }
+
+ virtual bool fetchCustomFixedPositionLayoutRect(IntRect&) { return false; }
+
+ // FIXME: Use std::unique_ptr instead of OwnPtr.
+ virtual void updateViewportConstrainedLayers(HashMap<PlatformLayer*, OwnPtr<ViewportConstraints>>&, HashMap<PlatformLayer*, PlatformLayer*>&) { }
+
+ virtual void addOrUpdateScrollingLayer(Node*, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer, const IntSize& scrollSize, bool allowHorizontalScrollbar, bool allowVerticalScrollbar) = 0;
+ virtual void removeScrollingLayer(Node*, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer) = 0;
+
+ virtual void webAppOrientationsUpdated() = 0;
+#endif
+
#if ENABLE(INPUT_TYPE_COLOR)
virtual PassOwnPtr<ColorChooser> createColorChooser(ColorChooserClient*, const Color&) = 0;
#endif
-#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+#if ENABLE(DATE_AND_TIME_INPUT_TYPES) && !PLATFORM(IOS)
virtual PassRefPtr<DateTimeChooser> openDateTimeChooser(DateTimeChooserClient*, const DateTimeChooserParameters&) = 0;
#endif
diff --git a/Source/WebCore/page/DOMTimer.cpp b/Source/WebCore/page/DOMTimer.cpp
index 6527a06..0c99e0d 100644
--- a/Source/WebCore/page/DOMTimer.cpp
+++ b/Source/WebCore/page/DOMTimer.cpp
@@ -35,6 +35,14 @@
#include <wtf/HashSet.h>
#include <wtf/StdLibExtras.h>
+#if PLATFORM(IOS)
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "Frame.h"
+#include "Page.h"
+#include "WKContentObservation.h"
+#endif
+
namespace WebCore {
static const int maxIntervalForUserGestureForwarding = 1000; // One second matches Gecko.
@@ -81,6 +89,16 @@
// The timer is deleted when context is deleted (DOMTimer::contextDestroyed) or explicitly via DOMTimer::removeById(),
// or if it is a one-time timer and it has fired (DOMTimer::fired).
DOMTimer* timer = new DOMTimer(context, action, timeout, singleShot);
+#if PLATFORM(IOS)
+ if (context->isDocument()) {
+ Document& document = toDocument(*context);
+ bool didDeferTimeout = document.frame() && document.frame()->timersPaused();
+ if (!didDeferTimeout && timeout <= 100 && singleShot) {
+ WKSetObservedContentChange(WKContentIndeterminateChange);
+ WebThreadAddObservedContentModifier(timer); // Will only take affect if not already visibility change.
+ }
+ }
+#endif
timer->suspendIfNeeded();
InspectorInstrumentation::didInstallTimer(context, timer->m_timeoutId, timeout, singleShot);
@@ -104,6 +122,14 @@
void DOMTimer::fired()
{
ScriptExecutionContext* context = scriptExecutionContext();
+ ASSERT(context);
+#if PLATFORM(IOS)
+ Document* document = nullptr;
+ if (!context->isDocument()) {
+ document = toDocument(context);
+ ASSERT(!document->frame()->timersPaused());
+ }
+#endif
timerNestingLevel = m_nestingLevel;
ASSERT(!isSuspended());
ASSERT(!context->activeDOMObjectsAreSuspended());
@@ -136,8 +162,35 @@
// No access to member variables after this point.
delete this;
+#if PLATFORM(IOS)
+ bool shouldReportLackOfChanges;
+ bool shouldBeginObservingChanges;
+ if (document) {
+ shouldReportLackOfChanges = WebThreadCountOfObservedContentModifiers() == 1;
+ shouldBeginObservingChanges = WebThreadContainsObservedContentModifier(this);
+ } else {
+ shouldReportLackOfChanges = false;
+ shouldBeginObservingChanges = false;
+ }
+
+ if (shouldBeginObservingChanges) {
+ WKBeginObservingContentChanges(false);
+ WebThreadRemoveObservedContentModifier(this);
+ }
+#endif
+
action->execute(context);
+#if PLATFORM(IOS)
+ if (shouldBeginObservingChanges) {
+ WKStopObservingContentChanges();
+
+ if (WKObservedContentChange() == WKContentVisibilityChange || shouldReportLackOfChanges)
+ if (document && document->page())
+ document->page()->chrome().client().observedContentChange(document->frame());
+ }
+#endif
+
InspectorInstrumentation::didFireTimer(cookie);
timerNestingLevel = 0;
diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp
index 966030c..c795b1b 100644
--- a/Source/WebCore/page/DOMWindow.cpp
+++ b/Source/WebCore/page/DOMWindow.cpp
@@ -117,6 +117,13 @@
#include "RequestAnimationFrameCallback.h"
#endif
+#if PLATFORM(IOS)
+#if ENABLE(GEOLOCATION)
+#include "NavigatorGeolocation.h"
+#endif
+#include "WKContentObservation.h"
+#endif
+
namespace WebCore {
class PostMessageTimer : public TimerBase {
@@ -371,6 +378,13 @@
, FrameDestructionObserver(document->frame())
, m_shouldPrintWhenFinishedLoading(false)
, m_suspendedForPageCache(false)
+ , m_lastPageStatus(PageStatusNone)
+#if PLATFORM(IOS)
+ , m_scrollEventListenerCount(0)
+#endif
+#if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS)
+ , m_touchEventListenerCount(0)
+#endif
{
ASSERT(frame());
ASSERT(DOMWindow::document());
@@ -1139,9 +1153,13 @@
if (!view)
return 0;
+#if PLATFORM(IOS)
+ return view->mapFromLayoutToCSSUnits(static_cast<int>(view->actualVisibleContentRect().height()));
+#else
// If the device height is overridden, do not include the horizontal scrollbar into the innerHeight (since it is absent on the real device).
bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenHeightOverride(m_frame);
return view->mapFromLayoutToCSSUnits(static_cast<int>(view->visibleContentRect(includeScrollbars ? ScrollableArea::IncludeScrollbars : ScrollableArea::ExcludeScrollbars).height()));
+#endif
}
int DOMWindow::innerWidth() const
@@ -1153,9 +1171,13 @@
if (!view)
return 0;
+#if PLATFORM(IOS)
+ return view->mapFromLayoutToCSSUnits(static_cast<int>(view->actualVisibleContentRect().width()));
+#else
// If the device width is overridden, do not include the vertical scrollbar into the innerWidth (since it is absent on the real device).
bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenWidthOverride(m_frame);
return view->mapFromLayoutToCSSUnits(static_cast<int>(view->visibleContentRect(includeScrollbars ? ScrollableArea::IncludeScrollbars : ScrollableArea::ExcludeScrollbars).width()));
+#endif
}
int DOMWindow::screenX() const
@@ -1196,7 +1218,11 @@
m_frame->document()->updateLayoutIgnorePendingStylesheets();
+#if PLATFORM(IOS)
+ return static_cast<int>(view->actualVisibleContentRect().x() / (m_frame->pageZoomFactor() * m_frame->frameScaleFactor()));
+#else
return view->mapFromLayoutToCSSUnits(view->scrollX());
+#endif
}
int DOMWindow::scrollY() const
@@ -1213,7 +1239,11 @@
m_frame->document()->updateLayoutIgnorePendingStylesheets();
+#if PLATFORM(IOS)
+ return static_cast<int>(view->actualVisibleContentRect().y() / (m_frame->pageZoomFactor() * m_frame->frameScaleFactor()));
+#else
return view->mapFromLayoutToCSSUnits(view->scrollY());
+#endif
}
bool DOMWindow::closed() const
@@ -1425,7 +1455,11 @@
return;
IntSize scaledOffset(view->mapFromCSSToLayoutUnits(x), view->mapFromCSSToLayoutUnits(y));
+#if PLATFORM(IOS)
+ view->setActualScrollPosition(view->actualVisibleContentRect().location() + scaledOffset);
+#else
view->scrollBy(scaledOffset);
+#endif
}
void DOMWindow::scrollTo(int x, int y) const
@@ -1439,8 +1473,15 @@
if (!view)
return;
+
+#if PLATFORM(IOS)
+ int zoomedX = static_cast<int>(x * m_frame->pageZoomFactor() * m_frame->frameScaleFactor());
+ int zoomedY = static_cast<int>(y * m_frame->pageZoomFactor() * m_frame->frameScaleFactor());
+ view->setActualScrollPosition(IntPoint(zoomedX, zoomedY));
+#else
IntPoint layoutPos(view->mapFromCSSToLayoutUnits(x), view->mapFromCSSToLayoutUnits(y));
view->setScrollPosition(layoutPos);
+#endif
}
bool DOMWindow::allowedToChangeWindowGeometry() const
@@ -1521,6 +1562,22 @@
void DOMWindow::clearTimeout(int timeoutId)
{
+#if PLATFORM(IOS)
+ if (m_frame) {
+ Document* document = m_frame->document();
+ if (timeoutId > 0 && document) {
+ DOMTimer* timer = document->findTimeout(timeoutId);
+ if (timer && WebThreadContainsObservedContentModifier(timer)) {
+ WebThreadRemoveObservedContentModifier(timer);
+
+ if (!WebThreadCountOfObservedContentModifiers()) {
+ if (Page* page = m_frame->page())
+ page->chrome().client().observedContentChange(m_frame);
+ }
+ }
+ }
+ }
+#endif
ScriptExecutionContext* context = scriptExecutionContext();
if (!context)
return;
@@ -1608,6 +1665,12 @@
else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this))
addBeforeUnloadEventListener(this);
#if ENABLE(DEVICE_ORIENTATION)
+#if PLATFORM(IOS)
+ else if (eventType == eventNames().devicemotionEvent && document())
+ document()->deviceMotionController()->addDeviceEventListener(this);
+ else if (eventType == eventNames().deviceorientationEvent && document())
+ document()->deviceOrientationController()->addDeviceEventListener(this);
+#else
else if (eventType == eventNames().devicemotionEvent && RuntimeEnabledFeatures::sharedFeatures().deviceMotionEnabled()) {
if (DeviceMotionController* controller = DeviceMotionController::from(page()))
controller->addDeviceEventListener(this);
@@ -1615,6 +1678,19 @@
if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
controller->addDeviceEventListener(this);
}
+#endif // PLATFORM(IOS)
+#endif // ENABLE(DEVICE_ORIENTATION)
+#if PLATFORM(IOS)
+ else if (eventType == eventNames().scrollEvent)
+ incrementScrollEventListenersCount();
+#endif
+#if ENABLE(IOS_TOUCH_EVENTS)
+ else if (eventNames().isTouchEventType(eventType))
+ ++m_touchEventListenerCount;
+#endif
+#if ENABLE(IOS_GESTURE_EVENTS)
+ else if (eventNames().isGestureEventType(eventType))
+ ++m_touchEventListenerCount;
#endif
#if ENABLE(PROXIMITY_EVENTS)
@@ -1627,6 +1703,37 @@
return true;
}
+#if PLATFORM(IOS)
+void DOMWindow::incrementScrollEventListenersCount()
+{
+ Document* document = this->document();
+ if (++m_scrollEventListenerCount == 1 && document == document->topDocument()) {
+ Frame* frame = this->frame();
+ if (frame && frame->page())
+ frame->page()->chrome().client().setNeedsScrollNotifications(frame, true);
+ }
+}
+
+void DOMWindow::decrementScrollEventListenersCount()
+{
+ Document* document = this->document();
+ if (!--m_scrollEventListenerCount && document == document->topDocument()) {
+ Frame* frame = this->frame();
+ if (frame && frame->page() && !document->inPageCache())
+ frame->page()->chrome().client().setNeedsScrollNotifications(frame, false);
+ }
+}
+#endif
+
+void DOMWindow::resetAllGeolocationPermission()
+{
+ // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to Geolocation.cpp.
+#if ENABLE(GEOLOCATION) && PLATFORM(IOS)
+ if (m_navigator)
+ NavigatorGeolocation::from(m_navigator.get())->resetAllGeolocationPermission();
+#endif
+}
+
bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
{
if (!EventTarget::removeEventListener(eventType, listener, useCapture))
@@ -1644,6 +1751,12 @@
else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this))
removeBeforeUnloadEventListener(this);
#if ENABLE(DEVICE_ORIENTATION)
+#if PLATFORM(IOS)
+ else if (eventType == eventNames().devicemotionEvent && document())
+ document()->deviceMotionController()->removeDeviceEventListener(this);
+ else if (eventType == eventNames().deviceorientationEvent && document())
+ document()->deviceOrientationController()->removeDeviceEventListener(this);
+#else
else if (eventType == eventNames().devicemotionEvent) {
if (DeviceMotionController* controller = DeviceMotionController::from(page()))
controller->removeDeviceEventListener(this);
@@ -1651,6 +1764,23 @@
if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
controller->removeDeviceEventListener(this);
}
+#endif // PLATFORM(IOS)
+#endif // ENABLE(DEVICE_ORIENTATION)
+#if PLATFORM(IOS)
+ else if (eventType == eventNames().scrollEvent)
+ decrementScrollEventListenersCount();
+#endif
+#if ENABLE(IOS_TOUCH_EVENTS)
+ else if (eventNames().isTouchEventType(eventType)) {
+ ASSERT(m_touchEventListenerCount > 0);
+ --m_touchEventListenerCount;
+ }
+#endif
+#if ENABLE(IOS_GESTURE_EVENTS)
+ else if (eventNames().isGestureEventType(eventType)) {
+ ASSERT(m_touchEventListenerCount > 0);
+ --m_touchEventListenerCount;
+ }
#endif
#if ENABLE(PROXIMITY_EVENTS)
@@ -1692,6 +1822,22 @@
Ref<EventTarget> protect(*this);
RefPtr<Event> event = prpEvent;
+ // Pausing a page may trigger pagehide and pageshow events. WebCore also implicitly fires these
+ // events when closing a WebView. Here we keep track of the state of the page to prevent duplicate,
+ // unbalanced events per the definition of the pageshow event:
+ // <http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-pageshow>.
+ if (event->eventInterface() == PageTransitionEventInterfaceType) {
+ if (event->type() == eventNames().pageshowEvent) {
+ if (m_lastPageStatus == PageStatusShown)
+ return true; // Event was previously dispatched; do not fire a duplicate event.
+ m_lastPageStatus = PageStatusShown;
+ } else if (event->type() == eventNames().pagehideEvent) {
+ if (m_lastPageStatus == PageStatusHidden)
+ return true; // Event was previously dispatched; do not fire a duplicate event.
+ m_lastPageStatus = PageStatusHidden;
+ }
+ }
+
event->setTarget(prpTarget ? prpTarget : this);
event->setCurrentTarget(this);
event->setEventPhase(Event::AT_TARGET);
@@ -1710,11 +1856,30 @@
EventTarget::removeAllEventListeners();
#if ENABLE(DEVICE_ORIENTATION)
+#if PLATFORM(IOS)
+ if (Document* document = this->document()) {
+ document->deviceMotionController()->removeAllDeviceEventListeners(this);
+ document->deviceOrientationController()->removeAllDeviceEventListeners(this);
+ }
+#else
if (DeviceMotionController* controller = DeviceMotionController::from(page()))
controller->removeAllDeviceEventListeners(this);
if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
controller->removeAllDeviceEventListeners(this);
+#endif // PLATFORM(IOS)
+#endif // ENABLE(DEVICE_ORIENTATION)
+
+#if PLATFORM(IOS)
+ if (m_scrollEventListenerCount) {
+ m_scrollEventListenerCount = 1;
+ decrementScrollEventListenersCount();
+ }
#endif
+
+#if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS)
+ m_touchEventListenerCount = 0;
+#endif
+
#if ENABLE(TOUCH_EVENTS)
if (Document* document = this->document())
document->didRemoveEventTargetNode(document);
diff --git a/Source/WebCore/page/DOMWindow.h b/Source/WebCore/page/DOMWindow.h
index c8b7062..fe7dc7f 100644
--- a/Source/WebCore/page/DOMWindow.h
+++ b/Source/WebCore/page/DOMWindow.h
@@ -397,10 +397,28 @@
DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
#endif
+#if ENABLE(IOS_GESTURE_EVENTS)
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(gesturestart);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(gesturechange);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(gestureend);
+#endif
+
#if ENABLE(WEB_TIMING)
Performance* performance() const;
#endif
+#if PLATFORM(IOS)
+ void incrementScrollEventListenersCount();
+ void decrementScrollEventListenersCount();
+ unsigned scrollEventListenerCount() const { return m_scrollEventListenerCount; }
+#endif
+
+ void resetAllGeolocationPermission();
+
+#if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS)
+ bool hasTouchEventListeners() const { return m_touchEventListenerCount > 0; }
+#endif
+
// FIXME: When this DOMWindow is no longer the active DOMWindow (i.e.,
// when its document is no longer the document that is displayed in its
// frame), we would like to zero out m_frame to avoid being confused
@@ -457,6 +475,17 @@
String m_status;
String m_defaultStatus;
+ enum PageStatus { PageStatusNone, PageStatusShown, PageStatusHidden };
+ PageStatus m_lastPageStatus;
+
+#if PLATFORM(IOS)
+ unsigned m_scrollEventListenerCount;
+#endif
+
+#if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS)
+ unsigned m_touchEventListenerCount;
+#endif
+
mutable RefPtr<Storage> m_sessionStorage;
mutable RefPtr<Storage> m_localStorage;
mutable RefPtr<DOMApplicationCache> m_applicationCache;
diff --git a/Source/WebCore/page/DOMWindow.idl b/Source/WebCore/page/DOMWindow.idl
index 74b4a6f..a067f54 100644
--- a/Source/WebCore/page/DOMWindow.idl
+++ b/Source/WebCore/page/DOMWindow.idl
@@ -285,6 +285,10 @@
[Conditional=TOUCH_EVENTS] attribute EventListener ontouchend;
[Conditional=TOUCH_EVENTS] attribute EventListener ontouchcancel;
+ [Conditional=IOS_GESTURE_EVENTS] attribute EventListener ongesturestart;
+ [Conditional=IOS_GESTURE_EVENTS] attribute EventListener ongesturechange;
+ [Conditional=IOS_GESTURE_EVENTS] attribute EventListener ongestureend;
+
[Conditional=DEVICE_ORIENTATION] attribute EventListener ondevicemotion;
[Conditional=DEVICE_ORIENTATION] attribute EventListener ondeviceorientation;
@@ -308,6 +312,10 @@
// Mozilla has a separate XMLDocument object for XML documents.
// We just use Document for this.
attribute DocumentConstructor XMLDocument;
+
+ [Conditional=IOS_TOUCH_EVENTS, CustomGetter] attribute TouchConstructor Touch; // Usable with the new operator
+ [Conditional=IOS_TOUCH_EVENTS, CustomGetter] attribute TouchListConstructor TouchList; // Usable with the new operator
+
[Conditional=BLOB] attribute DOMURLConstructor webkitURL; // FIXME: deprecate this.
attribute MutationObserverConstructor WebKitMutationObserver; // FIXME: Add metrics to determine when we can remove this.
[Conditional=INDEXED_DATABASE] attribute IDBCursorConstructor webkitIDBCursor;
diff --git a/Source/WebCore/page/EditorClient.h b/Source/WebCore/page/EditorClient.h
index 6fbad7d..8623994 100644
--- a/Source/WebCore/page/EditorClient.h
+++ b/Source/WebCore/page/EditorClient.h
@@ -41,6 +41,11 @@
OBJC_CLASS NSURL;
#endif
+#if PLATFORM(IOS)
+OBJC_CLASS NSArray;
+OBJC_CLASS NSDictionary;
+#endif
+
namespace WebCore {
class ArchiveResource;
@@ -113,6 +118,21 @@
virtual void textWillBeDeletedInTextField(Element*) = 0;
virtual void textDidChangeInTextArea(Element*) = 0;
+#if PLATFORM(IOS)
+ virtual void suppressSelectionNotifications() = 0;
+ virtual void restoreSelectionNotifications() = 0;
+ virtual void startDelayingAndCoalescingContentChangeNotifications() = 0;
+ virtual void stopDelayingAndCoalescingContentChangeNotifications() = 0;
+ virtual void writeDataToPasteboard(NSDictionary*) = 0;
+ virtual NSArray* supportedPasteboardTypesForCurrentSelection() = 0;
+ virtual NSArray* readDataFromPasteboard(NSString* type, int index) = 0;
+ virtual bool hasRichlyEditableSelection() = 0;
+ virtual int getPasteboardItemsCount() = 0;
+ virtual DocumentFragment* documentFragmentFromDelegate(int index) = 0;
+ virtual bool performsTwoStepPaste(DocumentFragment*) = 0;
+ virtual int pasteboardChangeCount() = 0;
+#endif
+
#if PLATFORM(MAC)
virtual NSString* userVisibleString(NSURL*) = 0;
virtual DocumentFragment* documentFragmentFromAttributedString(NSAttributedString*, Vector< RefPtr<ArchiveResource>>&) = 0;
diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp
index a6bab3a..bdbdab8 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -104,7 +104,11 @@
#endif
#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
+#include "PlatformTouchEventIOS.h"
+#else
#include "PlatformTouchEvent.h"
+#endif
#include "TouchEvent.h"
#include "TouchList.h"
#endif
@@ -127,6 +131,15 @@
const int GeneralDragHysteresis = 3;
#endif // ENABLE(DRAG_SUPPORT)
+#if ENABLE(IOS_GESTURE_EVENTS)
+const float GestureUnknown = 0;
+#endif
+
+#if ENABLE(IOS_TOUCH_EVENTS)
+// FIXME: Share this constant with EventHandler and SliderThumbElement.
+const unsigned InvalidTouchIdentifier = 0;
+#endif
+
// Match key code of composition keydown event on windows.
// IE sends VK_PROCESSKEY which has value 229;
const int CompositionEventKeyCode = 229;
@@ -142,7 +155,7 @@
const double fakeMouseMoveShortInterval = 0.1;
const double fakeMouseMoveLongInterval = 0.25;
-#if !PLATFORM(IOS)
+#if ENABLE(CURSOR_SUPPORT)
// The amount of time to wait for a cursor update on style and layout changes
// Set to 50Hz, no need to be faster than common screen refresh rate
const double cursorUpdateInterval = 0.02;
@@ -190,7 +203,7 @@
double m_start;
};
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
class SyntheticTouchPoint : public PlatformTouchPoint {
public:
@@ -255,7 +268,7 @@
m_touchPoints.append(SyntheticTouchPoint(event));
}
};
-#endif
+#endif // ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
static inline ScrollGranularity wheelGranularityToScrollGranularity(unsigned deltaMode)
{
@@ -320,7 +333,9 @@
, m_mouseDownWasSingleClickInSelection(false)
, m_selectionInitiationState(HaveNotStartedSelection)
, m_hoverTimer(this, &EventHandler::hoverTimerFired)
+#if ENABLE(CURSOR_SUPPORT)
, m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired)
+#endif
, m_autoscrollController(adoptPtr(new AutoscrollController))
, m_mouseDownMayStartAutoscroll(false)
, m_mouseDownWasInSubframe(false)
@@ -331,6 +346,15 @@
, m_resizeLayer(0)
, m_eventHandlerWillResetCapturingMouseEventsElement(nullptr)
, m_clickCount(0)
+#if ENABLE(IOS_GESTURE_EVENTS)
+ , m_gestureInitialDiameter(GestureUnknown)
+ , m_gestureLastDiameter(GestureUnknown)
+ , m_gestureInitialRotation(GestureUnknown)
+ , m_gestureLastRotation(GestureUnknown)
+#endif
+#if ENABLE(IOS_TOUCH_EVENTS)
+ , m_firstTouchID(InvalidTouchIdentifier)
+#endif
, m_mousePositionIsUnknown(true)
, m_mouseDownTimestamp(0)
, m_inTrackingScrollGesturePhase(false)
@@ -338,9 +362,11 @@
#if PLATFORM(MAC)
, m_mouseDownView(nil)
, m_sendingEventToSubview(false)
+#if !PLATFORM(IOS)
, m_activationEventNumber(-1)
+#endif // !PLATFORM(IOS)
#endif
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
, m_originatingTouchPointTargetKey(0)
, m_touchPressed(false)
#endif
@@ -374,7 +400,9 @@
void EventHandler::clear()
{
m_hoverTimer.stop();
+#if ENABLE(CURSOR_SUPPORT)
m_cursorUpdateTimer.stop();
+#endif
m_fakeMouseMoveEventTimer.stop();
#if ENABLE(CURSOR_VISIBILITY)
cancelAutoHideCursorTimer();
@@ -390,6 +418,18 @@
m_lastScrollbarUnderMouse = 0;
m_clickCount = 0;
m_clickNode = 0;
+#if ENABLE(IOS_GESTURE_EVENTS)
+ m_gestureInitialDiameter = GestureUnknown;
+ m_gestureLastDiameter = GestureUnknown;
+ m_gestureInitialRotation = GestureUnknown;
+ m_gestureLastRotation = GestureUnknown;
+ m_gestureTargets.clear();
+#endif
+#if ENABLE(IOS_TOUCH_EVENTS)
+ m_touches.clear();
+ m_firstTouchID = InvalidTouchIdentifier;
+ m_touchEventTargetSubframe = 0;
+#endif
m_frameSetBeingResized = 0;
#if ENABLE(DRAG_SUPPORT)
m_dragTarget = 0;
@@ -404,7 +444,7 @@
m_capturingMouseEventsElement = nullptr;
m_latchedWheelEventElement = nullptr;
m_previousWheelScrolledElement = nullptr;
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
m_originatingTouchPointTargets.clear();
m_originatingTouchPointDocument.clear();
m_originatingTouchPointTargetKey = 0;
@@ -973,10 +1013,12 @@
void EventHandler::startPanScrolling(RenderElement* renderer)
{
+#if !PLATFORM(IOS)
if (!renderer->isBox())
return;
m_autoscrollController->startPanScrolling(toRenderBox(renderer), lastKnownMousePosition());
invalidateClick();
+#endif
}
#endif // ENABLE(PAN_SCROLLING)
@@ -1178,6 +1220,7 @@
return &toFrameView(widget)->frame();
}
+#if ENABLE(CURSOR_SUPPORT)
static bool isSubmitImage(Node* node)
{
return node && isHTMLInputElement(node) && toHTMLInputElement(node)->isImageButton();
@@ -1444,6 +1487,7 @@
}
return pointerCursor();
}
+#endif // ENABLE(CURSOR_SUPPORT)
#if ENABLE(CURSOR_VISIBILITY)
void EventHandler::startAutoHideCursorTimer()
@@ -1564,6 +1608,11 @@
m_clickCount = mouseEvent.clickCount();
m_clickNode = mev.targetNode();
+ if (!m_clickNode) {
+ invalidateClick();
+ return false;
+ }
+
if (FrameView* view = m_frame.view()) {
RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0;
IntPoint p = view->windowToContents(mouseEvent.position());
@@ -1726,7 +1775,9 @@
if (m_hoverTimer.isActive())
m_hoverTimer.stop();
+#if ENABLE(CURSOR_SUPPORT)
m_cursorUpdateTimer.stop();
+#endif
cancelFakeMouseMoveEvent();
@@ -1740,9 +1791,12 @@
if (m_frameSetBeingResized)
return !dispatchMouseEvent(eventNames().mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false);
+ // On iOS, our scrollbars are managed by UIKit.
+#if !PLATFORM(IOS)
// Send events right to a scrollbar if the mouse is pressed.
if (m_lastScrollbarUnderMouse && m_mousePressed)
return m_lastScrollbarUnderMouse->mouseMoved(mouseEvent);
+#endif
HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::DisallowShadowContent | HitTestRequest::AllowFrameScrollbars;
if (m_mousePressed)
@@ -1755,7 +1809,7 @@
hitType |= HitTestRequest::ReadOnly;
}
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
// Treat any mouse move events as readonly if the user is currently touching the screen.
if (m_touchPressed)
hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly;
@@ -1770,8 +1824,12 @@
else {
Scrollbar* scrollbar = mev.scrollbar();
updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed);
+
+ // On iOS, our scrollbars are managed by UIKit.
+#if !PLATFORM(IOS)
if (!m_mousePressed && scrollbar)
scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
+#endif
if (onlyUpdateScrollbars)
return true;
}
@@ -1791,6 +1849,7 @@
// node to be detached from its FrameView, in which case the event should not be passed.
if (newSubframe->view())
swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
+#if ENABLE(CURSOR_SUPPORT)
} else {
if (FrameView* view = m_frame.view()) {
OptionalCursor optionalCursor = selectCursor(mev.hitTestResult(), mouseEvent.shiftKey());
@@ -1799,6 +1858,7 @@
view->setCursor(m_currentMouseCursor);
}
}
+#endif
}
m_lastMouseMoveEventSubframe = newSubframe;
@@ -2714,11 +2774,13 @@
m_hoverTimer.startOneShot(0);
}
+#if ENABLE(CURSOR_SUPPORT)
void EventHandler::scheduleCursorUpdate()
{
if (!m_cursorUpdateTimer.isActive())
m_cursorUpdateTimer.startOneShot(cursorUpdateInterval);
}
+#endif
void EventHandler::dispatchFakeMouseMoveEventSoon()
{
@@ -2830,7 +2892,7 @@
return true;
}
-#if !PLATFORM(MAC)
+#if !PLATFORM(MAC) || PLATFORM(IOS)
bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
{
return false;
@@ -3507,8 +3569,7 @@
}
}
-#if ENABLE(TOUCH_EVENTS)
-
+#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State state)
{
switch (state) {
@@ -3528,7 +3589,7 @@
}
}
-HitTestResult EventHandler::hitTestResultInFrame(Frame* frame, const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType)
+static HitTestResult hitTestResultInFrame(Frame* frame, const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType)
{
HitTestResult result(point);
@@ -3744,9 +3805,15 @@
return swallowedEvent;
}
+#endif // ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
+#if ENABLE(TOUCH_EVENTS)
bool EventHandler::dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent& event)
{
+#if ENABLE(IOS_TOUCH_EVENTS)
+ UNUSED_PARAM(event);
+ return false;
+#else
if (!m_frame.settings().isTouchEventEmulationEnabled())
return false;
@@ -3765,9 +3832,9 @@
SyntheticSingleTouchEvent touchEvent(event);
return handleTouchEvent(touchEvent);
-}
-
#endif
+}
+#endif // ENABLE(TOUCH_EVENTS)
void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event)
{
diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h
index 34c0095..8ed5d96 100644
--- a/Source/WebCore/page/EventHandler.h
+++ b/Source/WebCore/page/EventHandler.h
@@ -42,6 +42,16 @@
#include <wtf/OwnPtr.h>
#include <wtf/RefPtr.h>
+#if PLATFORM(IOS)
+#ifdef __OBJC__
+@class WebEvent;
+@class WAKView;
+#include "WAKAppKitStubs.h"
+#else
+class WebEvent;
+#endif
+#endif // PLATFORM(IOS)
+
#if PLATFORM(MAC) && !defined(__OBJC__)
class NSView;
#endif
@@ -50,6 +60,11 @@
#include <wtf/HashMap.h>
#endif
+#if ENABLE(IOS_TOUCH_EVENTS)
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+#endif
+
namespace WebCore {
class AutoscrollController;
@@ -78,6 +93,7 @@
class SVGElementInstance;
class Scrollbar;
class TextEvent;
+class Touch;
class TouchEvent;
class VisibleSelection;
class WheelEvent;
@@ -92,6 +108,10 @@
extern const int GeneralDragHysteresis;
#endif // ENABLE(DRAG_SUPPORT)
+#if ENABLE(IOS_GESTURE_EVENTS)
+extern const float GestureUnknown;
+#endif
+
enum AppendTrailingWhitespace { ShouldAppendTrailingWhitespace, DontAppendTrailingWhitespace };
enum CheckDragHysteresis { ShouldCheckDragHysteresis, DontCheckDragHysteresis };
@@ -144,7 +164,9 @@
#endif
void scheduleHoverStateUpdate();
+#if ENABLE(CURSOR_SUPPORT)
void scheduleCursorUpdate();
+#endif
void setResizingFrameSet(HTMLFrameSetElement*);
@@ -175,6 +197,24 @@
void defaultWheelEventHandler(Node*, WheelEvent*);
bool handlePasteGlobalSelection(const PlatformMouseEvent&);
+#if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS)
+ typedef Vector<RefPtr<Touch>> TouchArray;
+ typedef HashMap<EventTarget*, TouchArray*> EventTargetTouchMap;
+ typedef HashSet<RefPtr<EventTarget>> EventTargetSet;
+#endif
+
+#if ENABLE(IOS_TOUCH_EVENTS)
+ bool dispatchTouchEvent(const PlatformTouchEvent&, const AtomicString&, const EventTargetTouchMap&, float, float);
+#endif
+
+#if ENABLE(IOS_GESTURE_EVENTS)
+ bool dispatchGestureEvent(const PlatformTouchEvent&, const AtomicString&, const EventTargetSet&, float, float);
+#endif
+
+#if PLATFORM(IOS)
+ void defaultTouchEventHandler(Node*, TouchEvent*);
+#endif
+
#if ENABLE(TOUCH_ADJUSTMENT)
bool bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode);
bool bestContextMenuNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode);
@@ -213,20 +253,42 @@
void sendScrollEvent(); // Ditto
#if PLATFORM(MAC) && defined(__OBJC__)
+#if !PLATFORM(IOS)
void mouseDown(NSEvent *);
void mouseDragged(NSEvent *);
void mouseUp(NSEvent *);
void mouseMoved(NSEvent *);
bool keyEvent(NSEvent *);
bool wheelEvent(NSEvent *);
+#else
+ void mouseDown(WebEvent *);
+ void mouseUp(WebEvent *);
+ void mouseMoved(WebEvent *);
+ bool keyEvent(WebEvent *);
+ bool wheelEvent(WebEvent *);
+#endif
+#if ENABLE(IOS_TOUCH_EVENTS)
+ void touchEvent(WebEvent *);
+#endif
+
+#if !PLATFORM(IOS)
void passMouseMovedEventToScrollbars(NSEvent *);
void sendFakeEventsAfterWidgetTracking(NSEvent *initiatingEvent);
+#endif
+#if !PLATFORM(IOS)
void setActivationEventNumber(int num) { m_activationEventNumber = num; }
static NSEvent *currentNSEvent();
+#else
+ static WebEvent *currentEvent();
+#endif // !PLATFORM(IOS)
+#endif // PLATFORM(MAC) && defined(__OBJC__)
+
+#if PLATFORM(IOS)
+ void invalidateClick();
#endif
#if ENABLE(TOUCH_EVENTS)
@@ -266,7 +328,9 @@
OptionalCursor selectCursor(const HitTestResult&, bool shiftKey);
void hoverTimerFired(Timer<EventHandler>*);
+#if ENABLE(CURSOR_SUPPORT)
void cursorUpdateTimerFired(Timer<EventHandler>*);
+#endif
bool logicalScrollOverflow(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0);
@@ -291,10 +355,11 @@
#if ENABLE(TOUCH_EVENTS)
bool dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent&);
- HitTestResult hitTestResultInFrame(Frame*, const LayoutPoint&, HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
#endif
+#if !PLATFORM(IOS)
void invalidateClick();
+#endif
Node* nodeUnderMouse() const;
@@ -401,7 +466,9 @@
bool m_panScrollButtonPressed;
Timer<EventHandler> m_hoverTimer;
+#if ENABLE(CURSOR_SUPPORT)
Timer<EventHandler> m_cursorUpdateTimer;
+#endif
OwnPtr<AutoscrollController> m_autoscrollController;
bool m_mouseDownMayStartAutoscroll;
@@ -429,6 +496,21 @@
int m_clickCount;
RefPtr<Node> m_clickNode;
+#if ENABLE(IOS_GESTURE_EVENTS)
+ float m_gestureInitialDiameter;
+ float m_gestureLastDiameter;
+ float m_gestureInitialRotation;
+ float m_gestureLastRotation;
+#endif
+
+#if ENABLE(IOS_TOUCH_EVENTS)
+ unsigned m_firstTouchID;
+
+ TouchArray m_touches;
+ EventTargetSet m_gestureTargets;
+ RefPtr<Frame> m_touchEventTargetSubframe;
+#endif
+
#if ENABLE(DRAG_SUPPORT)
RefPtr<Element> m_dragTarget;
bool m_shouldOnlyFireDragOverEvent;
@@ -452,12 +534,14 @@
RefPtr<Element> m_previousWheelScrolledElement;
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || PLATFORM(IOS)
NSView *m_mouseDownView;
bool m_sendingEventToSubview;
+#if !PLATFORM(IOS)
int m_activationEventNumber;
#endif
-#if ENABLE(TOUCH_EVENTS)
+#endif
+#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
typedef HashMap<int, RefPtr<EventTarget>> TouchTargetMap;
TouchTargetMap m_originatingTouchPointTargets;
RefPtr<Document> m_originatingTouchPointDocument;
diff --git a/Source/WebCore/page/FocusController.h b/Source/WebCore/page/FocusController.h
index b894da6..b449d9c 100644
--- a/Source/WebCore/page/FocusController.h
+++ b/Source/WebCore/page/FocusController.h
@@ -82,6 +82,10 @@
void setContainingWindowIsVisible(bool);
bool containingWindowIsVisible() const { return m_containingWindowIsVisible; }
+ // These methods are used in WebCore/bindings/objc/DOM.mm.
+ Element* nextFocusableElement(FocusNavigationScope, Node* start, KeyboardEvent*);
+ Element* previousFocusableElement(FocusNavigationScope, Node* start, KeyboardEvent*);
+
private:
bool advanceFocusDirectionally(FocusDirection, KeyboardEvent*);
bool advanceFocusInDocumentOrder(FocusDirection, KeyboardEvent*, bool initialFocus);
@@ -101,9 +105,6 @@
// See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
Element* findFocusableElement(FocusDirection, FocusNavigationScope, Node* start, KeyboardEvent*);
- Element* nextFocusableElement(FocusNavigationScope, Node* start, KeyboardEvent*);
- Element* previousFocusableElement(FocusNavigationScope, Node* start, KeyboardEvent*);
-
Element* findElementWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent*, FocusDirection);
bool advanceFocusDirectionallyInContainer(Node* container, const LayoutRect& startingRect, FocusDirection, KeyboardEvent*);
diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp
index f91806e..d8440ea 100644
--- a/Source/WebCore/page/Frame.cpp
+++ b/Source/WebCore/page/Frame.cpp
@@ -121,10 +121,18 @@
#include "TiledBackingStore.h"
#endif
+#if PLATFORM(IOS)
+#include "WKContentObservation.h"
+#endif
+
namespace WebCore {
using namespace HTMLNames;
+#if PLATFORM(IOS)
+const unsigned scrollFrequency = 1000 / 60;
+#endif
+
DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
@@ -163,6 +171,11 @@
, m_selection(adoptPtr(new FrameSelection(this)))
, m_eventHandler(adoptPtr(new EventHandler(*this)))
, m_animationController(std::make_unique<AnimationController>(*this))
+#if PLATFORM(IOS)
+ , m_overflowAutoScrollTimer(this, &Frame::overflowAutoScrollTimerFired)
+ , m_selectionChangeCallbacksDisabled(false)
+ , m_timersPausedCount(0)
+#endif
, m_pageZoomFactor(parentPageZoomFactor(this))
, m_textZoomFactor(parentTextZoomFactor(this))
#if ENABLE(ORIENTATION_EVENTS)
@@ -197,10 +210,17 @@
frameCounter.increment();
#endif
- // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state.
+ // FIXME: We should reconcile the iOS and OpenSource code below.
Frame* parent = parentFromOwnerElement(ownerElement);
+#if PLATFORM(IOS)
+ // Pause future timers if this frame is created when page is in pending state.
+ if (parent && parent->timersPaused())
+ setTimersPaused(true);
+#else
+ // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state.
if (parent && parent->activeDOMObjectsAndAnimationsSuspended())
suspendActiveDOMObjectsAndAnimations();
+#endif
}
PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
@@ -471,6 +491,160 @@
return matchLabelsAgainstString(labels, element->getAttribute(idAttr));
}
+#if PLATFORM(IOS)
+void Frame::scrollOverflowLayer(RenderLayer* layer, const IntRect& visibleRect, const IntRect& exposeRect)
+{
+ if (!layer)
+ return;
+
+ RenderBox* box = layer->renderBox();
+ if (!box)
+ return;
+
+ if (visibleRect.intersects(exposeRect))
+ return;
+
+ int x = layer->scrollXOffset();
+ int exposeLeft = exposeRect.x();
+ int exposeRight = exposeLeft + exposeRect.width();
+ int clientWidth = box->clientWidth();
+ if (exposeLeft <= 0)
+ x = std::max(0, x + exposeLeft - clientWidth / 2);
+ else if (exposeRight >= clientWidth)
+ x = std::min(box->scrollWidth() - clientWidth, x + clientWidth / 2);
+
+ int y = layer->scrollYOffset();
+ int exposeTop = exposeRect.y();
+ int exposeBottom = exposeTop + exposeRect.height();
+ int clientHeight = box->clientHeight();
+ if (exposeTop <= 0)
+ y = std::max(0, y + exposeTop - clientHeight / 2);
+ else if (exposeBottom >= clientHeight)
+ y = std::min(box->scrollHeight() - clientHeight, y + clientHeight / 2);
+
+ layer->scrollToOffset(IntSize(x, y));
+ selection().setCaretRectNeedsUpdate();
+ selection().updateAppearance();
+}
+
+void Frame::overflowAutoScrollTimerFired(Timer<Frame>*)
+{
+ if (!eventHandler().mousePressed() || checkOverflowScroll(PerformOverflowScroll) == OverflowScrollNone) {
+ if (m_overflowAutoScrollTimer.isActive())
+ m_overflowAutoScrollTimer.stop();
+ }
+}
+
+void Frame::startOverflowAutoScroll(const IntPoint& mousePosition)
+{
+ m_overflowAutoScrollPos = mousePosition;
+
+ if (m_overflowAutoScrollTimer.isActive())
+ return;
+
+ if (checkOverflowScroll(DoNotPerformOverflowScroll) == OverflowScrollNone)
+ return;
+
+ m_overflowAutoScrollTimer.startRepeating(scrollFrequency);
+ m_overflowAutoScrollDelta = 3;
+}
+
+int Frame::checkOverflowScroll(OverflowScrollAction action)
+{
+ Position extent = selection().selection().extent();
+ if (extent.isNull())
+ return OverflowScrollNone;
+
+ RenderObject* renderer = extent.deprecatedNode()->renderer();
+ if (!renderer)
+ return OverflowScrollNone;
+
+ FrameView* view = this->view();
+ if (!view)
+ return OverflowScrollNone;
+
+ RenderBlock* containingBlock = renderer->containingBlock();
+ if (!containingBlock || !containingBlock->hasOverflowClip())
+ return OverflowScrollNone;
+ RenderLayer* layer = containingBlock->layer();
+ ASSERT(layer);
+
+ IntRect visibleRect = IntRect(view->scrollX(), view->scrollY(), view->visibleWidth(), view->visibleHeight());
+ IntPoint position = m_overflowAutoScrollPos;
+ if (visibleRect.contains(position.x(), position.y()))
+ return OverflowScrollNone;
+
+ int scrollType = 0;
+ int deltaX = 0;
+ int deltaY = 0;
+ IntPoint selectionPosition;
+
+ // This constant will make the selection draw a little bit beyond the edge of the visible area.
+ // This prevents a visual glitch, in that you can fail to select a portion of a character that
+ // is being rendered right at the edge of the visible rectangle.
+ // FIXME: This probably needs improvement, and may need to take the font size into account.
+ static const int scrollBoundsAdjustment = 3;
+
+ // FIXME: Make a small buffer at the end of a visible rectangle so that autoscrolling works
+ // even if the visible extends to the limits of the screen.
+ if (position.x() < visibleRect.x()) {
+ scrollType |= OverflowScrollLeft;
+ if (action == PerformOverflowScroll) {
+ deltaX -= static_cast<int>(m_overflowAutoScrollDelta);
+ selectionPosition.setX(view->scrollX() - scrollBoundsAdjustment);
+ }
+ } else if (position.x() > visibleRect.maxX()) {
+ scrollType |= OverflowScrollRight;
+ if (action == PerformOverflowScroll) {
+ deltaX += static_cast<int>(m_overflowAutoScrollDelta);
+ selectionPosition.setX(view->scrollX() + view->visibleWidth() + scrollBoundsAdjustment);
+ }
+ }
+
+ if (position.y() < visibleRect.y()) {
+ scrollType |= OverflowScrollUp;
+ if (action == PerformOverflowScroll) {
+ deltaY -= static_cast<int>(m_overflowAutoScrollDelta);
+ selectionPosition.setY(view->scrollY() - scrollBoundsAdjustment);
+ }
+ } else if (position.y() > visibleRect.maxY()) {
+ scrollType |= OverflowScrollDown;
+ if (action == PerformOverflowScroll) {
+ deltaY += static_cast<int>(m_overflowAutoScrollDelta);
+ selectionPosition.setY(view->scrollY() + view->visibleHeight() + scrollBoundsAdjustment);
+ }
+ }
+
+ if (action == PerformOverflowScroll && (deltaX || deltaY)) {
+ layer->scrollToOffset(IntSize(layer->scrollXOffset() + deltaX, layer->scrollYOffset() + deltaY));
+
+ // Handle making selection.
+ VisiblePosition visiblePosition(renderer->positionForPoint(selectionPosition));
+ if (visiblePosition.isNotNull()) {
+ VisibleSelection visibleSelection = selection().selection();
+ visibleSelection.setExtent(visiblePosition);
+ if (selection().granularity() != CharacterGranularity)
+ visibleSelection.expandUsingGranularity(selection().granularity());
+ if (selection().shouldChangeSelection(visibleSelection))
+ selection().setSelection(visibleSelection);
+ }
+
+ m_overflowAutoScrollDelta *= 1.02f; // Accelerate the scroll
+ }
+ return scrollType;
+}
+
+void Frame::setSelectionChangeCallbacksDisabled(bool selectionChangeCallbacksDisabled)
+{
+ m_selectionChangeCallbacksDisabled = selectionChangeCallbacksDisabled;
+}
+
+bool Frame::selectionChangeCallbacksDisabled() const
+{
+ return m_selectionChangeCallbacksDisabled;
+}
+#endif // PLATFORM(IOS)
+
void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
{
// In setting printing, we should not validate resources already cached for the document.
@@ -624,6 +798,11 @@
if (page() && page()->scrollingCoordinator() && m_view)
page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
+#if PLATFORM(IOS)
+ if (WebThreadCountOfObservedContentModifiers() > 0 && m_page)
+ m_page->chrome().client().clearContentChangeObservers(this);
+#endif
+
script().clearScriptObjects();
script().updatePlatformScriptObjects();
}
@@ -708,7 +887,7 @@
}
void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
- const IntSize& fixedLayoutSize, const IntRect& fixedVisibleContentRect ,
+ const IntSize& fixedLayoutSize, const IntRect& fixedVisibleContentRect,
bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
ScrollbarMode verticalScrollbarMode, bool verticalLock)
{
@@ -726,7 +905,11 @@
if (isMainFrame) {
frameView = FrameView::create(*this, viewportSize);
frameView->setFixedLayoutSize(fixedLayoutSize);
+#if !PLATFORM(IOS)
frameView->setFixedVisibleContentRect(fixedVisibleContentRect);
+#else
+ UNUSED_PARAM(fixedVisibleContentRect);
+#endif
frameView->setUseFixedLayout(useFixedLayout);
} else
frameView = FrameView::create(*this);
diff --git a/Source/WebCore/page/Frame.h b/Source/WebCore/page/Frame.h
index 5f1866f..f55eaaf 100644
--- a/Source/WebCore/page/Frame.h
+++ b/Source/WebCore/page/Frame.h
@@ -37,6 +37,11 @@
#include "UserScriptTypes.h"
#include <wtf/RefCounted.h>
+#if PLATFORM(IOS)
+#include "ViewportArguments.h"
+#include "VisibleSelection.h"
+#endif
+
#if PLATFORM(WIN)
#include "FrameWin.h"
#endif
@@ -45,6 +50,13 @@
#include "TiledBackingStoreClient.h"
#endif
+#if PLATFORM(IOS)
+OBJC_CLASS DOMCSSStyleDeclaration;
+OBJC_CLASS DOMNode;
+OBJC_CLASS NSArray;
+OBJC_CLASS NSString;
+#endif
+
#if PLATFORM(WIN)
typedef struct HBITMAP__* HBITMAP;
#endif
@@ -63,12 +75,14 @@
class FrameView;
class HTMLFrameOwnerElement;
class HTMLTableCellElement;
+ class HitTestResult;
class ImageBuffer;
class IntRect;
class MainFrame;
class Node;
class Range;
class RegularExpression;
+ class RenderLayer;
class RenderView;
class RenderWidget;
class ScriptController;
@@ -77,6 +91,19 @@
class VisiblePosition;
class Widget;
+#if PLATFORM(IOS)
+ enum {
+ OverflowScrollNone = 0,
+ OverflowScrollLeft = 1 << 0,
+ OverflowScrollRight = 1 << 1,
+ OverflowScrollUp = 1 << 2,
+ OverflowScrollDown = 1 << 3
+ };
+
+ enum OverflowScrollAction { DoNotPerformOverflowScroll, PerformOverflowScroll };
+ typedef Node* (*NodeQualifier)(const HitTestResult&, Node* terminationNode, IntRect* nodeBounds);
+#endif
+
#if !USE(TILED_BACKING_STORE)
class TiledBackingStoreClient { };
#endif
@@ -96,6 +123,10 @@
static PassRefPtr<Frame> create(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*);
void init();
+#if PLATFORM(IOS)
+ // Creates <html><body style="..."></body></html> doing minimal amount of work.
+ void initWithSimpleHTMLDocument(const String& style, const URL&);
+#endif
void setView(PassRefPtr<FrameView>);
void createView(const IntSize&, const Color&, bool,
const IntSize& fixedLayoutSize = IntSize(), const IntRect& fixedVisibleContentRect = IntRect(),
@@ -165,6 +196,30 @@
void deviceOrPageScaleFactorChanged();
#endif
+#if PLATFORM(IOS)
+ const ViewportArguments& viewportArguments() const;
+ void setViewportArguments(const ViewportArguments&);
+
+ Node* deepestNodeAtLocation(const FloatPoint& viewportLocation);
+ Node* nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation);
+ Node* nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation);
+
+ int indexCountOfWordPrecedingSelection(NSString* word) const;
+ NSArray* wordsInCurrentParagraph() const;
+ CGRect renderRectForPoint(CGPoint, bool* isReplaced, float* fontSize) const;
+
+ void setSelectionChangeCallbacksDisabled(bool = true);
+ bool selectionChangeCallbacksDisabled() const;
+
+ enum ViewportOffsetChangeType { IncrementalScrollOffset, CompletedScrollOffset };
+ void viewportOffsetChanged(ViewportOffsetChangeType);
+ bool containsTiledBackingLayers() const;
+
+ void overflowScrollPositionChangedForNode(const IntPoint&, Node*, bool isUserScroll);
+
+ void resetAllGeolocationPermission();
+#endif
+
#if ENABLE(ORIENTATION_EVENTS)
// Orientation is the interface orientation in degrees. Some examples are:
// 0 is straight up; -90 is when the device is rotated 90 clockwise;
@@ -191,6 +246,33 @@
float textAutosizingWidth() const;
#endif
+#if PLATFORM(IOS)
+ // Scroll the selection in an overflow layer on iOS.
+ void scrollOverflowLayer(RenderLayer* , const IntRect& visibleRect, const IntRect& exposeRect);
+
+ int preferredHeight() const;
+ int innerLineHeight(DOMNode*) const;
+ void updateLayout() const;
+ NSRect caretRect() const;
+ NSRect rectForScrollToVisible() const;
+ NSRect rectForSelection(VisibleSelection&) const;
+ DOMCSSStyleDeclaration* styleAtSelectionStart() const;
+ unsigned formElementsCharacterCount() const;
+ void setTimersPaused(bool);
+ bool timersPaused() const { return m_timersPausedCount; }
+ void dispatchPageHideEventBeforePause();
+ void dispatchPageShowEventBeforeResume();
+ void setRangedSelectionBaseToCurrentSelection();
+ void setRangedSelectionBaseToCurrentSelectionStart();
+ void setRangedSelectionBaseToCurrentSelectionEnd();
+ void clearRangedSelectionInitialExtent();
+ void setRangedSelectionInitialExtentToCurrentSelectionStart();
+ void setRangedSelectionInitialExtentToCurrentSelectionEnd();
+ VisibleSelection rangedSelectionBase() const;
+ VisibleSelection rangedSelectionInitialExtent() const;
+ void recursiveSetUpdateAppearanceEnabled(bool);
+ NSArray* interpretationsForCurrentRoot() const;
+#endif
void suspendActiveDOMObjectsAndAnimations();
void resumeActiveDOMObjectsAndAnimations();
bool activeDOMObjectsAndAnimationsSuspended() const { return m_activeDOMObjectsAndAnimationsSuspendedCount > 0; }
@@ -224,6 +306,27 @@
const OwnPtr<EventHandler> m_eventHandler;
const std::unique_ptr<AnimationController> m_animationController;
+#if PLATFORM(IOS)
+ void betterApproximateNode(const IntPoint& testPoint, NodeQualifier, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect);
+ bool hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult&, IntPoint& center);
+ Node* qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, NodeQualifier, bool shouldApproximate);
+
+ void overflowAutoScrollTimerFired(Timer<Frame>*);
+ void startOverflowAutoScroll(const IntPoint&);
+ int checkOverflowScroll(OverflowScrollAction);
+
+ void setTimersPausedInternal(bool);
+
+ Timer<Frame> m_overflowAutoScrollTimer;
+ float m_overflowAutoScrollDelta;
+ IntPoint m_overflowAutoScrollPos;
+ ViewportArguments m_viewportArguments;
+ bool m_selectionChangeCallbacksDisabled;
+ int m_timersPausedCount;
+ VisibleSelection m_rangedSelectionBase;
+ VisibleSelection m_rangedSelectionInitialExtent;
+#endif
+
#if ENABLE(IOS_TEXT_AUTOSIZING)
float m_textAutosizingWidth;
#endif
diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp
index 1fe2f2e..bdcaa75 100644
--- a/Source/WebCore/page/FrameView.cpp
+++ b/Source/WebCore/page/FrameView.cpp
@@ -65,6 +65,7 @@
#include "RenderScrollbar.h"
#include "RenderScrollbarPart.h"
#include "RenderStyle.h"
+#include "RenderText.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "RenderWidget.h"
@@ -98,6 +99,19 @@
#include "TextAutosizer.h"
#endif
+#if PLATFORM(IOS)
+#include "DocumentLoader.h"
+#include "Logging.h"
+#include "MemoryCache.h"
+#include "MemoryPressureHandler.h"
+#include "SystemMemory.h"
+#include "TileCache.h"
+#endif
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+#include "HTMLMediaElement.h"
+#endif
+
namespace WebCore {
using namespace HTMLNames;
@@ -190,6 +204,9 @@
, m_deferSetNeedsLayouts(0)
, m_setNeedsLayoutWasDeferred(false)
, m_scrollCorner(0)
+#if PLATFORM(IOS)
+ , m_useCustomFixedPositionLayoutRect(false)
+#endif
, m_shouldAutoSize(false)
, m_inAutoSize(false)
, m_didRunAutosize(false)
@@ -392,6 +409,13 @@
reset();
setScrollbarsSuppressed(true);
+
+#if PLATFORM(IOS)
+ // To avoid flashes of white, disable tile updates immediately when view is cleared at the beginning of a page load.
+ // Tiling will be re-enabled from UIKit via [WAKWindow setTilingMode:] when we have content to draw.
+ if (TileCache* tileCache = this->tileCache())
+ tileCache->setTilingMode(TileCache::Disabled);
+#endif
}
bool FrameView::didFirstLayout() const
@@ -883,6 +907,11 @@
// visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
flushDeferredRepaints();
+#if PLATFORM(IOS)
+ if (TileCache* tileCache = this->tileCache())
+ tileCache->doPendingRepaints();
+#endif
+
renderView->compositor().flushPendingLayerChanges(rootFrameForFlush == &frame());
return true;
@@ -894,6 +923,39 @@
page->chrome().client().setNeedsOneShotDrawingSynchronization();
}
+GraphicsLayer* FrameView::graphicsLayerForPlatformWidget(PlatformWidget platformWidget)
+{
+ // To find the Widget that corresponds with platformWidget we have to do a linear
+ // search of our child widgets.
+ Widget* foundWidget = nullptr;
+ for (auto& widget : children()) {
+ if (widget->platformWidget() != platformWidget)
+ continue;
+ foundWidget = widget.get();
+ break;
+ }
+
+ if (!foundWidget)
+ return nullptr;
+
+ auto* renderWidget = RenderWidget::find(foundWidget);
+ if (!renderWidget)
+ return nullptr;
+
+ RenderLayer* widgetLayer = renderWidget->layer();
+ if (!widgetLayer || !widgetLayer->isComposited())
+ return nullptr;
+
+ return widgetLayer->backing()->parentForSublayers();
+}
+
+void FrameView::scheduleLayerFlushAllowingThrottling()
+{
+ RenderView* view = this->renderView();
+ if (!view)
+ return;
+ view->compositor().scheduleLayerFlush(true /* canThrottle */);
+}
#endif // USE(ACCELERATED_COMPOSITING)
void FrameView::setHeaderHeight(int headerHeight)
@@ -1082,6 +1144,11 @@
return;
}
+#if PLATFORM(IOS)
+ if (updateFixedPositionLayoutRect())
+ allowSubtree = false;
+#endif
+
m_layoutTimer.stop();
m_delayedLayout = false;
m_setNeedsLayoutWasDeferred = false;
@@ -1198,7 +1265,11 @@
if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
m_lastViewportSize = fixedLayoutSize();
else
+#if PLATFORM(IOS)
+ m_lastViewportSize = actualVisibleContentRect().size();
+#else
m_lastViewportSize = visibleContentRect(IncludeScrollbars).size();
+#endif
m_lastZoomFactor = root->style().zoom();
@@ -1313,6 +1384,10 @@
updateAnnotatedRegions();
#endif
+#if ENABLE(IOS_TOUCH_EVENTS)
+ document.dirtyTouchEventRects();
+#endif
+
ASSERT(!root->needsLayout());
updateCanBlitOnScrollRecursively();
@@ -1902,6 +1977,7 @@
#endif
}
+#if !PLATFORM(IOS)
void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
{
bool visibleContentSizeDidChange = false;
@@ -1927,6 +2003,7 @@
}
frame().loader().client().didChangeScrollOffset();
}
+#endif
void FrameView::setViewportConstrainedObjectsNeedLayout()
{
@@ -2120,6 +2197,27 @@
ScrollView::repaintContentRectangle(r, immediate);
}
+static unsigned countRenderedCharactersInRenderObjectWithThreshold(const RenderObject& renderer, unsigned countSoFar, unsigned threshold)
+{
+ // FIXME: Consider writing this using RenderObject::nextInPreOrder() instead of using recursion.
+ if (renderer.isText())
+ countSoFar += toRenderText(renderer).text()->length();
+
+ for (RenderObject* child = renderer.firstChildSlow(); child; child = child->nextSibling()) {
+ if (countSoFar >= threshold)
+ break;
+ countSoFar = countRenderedCharactersInRenderObjectWithThreshold(*child, countSoFar, threshold);
+ }
+ return countSoFar;
+}
+
+bool FrameView::renderedCharactersExceed(unsigned threshold)
+{
+ if (!m_frame->contentRenderer())
+ return false;
+ return countRenderedCharactersInRenderObjectWithThreshold(*m_frame->contentRenderer(), 0, threshold) >= threshold;
+}
+
void FrameView::contentsResized()
{
ScrollView::contentsResized();
@@ -2144,6 +2242,18 @@
if (!frame().view())
return;
+#if PLATFORM(IOS)
+ if (RenderView* root = m_frame->contentRenderer()) {
+ if (useCustomFixedPositionLayoutRect() && hasViewportConstrainedObjects()) {
+ setViewportConstrainedObjectsNeedLayout();
+ // We must eagerly enter compositing mode because fixed position elements
+ // will not have been made compositing via a preceding style change before
+ // m_useCustomFixedPositionLayoutRect was true.
+ root->compositor().enableCompositingMode();
+ }
+ }
+#endif
+
if (!useFixedLayout() && needsLayout())
layout();
@@ -2320,6 +2430,10 @@
if (renderView && renderView->layer()->backing())
renderView->layer()->backing()->adjustTiledBackingCoverage();
#endif
+#if PLATFORM(IOS)
+ if (TileCache* tileCache = this->tileCache())
+ tileCache->setSpeculativeTileCreationEnabled(!m_frame->page()->progress().isMainLoadProgressing());
+#endif
}
void FrameView::layoutTimerFired(Timer<FrameView>*)
@@ -2681,6 +2795,14 @@
}
}
+#if PLATFORM(IOS)
+ // Only send layout-related delegate callbacks synchronously for the main frame to
+ // avoid re-entering layout for the main frame while delivering a layout-related delegate
+ // callback for a subframe.
+ if (frame().isMainFrame())
+ page->chrome().client().didLayout();
+#endif
+
if (milestonesAchieved && frame().isMainFrame())
frame().loader().didLayout(milestonesAchieved);
@@ -2733,7 +2855,11 @@
if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
currentSize = fixedLayoutSize();
else
+#if PLATFORM(IOS)
+ currentSize = actualVisibleContentRect().size();
+#else
currentSize = visibleContentRect(IncludeScrollbars).size();
+#endif
float currentZoomFactor = renderView->style().zoom();
bool shouldSendResizeEvent = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
@@ -2744,6 +2870,16 @@
if (!shouldSendResizeEvent)
return;
+#if PLATFORM(IOS)
+ // Don't send the resize event if the document is loading. Some pages automatically reload
+ // when the window is resized; Safari on iOS often resizes the window while setting up its
+ // viewport. This obviously can cause problems.
+ if (DocumentLoader* documentLoader = frame().loader().documentLoader()) {
+ if (documentLoader->isLoadingInAPISense())
+ return;
+ }
+#endif
+
bool isMainFrame = frame().isMainFrame();
bool canSendResizeEventSynchronously = isMainFrame && !isInLayout();
@@ -3423,6 +3559,16 @@
InspectorInstrumentation::willPaint(renderView);
bool isTopLevelPainter = !sCurrentPaintTimeStamp;
+#if PLATFORM(IOS)
+ // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to MemoryPressureHandler.h.
+ if (isTopLevelPainter && memoryPressureHandler().hasReceivedMemoryPressure()) {
+ LOG(MemoryPressure, "Under memory pressure: %s", __PRETTY_FUNCTION__);
+
+ // To avoid unnecessary image decoding, we don't prune recently-decoded live resources here since
+ // we might need some live bitmaps on painting.
+ memoryCache()->prune();
+ }
+#endif
if (isTopLevelPainter)
sCurrentPaintTimeStamp = monotonicallyIncreasingTime();
@@ -3475,6 +3621,14 @@
m_paintBehavior = oldPaintBehavior;
m_lastPaintTime = monotonicallyIncreasingTime();
+#if PLATFORM(IOS)
+ // Painting can lead to decoding of large amounts of bitmaps
+ // If we are low on memory, wipe them out after the paint.
+ // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to MemoryPressureHandler.h.
+ if (isTopLevelPainter && memoryPressureHandler().hasReceivedMemoryPressure())
+ memoryCache()->pruneLiveResources(true);
+#endif
+
// Regions may have changed as a result of the visibility/z-index of element changing.
#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
if (document->annotatedRegionsDirty())
@@ -4049,6 +4203,43 @@
return 0;
}
+#if PLATFORM(IOS)
+void FrameView::setUseCustomFixedPositionLayoutRect(bool useCustomFixedPositionLayoutRect)
+{
+ if (m_useCustomFixedPositionLayoutRect == useCustomFixedPositionLayoutRect)
+ return;
+ m_useCustomFixedPositionLayoutRect = useCustomFixedPositionLayoutRect;
+ visibleContentsResized();
+}
+
+void FrameView::setCustomFixedPositionLayoutRect(const IntRect& rect)
+{
+ if (m_useCustomFixedPositionLayoutRect && m_customFixedPositionLayoutRect == rect)
+ return;
+ m_useCustomFixedPositionLayoutRect = true;
+ m_customFixedPositionLayoutRect = rect;
+ visibleContentsResized();
+}
+
+bool FrameView::updateFixedPositionLayoutRect()
+{
+ if (!m_useCustomFixedPositionLayoutRect)
+ return false;
+
+ IntRect newRect;
+ Page* page = frame().page();
+ if (!page || !page->chrome().client().fetchCustomFixedPositionLayoutRect(newRect))
+ return false;
+
+ if (newRect != m_customFixedPositionLayoutRect) {
+ m_customFixedPositionLayoutRect = newRect;
+ setViewportConstrainedObjectsNeedLayout();
+ return true;
+ }
+ return false;
+}
+#endif // PLATFORM(IOS)
+
void FrameView::setScrollingPerformanceLoggingEnabled(bool flag)
{
#if USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/page/FrameView.h b/Source/WebCore/page/FrameView.h
index d657ae4..b320f9c 100644
--- a/Source/WebCore/page/FrameView.h
+++ b/Source/WebCore/page/FrameView.h
@@ -120,6 +120,16 @@
bool needsFullRepaint() const { return m_needsFullRepaint; }
+ bool renderedCharactersExceed(unsigned threshold);
+
+#if PLATFORM(IOS)
+ bool useCustomFixedPositionLayoutRect() const { return m_useCustomFixedPositionLayoutRect; }
+ void setUseCustomFixedPositionLayoutRect(bool);
+ IntRect customFixedPositionLayoutRect() const { return m_customFixedPositionLayoutRect; }
+ void setCustomFixedPositionLayoutRect(const IntRect&);
+ bool updateFixedPositionLayoutRect();
+#endif
+
#if ENABLE(REQUEST_ANIMATION_FRAME)
void serviceScriptedAnimations(double monotonicAnimationStartTime);
#endif
@@ -136,6 +146,9 @@
// content rendered via the normal painting path.
void setNeedsOneShotDrawingSynchronization();
+ GraphicsLayer* graphicsLayerForPlatformWidget(PlatformWidget);
+ void scheduleLayerFlushAllowingThrottling();
+
virtual TiledBacking* tiledBacking() OVERRIDE;
// In the future when any ScrollableArea can have a node in th ScrollingTree, this should
@@ -192,7 +205,9 @@
virtual float visibleContentScaleFactor() const OVERRIDE;
+#if !PLATFORM(IOS)
virtual void setFixedVisibleContentRect(const IntRect&) OVERRIDE;
+#endif
virtual void setScrollPosition(const IntPoint&) OVERRIDE;
void scrollPositionChangedViaPlatformWidget();
virtual void updateLayerPositionsAfterScrolling() OVERRIDE;
@@ -631,6 +646,11 @@
// Renderer to hold our custom scroll corner.
RenderScrollbarPart* m_scrollCorner;
+#if PLATFORM(IOS)
+ bool m_useCustomFixedPositionLayoutRect;
+ IntRect m_customFixedPositionLayoutRect;
+#endif
+
// If true, automatically resize the frame view around its content.
bool m_shouldAutoSize;
bool m_inAutoSize;
diff --git a/Source/WebCore/page/Navigator.cpp b/Source/WebCore/page/Navigator.cpp
index ab58a68..b88015b 100644
--- a/Source/WebCore/page/Navigator.cpp
+++ b/Source/WebCore/page/Navigator.cpp
@@ -132,6 +132,13 @@
return true;
}
+#if PLATFORM(IOS)
+bool Navigator::standalone() const
+{
+ return m_frame && m_frame->settings().standalone();
+}
+#endif
+
void Navigator::getStorageUpdates()
{
// FIXME: Remove this method or rename to yieldForStorageUpdates.
diff --git a/Source/WebCore/page/Navigator.h b/Source/WebCore/page/Navigator.h
index 9315213..044485e 100644
--- a/Source/WebCore/page/Navigator.h
+++ b/Source/WebCore/page/Navigator.h
@@ -53,6 +53,10 @@
virtual String userAgent() const;
+#if PLATFORM(IOS)
+ bool standalone() const;
+#endif
+
// Relinquishes the storage lock, if one exists.
void getStorageUpdates();
diff --git a/Source/WebCore/page/Navigator.idl b/Source/WebCore/page/Navigator.idl
index acc51ac..638d5a5 100644
--- a/Source/WebCore/page/Navigator.idl
+++ b/Source/WebCore/page/Navigator.idl
@@ -37,6 +37,11 @@
readonly attribute boolean onLine;
+ // FIXME: Convert this #if'def to an IDL conditional attribute.
+#if defined(WTF_PLATFORM_IOS) && WTF_PLATFORM_IOS
+ readonly attribute boolean standalone;
+#endif
+
void getStorageUpdates(); // FIXME: Remove this method or rename to yieldForStorageUpdates.
};
diff --git a/Source/WebCore/page/NavigatorBase.cpp b/Source/WebCore/page/NavigatorBase.cpp
index 7febae4..c89137d 100644
--- a/Source/WebCore/page/NavigatorBase.cpp
+++ b/Source/WebCore/page/NavigatorBase.cpp
@@ -35,8 +35,14 @@
#include <wtf/StdLibExtras.h>
#endif
+#if PLATFORM(IOS)
+#include "WebCoreSystemInterface.h"
+#endif
+
#ifndef WEBCORE_NAVIGATOR_PLATFORM
-#if OS(MAC_OS_X) && (CPU(PPC) || CPU(PPC64))
+#if PLATFORM(IOS)
+#define WEBCORE_NAVIGATOR_PLATFORM ""
+#elif OS(MAC_OS_X) && (CPU(PPC) || CPU(PPC64))
#define WEBCORE_NAVIGATOR_PLATFORM "MacPPC"
#elif OS(MAC_OS_X) && (CPU(X86) || CPU(X86_64))
#define WEBCORE_NAVIGATOR_PLATFORM "MacIntel"
diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h
index 87d0d4a..ced968f 100644
--- a/Source/WebCore/page/Page.h
+++ b/Source/WebCore/page/Page.h
@@ -48,6 +48,10 @@
#include <wtf/SchedulePair.h>
#endif
+#if PLATFORM(IOS)
+#include "Settings.h"
+#endif
+
namespace JSC {
class Debugger;
}
@@ -321,9 +325,16 @@
StorageNamespace* sessionStorage(bool optionalCreate = true);
void setSessionStorage(PassRefPtr<StorageNamespace>);
+ // FIXME: We should make Settings::maxParseDuration() platform-independent, remove {has, set}CustomHTMLTokenizerTimeDelay()
+ // and customHTMLTokenizerTimeDelay() and modify theirs callers to update or query Settings::maxParseDuration().
void setCustomHTMLTokenizerTimeDelay(double);
+#if PLATFORM(IOS)
+ bool hasCustomHTMLTokenizerTimeDelay() const { return m_settings->maxParseDuration() != -1; }
+ double customHTMLTokenizerTimeDelay() const { ASSERT(m_settings->maxParseDuration() != -1); return m_settings->maxParseDuration(); }
+#else
bool hasCustomHTMLTokenizerTimeDelay() const { return m_customHTMLTokenizerTimeDelay != -1; }
double customHTMLTokenizerTimeDelay() const { ASSERT(m_customHTMLTokenizerTimeDelay != -1); return m_customHTMLTokenizerTimeDelay; }
+#endif
void setCustomHTMLTokenizerChunkSize(int);
bool hasCustomHTMLTokenizerChunkSize() const { return m_customHTMLTokenizerChunkSize != -1; }
diff --git a/Source/WebCore/page/PageGroup.cpp b/Source/WebCore/page/PageGroup.cpp
index a6aa775..e435576 100644
--- a/Source/WebCore/page/PageGroup.cpp
+++ b/Source/WebCore/page/PageGroup.cpp
@@ -217,6 +217,16 @@
addVisitedLink(visitedLinkHash(characters, length));
}
+void PageGroup::removeVisitedLink(const URL& url)
+{
+ LinkHash hash = visitedLinkHash(url.string());
+ ASSERT(m_visitedLinkHashes.contains(hash));
+ m_visitedLinkHashes.remove(hash);
+
+ Page::allVisitedStateChanged(this);
+ pageCache()->markPagesForVistedLinkStyleRecalc();
+}
+
void PageGroup::removeVisitedLinks()
{
m_visitedLinksPopulated = false;
diff --git a/Source/WebCore/page/PageGroup.h b/Source/WebCore/page/PageGroup.h
index 08fa74a..2551ec0 100644
--- a/Source/WebCore/page/PageGroup.h
+++ b/Source/WebCore/page/PageGroup.h
@@ -77,6 +77,7 @@
void addVisitedLink(const URL&);
void addVisitedLink(const UChar*, size_t);
void addVisitedLinkHash(LinkHash);
+ void removeVisitedLink(const URL&);
void removeVisitedLinks();
static void setShouldTrackVisitedLinks(bool);
diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp
index c5fad49..18c08e4 100644
--- a/Source/WebCore/page/Settings.cpp
+++ b/Source/WebCore/page/Settings.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "Settings.h"
+#include "AudioSession.h"
#include "BackForwardController.h"
#include "CachedResourceLoader.h"
#include "CookieStorage.h"
@@ -45,6 +46,8 @@
#include "StorageMap.h"
#include "TextAutosizer.h"
#include <limits>
+#include <wtf/NeverDestroyed.h>
+
namespace WebCore {
@@ -93,6 +96,10 @@
bool Settings::gShouldRespectPriorityInCSSAttributeSetters = false;
bool Settings::gLowPowerVideoAudioBufferSizeEnabled = false;
+#if PLATFORM(IOS)
+bool Settings::gNetworkDataUsageTrackingEnabled = false;
+#endif
+
// NOTEs
// 1) EditingMacBehavior comprises Tiger, Leopard, SnowLeopard and iOS builds, as well as QtWebKit when built on Mac;
// 2) EditingWindowsBehavior comprises Win32 and WinCE builds, as well as QtWebKit and Chromium when built on Windows;
@@ -146,6 +153,9 @@
, m_fontGenericFamilies(std::make_unique<FontGenericFamilies>())
, m_storageBlockingPolicy(SecurityOrigin::AllowAllStorage)
, m_layoutInterval(layoutScheduleThreshold)
+#if PLATFORM(IOS)
+ , m_maxParseDuration(-1)
+#endif
#if ENABLE(TEXT_AUTOSIZING)
, m_textAutosizingFontScaleFactor(1)
#if HACK_FORCE_TEXT_AUTOSIZING_ON_DESKTOP
@@ -168,6 +178,15 @@
, m_usesPageCache(false)
, m_fontRenderingMode(0)
, m_isCSSCustomFilterEnabled(false)
+#if PLATFORM(IOS)
+ , m_standalone(false)
+ , m_telephoneNumberParsingEnabled(false)
+ , m_mediaDataLoadsAutomatically(false)
+ , m_shouldTransformsAffectOverflow(true)
+ , m_shouldDispatchJavaScriptWindowOnErrorEvents(false)
+ , m_alwaysUseBaselineOfPrimaryFont(false)
+ , m_alwaysUseAcceleratedOverflowScroll(false)
+#endif
#if ENABLE(CSS_STICKY_POSITION)
, m_cssStickyPositionEnabled(true)
#endif
@@ -382,7 +401,15 @@
void Settings::setScriptEnabled(bool isScriptEnabled)
{
+#if PLATFORM(IOS)
+ if (m_isScriptEnabled == isScriptEnabled)
+ return;
+#endif
+
m_isScriptEnabled = isScriptEnabled;
+#if PLATFORM(IOS)
+ m_page->setNeedsRecalcStyleInAllFrames();
+#endif
InspectorInstrumentation::scriptsEnabled(m_page, m_isScriptEnabled);
}
@@ -681,4 +708,47 @@
gLowPowerVideoAudioBufferSizeEnabled = flag;
}
+#if PLATFORM(IOS)
+void Settings::setStandalone(bool standalone)
+{
+ m_standalone = standalone;
+}
+
+void Settings::setAudioSessionCategoryOverride(unsigned sessionCategory)
+{
+ AudioSession::sharedSession().setCategoryOverride(static_cast<AudioSession::CategoryType>(sessionCategory));
+}
+
+unsigned Settings::audioSessionCategoryOverride()
+{
+ return AudioSession::sharedSession().categoryOverride();
+}
+
+void Settings::setNetworkDataUsageTrackingEnabled(bool trackingEnabled)
+{
+ gNetworkDataUsageTrackingEnabled = trackingEnabled;
+}
+
+bool Settings::networkDataUsageTrackingEnabled()
+{
+ return gNetworkDataUsageTrackingEnabled;
+}
+
+static String& sharedNetworkInterfaceNameGlobal()
+{
+ static NeverDestroyed<String> networkInterfaceName;
+ return networkInterfaceName;
+}
+
+void Settings::setNetworkInterfaceName(const String& networkInterfaceName)
+{
+ sharedNetworkInterfaceNameGlobal() = networkInterfaceName;
+}
+
+const String& Settings::networkInterfaceName()
+{
+ return sharedNetworkInterfaceNameGlobal();
+}
+#endif
+
} // namespace WebCore
diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h
index 0501141..96205fd 100644
--- a/Source/WebCore/page/Settings.h
+++ b/Source/WebCore/page/Settings.h
@@ -180,6 +180,33 @@
void setHiddenPageDOMTimerThrottlingEnabled(bool);
#endif
+#if PLATFORM(IOS)
+ // FIXME: This setting isn't specific to iOS.
+ void setMaxParseDuration(double maxParseDuration) { m_maxParseDuration = maxParseDuration; }
+ double maxParseDuration() const { return m_maxParseDuration; }
+
+ void setStandalone(bool);
+ bool standalone() const { return m_standalone; }
+
+ void setTelephoneNumberParsingEnabled(bool flag) { m_telephoneNumberParsingEnabled = flag; }
+ bool telephoneNumberParsingEnabled() const { return m_telephoneNumberParsingEnabled; }
+
+ void setMediaDataLoadsAutomatically(bool flag) { m_mediaDataLoadsAutomatically = flag; }
+ bool mediaDataLoadsAutomatically() const { return m_mediaDataLoadsAutomatically; }
+
+ void setShouldTransformsAffectOverflow(bool flag) { m_shouldTransformsAffectOverflow = flag; }
+ bool shouldTransformsAffectOverflow() const { return m_shouldTransformsAffectOverflow; }
+
+ void setShouldDispatchJavaScriptWindowOnErrorEvents(bool flag) { m_shouldDispatchJavaScriptWindowOnErrorEvents = flag; }
+ bool shouldDispatchJavaScriptWindowOnErrorEvents() const { return m_shouldDispatchJavaScriptWindowOnErrorEvents; }
+
+ void setAlwaysUseBaselineOfPrimaryFont(bool flag) { m_alwaysUseBaselineOfPrimaryFont = flag; }
+ bool alwaysUseBaselineOfPrimaryFont() const { return m_alwaysUseBaselineOfPrimaryFont; }
+
+ void setAlwaysUseAcceleratedOverflowScroll(bool flag) { m_alwaysUseAcceleratedOverflowScroll = flag; }
+ bool alwaysUseAcceleratedOverflowScroll() const { return m_alwaysUseAcceleratedOverflowScroll; }
+#endif
+
void setUsesPageCache(bool);
bool usesPageCache() const { return m_usesPageCache; }
@@ -268,6 +295,17 @@
static bool isVideoPluginProxyEnabled() { return gVideoPluginProxyEnabled; }
#endif
+#if PLATFORM(IOS)
+ static void setAudioSessionCategoryOverride(unsigned);
+ static unsigned audioSessionCategoryOverride();
+
+ static void setNetworkDataUsageTrackingEnabled(bool);
+ static bool networkDataUsageTrackingEnabled();
+
+ static void setNetworkInterfaceName(const String&);
+ static const String& networkInterfaceName();
+#endif
+
private:
explicit Settings(Page*);
@@ -281,6 +319,9 @@
const std::unique_ptr<FontGenericFamilies> m_fontGenericFamilies;
SecurityOrigin::StorageBlockingPolicy m_storageBlockingPolicy;
int m_layoutInterval;
+#if PLATFORM(IOS)
+ double m_maxParseDuration;
+#endif
#if ENABLE(TEXT_AUTOSIZING)
float m_textAutosizingFontScaleFactor;
IntSize m_textAutosizingWindowSizeOverride;
@@ -301,6 +342,16 @@
bool m_usesPageCache : 1;
unsigned m_fontRenderingMode : 1;
bool m_isCSSCustomFilterEnabled : 1;
+#if PLATFORM(IOS)
+ bool m_standalone : 1;
+ bool m_telephoneNumberParsingEnabled : 1;
+ bool m_mediaDataLoadsAutomatically : 1;
+ bool m_shouldTransformsAffectOverflow : 1;
+ bool m_shouldDispatchJavaScriptWindowOnErrorEvents : 1;
+ bool m_alwaysUseBaselineOfPrimaryFont : 1;
+ bool m_allowMultiElementImplicitFormSubmission : 1;
+ bool m_alwaysUseAcceleratedOverflowScroll : 1;
+#endif
#if ENABLE(CSS_STICKY_POSITION)
bool m_cssStickyPositionEnabled : 1;
#endif
@@ -348,6 +399,9 @@
static bool gShouldUseHighResolutionTimers;
#endif
static bool gShouldRespectPriorityInCSSAttributeSetters;
+#if PLATFORM(IOS)
+ static bool gNetworkDataUsageTrackingEnabled;
+#endif
static double gHiddenPageDOMTimerAlignmentInterval;
diff --git a/Source/WebCore/page/Settings.in b/Source/WebCore/page/Settings.in
index f48b4cd..4632606 100644
--- a/Source/WebCore/page/Settings.in
+++ b/Source/WebCore/page/Settings.in
@@ -217,3 +217,5 @@
# FIXME: Rename to allowMultiElementImplicitFormSubmission once we upstream the iOS changes to WebView.mm.
allowMultiElementImplicitSubmission initial=false
+
+mediaPlaybackAllowsAirPlay initial=true, conditional=IOS_AIRPLAY
diff --git a/Source/WebCore/page/animation/CSSPropertyAnimation.cpp b/Source/WebCore/page/animation/CSSPropertyAnimation.cpp
index 801eaa3..c28c134 100644
--- a/Source/WebCore/page/animation/CSSPropertyAnimation.cpp
+++ b/Source/WebCore/page/animation/CSSPropertyAnimation.cpp
@@ -1212,8 +1212,16 @@
new LengthPropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::specifiedLineHeight, &RenderStyle::setLineHeight),
new PropertyWrapper<int>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset),
new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth),
+
+ // FIXME: We should reconcile the difference in datatype between iOS and OpenSource. On iOS we want these properties to
+ // be float for sub-pixel kerning. See <rdar://problem/5020763>.
+#if !PLATFORM(IOS)
new PropertyWrapper<int>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing),
new PropertyWrapper<int>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing),
+#else
+ new PropertyWrapper<float>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing),
+ new PropertyWrapper<float>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing),
+#endif
new LengthPropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent),
new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective),
diff --git a/Source/WebCore/page/ios/EventHandlerIOS.mm b/Source/WebCore/page/ios/EventHandlerIOS.mm
new file mode 100644
index 0000000..1c37a34
--- /dev/null
+++ b/Source/WebCore/page/ios/EventHandlerIOS.mm
@@ -0,0 +1,503 @@
+/*
+ * Copyright (C) 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 COMPUTER, 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 COMPUTER, 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.
+ */
+
+#import "config.h"
+#import "EventHandler.h"
+
+#import "AXObjectCache.h"
+#import "BlockExceptions.h"
+#import "Chrome.h"
+#import "ChromeClient.h"
+#import "FocusController.h"
+#import "Frame.h"
+#import "FrameView.h"
+#import "KeyboardEvent.h"
+#import "MouseEventWithHitTestResults.h"
+#import "Page.h"
+#import "PlatformEventFactoryIOS.h"
+#import "PlatformKeyboardEvent.h"
+#import "RenderWidget.h"
+#import "WAKView.h"
+#import "WAKWindow.h"
+#import "WebEvent.h"
+#import <wtf/NeverDestroyed.h>
+#import <wtf/Noncopyable.h>
+
+#if ENABLE(IOS_TOUCH_EVENTS)
+#import <WebKitAdditions/EventHandlerIOSTouch.cpp>
+#endif
+
+namespace WebCore {
+
+static RetainPtr<WebEvent>& currentEventSlot()
+{
+ NeverDestroyed<RetainPtr<WebEvent>> event;
+ return event;
+}
+
+WebEvent *EventHandler::currentEvent()
+{
+ return currentEventSlot().get();
+}
+
+class CurrentEventScope {
+ WTF_MAKE_NONCOPYABLE(CurrentEventScope);
+public:
+ CurrentEventScope(WebEvent *);
+ ~CurrentEventScope();
+
+private:
+ RetainPtr<WebEvent> m_savedCurrentEvent;
+#ifndef NDEBUG
+ RetainPtr<WebEvent> m_event;
+#endif
+};
+
+inline CurrentEventScope::CurrentEventScope(WebEvent *event)
+ : m_savedCurrentEvent(currentEventSlot())
+#ifndef NDEBUG
+ , m_event(event)
+#endif
+{
+ currentEventSlot() = event;
+}
+
+inline CurrentEventScope::~CurrentEventScope()
+{
+ ASSERT(currentEventSlot() == m_event);
+ currentEventSlot() = m_savedCurrentEvent;
+}
+
+bool EventHandler::wheelEvent(WebEvent *event)
+{
+ Page* page = m_frame.page();
+ if (!page)
+ return false;
+
+ CurrentEventScope scope(event);
+
+ bool eventWasHandled = handleWheelEvent(PlatformEventFactory::createPlatformWheelEvent(event));
+ event.wasHandled = eventWasHandled;
+ return eventWasHandled;
+}
+
+#if ENABLE(IOS_TOUCH_EVENTS)
+void EventHandler::touchEvent(WebEvent *event)
+{
+ CurrentEventScope scope(event);
+
+ event.wasHandled = handleTouchEvent(PlatformEventFactory::createPlatformTouchEvent(event));
+}
+#endif
+
+bool EventHandler::tabsToAllFormControls(KeyboardEvent* event) const
+{
+ Page* page = m_frame.page();
+ if (!page)
+ return false;
+
+ KeyboardUIMode keyboardUIMode = page->chrome().client().keyboardUIMode();
+ bool handlingOptionTab = isKeyboardOptionTab(event);
+
+ // If tab-to-links is off, option-tab always highlights all controls.
+ if ((keyboardUIMode & KeyboardAccessTabsToLinks) == 0 && handlingOptionTab)
+ return true;
+
+ // If system preferences say to include all controls, we always include all controls.
+ if (keyboardUIMode & KeyboardAccessFull)
+ return true;
+
+ // Otherwise tab-to-links includes all controls, unless the sense is flipped via option-tab.
+ if (keyboardUIMode & KeyboardAccessTabsToLinks)
+ return !handlingOptionTab;
+
+ return handlingOptionTab;
+}
+
+bool EventHandler::keyEvent(WebEvent *event)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ ASSERT(event.type == WebEventKeyDown || event.type == WebEventKeyUp);
+
+ CurrentEventScope scope(event);
+ bool eventWasHandled = keyEvent(PlatformEventFactory::createPlatformKeyboardEvent(event));
+ event.wasHandled = eventWasHandled;
+ return eventWasHandled;
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return false;
+}
+
+void EventHandler::focusDocumentView()
+{
+ Page* page = m_frame.page();
+ if (!page)
+ return;
+
+ if (FrameView* frameView = m_frame.view()) {
+ if (NSView *documentView = frameView->documentView())
+ page->chrome().focusNSView(documentView);
+ }
+
+ page->focusController().setFocusedFrame(&m_frame);
+}
+
+bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event)
+{
+ // Figure out which view to send the event to.
+ RenderObject* target = event.targetNode() ? event.targetNode()->renderer() : nullptr;
+ if (!target || !target->isWidget())
+ return false;
+
+ // Double-click events don't exist in Cocoa. Since passWidgetMouseDownEventToWidget() will
+ // just pass currentEvent down to the widget, we don't want to call it for events that
+ // don't correspond to Cocoa events. The mousedown/ups will have already been passed on as
+ // part of the pressed/released handling.
+ return passMouseDownEventToWidget(toRenderWidget(target)->widget());
+}
+
+bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)
+{
+ return passMouseDownEventToWidget(renderWidget->widget());
+}
+
+static bool lastEventIsMouseUp()
+{
+ // Many AppKit widgets run their own event loops and consume events while the mouse is down.
+ // When they finish, currentEvent is the mouseUp that they exited on. We need to update
+ // the WebCore state with this mouseUp, which we never saw. This method lets us detect
+ // that state. Handling this was critical when we used AppKit widgets for form elements.
+ // It's not clear in what cases this is helpful now -- it's possible it can be removed.
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ WebEvent *currentEventAfterHandlingMouseDown = [WAKWindow currentEvent];
+ return currentEventAfterHandlingMouseDown
+ && EventHandler::currentEvent() != currentEventAfterHandlingMouseDown
+ && currentEventAfterHandlingMouseDown.type == WebEventMouseUp
+ && currentEventAfterHandlingMouseDown.timestamp >= EventHandler::currentEvent().timestamp;
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return false;
+}
+
+bool EventHandler::passMouseDownEventToWidget(Widget* pWidget)
+{
+ // FIXME: This function always returns true. It should be changed either to return
+ // false in some cases or the return value should be removed.
+
+ RefPtr<Widget> widget = pWidget;
+
+ if (!widget) {
+ LOG_ERROR("hit a RenderWidget without a corresponding Widget, means a frame is half-constructed");
+ return true;
+ }
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ NSView *nodeView = widget->platformWidget();
+ ASSERT(nodeView);
+ ASSERT([nodeView superview]);
+ NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:currentEvent().locationInWindow fromView:nil]];
+ if (!view) {
+ // We probably hit the border of a RenderWidget
+ return true;
+ }
+
+ Page* page = m_frame.page();
+ if (!page)
+ return true;
+
+ if (page->chrome().client().firstResponder() != view) {
+ // Normally [NSWindow sendEvent:] handles setting the first responder.
+ // But in our case, the event was sent to the view representing the entire web page.
+ if ([view acceptsFirstResponder] && [view needsPanelToBecomeKey])
+ page->chrome().client().makeFirstResponder(view);
+ }
+
+ // We need to "defer loading" while tracking the mouse, because tearing down the
+ // page while an AppKit control is tracking the mouse can cause a crash.
+
+ // FIXME: In theory, WebCore now tolerates tear-down while tracking the
+ // mouse. We should confirm that, and then remove the deferrsLoading
+ // hack entirely.
+
+ bool wasDeferringLoading = page->defersLoading();
+ if (!wasDeferringLoading)
+ page->setDefersLoading(true);
+
+ ASSERT(!m_sendingEventToSubview);
+ m_sendingEventToSubview = true;
+ [view mouseDown:currentEvent()];
+ m_sendingEventToSubview = false;
+
+ if (!wasDeferringLoading)
+ page->setDefersLoading(false);
+
+ // Remember which view we sent the event to, so we can direct the release event properly.
+ m_mouseDownView = view;
+ m_mouseDownWasInSubframe = false;
+
+ // Many AppKit widgets run their own event loops and consume events while the mouse is down.
+ // When they finish, currentEvent is the mouseUp that they exited on. We need to update
+ // the EventHandler state with this mouseUp, which we never saw.
+ // If this event isn't a mouseUp, we assume that the mouseUp will be coming later. There
+ // is a hole here if the widget consumes both the mouseUp and subsequent events.
+ if (lastEventIsMouseUp())
+ m_mousePressed = false;
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return true;
+}
+
+// Note that this does the same kind of check as [target isDescendantOf:superview].
+// There are two differences: This is a lot slower because it has to walk the whole
+// tree, and this works in cases where the target has already been deallocated.
+static bool findViewInSubviews(NSView *superview, NSView *target)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ NSEnumerator *e = [[superview subviews] objectEnumerator];
+ NSView *subview;
+ while ((subview = [e nextObject])) {
+ if (subview == target || findViewInSubviews(subview, target)) {
+ return true;
+ }
+ }
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return false;
+}
+
+NSView *EventHandler::mouseDownViewIfStillGood()
+{
+ // Since we have no way of tracking the lifetime of m_mouseDownView, we have to assume that
+ // it could be deallocated already. We search for it in our subview tree; if we don't find
+ // it, we set it to nil.
+ NSView *mouseDownView = m_mouseDownView;
+ if (!mouseDownView) {
+ return nil;
+ }
+ FrameView* topFrameView = m_frame.view();
+ NSView *topView = topFrameView ? topFrameView->platformWidget() : nil;
+ if (!topView || !findViewInSubviews(topView, mouseDownView)) {
+ m_mouseDownView = nil;
+ return nil;
+ }
+ return mouseDownView;
+}
+
+bool EventHandler::eventActivatedView(const PlatformMouseEvent&) const
+{
+ return false;
+}
+
+bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&)
+{
+ NSView *view = mouseDownViewIfStillGood();
+ if (!view)
+ return false;
+
+ if (!m_mouseDownWasInSubframe) {
+ ASSERT(!m_sendingEventToSubview);
+ m_sendingEventToSubview = true;
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ [view mouseUp:currentEvent()];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ m_sendingEventToSubview = false;
+ }
+
+ return true;
+}
+
+bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& event, Frame* subframe, HitTestResult* hoveredNode)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ WebEventType currentEventType = currentEvent().type;
+ switch (currentEventType) {
+ case WebEventMouseMoved: {
+ // Since we're passing in currentNSEvent() here, we can call
+ // handleMouseMoveEvent() directly, since the save/restore of
+ // currentNSEvent() that mouseMoved() does would have no effect.
+ ASSERT(!m_sendingEventToSubview);
+ m_sendingEventToSubview = true;
+ subframe->eventHandler().handleMouseMoveEvent(currentPlatformMouseEvent(), hoveredNode);
+ m_sendingEventToSubview = false;
+ return true;
+ }
+ case WebEventMouseDown: {
+ Node* node = event.targetNode();
+ if (!node)
+ return false;
+ RenderObject* renderer = node->renderer();
+ if (!renderer || !renderer->isWidget())
+ return false;
+ Widget* widget = toRenderWidget(renderer)->widget();
+ if (!widget || !widget->isFrameView())
+ return false;
+ if (!passWidgetMouseDownEventToWidget(toRenderWidget(renderer)))
+ return false;
+ m_mouseDownWasInSubframe = true;
+ return true;
+ }
+ case WebEventMouseUp: {
+ if (!m_mouseDownWasInSubframe)
+ return false;
+ ASSERT(!m_sendingEventToSubview);
+ m_sendingEventToSubview = true;
+ subframe->eventHandler().handleMouseReleaseEvent(currentPlatformMouseEvent());
+ m_sendingEventToSubview = false;
+ return true;
+ }
+ case WebEventKeyDown:
+ case WebEventKeyUp:
+ case WebEventScrollWheel:
+ case WebEventTouchBegin:
+ case WebEventTouchCancel:
+ case WebEventTouchChange:
+ case WebEventTouchEnd:
+ return false;
+ }
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return false;
+}
+
+bool EventHandler::passWheelEventToWidget(const PlatformWheelEvent&, Widget* widget)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ if (currentEvent().type != WebEventScrollWheel || m_sendingEventToSubview || !widget)
+ return false;
+
+ NSView* nodeView = widget->platformWidget();
+ ASSERT(nodeView);
+ ASSERT([nodeView superview]);
+ NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:currentEvent().locationInWindow fromView:nil]];
+ if (!view) {
+ // We probably hit the border of a RenderWidget
+ return false;
+ }
+
+ ASSERT(!m_sendingEventToSubview);
+ m_sendingEventToSubview = true;
+ [view scrollWheel:currentEvent()];
+ m_sendingEventToSubview = false;
+ return true;
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return false;
+}
+
+void EventHandler::mouseDown(WebEvent *event)
+{
+ FrameView* v = m_frame.view();
+ if (!v || m_sendingEventToSubview)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ m_frame.loader().resetMultipleFormSubmissionProtection();
+
+ m_mouseDownView = nil;
+
+ CurrentEventScope scope(event);
+
+ event.wasHandled = handleMousePressEvent(currentPlatformMouseEvent());
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+void EventHandler::mouseUp(WebEvent *event)
+{
+ FrameView* v = m_frame.view();
+ if (!v || m_sendingEventToSubview)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ CurrentEventScope scope(event);
+
+ event.wasHandled = handleMouseReleaseEvent(currentPlatformMouseEvent());
+
+ m_mouseDownView = nil;
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+void EventHandler::mouseMoved(WebEvent *event)
+{
+ // Reject a mouse moved if the button is down - screws up tracking during autoscroll
+ // These happen because WebKit sometimes has to fake up moved events.
+ if (!m_frame.view() || m_mousePressed || m_sendingEventToSubview)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ m_frame.document()->updateStyleIfNeeded();
+
+ WKBeginObservingContentChanges(true);
+ CurrentEventScope scope(event);
+ event.wasHandled = mouseMoved(currentPlatformMouseEvent());
+ m_frame.document()->updateStyleIfNeeded();
+ WKStopObservingContentChanges();
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe)
+{
+ return passSubframeEventToSubframe(mev, subframe);
+}
+
+bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe, HitTestResult* hoveredNode)
+{
+ return passSubframeEventToSubframe(mev, subframe, hoveredNode);
+}
+
+bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe)
+{
+ return passSubframeEventToSubframe(mev, subframe);
+}
+
+unsigned EventHandler::accessKeyModifiers()
+{
+ // Control+Option key combinations are usually unused on Mac OS X, but not when VoiceOver is enabled.
+ // So, we use Control in this case, even though it conflicts with Emacs-style key bindings.
+ // See <https://bugs.webkit.org/show_bug.cgi?id=21107> for more detail.
+ if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
+ return PlatformKeyboardEvent::CtrlKey;
+
+ return PlatformKeyboardEvent::CtrlKey | PlatformKeyboardEvent::AltKey;
+}
+
+PlatformMouseEvent EventHandler::currentPlatformMouseEvent() const
+{
+ return PlatformEventFactory::createPlatformMouseEvent(currentEvent());
+}
+
+}
diff --git a/Source/WebCore/page/ios/FrameIOS.mm b/Source/WebCore/page/ios/FrameIOS.mm
new file mode 100644
index 0000000..94a4dbb
--- /dev/null
+++ b/Source/WebCore/page/ios/FrameIOS.mm
@@ -0,0 +1,930 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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. 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 INC. 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 "config.h"
+#import "Frame.h"
+
+#if PLATFORM(IOS)
+
+#import "AnimationController.h"
+#import "BlockExceptions.h"
+#import "DOMCSSStyleDeclarationInternal.h"
+#import "DOMCore.h"
+#import "DOMInternal.h"
+#import "DOMNodeInternal.h"
+#import "DOMWindow.h"
+#import "Document.h"
+#import "DocumentMarker.h"
+#import "DocumentMarkerController.h"
+#import "Editor.h"
+#import "EditorClient.h"
+#import "EventHandler.h"
+#import "EventNames.h"
+#import "FormController.h"
+#import "FrameSelection.h"
+#import "FrameSnapshottingMac.h"
+#import "FrameView.h"
+#import "HTMLAreaElement.h"
+#import "HTMLDocument.h"
+#import "HTMLElement.h"
+#import "HTMLNames.h"
+#import "HTMLObjectElement.h"
+#import "HitTestRequest.h"
+#import "HitTestResult.h"
+#import "JSDOMWindowBase.h"
+#import "MainFrame.h"
+#import "NodeRenderStyle.h"
+#import "NodeTraversal.h"
+#import "Page.h"
+#import "PageTransitionEvent.h"
+#import "PropertySetCSSStyleDeclaration.h"
+#import "RenderLayer.h"
+#import "RenderLayerCompositor.h"
+#import "RenderTextControl.h"
+#import "RenderView.h"
+#import "TextBoundaries.h"
+#import "TextIterator.h"
+#import "VisiblePosition.h"
+#import "VisibleUnits.h"
+#import "WAKWindow.h"
+#import "WebCoreSystemInterface.h"
+#import <runtime/JSLock.h>
+
+using namespace WebCore::HTMLNames;
+using namespace WTF::Unicode;
+
+using JSC::JSLockHolder;
+
+namespace WebCore {
+
+// Create <html><body (style="...")></body></html> doing minimal amount of work.
+void Frame::initWithSimpleHTMLDocument(const String& style, const URL& url)
+{
+ m_loader.initForSynthesizedDocument(url);
+
+ RefPtr<HTMLDocument> document = HTMLDocument::createSynthesizedDocument(this, url);
+ document->setCompatibilityMode(Document::LimitedQuirksMode);
+ document->createDOMWindow();
+ setDocument(document);
+
+ ExceptionCode ec;
+ RefPtr<Element> rootElement = document->createElementNS(xhtmlNamespaceURI, ASCIILiteral("html"), ec);
+
+ RefPtr<Element> body = document->createElementNS(xhtmlNamespaceURI, ASCIILiteral("body"), ec);
+ if (!style.isEmpty())
+ body->setAttribute(HTMLNames::styleAttr, style);
+
+ rootElement->appendChild(body, ec);
+ document->appendChild(rootElement, ec);
+}
+
+// FIXME: Extract the common code in indexCountOfWordPrecedingSelection() and wordsInCurrentParagraph() into a shared function.
+int Frame::indexCountOfWordPrecedingSelection(NSString *word) const
+{
+ int result = -1;
+
+ if (!page() || page()->selection().isNone())
+ return result;
+
+ RefPtr<Range> searchRange(rangeOfContents(*document()));
+ VisiblePosition start(page()->selection().start(), page()->selection().affinity());
+ VisiblePosition oneBeforeStart = start.previous();
+
+ setEnd(searchRange.get(), oneBeforeStart.isNotNull() ? oneBeforeStart : start);
+
+ int exception = 0;
+ if (searchRange->collapsed(exception))
+ return result;
+
+ WordAwareIterator it(searchRange.get());
+ while (!it.atEnd()) {
+ const UChar* chars = it.characters();
+ int length = it.length();
+ if (length > 1 || !isSpaceOrNewline(chars[0])) {
+ int startOfWordBoundary = 0;
+ for (int i = 1; i < length; i++) {
+ if (isSpaceOrNewline(chars[i]) || chars[i] == 0xA0) {
+ int wordLength = i - startOfWordBoundary;
+ NSString *chunk = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(chars) + startOfWordBoundary length:wordLength freeWhenDone:NO];
+ if ([chunk isEqualToString:word])
+ ++result;
+ [chunk release];
+ startOfWordBoundary += wordLength + 1;
+ }
+ }
+ if (startOfWordBoundary < length) {
+ NSString *chunk = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(chars) + startOfWordBoundary length:length - startOfWordBoundary freeWhenDone:NO];
+ if ([chunk isEqualToString:word])
+ ++result;
+ [chunk release];
+ }
+ }
+ it.advance();
+ }
+
+ return result + 1;
+}
+
+// FIXME: Extract the common code in indexCountOfWordPrecedingSelection() and wordsInCurrentParagraph() into a shared function.
+NSArray *Frame::wordsInCurrentParagraph() const
+{
+ document()->updateLayout();
+
+ if (!page() || !page()->selection().isCaret())
+ return nil;
+
+ VisiblePosition position(page()->selection().start(), page()->selection().affinity());
+ VisiblePosition end(position);
+ if (!isStartOfParagraph(end)) {
+ VisiblePosition previous = end.previous();
+ UChar c(previous.characterAfter());
+ if (!iswpunct(c) && !isSpaceOrNewline(c) && c != 0xA0)
+ end = startOfWord(end);
+ }
+ VisiblePosition start(startOfParagraph(end));
+
+ RefPtr<Range> searchRange(rangeOfContents(*document()));
+ setStart(searchRange.get(), start);
+ setEnd(searchRange.get(), end);
+
+ int exception = 0;
+ if (searchRange->collapsed(exception))
+ return nil;
+
+ NSMutableArray *words = [NSMutableArray array];
+
+ WordAwareIterator it(searchRange.get());
+ while (!it.atEnd()) {
+ const UChar* chars = it.characters();
+ int length = it.length();
+ if (length > 1 || !isSpaceOrNewline(chars[0])) {
+ int startOfWordBoundary = 0;
+ for (int i = 1; i < length; i++) {
+ if (isSpaceOrNewline(chars[i]) || chars[i] == 0xA0) {
+ int wordLength = i - startOfWordBoundary;
+ if (wordLength > 0) {
+ NSString *chunk = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(chars) + startOfWordBoundary length:wordLength freeWhenDone:NO];
+ [words addObject:chunk];
+ [chunk release];
+ }
+ startOfWordBoundary += wordLength + 1;
+ }
+ }
+ if (startOfWordBoundary < length) {
+ NSString *chunk = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(chars) + startOfWordBoundary length:length - startOfWordBoundary freeWhenDone:NO];
+ [words addObject:chunk];
+ [chunk release];
+ }
+ }
+ it.advance();
+ }
+
+ if ([words count] > 0 && isEndOfParagraph(position) && !isStartOfParagraph(position)) {
+ VisiblePosition previous = position.previous();
+ UChar c(previous.characterAfter());
+ if (!isSpaceOrNewline(c) && c != 0xA0)
+ [words removeLastObject];
+ }
+
+ return words;
+}
+
+#define CHECK_FONT_SIZE 0
+#define RECT_LOGGING 0
+
+CGRect Frame::renderRectForPoint(CGPoint point, bool* isReplaced, float* fontSize) const
+{
+ *isReplaced = false;
+ *fontSize = 0;
+
+ if (!m_doc || !m_doc->renderBox())
+ return CGRectZero;
+
+ // FIXME: why this layer check?
+ RenderLayer* layer = m_doc->renderBox()->layer();
+ if (!layer)
+ return CGRectZero;
+
+ HitTestResult result = eventHandler().hitTestResultAtPoint(IntPoint(roundf(point.x), roundf(point.y)));
+
+ Node* node = result.innerNode();
+ if (!node)
+ return CGRectZero;
+
+ RenderObject* hitRenderer = node->renderer();
+ RenderObject* renderer = hitRenderer;
+#if RECT_LOGGING
+ printf("\n%f %f\n", point.x, point.y);
+#endif
+ while (renderer && !renderer->isBody() && !renderer->isRoot()) {
+#if RECT_LOGGING
+ CGRect rect = renderer->absoluteBoundingBoxRect(true);
+ if (renderer->node()) {
+ const char *nodeName = renderer->node()->nodeName().ascii().data();
+ printf("%s %f %f %f %f\n", nodeName, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+ }
+#endif
+ if (renderer->isRenderBlock() || renderer->isInlineBlockOrInlineTable() || renderer->isReplaced()) {
+ *isReplaced = renderer->isReplaced();
+#if CHECK_FONT_SIZE
+ for (RenderObject* textRenderer = hitRenderer; textRenderer; textRenderer = textRenderer->traverseNext(hitRenderer)) {
+ if (textRenderer->isText()) {
+ *fontSize = textRenderer->font(true).pixelSize();
+ break;
+ }
+ }
+#endif
+ IntRect targetRect = renderer->absoluteBoundingBoxRect(true);
+ for (Widget* currView = &(renderer->view().frameView()); currView && currView != view(); currView = currView->parent())
+ targetRect = currView->convertToContainingView(targetRect);
+
+ return targetRect;
+ }
+ renderer = renderer->parent();
+ }
+
+ return CGRectZero;
+}
+
+#define ALLOW_SCROLL_LISTENERS 0
+
+static Node* ancestorRespondingToScrollWheelEvents(const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds)
+{
+ if (nodeBounds)
+ *nodeBounds = IntRect();
+
+ Node* scrollingAncestor = nullptr;
+ for (Node* node = hitTestResult.innerNode(); node && node != terminationNode && !node->hasTagName(HTMLNames::bodyTag); node = node->parentNode()) {
+#if ALLOW_SCROLL_LISTENERS
+ if (node->willRespondToMouseWheelEvents()) {
+ scrollingAncestor = node;
+ continue;
+ }
+#endif
+
+ RenderObject* renderer = node->renderer();
+ if (!renderer)
+ continue;
+
+ if ((renderer->isTextField() || renderer->isTextArea()) && toRenderTextControl(renderer)->canScroll()) {
+ scrollingAncestor = node;
+ continue;
+ }
+
+ RenderStyle& style = renderer->style();
+
+ if (renderer->hasOverflowClip() &&
+ (style.overflowY() == OAUTO || style.overflowY() == OSCROLL || style.overflowY() == OOVERLAY ||
+ style.overflowX() == OAUTO || style.overflowX() == OSCROLL || style.overflowX() == OOVERLAY))
+ scrollingAncestor = node;
+ }
+
+ return scrollingAncestor;
+}
+
+static Node* ancestorRespondingToClickEvents(const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds)
+{
+ bool bodyHasBeenReached = false;
+ bool pointerCursorStillValid = true;
+
+ if (nodeBounds)
+ *nodeBounds = IntRect();
+
+ Node* pointerCursorNode = nullptr;
+ for (Node* node = hitTestResult.innerNode(); node && node != terminationNode; node = node->parentNode()) {
+ ASSERT(!node->isInShadowTree());
+
+ // We only accept pointer nodes before reaching the body tag.
+ if (node->hasTagName(HTMLNames::bodyTag)) {
+#if USE(UIKIT_EDITING)
+ // Make sure we cover the case of an empty editable body.
+ if (!pointerCursorNode && node->isContentEditable())
+ pointerCursorNode = node;
+#endif
+ bodyHasBeenReached = true;
+ pointerCursorStillValid = false;
+ }
+
+ // If we already have a pointer, and we reach a table, don't accept it.
+ if (pointerCursorNode && (node->hasTagName(HTMLNames::tableTag) || node->hasTagName(HTMLNames::tbodyTag)))
+ pointerCursorStillValid = false;
+
+ // If we haven't reached the body, and we are still paying attention to pointer cursors, and the node has a pointer cursor...
+ if (pointerCursorStillValid && node->renderStyle() && node->renderStyle()->cursor() == CURSOR_POINTER)
+ pointerCursorNode = node;
+ // We want the lowest unbroken chain of pointer cursors.
+ else if (pointerCursorNode)
+ pointerCursorStillValid = false;
+
+ if (node->willRespondToMouseClickEvents() || node->willRespondToMouseMoveEvents()) {
+ // If we're at the body or higher, use the pointer cursor node (which may be null).
+ if (bodyHasBeenReached)
+ node = pointerCursorNode;
+
+ // If we are interested about the frame, use it.
+ if (nodeBounds) {
+ // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check.
+ if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && node->hasTagName(HTMLNames::areaTag))
+ *nodeBounds = pixelSnappedIntRect(toHTMLAreaElement(node)->computeRect(hitTestResult.innerNonSharedNode()->renderer()));
+ else if (node && node->renderer())
+ *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true);
+ }
+
+ return node;
+ }
+ }
+
+ return nullptr;
+}
+
+void Frame::betterApproximateNode(const IntPoint& testPoint, NodeQualifier nodeQualifierFunction, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect)
+{
+ IntRect candidateRect;
+ Node* candidate = nodeQualifierFunction(eventHandler().hitTestResultAtPoint(testPoint), failedNode, &candidateRect);
+
+ // Bail if we have no candidate, or the candidate is already equal to our current best node,
+ // or our candidate is the avoidedNode and there is a current best node.
+ if (!candidate || candidate == best)
+ return;
+
+ // The document should never be considered the best alternative.
+ if (candidate->isDocumentNode())
+ return;
+
+ if (best) {
+ IntRect bestIntersect = intersection(testRect, bestRect);
+ IntRect candidateIntersect = intersection(testRect, candidateRect);
+ // if the candidate intersection is smaller than the current best intersection, bail.
+ if (candidateIntersect.width() * candidateIntersect.height() <= bestIntersect.width() * bestIntersect.height())
+ return;
+ }
+
+ // At this point we either don't have a previous best, or our current candidate has a better intersection.
+ best = candidate;
+ bestPoint = testPoint;
+ bestRect = candidateRect;
+}
+
+bool Frame::hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult& hitTestResult, IntPoint& center)
+{
+ if (!m_doc || !m_doc->renderView())
+ return false;
+
+ FrameView* view = m_view.get();
+ if (!view)
+ return false;
+
+ center = view->windowToContents(roundedIntPoint(viewportLocation));
+ hitTestResult = eventHandler().hitTestResultAtPoint(center);
+ return true;
+}
+
+Node* Frame::qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, NodeQualifier nodeQualifierFunction, bool shouldApproximate)
+{
+ adjustedViewportLocation = viewportLocation;
+
+ IntPoint testCenter;
+ HitTestResult candidateInfo;
+ if (!hitTestResultAtViewportLocation(viewportLocation, candidateInfo, testCenter))
+ return nullptr;
+
+ IntPoint bestPoint = testCenter;
+
+ // We have the candidate node at the location, check whether it or one of its ancestors passes
+ // the qualifier function, which typically checks if the node responds to a particular event type.
+ Node* approximateNode = nodeQualifierFunction(candidateInfo, 0, 0);
+
+#if USE(UIKIT_EDITING)
+ if (approximateNode && approximateNode->isContentEditable()) {
+ // If we are in editable content, we look for the root editable element.
+ approximateNode = approximateNode->rootEditableElement();
+ // If we have a focusable node, there is no need to approximate.
+ if (approximateNode)
+ shouldApproximate = false;
+ }
+#endif
+ if (approximateNode && shouldApproximate) {
+ float scale = page() ? page()->pageScaleFactor() : 1;
+
+ const int defaultMaxRadius = 15;
+ int maxRadius = scale < 1 ? static_cast<int>(defaultMaxRadius / scale) : defaultMaxRadius;
+
+ const float testOffsets[] = {
+ -.3f, -.3f,
+ -.6f, -.6f,
+ +.3f, +.3f,
+ -.9f, -.9f,
+ };
+
+ Node* originalApproximateNode = approximateNode;
+ for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) {
+ IntSize testOffset(testOffsets[n] * maxRadius, testOffsets[n + 1] * maxRadius);
+ IntPoint testPoint = testCenter + testOffset;
+
+ HitTestResult candidateInfo = eventHandler().hitTestResultAtPoint(testPoint);
+ Node* candidateNode = nodeQualifierFunction(candidateInfo, 0, 0);
+ if (candidateNode && candidateNode->isDescendantOf(originalApproximateNode)) {
+ approximateNode = candidateNode;
+ bestPoint = testPoint;
+ break;
+ }
+ }
+ } else if (!approximateNode && shouldApproximate) {
+ // Grab the closest parent element of our failed candidate node.
+ Node* candidate = candidateInfo.innerNode();
+ Node* failedNode = candidate;
+
+ while (candidate && !candidate->isElementNode())
+ candidate = candidate->parentNode();
+
+ if (candidate)
+ failedNode = candidate;
+
+ // We don't approximate the node if we are dragging, we instead force the user to be precise.
+ float scale = page() ? page()->pageScaleFactor() : 1;
+
+ const int defaultMaxRadius = 15;
+ int maxRadius = (scale < 1.0) ? static_cast<int>(defaultMaxRadius / scale) : defaultMaxRadius;
+
+ // The center point was tested earlier.
+ const float testOffsets[] = {
+ -.3f, -.3f,
+ +.3f, -.3f,
+ -.3f, +.3f,
+ +.3f, +.3f,
+ -.6f, -.6f,
+ +.6f, -.6f,
+ -.6f, +.6f,
+ +.6f, +.6f,
+ -1.f, 0,
+ +1.f, 0,
+ 0, +1.f,
+ 0, -1.f,
+ };
+ IntRect bestFrame;
+ IntRect testRect(testCenter, IntSize());
+ testRect.inflate(maxRadius);
+ int currentTestRadius = 0;
+ for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) {
+ IntSize testOffset(testOffsets[n] * maxRadius, testOffsets[n + 1] * maxRadius);
+ IntPoint testPoint = testCenter + testOffset;
+ int testRadius = std::max(abs(testOffset.width()), abs(testOffset.height()));
+ if (testRadius > currentTestRadius) {
+ // Bail out with the best match within a radius
+ currentTestRadius = testRadius;
+ if (approximateNode)
+ break;
+ }
+ betterApproximateNode(testPoint, nodeQualifierFunction, approximateNode, failedNode, bestPoint, bestFrame, testRect);
+ }
+ }
+
+ if (approximateNode) {
+ IntPoint p = m_view->contentsToWindow(bestPoint);
+ adjustedViewportLocation = p;
+#if USE(UIKIT_EDITING)
+ if (approximateNode->isContentEditable()) {
+ // When in editable content, look for the root editable node again,
+ // since this could be the node found with the approximation.
+ approximateNode = approximateNode->rootEditableElement();
+ }
+#endif
+ }
+
+ return approximateNode;
+}
+
+Node* Frame::deepestNodeAtLocation(const FloatPoint& viewportLocation)
+{
+ IntPoint center;
+ HitTestResult hitTestResult;
+ if (!hitTestResultAtViewportLocation(viewportLocation, hitTestResult, center))
+ return nullptr;
+
+ return hitTestResult.innerNode();
+}
+
+Node* Frame::nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation)
+{
+ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, &ancestorRespondingToClickEvents, true);
+}
+
+Node* Frame::nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation)
+{
+ FloatPoint adjustedViewportLocation;
+ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, &ancestorRespondingToScrollWheelEvents, false);
+}
+
+int Frame::preferredHeight() const
+{
+ Document* document = this->document();
+ if (!document)
+ return 0;
+
+ document->updateLayout();
+
+ Node* body = document->body();
+ if (!body)
+ return 0;
+
+ RenderObject* renderer = body->renderer();
+ if (!renderer || !renderer->isRenderBlock())
+ return 0;
+
+ RenderBlock* block = toRenderBlock(renderer);
+ return block->height() + block->marginTop() + block->marginBottom();
+}
+
+int Frame::innerLineHeight(DOMNode* domNode) const
+{
+ if (!domNode)
+ return 0;
+
+ Document* document = this->document();
+ if (!document)
+ return 0;
+
+ document->updateLayout();
+
+ Node* node = core(domNode);
+ if (!node)
+ return 0;
+
+ RenderObject* renderer = node->renderer();
+ if (!renderer)
+ return 0;
+
+ return renderer->innerLineHeight();
+}
+
+void Frame::updateLayout() const
+{
+ Document* document = this->document();
+ if (!document)
+ return;
+
+ document->updateLayout();
+
+ if (FrameView* view = this->view())
+ view->adjustViewSize();
+}
+
+NSRect Frame::caretRect() const
+{
+ if (selection().isNone())
+ return CGRectZero;
+ return selection().isCaret() ? selection().absoluteCaretBounds() : VisiblePosition(selection().end()).absoluteCaretBounds();
+}
+
+NSRect Frame::rectForScrollToVisible() const
+{
+ VisibleSelection selection(this->selection().selection());
+ return rectForSelection(selection);
+}
+
+NSRect Frame::rectForSelection(VisibleSelection& selection) const
+{
+ if (selection.isNone())
+ return CGRectZero;
+
+ if (selection.isCaret())
+ return caretRect();
+
+ EditorClient* client = editor().client();
+ if (client)
+ client->suppressSelectionNotifications();
+
+ VisibleSelection originalSelection(selection);
+ Position position;
+
+ // The selection controllers below need to be associated with a frame in order
+ // to calculate geometry. This causes them to do more work here than we would
+ // like. Ideally, we would have a sort offline geometry-only mode for selection
+ // controllers so we could do this kind of work as cheaply as possible.
+
+ position = originalSelection.start();
+ selection.setBase(position);
+ selection.setExtent(position);
+ FrameSelection startFrameSelection(const_cast<Frame*>(this));
+ startFrameSelection.suppressCloseTyping();
+ startFrameSelection.setSelection(selection);
+ FloatRect startRect(startFrameSelection.absoluteCaretBounds());
+ startFrameSelection.restoreCloseTyping();
+
+ position = originalSelection.end();
+ selection.setBase(position);
+ selection.setExtent(position);
+ FrameSelection endFrameSelection(const_cast<Frame*>(this));
+ endFrameSelection.suppressCloseTyping();
+ endFrameSelection.setSelection(selection);
+ FloatRect endRect(endFrameSelection.absoluteCaretBounds());
+ endFrameSelection.restoreCloseTyping();
+
+ if (client)
+ client->restoreSelectionNotifications();
+
+ return unionRect(startRect, endRect);
+}
+
+DOMCSSStyleDeclaration* Frame::styleAtSelectionStart() const
+{
+ Position start = selection().start();
+ RefPtr<EditingStyle> editingStyle = EditingStyle::styleAtSelectionStart(selection().selection());
+ if (!editingStyle)
+ return nullptr;
+ PropertySetCSSStyleDeclaration* propertySetCSSStyleDeclaration = new PropertySetCSSStyleDeclaration(editingStyle->style());
+ // The auto-generated code for DOMCSSStyleDeclaration derefs its pointer when it is deallocated.
+ return kit(static_cast<CSSStyleDeclaration*>(propertySetCSSStyleDeclaration));
+}
+
+unsigned Frame::formElementsCharacterCount() const
+{
+ Document* document = this->document();
+ if (!document)
+ return 0;
+ return document->formController().formElementsCharacterCount();
+}
+
+void Frame::setTimersPaused(bool paused)
+{
+ JSLockHolder lock(JSDOMWindowBase::commonVM());
+ setTimersPausedInternal(paused);
+}
+
+void Frame::setTimersPausedInternal(bool paused)
+{
+ if (paused) {
+ ++m_timersPausedCount;
+ if (m_timersPausedCount == 1) {
+ clearTimers();
+ if (document())
+ document()->suspendScheduledTasks(ActiveDOMObject::DocumentWillBePaused);
+ }
+ } else {
+ --m_timersPausedCount;
+ ASSERT(m_timersPausedCount >= 0);
+ if (m_timersPausedCount == 0) {
+ if (document())
+ document()->resumeScheduledTasks(ActiveDOMObject::DocumentWillBePaused);
+
+ // clearTimers() suspended animations and pending relayouts, reschedule if needed.
+ animation().resumeAnimationsForDocument(document());
+
+ if (view())
+ view()->scheduleRelayout();
+ }
+ }
+
+ // We need to make sure all subframes' states are up to date.
+ for (Frame* frame = tree().firstChild(); frame; frame = frame->tree().nextSibling())
+ frame->setTimersPausedInternal(paused);
+}
+
+void Frame::dispatchPageHideEventBeforePause()
+{
+ ASSERT(isMainFrame());
+ if (!isMainFrame())
+ return;
+
+ for (Frame* frame = this; frame; frame = frame->tree().traverseNext(this))
+ frame->document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, true), document());
+}
+
+void Frame::dispatchPageShowEventBeforeResume()
+{
+ ASSERT(isMainFrame());
+ if (!isMainFrame())
+ return;
+
+ for (Frame* frame = this; frame; frame = frame->tree().traverseNext(this))
+ frame->document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pageshowEvent, true), document());
+}
+
+void Frame::setRangedSelectionBaseToCurrentSelection()
+{
+ m_rangedSelectionBase = selection().selection();
+}
+
+void Frame::setRangedSelectionBaseToCurrentSelectionStart()
+{
+ FrameSelection& frameSelection = selection();
+ m_rangedSelectionBase = VisibleSelection(frameSelection.selection().start(), frameSelection.affinity());
+}
+
+void Frame::setRangedSelectionBaseToCurrentSelectionEnd()
+{
+ FrameSelection& frameSelection = selection();
+ m_rangedSelectionBase = VisibleSelection(frameSelection.selection().end(), frameSelection.affinity());
+}
+
+VisibleSelection Frame::rangedSelectionBase() const
+{
+ return m_rangedSelectionBase;
+}
+
+void Frame::clearRangedSelectionInitialExtent()
+{
+ m_rangedSelectionInitialExtent = VisibleSelection();
+}
+
+void Frame::setRangedSelectionInitialExtentToCurrentSelectionStart()
+{
+ FrameSelection& frameSelection = selection();
+ m_rangedSelectionInitialExtent = VisibleSelection(frameSelection.selection().start(), frameSelection.affinity());
+}
+
+void Frame::setRangedSelectionInitialExtentToCurrentSelectionEnd()
+{
+ FrameSelection& frameSelection = selection();
+ m_rangedSelectionInitialExtent = VisibleSelection(frameSelection.selection().end(), frameSelection.affinity());
+}
+
+VisibleSelection Frame::rangedSelectionInitialExtent() const
+{
+ return m_rangedSelectionInitialExtent;
+}
+
+void Frame::recursiveSetUpdateAppearanceEnabled(bool enabled)
+{
+ selection().setUpdateAppearanceEnabled(enabled);
+ for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling())
+ child->recursiveSetUpdateAppearanceEnabled(enabled);
+}
+
+// FIXME: Break this function up into pieces with descriptive function names so that it's easier to follow.
+NSArray *Frame::interpretationsForCurrentRoot() const
+{
+ if (!document())
+ return nil;
+
+ Element* root = selection().selectionType() == VisibleSelection::NoSelection ? document()->body() : selection().rootEditableElement();
+ unsigned rootChildCount = root->childNodeCount();
+ RefPtr<Range> rangeOfRootContents = Range::create(*document(), createLegacyEditingPosition(root, 0), createLegacyEditingPosition(root, rootChildCount));
+
+ Vector<DocumentMarker*> markersInRoot = document()->markers().markersInRange(rangeOfRootContents.get(), DocumentMarker::DictationPhraseWithAlternatives);
+
+ // There are no phrases with alternatives, so there is just one interpretation.
+ if (markersInRoot.isEmpty())
+ return [NSArray arrayWithObject:plainText(rangeOfRootContents.get())];
+
+ // The number of interpretations will be i1 * i2 * ... * iN, where iX is the number of interpretations for the Xth phrase with alternatives.
+ size_t interpretationsCount = 1;
+
+ for (auto marker : markersInRoot)
+ interpretationsCount *= marker->alternatives().size() + 1;
+
+ Vector<Vector<UChar>> interpretations;
+ interpretations.grow(interpretationsCount);
+
+ Position precedingTextStartPosition = createLegacyEditingPosition(root, 0);
+
+ unsigned combinationsSoFar = 1;
+
+ Node* pastLastNode = rangeOfRootContents->pastLastNode();
+ for (Node* node = rangeOfRootContents->firstNode(); node != pastLastNode; node = NodeTraversal::next(node)) {
+ const Vector<DocumentMarker*>& markers = document()->markers().markersFor(node, DocumentMarker::MarkerTypes(DocumentMarker::DictationPhraseWithAlternatives));
+ for (auto marker : markers) {
+ // First, add text that precede the marker.
+ if (precedingTextStartPosition != createLegacyEditingPosition(node, marker->startOffset())) {
+ RefPtr<Range> precedingTextRange = Range::create(*document(), precedingTextStartPosition, createLegacyEditingPosition(node, marker->startOffset()));
+ String precedingText = plainText(precedingTextRange.get());
+ if (unsigned length = precedingText.length()) {
+ const UChar* characters = precedingText.characters();
+ for (size_t i = 0; i < interpretationsCount; ++i)
+ interpretations.at(i).append(characters, length);
+ }
+ }
+
+ RefPtr<Range> rangeForMarker = Range::create(*document(), createLegacyEditingPosition(node, marker->startOffset()), createLegacyEditingPosition(node, marker->endOffset()));
+ String visibleTextForMarker = plainText(rangeForMarker.get());
+ size_t interpretationsCountForCurrentMarker = marker->alternatives().size() + 1;
+ unsigned visibleTextForMarkerLength = visibleTextForMarker.length();
+ const UChar* visibleTextForMarkerCharacters = visibleTextForMarker.characters();
+ for (size_t i = 0; i < interpretationsCount; ++i) {
+ // Determine text for the ith interpretation. It will either be the visible text, or one of its
+ // alternatives stored in the marker.
+
+ size_t indexOfInterpretationForCurrentMarker = (i / combinationsSoFar) % interpretationsCountForCurrentMarker;
+ if (!indexOfInterpretationForCurrentMarker)
+ interpretations.at(i).append(visibleTextForMarkerCharacters, visibleTextForMarkerLength);
+ else {
+ const String& alternative = marker->alternatives().at(i % marker->alternatives().size());
+ interpretations.at(i).append(alternative.characters(), alternative.length());
+ }
+ }
+
+ combinationsSoFar *= interpretationsCountForCurrentMarker;
+
+ precedingTextStartPosition = createLegacyEditingPosition(node, marker->endOffset());
+ }
+ }
+
+ // Finally, add any text after the last marker.
+ RefPtr<Range> afterLastMarkerRange = Range::create(*document(), precedingTextStartPosition, createLegacyEditingPosition(root, rootChildCount));
+ String textAfterLastMarker = plainText(afterLastMarkerRange.get());
+ const UChar* textAfterLastMarkerCharacters = textAfterLastMarker.characters();
+ if (unsigned length = textAfterLastMarker.length()) {
+ for (size_t i = 0; i < interpretationsCount; ++i)
+ interpretations.at(i).append(textAfterLastMarkerCharacters, length);
+ }
+
+ NSMutableArray *result = [NSMutableArray array];
+ for (size_t i = 0; i < interpretationsCount; ++i)
+ [result addObject:static_cast<NSString *>(String(interpretations.at(i)))];
+
+ return result;
+}
+
+static bool anyFrameHasTiledLayers(Frame* rootFrame)
+{
+ for (Frame* frame = rootFrame; frame; frame = frame->tree().traverseNext(rootFrame)) {
+ if (frame->containsTiledBackingLayers())
+ return true;
+ }
+ return false;
+}
+
+void Frame::viewportOffsetChanged(ViewportOffsetChangeType changeType)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (changeType == IncrementalScrollOffset) {
+ if (anyFrameHasTiledLayers(this)) {
+ if (RenderView* root = contentRenderer())
+ root->compositor().didChangeVisibleRect();
+ }
+ }
+
+ if (changeType == CompletedScrollOffset) {
+ if (RenderView* root = contentRenderer())
+ root->compositor().updateCompositingLayers(CompositingUpdateOnScroll);
+ }
+#endif
+}
+
+bool Frame::containsTiledBackingLayers() const
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (RenderView* root = contentRenderer())
+ return root->compositor().hasNonMainLayersWithTiledBacking();
+#endif
+ return false;
+}
+
+void Frame::overflowScrollPositionChangedForNode(const IntPoint& position, Node* node, bool isUserScroll)
+{
+ RenderObject* renderer = node->renderer();
+ if (!renderer || !renderer->hasLayer())
+ return;
+
+ RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
+
+ layer->setIsUserScroll(isUserScroll);
+ layer->scrollToOffsetWithoutAnimation(position);
+ layer->setIsUserScroll(false);
+ layer->didEndScroll(); // FIXME: Should we always call this?
+}
+
+void Frame::resetAllGeolocationPermission()
+{
+ if (document()->domWindow())
+ document()->domWindow()->resetAllGeolocationPermission();
+
+ for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling())
+ child->resetAllGeolocationPermission();
+}
+
+#if ENABLE(IOS_TEXT_AUTOSIZING)
+float Frame::textAutosizingWidth() const
+{
+ return m_textAutosizingWidth;
+}
+
+void Frame::setTextAutosizingWidth(float width)
+{
+ m_textAutosizingWidth = width;
+}
+#endif
+
+} // namespace WebCore
+#endif // PLATFORM(IOS)
diff --git a/Source/WebCore/page/mac/ChromeMac.mm b/Source/WebCore/page/mac/ChromeMac.mm
index afa9e68..1d67236 100644
--- a/Source/WebCore/page/mac/ChromeMac.mm
+++ b/Source/WebCore/page/mac/ChromeMac.mm
@@ -23,6 +23,11 @@
#import "BlockExceptions.h"
#import "ChromeClient.h"
+#if PLATFORM(IOS)
+#include "WAKResponder.h"
+#include "WAKView.h"
+#endif
+
namespace WebCore {
diff --git a/Source/WebCore/page/mac/PageMac.cpp b/Source/WebCore/page/mac/PageMac.cpp
index 212b117..d4c0d1d 100644
--- a/Source/WebCore/page/mac/PageMac.cpp
+++ b/Source/WebCore/page/mac/PageMac.cpp
@@ -44,12 +44,14 @@
m_scheduledRunLoopPairs = adoptPtr(new SchedulePairHashSet);
m_scheduledRunLoopPairs->add(pair);
+#if !PLATFORM(IOS)
for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
if (DocumentLoader* documentLoader = frame->loader().documentLoader())
documentLoader->schedule(pair.get());
if (DocumentLoader* documentLoader = frame->loader().provisionalDocumentLoader())
documentLoader->schedule(pair.get());
}
+#endif
// FIXME: make SharedTimerMac use these SchedulePairs.
}
@@ -63,12 +65,14 @@
RefPtr<SchedulePair> pair = prpPair;
m_scheduledRunLoopPairs->remove(pair);
+#if !PLATFORM(IOS)
for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
if (DocumentLoader* documentLoader = frame->loader().documentLoader())
documentLoader->unschedule(pair.get());
if (DocumentLoader* documentLoader = frame->loader().provisionalDocumentLoader())
documentLoader->unschedule(pair.get());
}
+#endif
}
} // namespace
diff --git a/Source/WebCore/page/mac/SettingsMac.mm b/Source/WebCore/page/mac/SettingsMac.mm
index 0a51c30..8cdeee9 100644
--- a/Source/WebCore/page/mac/SettingsMac.mm
+++ b/Source/WebCore/page/mac/SettingsMac.mm
@@ -30,7 +30,7 @@
bool Settings::shouldEnableScreenFontSubstitutionByDefault()
{
-#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
+#if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
return false;
#else
return true;
diff --git a/Source/WebCore/page/mac/WebCoreFrameView.h b/Source/WebCore/page/mac/WebCoreFrameView.h
index 93a0296..738d39b 100644
--- a/Source/WebCore/page/mac/WebCoreFrameView.h
+++ b/Source/WebCore/page/mac/WebCoreFrameView.h
@@ -25,18 +25,30 @@
#include "ScrollTypes.h"
+// WTF_PLATFORM_IOS
+#ifdef __cplusplus
namespace WebCore {
class Frame;
}
+#endif
@protocol WebCoreFrameScrollView
+// WTF_PLATFORM_IOS
+#ifdef __cplusplus
- (void)setScrollingModes:(WebCore::ScrollbarMode)hMode vertical:(WebCore::ScrollbarMode)vMode andLock:(BOOL)lock;
- (void)scrollingModes:(WebCore::ScrollbarMode*)hMode vertical:(WebCore::ScrollbarMode*)vMode;
+#else
+- (void)setScrollingModes:(int)hMode vertical:(int)vMode andLock:(BOOL)lock;
+- (void)scrollingModes:(int*)hMode vertical:(int*)vMode;
+#endif
- (void)setScrollBarsSuppressed:(BOOL)suppressed repaintOnUnsuppress:(BOOL)repaint;
- (void)setScrollOrigin:(NSPoint)origin updatePositionAtAll:(BOOL)updatePositionAtAll immediately:(BOOL)updatePositionImmediately;
- (NSPoint)scrollOrigin;
@end
@protocol WebCoreFrameView
+// WTF_PLATFORM_IOS
+#ifdef __cplusplus
- (WebCore::Frame*)_web_frame;
+#endif
@end
diff --git a/Source/WebKit/ios/ChangeLog b/Source/WebKit/ios/ChangeLog
index 75be90f..c1ecaa7 100644
--- a/Source/WebKit/ios/ChangeLog
+++ b/Source/WebKit/ios/ChangeLog
@@ -1,3 +1,12 @@
+2013-12-27 Daniel Bates <dabates@apple.com>
+
+ [iOS] Upstream WebCore/page changes
+ https://bugs.webkit.org/show_bug.cgi?id=126180
+
+ Reviewed by Darin Adler.
+
+ * WebCoreSupport/WebChromeClientIOS.mm: Substitute ENABLE(IOS_TOUCH_EVENTS) for ENABLE(TOUCH_EVENTS).
+
2013-12-23 Andy Estes <aestes@apple.com>
Roll out r161043. It broke 32-bit Mac builds.
diff --git a/Source/WebKit/ios/WebCoreSupport/WebChromeClientIOS.mm b/Source/WebKit/ios/WebCoreSupport/WebChromeClientIOS.mm
index bff59fa..7755331 100644
--- a/Source/WebKit/ios/WebCoreSupport/WebChromeClientIOS.mm
+++ b/Source/WebKit/ios/WebCoreSupport/WebChromeClientIOS.mm
@@ -124,7 +124,7 @@
[listener release];
}
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
void WebChromeClientIOS::didPreventDefaultForEvent()
{
[[webView() _UIKitDelegateForwarder] webViewDidPreventDefaultForEvent:webView()];
diff --git a/Source/WebKit/ios/WebView/WebPDFViewIOS.mm b/Source/WebKit/ios/WebView/WebPDFViewIOS.mm
index e86156a..30e2c7c 100644
--- a/Source/WebKit/ios/WebView/WebPDFViewIOS.mm
+++ b/Source/WebKit/ios/WebView/WebPDFViewIOS.mm
@@ -28,18 +28,11 @@
#import "WebPDFViewIOS.h"
#import "WebDataSourceInternal.h"
-#import <WebKit/WebFrameLoadDelegate.h>
-#import <WebKit/WebFrame.h>
-#import <WebKit/WebFramePrivate.h>
-#import <WebKit/WebFrameView.h>
-#import <WebKit/WebNSViewExtras.h>
-#import <WebKit/WebViewPrivate.h>
#import "WebFrameInternal.h"
#import "WebJSPDFDoc.h"
+#import "WebKitVersionChecks.h"
#import "WebPDFDocumentExtras.h"
#import "WebPDFViewPlaceholder.h"
-#import "WebKitVersionChecks.h"
-
#import <JavaScriptCore/JSContextRef.h>
#import <JavaScriptCore/JSStringRef.h>
#import <JavaScriptCore/JSStringRefCF.h>
@@ -48,7 +41,14 @@
#import <WebCore/FrameLoader.h>
#import <WebCore/FrameLoaderClient.h>
#import <WebCore/GraphicsContext.h>
+#import <WebCore/StringWithDirection.h>
#import <WebCore/WKGraphics.h>
+#import <WebKit/WebFrame.h>
+#import <WebKit/WebFrameLoadDelegate.h>
+#import <WebKit/WebFramePrivate.h>
+#import <WebKit/WebFrameView.h>
+#import <WebKit/WebNSViewExtras.h>
+#import <WebKit/WebViewPrivate.h>
#import <wtf/Assertions.h>
#import <wtf/RetainPtr.h>
#import <wtf/StdLibExtras.h>
diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog
index 5ad10f1..6b6fc7e 100644
--- a/Source/WebKit2/ChangeLog
+++ b/Source/WebKit2/ChangeLog
@@ -1,3 +1,14 @@
+2013-12-27 Daniel Bates <dabates@apple.com>
+
+ [iOS] Upstream WebCore/page changes
+ https://bugs.webkit.org/show_bug.cgi?id=126180
+
+ Reviewed by Darin Adler.
+
+ * WebProcess/WebCoreSupport/WebChromeClient.h:
+ * WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm: Added.
+ * WebProcess/WebPage/WebPage.cpp: Include header <WebCore/HitTestResult.h>.
+
2013-12-27 Gavin Barraclough <barraclough@apple.com>
Merge PageVisibilityState & ViewState::IsVisible in WebKit2
diff --git a/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h b/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h
index 7041e9a..8790231 100644
--- a/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h
+++ b/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h
@@ -155,10 +155,11 @@
virtual PassOwnPtr<WebCore::ColorChooser> createColorChooser(WebCore::ColorChooserClient*, const WebCore::Color&) OVERRIDE;
#endif
-#if PLATFORM(IOS)
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
virtual void didPreventDefaultForEvent() OVERRIDE;
#endif
+
+#if PLATFORM(IOS)
virtual void didReceiveMobileDocType() OVERRIDE;
virtual void setNeedsScrollNotifications(WebCore::Frame*, bool) OVERRIDE;
virtual void observedContentChange(WebCore::Frame*) OVERRIDE;
diff --git a/Source/WebKit2/WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm b/Source/WebKit2/WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm
index 9f02b2f..4fdca17 100644
--- a/Source/WebKit2/WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm
+++ b/Source/WebKit2/WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm
@@ -34,7 +34,7 @@
namespace WebKit {
-#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(IOS_TOUCH_EVENTS)
void WebChromeClient::didPreventDefaultForEvent()
{
notImplemented();
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
index 0e702dd..535a9c4 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
@@ -108,6 +108,7 @@
#include <WebCore/HTMLPlugInImageElement.h>
#include <WebCore/HistoryController.h>
#include <WebCore/HistoryItem.h>
+#include <WebCore/HitTestResult.h>
#include <WebCore/JSDOMWindow.h>
#include <WebCore/KeyboardEvent.h>
#include <WebCore/MIMETypeRegistry.h>