WebKit Bugzilla
Attachment 361056 Details for
Bug 193919
: [GTK] Implement back/forward touchpad gesture
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-193919-20190204210016.patch (text/plain), 171.18 KB, created by
Alice Mikhaylenko
on 2019-02-04 08:00:19 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Alice Mikhaylenko
Created:
2019-02-04 08:00:19 PST
Size:
171.18 KB
patch
obsolete
>Subversion Revision: 240918 >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 87c79913062d14e0575c6de244a09543722f9643..339e6119f050b1bc8e63498ac032828908d9f5e3 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,232 @@ >+2019-02-04 Alexander Mikhaylenko <exalm7659@gmail.com> >+ >+ [GTK] Implement back/forward touchpad gesture >+ https://bugs.webkit.org/show_bug.cgi?id=193919 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Move ViewSnapshotStore and ViewGestureController from Cocoa/Mac directory >+ to UIProcess/, split up Mac- and iOS-specific parts of ViewSnapshotStore.cpp >+ into mac/ViewSnapshotMac.mm, then implement 2-finger touchpad swipe >+ back-forward gesture for GTK based on that. To avoid name conflict, rename >+ existing ViewGestureController class inside UIProcess/API/gtk/WebKitWebViewBase.cpp >+ into TouchGestureController. >+ >+ Since GTK gestures can only work with 3 or 4 fingers, treat horizontal >+ scrolling events as a swipe as long as there's nowhere to scroll in that >+ direction and web page doesn't intercept the scrolling. >+ >+ This is only allowed for touchpads, even though it can theoretically work >+ with touch mice and trackpoints. >+ >+ The gesture requires every item in back-forward list to have a snapshot. >+ There's already an existing infrastructure for that, so the patch changes >+ a bunch of #if PLATFORM(COCOA) statements to also check for GTK platform. >+ The snapshots have to be taken in sync, so the implementation draws webview >+ widget into a Cairo image surface. >+ >+ The gesture is disabled by default, and can be enabled by setting the newly >+ added 'allow-back-forward-navigation-gestures' property in WebKitSettings to >+ true. >+ >+ Gesture drawing is implemented via Cairo. When the gesture is active, the >+ actual page is drawn into a Cairo group, which is then drawn together with >+ a given snapshot, as well as dimming and a drop shadow over the "lower" layer. >+ >+ Also add a memory pressure handler that clears snapshot store when low on memory. >+ >+ * DerivedSources-input.xcfilelist: >+ * PlatformGTK.cmake: >+ * PlatformMac.cmake: >+ * Shared/SessionState.h: Add snapshot to back-forward items for GTK. >+ * Shared/WebBackForwardListItem.h: Add snapshot to back-forward items for GTK. >+ * SourcesCocoa.txt: >+ * SourcesGTK.txt: >+ * UIProcess/API/glib/WebKitSettings.cpp: >+ Added 'allow-back-forward-navigation-gestures' property for enabling the gesture. >+ (webKitSettingsSetProperty): >+ (webKitSettingsGetProperty): >+ (webkit_settings_class_init): >+ (webkit_settings_get_allow_back_forward_navigation_gestures): Added, GTK only. >+ (webkit_settings_set_allow_back_forward_navigation_gestures): Added, GTK only. >+ * UIProcess/API/glib/WebKitWebView.cpp: >+ (allowBackForwardNavigationGesturesChanged): Added, GTK only. >+ (webkitWebViewUpdateSettings): >+ (webkitWebViewDisconnectSettingsSignalHandlers): >+ * UIProcess/API/gtk/PageClientImpl.cpp: >+ (WebKit::PageClientImpl::setViewNeedsDisplay): Redraw the whole screen instead of a region during the gesture. >+ (WebKit::PageClientImpl::takeViewSnapshot): Added. >+ (WebKit::PageClientImpl::wheelEventWasNotHandledByWebCore): Pass unhandled events to the gesture controller. >+ (WebKit::PageClientImpl::didStartProvisionalLoadForMainFrame): Added, send a notification to the gesture controller. >+ (WebKit::PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame): Send a notification to the gesture controller. >+ (WebKit::PageClientImpl::didFinishLoadForMainFrame): Send a notification to the gesture controller. >+ (WebKit::PageClientImpl::didFailLoadForMainFrame): Added, send a notification to the gesture controller. >+ (WebKit::PageClientImpl::didSameDocumentNavigationForMainFrame): Send a notification to the gesture controller. >+ (WebKit::PageClientImpl::didRestoreScrollPosition): Added, send a notification to the gesture controller. >+ * UIProcess/API/gtk/PageClientImpl.h: >+ * UIProcess/API/gtk/WebKitSettings.h: >+ Add webkit_settings_get_allow_back_forward_navigation_gestures() and webkit_settings_get_allow_back_forward_navigation_gestures() >+ to public API. >+ * UIProcess/API/gtk/WebKitWebViewBase.cpp: >+ (webkitWebViewBaseDraw): Pass drawing to ViewGestureController during the gesture. >+ (webkitWebViewBaseScrollEvent): Pass scroll events to ViewGestureController during the gesture. >+ (webkitWebViewBaseGestureController): Renamed ViewGestureController to TouchGestureController. >+ * UIProcess/API/gtk/WebKitWebViewBasePrivate.h: >+ (webkitWebViewBaseViewGestureController): Added. >+ (webkitWebViewBaseTakeViewSnapshot): Added. >+ (webkitWebViewBaseDidStartProvisionalLoadForMainFrame): Added. >+ (webkitWebViewBaseDidFirstVisuallyNonEmptyLayoutForMainFrame): Added. >+ (webkitWebViewBaseDidFinishLoadForMainFrame): Added. >+ (webkitWebViewBaseDidFailLoadForMainFrame): Added. >+ (webkitWebViewBaseDidSameDocumentNavigationForMainFrame): Added. >+ (webkitWebViewBaseDidRestoreScrollPosition): Added. >+ * UIProcess/API/gtk/WebKitWebViewBasePrivate.h: >+ * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt: Mentioned the added functions in docs. >+ * UIProcess/PageClient.h: Add takeViewSnapshot() for GTK. >+ * UIProcess/ViewGestureController.cpp: Renamed from Source/WebKit/UIProcess/Cocoa/ViewGestureController.cpp. >+ (WebKit::ViewGestureController::ViewGestureController): >+ (WebKit::ViewGestureController::~ViewGestureController): >+ (WebKit::ViewGestureController::disconnectFromProcess): >+ (WebKit::ViewGestureController::connectToProcess): >+ (WebKit::ViewGestureController::controllerForGesture): >+ (WebKit::ViewGestureController::takeNextGestureID): >+ (WebKit::ViewGestureController::willBeginGesture): >+ (WebKit::ViewGestureController::didEndGesture): >+ (WebKit::ViewGestureController::setAlternateBackForwardListSourcePage): >+ (WebKit::ViewGestureController::canSwipeInDirection const): >+ (WebKit::ViewGestureController::didStartProvisionalOrSameDocumentLoadForMainFrame): >+ (WebKit::ViewGestureController::didStartProvisionalLoadForMainFrame): >+ (WebKit::ViewGestureController::didFirstVisuallyNonEmptyLayoutForMainFrame): >+ (WebKit::ViewGestureController::didRepaintAfterNavigation): >+ (WebKit::ViewGestureController::didHitRenderTreeSizeThreshold): >+ (WebKit::ViewGestureController::didRestoreScrollPosition): >+ (WebKit::ViewGestureController::didReachMainFrameLoadTerminalState): >+ (WebKit::ViewGestureController::didSameDocumentNavigationForMainFrame): >+ (WebKit::ViewGestureController::checkForActiveLoads): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::SnapshotRemovalTracker): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::eventsDescription): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::log const): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::resume): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::start): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::reset): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::stopWaitingForEvent): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::eventOccurred): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::cancelOutstandingEvent): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::hasOutstandingEvent): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::fireRemovalCallbackIfPossible): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::fireRemovalCallbackImmediately): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::watchdogTimerFired): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::startWatchdog): >+ * UIProcess/ViewGestureController.h: Renamed from Source/WebKit/UIProcess/Cocoa/ViewGestureController.h. >+ (WebKit::ViewGestureController::wheelEventWasNotHandledByWebCore): >+ (WebKit::ViewGestureController::shouldIgnorePinnedState): >+ (WebKit::ViewGestureController::setShouldIgnorePinnedState): >+ (WebKit::ViewGestureController::hasActiveMagnificationGesture const): >+ (WebKit::ViewGestureController::setCustomSwipeViews): >+ (WebKit::ViewGestureController::setCustomSwipeViewsTopContentInset): >+ (WebKit::ViewGestureController::setDidMoveSwipeSnapshotCallback): >+ (WebKit::ViewGestureController::backgroundColorForCurrentSnapshot const): >+ (WebKit::ViewGestureController::didFinishLoadForMainFrame): >+ (WebKit::ViewGestureController::didFailLoadForMainFrame): >+ (WebKit::ViewGestureController::setSwipeGestureEnabled): >+ (WebKit::ViewGestureController::isSwipeGestureEnabled): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::pause): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::isPaused const): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::hasRemovalCallback const): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::renderTreeSizeThreshold const): >+ (WebKit::ViewGestureController::SnapshotRemovalTracker::setRenderTreeSizeThreshold): >+ (WebKit::ViewGestureController::PendingSwipeTracker::shouldIgnorePinnedState): >+ (WebKit::ViewGestureController::PendingSwipeTracker::setShouldIgnorePinnedState): >+ (WebKit::ViewGestureController::SwipeProgressTracker::getDirection): >+ * UIProcess/ViewGestureController.messages.in: Renamed from Source/WebKit/UIProcess/Cocoa/ViewGestureController.messages.in. >+ * UIProcess/ViewSnapshotStore.cpp: Copied from Source/WebKit/UIProcess/mac/ViewSnapshotStore.mm. >+ (WebKit::ViewSnapshotStore::ViewSnapshotStore): >+ (WebKit::ViewSnapshotStore::~ViewSnapshotStore): >+ (WebKit::ViewSnapshotStore::singleton): >+ (WebKit::ViewSnapshotStore::didAddImageToSnapshot): >+ (WebKit::ViewSnapshotStore::willRemoveImageFromSnapshot): >+ (WebKit::ViewSnapshotStore::pruneSnapshots): >+ (WebKit::ViewSnapshotStore::recordSnapshot): >+ (WebKit::ViewSnapshotStore::discardSnapshotImages): >+ (WebKit::ViewSnapshot::~ViewSnapshot): >+ * UIProcess/ViewSnapshotStore.h: Renamed from Source/WebKit/UIProcess/mac/ViewSnapshotStore.h. >+ (WebKit::ViewSnapshot::setRenderTreeSize): >+ (WebKit::ViewSnapshot::renderTreeSize const): >+ (WebKit::ViewSnapshot::setBackgroundColor): >+ (WebKit::ViewSnapshot::backgroundColor const): >+ (WebKit::ViewSnapshot::setViewScrollPosition): >+ (WebKit::ViewSnapshot::viewScrollPosition const): >+ (WebKit::ViewSnapshot::setDeviceScaleFactor): >+ (WebKit::ViewSnapshot::deviceScaleFactor const): >+ (WebKit::ViewSnapshot::surface const): >+ (WebKit::ViewSnapshot::imageSizeInBytes const): >+ (WebKit::ViewSnapshot::size const): >+ (WebKit::ViewSnapshotStore::setDisableSnapshotVolatilityForTesting): >+ (WebKit::ViewSnapshotStore::disableSnapshotVolatilityForTesting const): >+ * UIProcess/WebBackForwardList.cpp: >+ (WebKit::WebBackForwardList::didRemoveItem): Unset snapshot for GTK. >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::recordNavigationSnapshot): Take snapshots for GTK. >+ * UIProcess/WebPageProxy.h: >+ * UIProcess/gtk/ViewGestureControllerGtk.cpp: Added. This is a port of >+ UIProcess/mac/ViewGestureControllerMac.mm. SwipeProgressTracker class is a >+ re-implementation of trackSwipeEventWithOptions. >+ (WebKit::ViewGestureController::PendingSwipeTracker::PendingSwipeTracker): >+ (WebKit::ViewGestureController::platformTeardown): >+ (WebKit::scrollEventCanInfluenceSwipe): >+ (WebKit::deltaShouldCancelSwipe): >+ (WebKit::ViewGestureController::PendingSwipeTracker::scrollEventCanBecomeSwipe): >+ (WebKit::ViewGestureController::handleScrollWheelEvent): >+ (WebKit::ViewGestureController::PendingSwipeTracker::handleEvent): >+ (WebKit::ViewGestureController::PendingSwipeTracker::eventWasNotHandledByWebCore): >+ (WebKit::ViewGestureController::PendingSwipeTracker::tryToStartSwipe): >+ (WebKit::ViewGestureController::PendingSwipeTracker::reset): >+ (WebKit::ViewGestureController::trackSwipeGesture): >+ (WebKit::ViewGestureController::isPhysicallySwipingLeft const): >+ (WebKit::ViewGestureController::SwipeProgressTracker::SwipeProgressTracker): >+ (WebKit::ViewGestureController::SwipeProgressTracker::startTracking): >+ (WebKit::ViewGestureController::SwipeProgressTracker::reset): >+ (WebKit::ViewGestureController::SwipeProgressTracker::handleEvent): >+ (WebKit::ViewGestureController::SwipeProgressTracker::getProgress): >+ (WebKit::ViewGestureController::SwipeProgressTracker::startAnimation): >+ (WebKit::easeOutCubic): >+ (WebKit::ViewGestureController::SwipeProgressTracker::onAnimationTick): >+ (WebKit::ViewGestureController::SwipeProgressTracker::endAnimation): >+ (WebKit::ViewGestureController::beginSwipeGesture): >+ (WebKit::ViewGestureController::handleSwipeGesture): >+ (WebKit::ViewGestureController::willEndSwipeGesture): >+ (WebKit::ViewGestureController::endSwipeGesture): >+ (WebKit::ViewGestureController::forceRepaintIfNeeded): >+ (WebKit::ViewGestureController::shouldUseSnapshotForSize): >+ (WebKit::ViewGestureController::draw): >+ (WebKit::ViewGestureController::removeSwipeSnapshot): >+ (WebKit::ViewGestureController::beginSimulatedSwipeInDirectionForTesting): >+ (WebKit::ViewGestureController::completeSimulatedSwipeInDirectionForTesting): >+ * UIProcess/gtk/ViewSnapshotStoreGtk.cpp: Added. >+ (WebKit::ViewSnapshot::create): >+ (WebKit::ViewSnapshot::ViewSnapshot): >+ (WebKit::ViewSnapshot::hasImage const): >+ (WebKit::ViewSnapshot::clearImage): >+ (WebKit::ViewSnapshot::imageSizeInBytes const): >+ (WebKit::ViewSnapshot::size const): >+ * UIProcess/gtk/WebMemoryPressureHandlerGtk.cpp: Added. >+ (WebKit::installMemoryPressureHandler): >+ * UIProcess/gtk/WebMemoryPressureHandlerGtk.h: Added. >+ * UIProcess/gtk/WebProcessPoolGtk.cpp: >+ (WebKit::WebProcessPool::platformInitialize): Install memory pressure handler. >+ * UIProcess/mac/ViewSnapshotStoreMac.mm: Renamed from Source/WebKit/UIProcess/mac/ViewSnapshotStore.mm. >+ (WebKit::ViewSnapshotStore::snapshottingContext): >+ (WebKit::ViewSnapshot::create): >+ (WebKit::ViewSnapshot::ViewSnapshot): >+ (WebKit::ViewSnapshot::setSurface): >+ (WebKit::ViewSnapshot::hasImage const): >+ (WebKit::ViewSnapshot::clearImage): >+ (WebKit::ViewSnapshot::setVolatile): >+ (WebKit::ViewSnapshot::asLayerContents): >+ (WebKit::ViewSnapshot::asImageForTesting): >+ * UnifiedSources-input.xcfilelist: >+ * WebKit.xcodeproj/project.pbxproj: >+ > 2019-02-04 Antti Koivisto <antti@apple.com> > > Rename GraphicsLayer and PlatformCALayer type enum values to match "scroll container layer" convention >diff --git a/Source/WebKit/DerivedSources-input.xcfilelist b/Source/WebKit/DerivedSources-input.xcfilelist >index 586977c902d00c89bd90c2e161f39c290a0d249e..517f3ed5cfa1d5e89bcc4dd02301a86b3db495fe 100644 >--- a/Source/WebKit/DerivedSources-input.xcfilelist >+++ b/Source/WebKit/DerivedSources-input.xcfilelist >@@ -63,7 +63,6 @@ $(PROJECT_DIR)/UIProcess/Automation/WebAutomationSession.messages.in > $(PROJECT_DIR)/UIProcess/Cocoa/PlaybackSessionManagerProxy.messages.in > $(PROJECT_DIR)/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in > $(PROJECT_DIR)/UIProcess/Cocoa/VideoFullscreenManagerProxy.messages.in >-$(PROJECT_DIR)/UIProcess/Cocoa/ViewGestureController.messages.in > $(PROJECT_DIR)/UIProcess/Downloads/DownloadProxy.messages.in > $(PROJECT_DIR)/UIProcess/DrawingAreaProxy.messages.in > $(PROJECT_DIR)/UIProcess/Network/CustomProtocols/LegacyCustomProtocolManagerProxy.messages.in >@@ -72,6 +71,7 @@ $(PROJECT_DIR)/UIProcess/Plugins/PluginProcessProxy.messages.in > $(PROJECT_DIR)/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in > $(PROJECT_DIR)/UIProcess/RemoteWebInspectorProxy.messages.in > $(PROJECT_DIR)/UIProcess/UserContent/WebUserContentControllerProxy.messages.in >+$(PROJECT_DIR)/UIProcess/ViewGestureController.messages.in > $(PROJECT_DIR)/UIProcess/VisitedLinkStore.messages.in > $(PROJECT_DIR)/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in > $(PROJECT_DIR)/UIProcess/WebCookieManagerProxy.messages.in >diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake >index 8a8b41a1b46a9bb24b75b0de85b8a668fcb71e49..19e877e95b176bacff631ee87ead672970c4fd22 100644 >--- a/Source/WebKit/PlatformGTK.cmake >+++ b/Source/WebKit/PlatformGTK.cmake >@@ -35,6 +35,8 @@ list(APPEND WebKit_UNIFIED_SOURCE_LIST_FILES > list(APPEND WebKit_MESSAGES_IN_FILES > NetworkProcess/CustomProtocols/LegacyCustomProtocolManager.messages.in > >+ UIProcess/ViewGestureController.messages.in >+ > UIProcess/Network/CustomProtocols/LegacyCustomProtocolManagerProxy.messages.in > ) > >diff --git a/Source/WebKit/PlatformMac.cmake b/Source/WebKit/PlatformMac.cmake >index a6cfe1de86edec09da5ed95c9a7397a81d85ae7b..19362b2984297a379929236b12e0274a178fe511 100644 >--- a/Source/WebKit/PlatformMac.cmake >+++ b/Source/WebKit/PlatformMac.cmake >@@ -161,6 +161,8 @@ list(APPEND WebKit_SOURCES > > UIProcess/HighPerformanceGraphicsUsageSampler.cpp > UIProcess/PerActivityStateCPUUsageSampler.cpp >+ UIProcess/ViewGestureController.cpp >+ UIProcess/ViewSnapshotStore.cpp > > UIProcess/Automation/WebAutomationSession.cpp > >@@ -253,7 +255,6 @@ list(APPEND WebKit_SOURCES > UIProcess/Cocoa/SessionStateCoding.mm > UIProcess/Cocoa/UIDelegate.mm > UIProcess/Cocoa/VersionChecks.mm >- UIProcess/Cocoa/ViewGestureController.cpp > UIProcess/Cocoa/WKFullKeyboardAccessWatcher.mm > UIProcess/Cocoa/WKReloadFrameErrorRecoveryAttempter.mm > UIProcess/Cocoa/WKWebViewContentProviderRegistry.mm >@@ -291,7 +292,7 @@ list(APPEND WebKit_SOURCES > UIProcess/mac/TextCheckerMac.mm > UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm > UIProcess/mac/ViewGestureControllerMac.mm >- UIProcess/mac/ViewSnapshotStore.mm >+ UIProcess/mac/ViewSnapshotStoreMac.mm > UIProcess/mac/WKFullScreenWindowController.mm > UIProcess/mac/WKImmediateActionController.mm > UIProcess/mac/WKInspectorViewController.mm >@@ -466,8 +467,9 @@ list(APPEND WebKit_MESSAGES_IN_FILES > > Shared/API/Cocoa/RemoteObjectRegistry.messages.in > >+ UIProcess/ViewGestureController.messages.in >+ > UIProcess/Cocoa/VideoFullscreenManagerProxy.messages.in >- UIProcess/Cocoa/ViewGestureController.messages.in > > UIProcess/Network/CustomProtocols/LegacyCustomProtocolManagerProxy.messages.in > >diff --git a/Source/WebKit/Shared/SessionState.h b/Source/WebKit/Shared/SessionState.h >index d26791da99c36d284ff2e7d50ce082678d0f08b0..fb0e27aa9a56be0f66f1195c38d6d7627d7d4dc9 100644 >--- a/Source/WebKit/Shared/SessionState.h >+++ b/Source/WebKit/Shared/SessionState.h >@@ -25,7 +25,7 @@ > > #pragma once > >-#if PLATFORM(COCOA) >+#if PLATFORM(COCOA) || PLATFORM(GTK) > #include "ViewSnapshotStore.h" > #endif > >@@ -133,7 +133,7 @@ struct BackForwardListItemState { > WebCore::BackForwardItemIdentifier identifier; > > PageState pageState; >-#if PLATFORM(COCOA) >+#if PLATFORM(COCOA) || PLATFORM(GTK) > RefPtr<ViewSnapshot> snapshot; > #endif > }; >diff --git a/Source/WebKit/Shared/WebBackForwardListItem.h b/Source/WebKit/Shared/WebBackForwardListItem.h >index aaf6514e7a67c36187b11f99d7ad4e7d03efd4f2..bff0c882041f6a9aa8332166fd7b377ec3f1b583 100644 >--- a/Source/WebKit/Shared/WebBackForwardListItem.h >+++ b/Source/WebKit/Shared/WebBackForwardListItem.h >@@ -66,7 +66,7 @@ public: > bool itemIsInSameDocument(const WebBackForwardListItem&) const; > bool itemIsClone(const WebBackForwardListItem&); > >-#if PLATFORM(COCOA) >+#if PLATFORM(COCOA) || PLATFORM(GTK) > ViewSnapshot* snapshot() const { return m_itemState.snapshot.get(); } > void setSnapshot(RefPtr<ViewSnapshot>&& snapshot) { m_itemState.snapshot = WTFMove(snapshot); } > #endif >diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt >index 7498badfda125af4d9ee82e1643d00c7147e1348..6e03b71ae1e2bf43c1d15c90f3b208fe6a179671 100644 >--- a/Source/WebKit/SourcesCocoa.txt >+++ b/Source/WebKit/SourcesCocoa.txt >@@ -203,6 +203,8 @@ UIProcess/_WKWebViewPrintFormatter.mm > UIProcess/ApplicationStateTracker.mm > UIProcess/HighPerformanceGraphicsUsageSampler.cpp > UIProcess/PerActivityStateCPUUsageSampler.cpp >+UIProcess/ViewGestureController.cpp >+UIProcess/ViewSnapshotStore.cpp @no-unify > UIProcess/WebDataListSuggestionsDropdown.cpp > UIProcess/WebMediaSessionFocusManager.cpp > UIProcess/WebMediaSessionFocusManagerClient.cpp >@@ -336,7 +338,6 @@ UIProcess/Cocoa/UIDelegate.mm > UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp > UIProcess/Cocoa/VersionChecks.mm > UIProcess/Cocoa/VideoFullscreenManagerProxy.mm >-UIProcess/Cocoa/ViewGestureController.cpp > UIProcess/Cocoa/WebMemoryPressureHandlerCocoa.mm > UIProcess/Cocoa/WebPageProxyCocoa.mm > UIProcess/Cocoa/WebPasteboardProxyCocoa.mm >@@ -424,7 +425,7 @@ UIProcess/mac/ServicesController.mm > UIProcess/mac/TextCheckerMac.mm > UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm > UIProcess/mac/ViewGestureControllerMac.mm >-UIProcess/mac/ViewSnapshotStore.mm >+UIProcess/mac/ViewSnapshotStoreMac.mm > UIProcess/mac/WebColorPickerMac.mm > UIProcess/mac/WebContextMenuProxyMac.mm > UIProcess/mac/WebCookieManagerProxyMac.mm >diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt >index b832b7acf134f172950b243e253e1d512cdc007d..3c88160596a3fb3c4eed24917f067e941419b00a 100644 >--- a/Source/WebKit/SourcesGTK.txt >+++ b/Source/WebKit/SourcesGTK.txt >@@ -112,6 +112,8 @@ UIProcess/BackingStore.cpp > UIProcess/DefaultUndoController.cpp > UIProcess/DrawingAreaProxyImpl.cpp > UIProcess/LegacySessionStateCodingNone.cpp >+UIProcess/ViewGestureController.cpp >+UIProcess/ViewSnapshotStore.cpp @no-unify > UIProcess/WebGrammarDetail.cpp > UIProcess/WebTextChecker.cpp > UIProcess/WebTextCheckerClient.cpp >@@ -239,11 +241,14 @@ UIProcess/gtk/InputMethodFilter.cpp @no-unify > UIProcess/gtk/KeyBindingTranslator.cpp > UIProcess/gtk/RemoteWebInspectorProxyGtk.cpp @no-unify > UIProcess/gtk/TextCheckerGtk.cpp @no-unify >+UIProcess/gtk/ViewGestureControllerGtk.cpp @no-unify >+UIProcess/gtk/ViewSnapshotStoreGtk.cpp @no-unify > UIProcess/gtk/WaylandCompositor.cpp @no-unify > UIProcess/gtk/WebColorPickerGtk.cpp @no-unify > UIProcess/gtk/WebContextMenuProxyGtk.cpp > UIProcess/gtk/WebInspectorProxyGtk.cpp > UIProcess/gtk/WebKitInspectorWindow.cpp >+UIProcess/gtk/WebMemoryPressureHandlerGtk.cpp @no-unify > UIProcess/gtk/WebPageProxyGtk.cpp @no-unify > UIProcess/gtk/WebPasteboardProxyGtk.cpp > UIProcess/gtk/WebPopupMenuProxyGtk.cpp >diff --git a/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp b/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp >index 4ec7f98139a071fcbd1682a2066d90a7a9f4a712..32efd616b4d177d30e35abcdd8af2e18ecc093cf 100644 >--- a/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp >+++ b/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp >@@ -80,6 +80,9 @@ struct _WebKitSettingsPrivate { > bool allowModalDialogs { false }; > bool zoomTextOnly { false }; > double screenDpi { 96 }; >+#if PLATFORM(GTK) >+ bool allowBackForwardNavigationGestures { false }; >+#endif > }; > > /** >@@ -161,6 +164,7 @@ enum { > PROP_ALLOW_UNIVERSAL_ACCESS_FROM_FILE_URLS, > #if PLATFORM(GTK) > PROP_HARDWARE_ACCELERATION_POLICY, >+ PROP_ALLOW_BACK_FORWARD_NAVIGATION_GESTURES, > #endif > }; > >@@ -381,6 +385,9 @@ static void webKitSettingsSetProperty(GObject* object, guint propId, const GValu > case PROP_HARDWARE_ACCELERATION_POLICY: > webkit_settings_set_hardware_acceleration_policy(settings, static_cast<WebKitHardwareAccelerationPolicy>(g_value_get_enum(value))); > break; >+ case PROP_ALLOW_BACK_FORWARD_NAVIGATION_GESTURES: >+ webkit_settings_set_allow_back_forward_navigation_gestures(settings, g_value_get_boolean(value)); >+ break; > #endif > default: > G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); >@@ -560,6 +567,9 @@ static void webKitSettingsGetProperty(GObject* object, guint propId, GValue* val > case PROP_HARDWARE_ACCELERATION_POLICY: > g_value_set_enum(value, webkit_settings_get_hardware_acceleration_policy(settings)); > break; >+ case PROP_ALLOW_BACK_FORWARD_NAVIGATION_GESTURES: >+ g_value_set_boolean(value, webkit_settings_get_allow_back_forward_navigation_gestures(settings)); >+ break; > #endif > default: > G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); >@@ -1443,6 +1453,21 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass) > WEBKIT_TYPE_HARDWARE_ACCELERATION_POLICY, > WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND, > readWriteConstructParamFlags)); >+ >+ /** >+ * WebKitSettings:allow-back-forward-navigation-gestures: >+ * >+ * Enable or disable horizontal swipe gesture for back-forward navigation. >+ * >+ * Since: 2.24 >+ */ >+ g_object_class_install_property(gObjectClass, >+ PROP_ALLOW_BACK_FORWARD_NAVIGATION_GESTURES, >+ g_param_spec_boolean("allow-back-forward-navigation-gestures", >+ _("Allow back-forward navigation gestures"), >+ _("Whether horizontal swipe gesture will trigger back-forward navigation"), >+ FALSE, >+ readWriteConstructParamFlags)); > #endif // PLATFOTM(GTK) > } > >@@ -3512,6 +3537,44 @@ void webkit_settings_set_hardware_acceleration_policy(WebKitSettings* settings, > g_object_notify(G_OBJECT(settings), "hardware-acceleration-policy"); > } > >+/** >+ * webkit_settings_get_allow_back_forward_navigation_gestures: >+ * @settings: a #WebKitSettings >+ * >+ * Get the #WebKitSettings:allow-back-forward-navigation-gestures property. >+ * >+ * Returns: %TRUE if horizontal swipe gesture will trigger back-forward navigaiton or %FALSE otherwise. >+ * >+ * Since: 2.24 >+ */ >+gboolean webkit_settings_get_allow_back_forward_navigation_gestures(WebKitSettings* settings) >+{ >+ g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE); >+ >+ return settings->priv->allowBackForwardNavigationGestures; >+} >+ >+/** >+ * webkit_settings_set_allow_back_forward_navigation_gestures: >+ * @settings: a #WebKitSettings >+ * @allowed: value to be set >+ * >+ * Set the #WebKitSettings:allow-back-forward-navigation-gestures property. >+ * >+ * Since: 2.24 >+ */ >+void webkit_settings_set_allow_back_forward_navigation_gestures(WebKitSettings* settings, gboolean allowed) >+{ >+ g_return_if_fail(WEBKIT_IS_SETTINGS(settings)); >+ >+ WebKitSettingsPrivate* priv = settings->priv; >+ if (priv->allowBackForwardNavigationGestures == allowed) >+ return; >+ >+ priv->allowBackForwardNavigationGestures = allowed; >+ g_object_notify(G_OBJECT(settings), "allow-back-forward-navigation-gestures"); >+} >+ > /** > * webkit_settings_font_size_to_points: > * @pixels: the font size in pixels to convert to points >diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp >index 67201d89eaa1f3f20df8b91f1da15d9c258b638f..9a1289f506da65eb6a42ad57a43f0f53bc262fdc 100644 >--- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp >+++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp >@@ -501,6 +501,16 @@ static void userAgentChanged(WebKitSettings* settings, GParamSpec*, WebKitWebVie > } > > #if PLATFORM(GTK) >+static void allowBackForwardNavigationGesturesChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView) >+{ >+ gboolean allowsBackForwardNavigationGestures = webkit_settings_get_allow_back_forward_navigation_gestures(settings); >+ >+ ViewGestureController& controller = webkitWebViewBaseViewGestureController(WEBKIT_WEB_VIEW_BASE(webView)); >+ controller.setSwipeGestureEnabled(allowsBackForwardNavigationGestures); >+ >+ getPage(webView).setShouldRecordNavigationSnapshots(allowsBackForwardNavigationGestures); >+} >+ > static void webkitWebViewUpdateFavicon(WebKitWebView* webView, cairo_surface_t* favicon) > { > WebKitWebViewPrivate* priv = webView->priv; >@@ -581,10 +591,16 @@ static void webkitWebViewUpdateSettings(WebKitWebView* webView) > page.setPreferences(*webkitSettingsGetPreferences(settings)); > page.setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings)); > page.setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings))); >+#if PLATFORM(GTK) >+ allowBackForwardNavigationGesturesChanged(settings, nullptr, webView); >+#endif > > g_signal_connect(settings, "notify::allow-modal-dialogs", G_CALLBACK(allowModalDialogsChanged), webView); > g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView); > g_signal_connect(settings, "notify::user-agent", G_CALLBACK(userAgentChanged), webView); >+#if PLATFORM(GTK) >+ g_signal_connect(settings, "notify::allow-back-forward-navigation-gestures", G_CALLBACK(allowBackForwardNavigationGesturesChanged), webView); >+#endif > } > > static void webkitWebViewDisconnectSettingsSignalHandlers(WebKitWebView* webView) >@@ -596,6 +612,9 @@ static void webkitWebViewDisconnectSettingsSignalHandlers(WebKitWebView* webView > g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(allowModalDialogsChanged), webView); > g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(zoomTextOnlyChanged), webView); > g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(userAgentChanged), webView); >+#if PLATFORM(GTK) >+ g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(allowBackForwardNavigationGesturesChanged), webView); >+#endif > } > > #if PLATFORM(GTK) >diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp >index 317859d75335e7ddca0307204dcce5e4de1e012e..4ad79cbaff3a47473b9d7b1bd0216db5f2adcd6b 100644 >--- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp >+++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp >@@ -32,6 +32,7 @@ > #include "NativeWebKeyboardEvent.h" > #include "NativeWebMouseEvent.h" > #include "NativeWebWheelEvent.h" >+#include "ViewSnapshotStore.h" > #include "WebColorPickerGtk.h" > #include "WebContextMenuProxyGtk.h" > #include "WebEventFactory.h" >@@ -67,6 +68,16 @@ std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy(WebProc > > void PageClientImpl::setViewNeedsDisplay(const WebCore::Region& region) > { >+ WebPageProxy* pageProxy = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); >+ ASSERT(pageProxy); >+ >+ // During the gesture, the page may be displayed with an offset. >+ // To avoid visual glitches, redraw the whole page. >+ if (pageProxy->isShowingNavigationGestureSnapshot()) { >+ gtk_widget_queue_draw(m_viewWidget); >+ return; >+ } >+ > gtk_widget_queue_draw_region(m_viewWidget, toCairoRegion(region).get()); > } > >@@ -255,6 +266,11 @@ void PageClientImpl::selectionDidChange() > webkitWebViewSelectionDidChange(WEBKIT_WEB_VIEW(m_viewWidget)); > } > >+RefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot() >+{ >+ return webkitWebViewBaseTakeViewSnapshot(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); >+} >+ > void PageClientImpl::didChangeContentSize(const IntSize& size) > { > webkitWebViewBaseSetContentsSize(WEBKIT_WEB_VIEW_BASE(m_viewWidget), size); >@@ -404,6 +420,12 @@ void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& event, bool w > > void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event) > { >+ ViewGestureController& controller = webkitWebViewBaseViewGestureController(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); >+ if (controller.isSwipeGestureEnabled()) { >+ controller.wheelEventWasNotHandledByWebCore(&event.nativeEvent()->scroll); >+ return; >+ } >+ > webkitWebViewBaseForwardNextWheelEvent(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); > gtk_main_do_event(event.nativeEvent()); > } >@@ -436,16 +458,34 @@ void PageClientImpl::didRemoveNavigationGestureSnapshot() > { > } > >+void PageClientImpl::didStartProvisionalLoadForMainFrame() >+{ >+ webkitWebViewBaseDidStartProvisionalLoadForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); >+} >+ > void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame() > { >+ webkitWebViewBaseDidFirstVisuallyNonEmptyLayoutForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); > } > > void PageClientImpl::didFinishLoadForMainFrame() > { >+ webkitWebViewBaseDidFinishLoadForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); >+} >+ >+void PageClientImpl::didFailLoadForMainFrame() >+{ >+ webkitWebViewBaseDidFailLoadForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); >+} >+ >+void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type) >+{ >+ webkitWebViewBaseDidSameDocumentNavigationForMainFrame(WEBKIT_WEB_VIEW_BASE(m_viewWidget), type); > } > >-void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType) >+void PageClientImpl::didRestoreScrollPosition() > { >+ webkitWebViewBaseDidRestoreScrollPosition(WEBKIT_WEB_VIEW_BASE(m_viewWidget)); > } > > void PageClientImpl::didChangeBackgroundColor() >diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h >index 6dea8f39fd8151d464ce64a15e530ce96f9c4de3..a84542e5309cd8fe87325e4ea75c8342d5dbc8ae 100644 >--- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h >+++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h >@@ -87,6 +87,7 @@ private: > RefPtr<WebColorPicker> createColorPicker(WebPageProxy*, const WebCore::Color& initialColor, const WebCore::IntRect&, Vector<WebCore::Color>&&) override; > #endif > void selectionDidChange() override; >+ RefPtr<ViewSnapshot> takeViewSnapshot() override; > #if ENABLE(DRAG_SUPPORT) > void startDrag(Ref<WebCore::SelectionData>&&, WebCore::DragOperation, RefPtr<ShareableBitmap>&& dragImage) override; > #endif >@@ -98,7 +99,7 @@ private: > void handleDownloadRequest(DownloadProxy*) override; > void didChangeContentSize(const WebCore::IntSize&) override; > void didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider) override; >- void didFailLoadForMainFrame() override { } >+ void didFailLoadForMainFrame() override; > > // Auxiliary Client Creation > #if ENABLE(FULLSCREEN_API) >@@ -124,6 +125,7 @@ private: > void willRecordNavigationSnapshot(WebBackForwardListItem&) override; > void didRemoveNavigationGestureSnapshot() override; > >+ void didStartProvisionalLoadForMainFrame() override; > void didFirstVisuallyNonEmptyLayoutForMainFrame() override; > void didFinishLoadForMainFrame() override; > void didSameDocumentNavigationForMainFrame(SameDocumentNavigationType) override; >@@ -139,7 +141,7 @@ private: > void refView() override; > void derefView() override; > >- void didRestoreScrollPosition() override { } >+ void didRestoreScrollPosition() override; > void isPlayingAudioWillChange() final { } > void isPlayingAudioDidChange() final { } > >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitSettings.h b/Source/WebKit/UIProcess/API/gtk/WebKitSettings.h >index cb2c206e2f6879d7377e209538c56ce5b03ab391..3ecf852181115680d5baac1d42d54c8426ffaf6d 100644 >--- a/Source/WebKit/UIProcess/API/gtk/WebKitSettings.h >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitSettings.h >@@ -472,6 +472,13 @@ WEBKIT_API void > webkit_settings_set_hardware_acceleration_policy (WebKitSettings *settings, > WebKitHardwareAccelerationPolicy policy); > >+WEBKIT_API gboolean >+webkit_settings_get_allow_back_forward_navigation_gestures (WebKitSettings *settings); >+ >+WEBKIT_API void >+webkit_settings_set_allow_back_forward_navigation_gestures (WebKitSettings *settings, >+ gboolean allowed); >+ > WEBKIT_API guint32 > webkit_settings_font_size_to_points (guint32 pixels); > >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp >index e224a1e65735e043ed2ce76ae1b6579e5c90ae73..2712829052b69a63652ae17ee2be14153889aeff 100644 >--- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp >@@ -38,6 +38,7 @@ > #include "NativeWebMouseEvent.h" > #include "NativeWebWheelEvent.h" > #include "PageClientImpl.h" >+#include "ViewGestureController.h" > #include "WebEventFactory.h" > #include "WebInspectorProxy.h" > #include "WebKit2Initialize.h" >@@ -202,6 +203,7 @@ struct _WebKitWebViewBasePrivate { > #if HAVE(GTK_GESTURES) > std::unique_ptr<GestureController> gestureController; > #endif >+ std::unique_ptr<ViewGestureController> viewGestureController; > }; > > WEBKIT_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER) >@@ -533,6 +535,10 @@ static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr) > if (!gdk_cairo_get_clip_rectangle(cr, &clipRect)) > return FALSE; > >+ bool showingNavigationSnapshot = webViewBase->priv->pageProxy->isShowingNavigationGestureSnapshot(); >+ if (showingNavigationSnapshot) >+ cairo_push_group(cr); >+ > if (webViewBase->priv->acceleratedBackingStore && drawingArea->isInAcceleratedCompositingMode()) > webViewBase->priv->acceleratedBackingStore->paint(cr, clipRect); > else { >@@ -540,6 +546,12 @@ static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr) > drawingArea->paint(cr, clipRect, unpaintedRegion); > } > >+ if (showingNavigationSnapshot) { >+ ViewGestureController& controller = webkitWebViewBaseViewGestureController(webViewBase); >+ RefPtr<cairo_pattern_t> group = adoptRef(cairo_pop_group(cr)); >+ controller.draw(cr, group.get()); >+ } >+ > GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr); > > return FALSE; >@@ -852,6 +864,10 @@ static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll* > } > } > >+ WebKit::ViewGestureController& controller = webkitWebViewBaseViewGestureController(webViewBase); >+ if (controller.isSwipeGestureEnabled() && controller.handleScrollWheelEvent(event)) >+ return GDK_EVENT_STOP; >+ > webkitWebViewBaseHandleWheelEvent(webViewBase, reinterpret_cast<GdkEvent*>(event)); > > return GDK_EVENT_STOP; >@@ -1024,11 +1040,11 @@ static gboolean webkitWebViewBaseTouchEvent(GtkWidget* widget, GdkEventTouch* ev > #endif // ENABLE(TOUCH_EVENTS) > > #if HAVE(GTK_GESTURES) >-class ViewGestureController final : public GestureControllerClient { >+class TouchGestureController final : public GestureControllerClient { > WTF_MAKE_FAST_ALLOCATED; > > public: >- explicit ViewGestureController(WebKitWebViewBase* webViewBase) >+ explicit TouchGestureController(WebKitWebViewBase* webViewBase) > : m_webView(webViewBase) > { > } >@@ -1143,11 +1159,19 @@ GestureController& webkitWebViewBaseGestureController(WebKitWebViewBase* webView > { > WebKitWebViewBasePrivate* priv = webViewBase->priv; > if (!priv->gestureController) >- priv->gestureController = std::make_unique<GestureController>(GTK_WIDGET(webViewBase), std::make_unique<ViewGestureController>(webViewBase)); >+ priv->gestureController = std::make_unique<GestureController>(GTK_WIDGET(webViewBase), std::make_unique<TouchGestureController>(webViewBase)); > return *priv->gestureController; > } > #endif > >+ViewGestureController& webkitWebViewBaseViewGestureController(WebKitWebViewBase* webViewBase) >+{ >+ WebKitWebViewBasePrivate* priv = webViewBase->priv; >+ if (!priv->viewGestureController) >+ priv->viewGestureController = std::make_unique<WebKit::ViewGestureController>(*priv->pageProxy); >+ return *priv->viewGestureController; >+} >+ > static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint /* x */, gint /* y */, gboolean keyboardMode, GtkTooltip* tooltip) > { > WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv; >@@ -1626,3 +1650,63 @@ void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase) > drawingArea->destroyNativeSurfaceHandleForCompositing(); > #endif > } >+ >+RefPtr<WebKit::ViewSnapshot> webkitWebViewBaseTakeViewSnapshot(WebKitWebViewBase* webkitWebViewBase) >+{ >+ WebPageProxy* proxy = webkitWebViewBase->priv->pageProxy.get(); >+ >+ IntSize size = proxy->viewSize(); >+ >+#if HAVE_GTK_SCALE_FACTOR >+ float deviceScale = proxy->deviceScaleFactor(); >+ size.scale(deviceScale); >+#endif >+ >+ RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_RGB24, size.width(), size.height())); >+ >+#if HAVE_GTK_SCALE_FACTOR >+ cairoSurfaceSetDeviceScale(surface.get(), deviceScale, deviceScale); >+#endif >+ >+ RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get())); >+ webkitWebViewBaseDraw(GTK_WIDGET(webkitWebViewBase), cr.get()); >+ >+ RefPtr<ViewSnapshot> snapshot = ViewSnapshot::create(WTFMove(surface)); >+ return snapshot; >+} >+ >+void webkitWebViewBaseDidStartProvisionalLoadForMainFrame(WebKitWebViewBase* webkitWebViewBase) >+{ >+ if (webkitWebViewBase->priv->viewGestureController) >+ webkitWebViewBase->priv->viewGestureController->didStartProvisionalLoadForMainFrame(); >+} >+ >+void webkitWebViewBaseDidFirstVisuallyNonEmptyLayoutForMainFrame(WebKitWebViewBase* webkitWebViewBase) >+{ >+ if (webkitWebViewBase->priv->viewGestureController) >+ webkitWebViewBase->priv->viewGestureController->didFirstVisuallyNonEmptyLayoutForMainFrame(); >+} >+ >+void webkitWebViewBaseDidFinishLoadForMainFrame(WebKitWebViewBase* webkitWebViewBase) >+{ >+ if (webkitWebViewBase->priv->viewGestureController) >+ webkitWebViewBase->priv->viewGestureController->didFinishLoadForMainFrame(); >+} >+ >+void webkitWebViewBaseDidFailLoadForMainFrame(WebKitWebViewBase* webkitWebViewBase) >+{ >+ if (webkitWebViewBase->priv->viewGestureController) >+ webkitWebViewBase->priv->viewGestureController->didFailLoadForMainFrame(); >+} >+ >+void webkitWebViewBaseDidSameDocumentNavigationForMainFrame(WebKitWebViewBase* webkitWebViewBase, SameDocumentNavigationType type) >+{ >+ if (webkitWebViewBase->priv->viewGestureController) >+ webkitWebViewBase->priv->viewGestureController->didSameDocumentNavigationForMainFrame(type); >+} >+ >+void webkitWebViewBaseDidRestoreScrollPosition(WebKitWebViewBase* webkitWebViewBase) >+{ >+ if (webkitWebViewBase->priv->viewGestureController) >+ webkitWebViewBase->priv->viewGestureController->didRestoreScrollPosition(); >+} >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h >index 8dde69b1bb8cb59bcdd05ea66f77eef0cf9700ea..1360285bfa236b4c35c7444f259e1698f4a0451f 100644 >--- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h >@@ -30,6 +30,9 @@ > #include "APIPageConfiguration.h" > #include "DragAndDropHandler.h" > #include "GestureController.h" >+#include "SameDocumentNavigationType.h" >+#include "ViewGestureController.h" >+#include "ViewSnapshotStore.h" > #include "WebContextMenuProxyGtk.h" > #include "WebInspectorProxy.h" > #include "WebKitWebViewBase.h" >@@ -78,3 +81,14 @@ WebKit::DragAndDropHandler& webkitWebViewBaseDragAndDropHandler(WebKitWebViewBas > #if HAVE(GTK_GESTURES) > WebKit::GestureController& webkitWebViewBaseGestureController(WebKitWebViewBase*); > #endif >+ >+RefPtr<WebKit::ViewSnapshot> webkitWebViewBaseTakeViewSnapshot(WebKitWebViewBase*); >+ >+WebKit::ViewGestureController& webkitWebViewBaseViewGestureController(WebKitWebViewBase*); >+ >+void webkitWebViewBaseDidStartProvisionalLoadForMainFrame(WebKitWebViewBase*); >+void webkitWebViewBaseDidFirstVisuallyNonEmptyLayoutForMainFrame(WebKitWebViewBase*); >+void webkitWebViewBaseDidFinishLoadForMainFrame(WebKitWebViewBase*); >+void webkitWebViewBaseDidFailLoadForMainFrame(WebKitWebViewBase*); >+void webkitWebViewBaseDidSameDocumentNavigationForMainFrame(WebKitWebViewBase*, WebKit::SameDocumentNavigationType); >+void webkitWebViewBaseDidRestoreScrollPosition(WebKitWebViewBase*); >diff --git a/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt b/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >index 1b7b5b865638491c6d033b55588ca34e8d3b8f6a..aaeb3821d0e74fbe85906272942a896a4d3f2874 100644 >--- a/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >+++ b/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >@@ -488,6 +488,8 @@ webkit_settings_get_allow_universal_access_from_file_urls > webkit_settings_set_allow_universal_access_from_file_urls > webkit_settings_get_hardware_acceleration_policy > webkit_settings_set_hardware_acceleration_policy >+webkit_settings_get_allow_back_forward_navigation_gestures >+webkit_settings_set_allow_back_forward_navigation_gestures > webkit_settings_font_size_to_points > webkit_settings_font_size_to_pixels > >diff --git a/Source/WebKit/UIProcess/Cocoa/ViewGestureController.cpp b/Source/WebKit/UIProcess/Cocoa/ViewGestureController.cpp >deleted file mode 100644 >index bd041dd200ffd6e8bb487acf44471c2afd56ea97..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/Cocoa/ViewGestureController.cpp >+++ /dev/null >@@ -1,376 +0,0 @@ >-/* >- * Copyright (C) 2013-2015 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 "ViewGestureController.h" >- >-#import "Logging.h" >-#import "RemoteLayerTreeDrawingAreaProxy.h" >-#import "ViewGestureControllerMessages.h" >-#import "WebBackForwardList.h" >-#import "WebFullScreenManagerProxy.h" >-#import "WebPageProxy.h" >-#import "WebProcessProxy.h" >-#import <wtf/MathExtras.h> >-#import <wtf/NeverDestroyed.h> >-#import <wtf/text/StringBuilder.h> >-#import <wtf/text/StringConcatenateNumbers.h> >- >-namespace WebKit { >-using namespace WebCore; >- >-static const Seconds swipeSnapshotRemovalWatchdogAfterFirstVisuallyNonEmptyLayoutDuration { 3_s }; >-static const Seconds swipeSnapshotRemovalActiveLoadMonitoringInterval { 250_ms }; >- >-#if PLATFORM(MAC) >-static const Seconds swipeSnapshotRemovalWatchdogDuration = 5_s; >-#else >-static const Seconds swipeSnapshotRemovalWatchdogDuration = 3_s; >-#endif >- >-static HashMap<uint64_t, ViewGestureController*>& viewGestureControllersForAllPages() >-{ >- // The key in this map is the associated page ID. >- static NeverDestroyed<HashMap<uint64_t, ViewGestureController*>> viewGestureControllers; >- return viewGestureControllers.get(); >-} >- >-ViewGestureController::ViewGestureController(WebPageProxy& webPageProxy) >- : m_webPageProxy(webPageProxy) >- , m_swipeActiveLoadMonitoringTimer(RunLoop::main(), this, &ViewGestureController::checkForActiveLoads) >-#if PLATFORM(MAC) >- , m_pendingSwipeTracker(webPageProxy, *this) >-#endif >-{ >- connectToProcess(); >- >- viewGestureControllersForAllPages().add(webPageProxy.pageID(), this); >-} >- >-ViewGestureController::~ViewGestureController() >-{ >- platformTeardown(); >- >- viewGestureControllersForAllPages().remove(m_webPageProxy.pageID()); >- >- disconnectFromProcess(); >-} >- >-void ViewGestureController::disconnectFromProcess() >-{ >- if (!m_isConnectedToProcess) >- return; >- >- m_webPageProxy.process().removeMessageReceiver(Messages::ViewGestureController::messageReceiverName(), m_webPageProxy.pageID()); >- m_isConnectedToProcess = false; >-} >- >-void ViewGestureController::connectToProcess() >-{ >- if (m_isConnectedToProcess) >- return; >- >- m_webPageProxy.process().addMessageReceiver(Messages::ViewGestureController::messageReceiverName(), m_webPageProxy.pageID(), *this); >- m_isConnectedToProcess = true; >-} >- >-ViewGestureController* ViewGestureController::controllerForGesture(uint64_t pageID, ViewGestureController::GestureID gestureID) >-{ >- auto gestureControllerIter = viewGestureControllersForAllPages().find(pageID); >- if (gestureControllerIter == viewGestureControllersForAllPages().end()) >- return nullptr; >- if (gestureControllerIter->value->m_currentGestureID != gestureID) >- return nullptr; >- return gestureControllerIter->value; >-} >- >-ViewGestureController::GestureID ViewGestureController::takeNextGestureID() >-{ >- static GestureID nextGestureID; >- return ++nextGestureID; >-} >- >-void ViewGestureController::willBeginGesture(ViewGestureType type) >-{ >- m_activeGestureType = type; >- m_currentGestureID = takeNextGestureID(); >-} >- >-void ViewGestureController::didEndGesture() >-{ >- m_activeGestureType = ViewGestureType::None; >- m_currentGestureID = 0; >-} >- >-void ViewGestureController::setAlternateBackForwardListSourcePage(WebPageProxy* page) >-{ >- m_alternateBackForwardListSourcePage = makeWeakPtr(page); >-} >- >-bool ViewGestureController::canSwipeInDirection(SwipeDirection direction) const >-{ >- if (!m_swipeGestureEnabled) >- return false; >- >-#if ENABLE(FULLSCREEN_API) >- if (m_webPageProxy.fullScreenManager() && m_webPageProxy.fullScreenManager()->isFullScreen()) >- return false; >-#endif >- >- RefPtr<WebPageProxy> alternateBackForwardListSourcePage = m_alternateBackForwardListSourcePage.get(); >- auto& backForwardList = alternateBackForwardListSourcePage ? alternateBackForwardListSourcePage->backForwardList() : m_webPageProxy.backForwardList(); >- if (direction == SwipeDirection::Back) >- return !!backForwardList.backItem(); >- return !!backForwardList.forwardItem(); >-} >- >-void ViewGestureController::didStartProvisionalOrSameDocumentLoadForMainFrame() >-{ >- m_snapshotRemovalTracker.resume(); >-#if PLATFORM(MAC) >- requestRenderTreeSizeNotificationIfNeeded(); >-#endif >- >- if (auto loadCallback = WTFMove(m_loadCallback)) >- loadCallback(); >-} >- >-void ViewGestureController::didStartProvisionalLoadForMainFrame() >-{ >- didStartProvisionalOrSameDocumentLoadForMainFrame(); >-} >- >-void ViewGestureController::didFirstVisuallyNonEmptyLayoutForMainFrame() >-{ >- if (!m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::VisuallyNonEmptyLayout)) >- return; >- >- m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::MainFrameLoad); >- m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::SubresourceLoads); >- m_snapshotRemovalTracker.startWatchdog(swipeSnapshotRemovalWatchdogAfterFirstVisuallyNonEmptyLayoutDuration); >-} >- >-void ViewGestureController::didRepaintAfterNavigation() >-{ >- m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::RepaintAfterNavigation); >-} >- >-void ViewGestureController::didHitRenderTreeSizeThreshold() >-{ >- m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::RenderTreeSizeThreshold); >-} >- >-void ViewGestureController::didRestoreScrollPosition() >-{ >- m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::ScrollPositionRestoration); >-} >- >-void ViewGestureController::didReachMainFrameLoadTerminalState() >-{ >- if (m_snapshotRemovalTracker.isPaused() && m_snapshotRemovalTracker.hasRemovalCallback()) { >- removeSwipeSnapshot(); >- return; >- } >- >- if (!m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::MainFrameLoad)) >- return; >- >- // Coming back from the page cache will result in getting a load event, but no first visually non-empty layout. >- // WebCore considers a loaded document enough to be considered visually non-empty, so that's good >- // enough for us too. >- m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::VisuallyNonEmptyLayout); >- >- checkForActiveLoads(); >-} >- >-void ViewGestureController::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type) >-{ >- didStartProvisionalOrSameDocumentLoadForMainFrame(); >- >- bool cancelledOutstandingEvent = false; >- >- // Same-document navigations don't have a main frame load or first visually non-empty layout. >- cancelledOutstandingEvent |= m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::MainFrameLoad); >- cancelledOutstandingEvent |= m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::VisuallyNonEmptyLayout); >- >- if (!cancelledOutstandingEvent) >- return; >- >- if (type != SameDocumentNavigationSessionStateReplace && type != SameDocumentNavigationSessionStatePop) >- return; >- >- checkForActiveLoads(); >-} >- >-void ViewGestureController::checkForActiveLoads() >-{ >- if (m_webPageProxy.pageLoadState().isLoading()) { >- if (!m_swipeActiveLoadMonitoringTimer.isActive()) >- m_swipeActiveLoadMonitoringTimer.startRepeating(swipeSnapshotRemovalActiveLoadMonitoringInterval); >- return; >- } >- >- m_swipeActiveLoadMonitoringTimer.stop(); >- m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::SubresourceLoads); >-} >- >-ViewGestureController::SnapshotRemovalTracker::SnapshotRemovalTracker() >- : m_watchdogTimer(RunLoop::main(), this, &SnapshotRemovalTracker::watchdogTimerFired) >-{ >-} >- >-String ViewGestureController::SnapshotRemovalTracker::eventsDescription(Events event) >-{ >- StringBuilder description; >- >- if (event & ViewGestureController::SnapshotRemovalTracker::VisuallyNonEmptyLayout) >- description.append("VisuallyNonEmptyLayout "); >- >- if (event & ViewGestureController::SnapshotRemovalTracker::RenderTreeSizeThreshold) >- description.append("RenderTreeSizeThreshold "); >- >- if (event & ViewGestureController::SnapshotRemovalTracker::RepaintAfterNavigation) >- description.append("RepaintAfterNavigation "); >- >- if (event & ViewGestureController::SnapshotRemovalTracker::MainFrameLoad) >- description.append("MainFrameLoad "); >- >- if (event & ViewGestureController::SnapshotRemovalTracker::SubresourceLoads) >- description.append("SubresourceLoads "); >- >- if (event & ViewGestureController::SnapshotRemovalTracker::ScrollPositionRestoration) >- description.append("ScrollPositionRestoration "); >- >- return description.toString(); >-} >- >- >-void ViewGestureController::SnapshotRemovalTracker::log(const String& log) const >-{ >- auto sinceStart = MonotonicTime::now() - m_startTime; >- RELEASE_LOG(ViewGestures, "Swipe Snapshot Removal (%0.2f ms) - %{public}s", sinceStart.milliseconds(), log.utf8().data()); >-} >- >-void ViewGestureController::SnapshotRemovalTracker::resume() >-{ >- if (isPaused() && m_outstandingEvents) >- log("resume"); >- m_paused = false; >-} >- >-void ViewGestureController::SnapshotRemovalTracker::start(Events desiredEvents, WTF::Function<void()>&& removalCallback) >-{ >- m_outstandingEvents = desiredEvents; >- m_removalCallback = WTFMove(removalCallback); >- m_startTime = MonotonicTime::now(); >- >- log("start"); >- >- startWatchdog(swipeSnapshotRemovalWatchdogDuration); >- >- // Initially start out paused; we'll resume when the load is committed. >- // This avoids processing callbacks from earlier loads. >- pause(); >-} >- >-void ViewGestureController::SnapshotRemovalTracker::reset() >-{ >- if (m_outstandingEvents) >- log("reset; had outstanding events: " + eventsDescription(m_outstandingEvents)); >- m_outstandingEvents = 0; >- m_watchdogTimer.stop(); >- m_removalCallback = nullptr; >-} >- >-bool ViewGestureController::SnapshotRemovalTracker::stopWaitingForEvent(Events event, const String& logReason) >-{ >- ASSERT(hasOneBitSet(event)); >- >- if (!(m_outstandingEvents & event)) >- return false; >- >- if (isPaused()) { >- log("is paused; ignoring event: " + eventsDescription(event)); >- return false; >- } >- >- log(logReason + eventsDescription(event)); >- >- m_outstandingEvents &= ~event; >- >- fireRemovalCallbackIfPossible(); >- return true; >-} >- >-bool ViewGestureController::SnapshotRemovalTracker::eventOccurred(Events event) >-{ >- return stopWaitingForEvent(event, "outstanding event occurred: "); >-} >- >-bool ViewGestureController::SnapshotRemovalTracker::cancelOutstandingEvent(Events event) >-{ >- return stopWaitingForEvent(event, "wait for event cancelled: "); >-} >- >-bool ViewGestureController::SnapshotRemovalTracker::hasOutstandingEvent(Event event) >-{ >- return m_outstandingEvents & event; >-} >- >-void ViewGestureController::SnapshotRemovalTracker::fireRemovalCallbackIfPossible() >-{ >- if (m_outstandingEvents) { >- log("deferring removal; had outstanding events: " + eventsDescription(m_outstandingEvents)); >- return; >- } >- >- fireRemovalCallbackImmediately(); >-} >- >-void ViewGestureController::SnapshotRemovalTracker::fireRemovalCallbackImmediately() >-{ >- m_watchdogTimer.stop(); >- >- auto removalCallback = WTFMove(m_removalCallback); >- if (removalCallback) { >- log("removing snapshot"); >- reset(); >- removalCallback(); >- } >-} >- >-void ViewGestureController::SnapshotRemovalTracker::watchdogTimerFired() >-{ >- log("watchdog timer fired"); >- fireRemovalCallbackImmediately(); >-} >- >-void ViewGestureController::SnapshotRemovalTracker::startWatchdog(Seconds duration) >-{ >- log(makeString("(re)started watchdog timer for ", FormattedNumber::fixedWidth(duration.seconds(), 1), " seconds")); >- m_watchdogTimer.startOneShot(duration); >-} >- >-} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/Cocoa/ViewGestureController.h b/Source/WebKit/UIProcess/Cocoa/ViewGestureController.h >deleted file mode 100644 >index a18fd8fa45a7a2a74a4df746f146311674ee5109..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/Cocoa/ViewGestureController.h >+++ /dev/null >@@ -1,332 +0,0 @@ >-/* >- * Copyright (C) 2013, 2014 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. >- */ >- >-#ifndef ViewGestureController_h >-#define ViewGestureController_h >- >-#include "MessageReceiver.h" >-#include "SameDocumentNavigationType.h" >-#include <WebCore/Color.h> >-#include <WebCore/FloatRect.h> >-#include <wtf/BlockPtr.h> >-#include <wtf/MonotonicTime.h> >-#include <wtf/RetainPtr.h> >-#include <wtf/RunLoop.h> >-#include <wtf/WeakPtr.h> >- >-OBJC_CLASS CALayer; >- >-#if PLATFORM(IOS_FAMILY) >-OBJC_CLASS UIGestureRecognizer; >-OBJC_CLASS UIView; >-OBJC_CLASS WKSwipeTransitionController; >-OBJC_CLASS _UINavigationInteractiveTransitionBase; >-OBJC_CLASS _UIViewControllerOneToOneTransitionContext; >-OBJC_CLASS _UIViewControllerTransitionContext; >-#else >-OBJC_CLASS CAGradientLayer; >-OBJC_CLASS NSEvent; >-OBJC_CLASS NSView; >-OBJC_CLASS WKSwipeCancellationTracker; >-#endif >- >-namespace WebCore { >-class IOSurface; >-} >- >-namespace WebKit { >- >-class ViewSnapshot; >-class WebBackForwardListItem; >-class WebPageProxy; >-class WebProcessProxy; >- >-class ViewGestureController : private IPC::MessageReceiver { >- WTF_MAKE_NONCOPYABLE(ViewGestureController); >-public: >- ViewGestureController(WebPageProxy&); >- ~ViewGestureController(); >- void platformTeardown(); >- >- void disconnectFromProcess(); >- void connectToProcess(); >- >- enum class ViewGestureType { >- None, >-#if PLATFORM(MAC) >- Magnification, >- SmartMagnification, >-#endif >- Swipe >- }; >- >- enum class SwipeDirection { >- Back, >- Forward >- }; >- >- typedef uint64_t GestureID; >- >-#if PLATFORM(MAC) >- double magnification() const; >- >- void handleMagnificationGestureEvent(NSEvent *, WebCore::FloatPoint origin); >- >- bool hasActiveMagnificationGesture() const { return m_activeGestureType == ViewGestureType::Magnification; } >- >- void handleSmartMagnificationGesture(WebCore::FloatPoint origin); >- >- bool handleScrollWheelEvent(NSEvent *); >- void wheelEventWasNotHandledByWebCore(NSEvent *event) { m_pendingSwipeTracker.eventWasNotHandledByWebCore(event); } >- void gestureEventWasNotHandledByWebCore(NSEvent *, WebCore::FloatPoint origin); >- >- void setCustomSwipeViews(Vector<RetainPtr<NSView>> views) { m_customSwipeViews = WTFMove(views); } >- void setCustomSwipeViewsTopContentInset(float topContentInset) { m_customSwipeViewsTopContentInset = topContentInset; } >- WebCore::FloatRect windowRelativeBoundsForCustomSwipeViews() const; >- void setDidMoveSwipeSnapshotCallback(BlockPtr<void (CGRect)>&& callback) { m_didMoveSwipeSnapshotCallback = WTFMove(callback); } >- >- bool shouldIgnorePinnedState() { return m_pendingSwipeTracker.shouldIgnorePinnedState(); } >- void setShouldIgnorePinnedState(bool ignore) { m_pendingSwipeTracker.setShouldIgnorePinnedState(ignore); } >- >- bool isPhysicallySwipingLeft(SwipeDirection) const; >-#else >- bool isNavigationSwipeGestureRecognizer(UIGestureRecognizer *) const; >- void installSwipeHandler(UIView *gestureRecognizerView, UIView *swipingView); >- void beginSwipeGesture(_UINavigationInteractiveTransitionBase *, SwipeDirection); >- void endSwipeGesture(WebBackForwardListItem* targetItem, _UIViewControllerTransitionContext *, bool cancelled); >- void willCommitPostSwipeTransitionLayerTree(bool); >- void setRenderTreeSize(uint64_t); >-#endif >- >- void setAlternateBackForwardListSourcePage(WebPageProxy*); >- >- bool canSwipeInDirection(SwipeDirection) const; >- >- WebCore::Color backgroundColorForCurrentSnapshot() const { return m_backgroundColorForCurrentSnapshot; } >- >- void didStartProvisionalLoadForMainFrame(); >- void didFinishLoadForMainFrame() { didReachMainFrameLoadTerminalState(); } >- void didFailLoadForMainFrame() { didReachMainFrameLoadTerminalState(); } >- void didFirstVisuallyNonEmptyLayoutForMainFrame(); >- void didRepaintAfterNavigation(); >- void didHitRenderTreeSizeThreshold(); >- void didRestoreScrollPosition(); >- void didReachMainFrameLoadTerminalState(); >- void didSameDocumentNavigationForMainFrame(SameDocumentNavigationType); >- >- void checkForActiveLoads(); >- >- void removeSwipeSnapshot(); >- >- void setSwipeGestureEnabled(bool enabled) { m_swipeGestureEnabled = enabled; } >- bool isSwipeGestureEnabled() { return m_swipeGestureEnabled; } >- >- // Testing >- bool beginSimulatedSwipeInDirectionForTesting(SwipeDirection); >- bool completeSimulatedSwipeInDirectionForTesting(SwipeDirection); >- >-private: >- // IPC::MessageReceiver. >- void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override; >- >- static ViewGestureController* controllerForGesture(uint64_t pageID, GestureID); >- >- static GestureID takeNextGestureID(); >- void willBeginGesture(ViewGestureType); >- void didEndGesture(); >- >- void didStartProvisionalOrSameDocumentLoadForMainFrame(); >- >- class SnapshotRemovalTracker { >- public: >- enum Event : uint8_t { >- VisuallyNonEmptyLayout = 1 << 0, >- RenderTreeSizeThreshold = 1 << 1, >- RepaintAfterNavigation = 1 << 2, >- MainFrameLoad = 1 << 3, >- SubresourceLoads = 1 << 4, >- ScrollPositionRestoration = 1 << 5 >- }; >- typedef uint8_t Events; >- >- SnapshotRemovalTracker(); >- >- void start(Events, WTF::Function<void()>&&); >- void reset(); >- >- void pause() { m_paused = true; } >- void resume(); >- bool isPaused() const { return m_paused; } >- bool hasRemovalCallback() const { return !!m_removalCallback; } >- >- bool eventOccurred(Events); >- bool cancelOutstandingEvent(Events); >- bool hasOutstandingEvent(Event); >- >- void startWatchdog(Seconds); >- >- uint64_t renderTreeSizeThreshold() const { return m_renderTreeSizeThreshold; } >- void setRenderTreeSizeThreshold(uint64_t threshold) { m_renderTreeSizeThreshold = threshold; } >- >- private: >- static String eventsDescription(Events); >- void log(const String&) const; >- >- void fireRemovalCallbackImmediately(); >- void fireRemovalCallbackIfPossible(); >- void watchdogTimerFired(); >- >- bool stopWaitingForEvent(Events, const String& logReason); >- >- Events m_outstandingEvents { 0 }; >- WTF::Function<void()> m_removalCallback; >- MonotonicTime m_startTime; >- >- uint64_t m_renderTreeSizeThreshold { 0 }; >- >- RunLoop::Timer<SnapshotRemovalTracker> m_watchdogTimer; >- >- bool m_paused { true }; >- }; >- >-#if PLATFORM(MAC) >- // Message handlers. >- void didCollectGeometryForMagnificationGesture(WebCore::FloatRect visibleContentBounds, bool frameHandlesMagnificationGesture); >- void didCollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin, WebCore::FloatRect renderRect, WebCore::FloatRect visibleContentBounds, bool fitEntireRect, double viewportMinimumScale, double viewportMaximumScale); >- >- void endMagnificationGesture(); >- >- WebCore::FloatPoint scaledMagnificationOrigin(WebCore::FloatPoint origin, double scale); >- >- void trackSwipeGesture(NSEvent *, SwipeDirection); >- void beginSwipeGesture(WebBackForwardListItem* targetItem, SwipeDirection); >- void handleSwipeGesture(WebBackForwardListItem* targetItem, double progress, SwipeDirection); >- void willEndSwipeGesture(WebBackForwardListItem& targetItem, bool cancelled); >- void endSwipeGesture(WebBackForwardListItem* targetItem, bool cancelled); >- bool shouldUseSnapshotForSize(ViewSnapshot&, WebCore::FloatSize swipeLayerSize, float topContentInset); >- >- CALayer *determineSnapshotLayerParent() const; >- CALayer *determineLayerAdjacentToSnapshotForParent(SwipeDirection, CALayer *snapshotLayerParent) const; >- void applyDebuggingPropertiesToSwipeViews(); >- void didMoveSwipeSnapshotLayer(); >- >- void forceRepaintIfNeeded(); >- >- void requestRenderTreeSizeNotificationIfNeeded(); >- >- class PendingSwipeTracker { >- public: >- PendingSwipeTracker(WebPageProxy&, ViewGestureController&); >- bool handleEvent(NSEvent *); >- void eventWasNotHandledByWebCore(NSEvent *); >- >- void reset(const char* resetReasonForLogging); >- >- bool shouldIgnorePinnedState() { return m_shouldIgnorePinnedState; } >- void setShouldIgnorePinnedState(bool ignore) { m_shouldIgnorePinnedState = ignore; } >- >- private: >- bool tryToStartSwipe(NSEvent *); >- bool scrollEventCanBecomeSwipe(NSEvent *, SwipeDirection&); >- >- enum class State { >- None, >- WaitingForWebCore, >- InsufficientMagnitude >- }; >- >- State m_state { State::None }; >- SwipeDirection m_direction; >- WebCore::FloatSize m_cumulativeDelta; >- >- bool m_shouldIgnorePinnedState { false }; >- >- ViewGestureController& m_viewGestureController; >- WebPageProxy& m_webPageProxy; >- }; >-#endif >- >- WebPageProxy& m_webPageProxy; >- ViewGestureType m_activeGestureType { ViewGestureType::None }; >- >- bool m_swipeGestureEnabled { true }; >- >- RunLoop::Timer<ViewGestureController> m_swipeActiveLoadMonitoringTimer; >- >- WebCore::Color m_backgroundColorForCurrentSnapshot; >- >- WeakPtr<WebPageProxy> m_alternateBackForwardListSourcePage; >- RefPtr<WebPageProxy> m_webPageProxyForBackForwardListForCurrentSwipe; >- >- GestureID m_currentGestureID; >- >-#if PLATFORM(MAC) >- RefPtr<ViewSnapshot> m_currentSwipeSnapshot; >- >- double m_magnification; >- WebCore::FloatPoint m_magnificationOrigin; >- >- WebCore::FloatRect m_lastSmartMagnificationUnscaledTargetRect; >- bool m_lastMagnificationGestureWasSmartMagnification { false }; >- WebCore::FloatPoint m_lastSmartMagnificationOrigin; >- >- WebCore::FloatRect m_visibleContentRect; >- bool m_visibleContentRectIsValid { false }; >- bool m_frameHandlesMagnificationGesture { false }; >- >- RetainPtr<WKSwipeCancellationTracker> m_swipeCancellationTracker; >- RetainPtr<CALayer> m_swipeLayer; >- RetainPtr<CALayer> m_swipeSnapshotLayer; >- RetainPtr<CAGradientLayer> m_swipeShadowLayer; >- RetainPtr<CALayer> m_swipeDimmingLayer; >- Vector<RetainPtr<CALayer>> m_currentSwipeLiveLayers; >- >- Vector<RetainPtr<NSView>> m_customSwipeViews; >- float m_customSwipeViewsTopContentInset { 0 }; >- WebCore::FloatRect m_currentSwipeCustomViewBounds; >- >- PendingSwipeTracker m_pendingSwipeTracker; >- >- BlockPtr<void (CGRect)> m_didMoveSwipeSnapshotCallback; >- >- bool m_hasOutstandingRepaintRequest { false }; >-#else >- UIView *m_liveSwipeView { nullptr }; >- RetainPtr<UIView> m_liveSwipeViewClippingView; >- RetainPtr<UIView> m_snapshotView; >- RetainPtr<UIView> m_transitionContainerView; >- RetainPtr<WKSwipeTransitionController> m_swipeInteractiveTransitionDelegate; >- RetainPtr<_UIViewControllerOneToOneTransitionContext> m_swipeTransitionContext; >- uint64_t m_snapshotRemovalTargetRenderTreeSize { 0 }; >-#endif >- bool m_isConnectedToProcess { false }; >- >- SnapshotRemovalTracker m_snapshotRemovalTracker; >- WTF::Function<void()> m_loadCallback; >-}; >- >-} // namespace WebKit >- >-#endif // ViewGestureController_h >diff --git a/Source/WebKit/UIProcess/Cocoa/ViewGestureController.messages.in b/Source/WebKit/UIProcess/Cocoa/ViewGestureController.messages.in >deleted file mode 100644 >index bb1baf361949403416c8819ec275458c23c2fc9c..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/Cocoa/ViewGestureController.messages.in >+++ /dev/null >@@ -1,29 +0,0 @@ >-# Copyright (C) 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. >- >-messages -> ViewGestureController { >-#if PLATFORM(MAC) >- DidCollectGeometryForMagnificationGesture(WebCore::FloatRect visibleContentBounds, bool frameHandlesMagnificationGesture) >- DidCollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin, WebCore::FloatRect renderRect, WebCore::FloatRect visibleContentBounds, bool fitEntireRect, double viewportMinimumScale, double viewportMaximumScale) >- DidHitRenderTreeSizeThreshold() >-#endif >-} >diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h >index 38c6552bb1e8a95d02a1822387a0228300f0eb80..3961ed4512a927469d45a975b29b0a725114428f 100644 >--- a/Source/WebKit/UIProcess/PageClient.h >+++ b/Source/WebKit/UIProcess/PageClient.h >@@ -254,7 +254,6 @@ public: > virtual void assistiveTechnologyMakeFirstResponder() = 0; > virtual void setRemoteLayerTreeRootNode(RemoteLayerTreeNode*) = 0; > virtual CALayer *acceleratedCompositingRootLayer() const = 0; >- virtual RefPtr<ViewSnapshot> takeViewSnapshot() = 0; > #if ENABLE(MAC_GESTURE_EVENTS) > virtual void gestureEventWasNotHandledByWebCore(const NativeWebGestureEvent&) = 0; > #endif >@@ -262,6 +261,7 @@ public: > > #if PLATFORM(COCOA) || PLATFORM(GTK) > virtual void selectionDidChange() = 0; >+ virtual RefPtr<ViewSnapshot> takeViewSnapshot() = 0; > #endif > > #if USE(APPKIT) >diff --git a/Source/WebKit/UIProcess/ViewGestureController.cpp b/Source/WebKit/UIProcess/ViewGestureController.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..c5babd9e37deeddcf0c6ecdda974a8834844aa94 >--- /dev/null >+++ b/Source/WebKit/UIProcess/ViewGestureController.cpp >@@ -0,0 +1,380 @@ >+/* >+ * Copyright (C) 2013-2015 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. >+ */ >+ >+#include "config.h" >+#include "ViewGestureController.h" >+ >+#include "Logging.h" >+#if PLATFORM(COCOA) >+#include "RemoteLayerTreeDrawingAreaProxy.h" >+#endif >+#include "ViewGestureControllerMessages.h" >+#include "WebBackForwardList.h" >+#include "WebFullScreenManagerProxy.h" >+#include "WebPageProxy.h" >+#include "WebProcessProxy.h" >+#include <wtf/MathExtras.h> >+#include <wtf/NeverDestroyed.h> >+#include <wtf/text/StringBuilder.h> >+#include <wtf/text/StringConcatenateNumbers.h> >+ >+namespace WebKit { >+using namespace WebCore; >+ >+static const Seconds swipeSnapshotRemovalWatchdogAfterFirstVisuallyNonEmptyLayoutDuration { 3_s }; >+static const Seconds swipeSnapshotRemovalActiveLoadMonitoringInterval { 250_ms }; >+ >+#if !PLATFORM(IOS_FAMILY) >+static const Seconds swipeSnapshotRemovalWatchdogDuration = 5_s; >+#else >+static const Seconds swipeSnapshotRemovalWatchdogDuration = 3_s; >+#endif >+ >+static HashMap<uint64_t, ViewGestureController*>& viewGestureControllersForAllPages() >+{ >+ // The key in this map is the associated page ID. >+ static NeverDestroyed<HashMap<uint64_t, ViewGestureController*>> viewGestureControllers; >+ return viewGestureControllers.get(); >+} >+ >+ViewGestureController::ViewGestureController(WebPageProxy& webPageProxy) >+ : m_webPageProxy(webPageProxy) >+ , m_swipeActiveLoadMonitoringTimer(RunLoop::main(), this, &ViewGestureController::checkForActiveLoads) >+#if !PLATFORM(IOS_FAMILY) >+ , m_pendingSwipeTracker(webPageProxy, *this) >+#endif >+#if PLATFORM(GTK) >+ , m_swipeProgressTracker(webPageProxy, *this) >+#endif >+{ >+ connectToProcess(); >+ >+ viewGestureControllersForAllPages().add(webPageProxy.pageID(), this); >+} >+ >+ViewGestureController::~ViewGestureController() >+{ >+ platformTeardown(); >+ >+ viewGestureControllersForAllPages().remove(m_webPageProxy.pageID()); >+ >+ disconnectFromProcess(); >+} >+ >+void ViewGestureController::disconnectFromProcess() >+{ >+ if (!m_isConnectedToProcess) >+ return; >+ >+ m_webPageProxy.process().removeMessageReceiver(Messages::ViewGestureController::messageReceiverName(), m_webPageProxy.pageID()); >+ m_isConnectedToProcess = false; >+} >+ >+void ViewGestureController::connectToProcess() >+{ >+ if (m_isConnectedToProcess) >+ return; >+ >+ m_webPageProxy.process().addMessageReceiver(Messages::ViewGestureController::messageReceiverName(), m_webPageProxy.pageID(), *this); >+ m_isConnectedToProcess = true; >+} >+ >+ViewGestureController* ViewGestureController::controllerForGesture(uint64_t pageID, ViewGestureController::GestureID gestureID) >+{ >+ auto gestureControllerIter = viewGestureControllersForAllPages().find(pageID); >+ if (gestureControllerIter == viewGestureControllersForAllPages().end()) >+ return nullptr; >+ if (gestureControllerIter->value->m_currentGestureID != gestureID) >+ return nullptr; >+ return gestureControllerIter->value; >+} >+ >+ViewGestureController::GestureID ViewGestureController::takeNextGestureID() >+{ >+ static GestureID nextGestureID; >+ return ++nextGestureID; >+} >+ >+void ViewGestureController::willBeginGesture(ViewGestureType type) >+{ >+ m_activeGestureType = type; >+ m_currentGestureID = takeNextGestureID(); >+} >+ >+void ViewGestureController::didEndGesture() >+{ >+ m_activeGestureType = ViewGestureType::None; >+ m_currentGestureID = 0; >+} >+ >+void ViewGestureController::setAlternateBackForwardListSourcePage(WebPageProxy* page) >+{ >+ m_alternateBackForwardListSourcePage = makeWeakPtr(page); >+} >+ >+bool ViewGestureController::canSwipeInDirection(SwipeDirection direction) const >+{ >+ if (!m_swipeGestureEnabled) >+ return false; >+ >+#if ENABLE(FULLSCREEN_API) >+ if (m_webPageProxy.fullScreenManager() && m_webPageProxy.fullScreenManager()->isFullScreen()) >+ return false; >+#endif >+ >+ RefPtr<WebPageProxy> alternateBackForwardListSourcePage = m_alternateBackForwardListSourcePage.get(); >+ auto& backForwardList = alternateBackForwardListSourcePage ? alternateBackForwardListSourcePage->backForwardList() : m_webPageProxy.backForwardList(); >+ if (direction == SwipeDirection::Back) >+ return !!backForwardList.backItem(); >+ return !!backForwardList.forwardItem(); >+} >+ >+void ViewGestureController::didStartProvisionalOrSameDocumentLoadForMainFrame() >+{ >+ m_snapshotRemovalTracker.resume(); >+#if PLATFORM(MAC) >+ requestRenderTreeSizeNotificationIfNeeded(); >+#endif >+ >+ if (auto loadCallback = std::exchange(m_loadCallback, nullptr)) >+ loadCallback(); >+} >+ >+void ViewGestureController::didStartProvisionalLoadForMainFrame() >+{ >+ didStartProvisionalOrSameDocumentLoadForMainFrame(); >+} >+ >+void ViewGestureController::didFirstVisuallyNonEmptyLayoutForMainFrame() >+{ >+ if (!m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::VisuallyNonEmptyLayout)) >+ return; >+ >+ m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::MainFrameLoad); >+ m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::SubresourceLoads); >+ m_snapshotRemovalTracker.startWatchdog(swipeSnapshotRemovalWatchdogAfterFirstVisuallyNonEmptyLayoutDuration); >+} >+ >+void ViewGestureController::didRepaintAfterNavigation() >+{ >+ m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::RepaintAfterNavigation); >+} >+ >+void ViewGestureController::didHitRenderTreeSizeThreshold() >+{ >+ m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::RenderTreeSizeThreshold); >+} >+ >+void ViewGestureController::didRestoreScrollPosition() >+{ >+ m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::ScrollPositionRestoration); >+} >+ >+void ViewGestureController::didReachMainFrameLoadTerminalState() >+{ >+ if (m_snapshotRemovalTracker.isPaused() && m_snapshotRemovalTracker.hasRemovalCallback()) { >+ removeSwipeSnapshot(); >+ return; >+ } >+ >+ if (!m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::MainFrameLoad)) >+ return; >+ >+ // Coming back from the page cache will result in getting a load event, but no first visually non-empty layout. >+ // WebCore considers a loaded document enough to be considered visually non-empty, so that's good >+ // enough for us too. >+ m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::VisuallyNonEmptyLayout); >+ >+ checkForActiveLoads(); >+} >+ >+void ViewGestureController::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type) >+{ >+ didStartProvisionalOrSameDocumentLoadForMainFrame(); >+ >+ bool cancelledOutstandingEvent = false; >+ >+ // Same-document navigations don't have a main frame load or first visually non-empty layout. >+ cancelledOutstandingEvent |= m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::MainFrameLoad); >+ cancelledOutstandingEvent |= m_snapshotRemovalTracker.cancelOutstandingEvent(SnapshotRemovalTracker::VisuallyNonEmptyLayout); >+ >+ if (!cancelledOutstandingEvent) >+ return; >+ >+ if (type != SameDocumentNavigationSessionStateReplace && type != SameDocumentNavigationSessionStatePop) >+ return; >+ >+ checkForActiveLoads(); >+} >+ >+void ViewGestureController::checkForActiveLoads() >+{ >+ if (m_webPageProxy.pageLoadState().isLoading()) { >+ if (!m_swipeActiveLoadMonitoringTimer.isActive()) >+ m_swipeActiveLoadMonitoringTimer.startRepeating(swipeSnapshotRemovalActiveLoadMonitoringInterval); >+ return; >+ } >+ >+ m_swipeActiveLoadMonitoringTimer.stop(); >+ m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::SubresourceLoads); >+} >+ >+ViewGestureController::SnapshotRemovalTracker::SnapshotRemovalTracker() >+ : m_watchdogTimer(RunLoop::main(), this, &SnapshotRemovalTracker::watchdogTimerFired) >+{ >+} >+ >+String ViewGestureController::SnapshotRemovalTracker::eventsDescription(Events event) >+{ >+ StringBuilder description; >+ >+ if (event & ViewGestureController::SnapshotRemovalTracker::VisuallyNonEmptyLayout) >+ description.append("VisuallyNonEmptyLayout "); >+ >+ if (event & ViewGestureController::SnapshotRemovalTracker::RenderTreeSizeThreshold) >+ description.append("RenderTreeSizeThreshold "); >+ >+ if (event & ViewGestureController::SnapshotRemovalTracker::RepaintAfterNavigation) >+ description.append("RepaintAfterNavigation "); >+ >+ if (event & ViewGestureController::SnapshotRemovalTracker::MainFrameLoad) >+ description.append("MainFrameLoad "); >+ >+ if (event & ViewGestureController::SnapshotRemovalTracker::SubresourceLoads) >+ description.append("SubresourceLoads "); >+ >+ if (event & ViewGestureController::SnapshotRemovalTracker::ScrollPositionRestoration) >+ description.append("ScrollPositionRestoration "); >+ >+ return description.toString(); >+} >+ >+ >+void ViewGestureController::SnapshotRemovalTracker::log(const String& log) const >+{ >+ RELEASE_LOG(ViewGestures, "Swipe Snapshot Removal (%0.2f ms) - %s", (MonotonicTime::now() - m_startTime).milliseconds(), log.utf8().data()); >+} >+ >+void ViewGestureController::SnapshotRemovalTracker::resume() >+{ >+ if (isPaused() && m_outstandingEvents) >+ log("resume"); >+ m_paused = false; >+} >+ >+void ViewGestureController::SnapshotRemovalTracker::start(Events desiredEvents, WTF::Function<void()>&& removalCallback) >+{ >+ m_outstandingEvents = desiredEvents; >+ m_removalCallback = WTFMove(removalCallback); >+ m_startTime = MonotonicTime::now(); >+ >+ log("start"); >+ >+ startWatchdog(swipeSnapshotRemovalWatchdogDuration); >+ >+ // Initially start out paused; we'll resume when the load is committed. >+ // This avoids processing callbacks from earlier loads. >+ pause(); >+} >+ >+void ViewGestureController::SnapshotRemovalTracker::reset() >+{ >+ if (m_outstandingEvents) >+ log("reset; had outstanding events: " + eventsDescription(m_outstandingEvents)); >+ m_outstandingEvents = 0; >+ m_watchdogTimer.stop(); >+ m_removalCallback = nullptr; >+} >+ >+bool ViewGestureController::SnapshotRemovalTracker::stopWaitingForEvent(Events event, const String& logReason) >+{ >+ ASSERT(hasOneBitSet(event)); >+ >+ if (!(m_outstandingEvents & event)) >+ return false; >+ >+ if (isPaused()) { >+ log("is paused; ignoring event: " + eventsDescription(event)); >+ return false; >+ } >+ >+ log(logReason + eventsDescription(event)); >+ >+ m_outstandingEvents &= ~event; >+ >+ fireRemovalCallbackIfPossible(); >+ return true; >+} >+ >+bool ViewGestureController::SnapshotRemovalTracker::eventOccurred(Events event) >+{ >+ return stopWaitingForEvent(event, "outstanding event occurred: "); >+} >+ >+bool ViewGestureController::SnapshotRemovalTracker::cancelOutstandingEvent(Events event) >+{ >+ return stopWaitingForEvent(event, "wait for event cancelled: "); >+} >+ >+bool ViewGestureController::SnapshotRemovalTracker::hasOutstandingEvent(Event event) >+{ >+ return m_outstandingEvents & event; >+} >+ >+void ViewGestureController::SnapshotRemovalTracker::fireRemovalCallbackIfPossible() >+{ >+ if (m_outstandingEvents) { >+ log("deferring removal; had outstanding events: " + eventsDescription(m_outstandingEvents)); >+ return; >+ } >+ >+ fireRemovalCallbackImmediately(); >+} >+ >+void ViewGestureController::SnapshotRemovalTracker::fireRemovalCallbackImmediately() >+{ >+ m_watchdogTimer.stop(); >+ >+ auto removalCallback = WTFMove(m_removalCallback); >+ if (removalCallback) { >+ log("removing snapshot"); >+ reset(); >+ removalCallback(); >+ } >+} >+ >+void ViewGestureController::SnapshotRemovalTracker::watchdogTimerFired() >+{ >+ log("watchdog timer fired"); >+ fireRemovalCallbackImmediately(); >+} >+ >+void ViewGestureController::SnapshotRemovalTracker::startWatchdog(Seconds duration) >+{ >+ log(makeString("(re)started watchdog timer for ", FormattedNumber::fixedWidth(duration.seconds(), 1), " seconds")); >+ m_watchdogTimer.startOneShot(duration); >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/ViewGestureController.h b/Source/WebKit/UIProcess/ViewGestureController.h >new file mode 100644 >index 0000000000000000000000000000000000000000..077fe562655623b5aa7a6f6cb103970618ba7ea4 >--- /dev/null >+++ b/Source/WebKit/UIProcess/ViewGestureController.h >@@ -0,0 +1,409 @@ >+/* >+ * Copyright (C) 2013, 2014 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. >+ */ >+ >+#pragma once >+ >+#include "MessageReceiver.h" >+#include "SameDocumentNavigationType.h" >+#if PLATFORM(GTK) >+#include <WebCore/CairoUtilities.h> >+#endif >+#include <WebCore/Color.h> >+#include <WebCore/FloatRect.h> >+#if PLATFORM(COCOA) >+#include <wtf/BlockPtr.h> >+#endif >+#if PLATFORM(GTK) >+#include <gtk/gtk.h> >+#endif >+#include <wtf/MonotonicTime.h> >+#include <wtf/RetainPtr.h> >+#include <wtf/RunLoop.h> >+#include <wtf/WeakPtr.h> >+ >+#if PLATFORM(COCOA) >+OBJC_CLASS CALayer; >+ >+#if PLATFORM(IOS_FAMILY) >+OBJC_CLASS UIGestureRecognizer; >+OBJC_CLASS UIView; >+OBJC_CLASS WKSwipeTransitionController; >+OBJC_CLASS _UINavigationInteractiveTransitionBase; >+OBJC_CLASS _UIViewControllerOneToOneTransitionContext; >+OBJC_CLASS _UIViewControllerTransitionContext; >+#else >+OBJC_CLASS CAGradientLayer; >+OBJC_CLASS NSEvent; >+OBJC_CLASS NSView; >+OBJC_CLASS WKSwipeCancellationTracker; >+#endif >+ >+namespace WebCore { >+class IOSurface; >+} >+#endif >+ >+#if PLATFORM(MAC) >+typedef NSEvent* PlatformScrollEvent; >+#elif PLATFORM(GTK) >+typedef struct _GdkEventScroll GdkEventScroll; >+typedef GdkEventScroll* PlatformScrollEvent; >+#endif >+ >+namespace WebKit { >+ >+class ViewSnapshot; >+class WebBackForwardListItem; >+class WebPageProxy; >+class WebProcessProxy; >+ >+class ViewGestureController : private IPC::MessageReceiver { >+ WTF_MAKE_NONCOPYABLE(ViewGestureController); >+public: >+ ViewGestureController(WebPageProxy&); >+ ~ViewGestureController(); >+ void platformTeardown(); >+ >+ void disconnectFromProcess(); >+ void connectToProcess(); >+ >+ enum class ViewGestureType { >+ None, >+#if PLATFORM(MAC) >+ Magnification, >+ SmartMagnification, >+#endif >+ Swipe >+ }; >+ >+ enum class SwipeDirection { >+ Back, >+ Forward >+ }; >+ >+ typedef uint64_t GestureID; >+ >+#if !PLATFORM(IOS_FAMILY) >+ bool handleScrollWheelEvent(PlatformScrollEvent); >+ void wheelEventWasNotHandledByWebCore(PlatformScrollEvent event) { m_pendingSwipeTracker.eventWasNotHandledByWebCore(event); } >+ >+ bool shouldIgnorePinnedState() { return m_pendingSwipeTracker.shouldIgnorePinnedState(); } >+ void setShouldIgnorePinnedState(bool ignore) { m_pendingSwipeTracker.setShouldIgnorePinnedState(ignore); } >+ >+ bool isPhysicallySwipingLeft(SwipeDirection) const; >+#endif >+ >+#if PLATFORM(MAC) >+ double magnification() const; >+ >+ void handleMagnificationGestureEvent(PlatformScrollEvent, WebCore::FloatPoint origin); >+ >+ bool hasActiveMagnificationGesture() const { return m_activeGestureType == ViewGestureType::Magnification; } >+ >+ void handleSmartMagnificationGesture(WebCore::FloatPoint origin); >+ >+ void gestureEventWasNotHandledByWebCore(PlatformScrollEvent, WebCore::FloatPoint origin); >+ >+ void setCustomSwipeViews(Vector<RetainPtr<NSView>> views) { m_customSwipeViews = WTFMove(views); } >+ void setCustomSwipeViewsTopContentInset(float topContentInset) { m_customSwipeViewsTopContentInset = topContentInset; } >+ WebCore::FloatRect windowRelativeBoundsForCustomSwipeViews() const; >+ void setDidMoveSwipeSnapshotCallback(BlockPtr<void (CGRect)>&& callback) { m_didMoveSwipeSnapshotCallback = WTFMove(callback); } >+#elif PLATFORM(IOS_FAMILY) >+ bool isNavigationSwipeGestureRecognizer(UIGestureRecognizer *) const; >+ void installSwipeHandler(UIView *gestureRecognizerView, UIView *swipingView); >+ void beginSwipeGesture(_UINavigationInteractiveTransitionBase *, SwipeDirection); >+ void endSwipeGesture(WebBackForwardListItem* targetItem, _UIViewControllerTransitionContext *, bool cancelled); >+ void willCommitPostSwipeTransitionLayerTree(bool); >+ void setRenderTreeSize(uint64_t); >+#endif >+ >+ void setAlternateBackForwardListSourcePage(WebPageProxy*); >+ >+ bool canSwipeInDirection(SwipeDirection) const; >+ >+ WebCore::Color backgroundColorForCurrentSnapshot() const { return m_backgroundColorForCurrentSnapshot; } >+ >+ void didStartProvisionalLoadForMainFrame(); >+ void didFinishLoadForMainFrame() { didReachMainFrameLoadTerminalState(); } >+ void didFailLoadForMainFrame() { didReachMainFrameLoadTerminalState(); } >+ void didFirstVisuallyNonEmptyLayoutForMainFrame(); >+ void didRepaintAfterNavigation(); >+ void didHitRenderTreeSizeThreshold(); >+ void didRestoreScrollPosition(); >+ void didReachMainFrameLoadTerminalState(); >+ void didSameDocumentNavigationForMainFrame(SameDocumentNavigationType); >+ >+ void checkForActiveLoads(); >+ >+ void removeSwipeSnapshot(); >+ >+ void setSwipeGestureEnabled(bool enabled) { m_swipeGestureEnabled = enabled; } >+ bool isSwipeGestureEnabled() { return m_swipeGestureEnabled; } >+ >+ // Testing >+ bool beginSimulatedSwipeInDirectionForTesting(SwipeDirection); >+ bool completeSimulatedSwipeInDirectionForTesting(SwipeDirection); >+ >+#if PLATFORM(GTK) >+ void draw(cairo_t*, cairo_pattern_t*); >+#endif >+ >+private: >+ // IPC::MessageReceiver. >+ void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override; >+ >+ static ViewGestureController* controllerForGesture(uint64_t pageID, GestureID); >+ >+ static GestureID takeNextGestureID(); >+ void willBeginGesture(ViewGestureType); >+ void didEndGesture(); >+ >+ void didStartProvisionalOrSameDocumentLoadForMainFrame(); >+ >+ class SnapshotRemovalTracker { >+ public: >+ enum Event : uint8_t { >+ VisuallyNonEmptyLayout = 1 << 0, >+ RenderTreeSizeThreshold = 1 << 1, >+ RepaintAfterNavigation = 1 << 2, >+ MainFrameLoad = 1 << 3, >+ SubresourceLoads = 1 << 4, >+ ScrollPositionRestoration = 1 << 5 >+ }; >+ typedef uint8_t Events; >+ >+ SnapshotRemovalTracker(); >+ >+ void start(Events, WTF::Function<void()>&&); >+ void reset(); >+ >+ void pause() { m_paused = true; } >+ void resume(); >+ bool isPaused() const { return m_paused; } >+ bool hasRemovalCallback() const { return !!m_removalCallback; } >+ >+ bool eventOccurred(Events); >+ bool cancelOutstandingEvent(Events); >+ bool hasOutstandingEvent(Event); >+ >+ void startWatchdog(Seconds); >+ >+ uint64_t renderTreeSizeThreshold() const { return m_renderTreeSizeThreshold; } >+ void setRenderTreeSizeThreshold(uint64_t threshold) { m_renderTreeSizeThreshold = threshold; } >+ >+ private: >+ static String eventsDescription(Events); >+ void log(const String&) const; >+ >+ void fireRemovalCallbackImmediately(); >+ void fireRemovalCallbackIfPossible(); >+ void watchdogTimerFired(); >+ >+ bool stopWaitingForEvent(Events, const String& logReason); >+ >+ Events m_outstandingEvents { 0 }; >+ WTF::Function<void()> m_removalCallback; >+ MonotonicTime m_startTime; >+ >+ uint64_t m_renderTreeSizeThreshold { 0 }; >+ >+ RunLoop::Timer<SnapshotRemovalTracker> m_watchdogTimer; >+ >+ bool m_paused { true }; >+ }; >+ >+#if PLATFORM(MAC) >+ // Message handlers. >+ void didCollectGeometryForMagnificationGesture(WebCore::FloatRect visibleContentBounds, bool frameHandlesMagnificationGesture); >+ void didCollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin, WebCore::FloatRect renderRect, WebCore::FloatRect visibleContentBounds, bool fitEntireRect, double viewportMinimumScale, double viewportMaximumScale); >+ >+ void endMagnificationGesture(); >+ >+ WebCore::FloatPoint scaledMagnificationOrigin(WebCore::FloatPoint origin, double scale); >+#endif >+ >+#if !PLATFORM(IOS_FAMILY) >+ void trackSwipeGesture(PlatformScrollEvent, SwipeDirection); >+ void beginSwipeGesture(WebBackForwardListItem* targetItem, SwipeDirection); >+ void handleSwipeGesture(WebBackForwardListItem* targetItem, double progress, SwipeDirection); >+ >+ void willEndSwipeGesture(WebBackForwardListItem& targetItem, bool cancelled); >+ void endSwipeGesture(WebBackForwardListItem* targetItem, bool cancelled); >+ bool shouldUseSnapshotForSize(ViewSnapshot&, WebCore::FloatSize swipeLayerSize, float topContentInset); >+ >+#if PLATFORM(MAC) >+ CALayer* determineSnapshotLayerParent() const; >+ CALayer* determineLayerAdjacentToSnapshotForParent(SwipeDirection, CALayer* snapshotLayerParent) const; >+ void applyDebuggingPropertiesToSwipeViews(); >+ void didMoveSwipeSnapshotLayer(); >+ >+ void requestRenderTreeSizeNotificationIfNeeded(); >+#endif >+ >+ void forceRepaintIfNeeded(); >+ >+ class PendingSwipeTracker { >+ public: >+ PendingSwipeTracker(WebPageProxy&, ViewGestureController&); >+ bool handleEvent(PlatformScrollEvent); >+ void eventWasNotHandledByWebCore(PlatformScrollEvent); >+ >+ void reset(const char* resetReasonForLogging); >+ >+ bool shouldIgnorePinnedState() { return m_shouldIgnorePinnedState; } >+ void setShouldIgnorePinnedState(bool ignore) { m_shouldIgnorePinnedState = ignore; } >+ >+ private: >+ bool tryToStartSwipe(PlatformScrollEvent); >+ bool scrollEventCanBecomeSwipe(PlatformScrollEvent, SwipeDirection&); >+ >+ enum class State { >+ None, >+ WaitingForWebCore, >+ InsufficientMagnitude >+ }; >+ >+ State m_state { State::None }; >+ SwipeDirection m_direction; >+ WebCore::FloatSize m_cumulativeDelta; >+ >+ bool m_shouldIgnorePinnedState { false }; >+ >+ ViewGestureController& m_viewGestureController; >+ WebPageProxy& m_webPageProxy; >+ }; >+#endif >+ >+ WebPageProxy& m_webPageProxy; >+ ViewGestureType m_activeGestureType { ViewGestureType::None }; >+ >+ bool m_swipeGestureEnabled { true }; >+ >+ RunLoop::Timer<ViewGestureController> m_swipeActiveLoadMonitoringTimer; >+ >+ WebCore::Color m_backgroundColorForCurrentSnapshot; >+ >+ WeakPtr<WebPageProxy> m_alternateBackForwardListSourcePage; >+ RefPtr<WebPageProxy> m_webPageProxyForBackForwardListForCurrentSwipe; >+ >+ GestureID m_currentGestureID; >+ >+#if !PLATFORM(IOS_FAMILY) >+ RefPtr<ViewSnapshot> m_currentSwipeSnapshot; >+ >+ PendingSwipeTracker m_pendingSwipeTracker; >+ >+ bool m_hasOutstandingRepaintRequest { false }; >+#endif >+ >+#if PLATFORM(MAC) >+ double m_magnification; >+ WebCore::FloatPoint m_magnificationOrigin; >+ >+ WebCore::FloatRect m_lastSmartMagnificationUnscaledTargetRect; >+ bool m_lastMagnificationGestureWasSmartMagnification { false }; >+ WebCore::FloatPoint m_lastSmartMagnificationOrigin; >+ >+ WebCore::FloatRect m_visibleContentRect; >+ bool m_visibleContentRectIsValid { false }; >+ bool m_frameHandlesMagnificationGesture { false }; >+ >+ RetainPtr<WKSwipeCancellationTracker> m_swipeCancellationTracker; >+ RetainPtr<CALayer> m_swipeLayer; >+ RetainPtr<CALayer> m_swipeSnapshotLayer; >+ RetainPtr<CAGradientLayer> m_swipeShadowLayer; >+ RetainPtr<CALayer> m_swipeDimmingLayer; >+ Vector<RetainPtr<CALayer>> m_currentSwipeLiveLayers; >+ >+ Vector<RetainPtr<NSView>> m_customSwipeViews; >+ float m_customSwipeViewsTopContentInset { 0 }; >+ WebCore::FloatRect m_currentSwipeCustomViewBounds; >+ >+ BlockPtr<void (CGRect)> m_didMoveSwipeSnapshotCallback; >+#elif PLATFORM(IOS_FAMILY) >+ UIView* m_liveSwipeView { nullptr }; >+ RetainPtr<UIView> m_liveSwipeViewClippingView; >+ RetainPtr<UIView> m_snapshotView; >+ RetainPtr<UIView> m_transitionContainerView; >+ RetainPtr<WKSwipeTransitionController> m_swipeInteractiveTransitionDelegate; >+ RetainPtr<_UIViewControllerOneToOneTransitionContext> m_swipeTransitionContext; >+ uint64_t m_snapshotRemovalTargetRenderTreeSize { 0 }; >+#endif >+ >+#if PLATFORM(GTK) >+ class SwipeProgressTracker { >+ public: >+ SwipeProgressTracker(WebPageProxy&, ViewGestureController&); >+ void startTracking(RefPtr<WebBackForwardListItem>&&, SwipeDirection); >+ void reset(); >+ bool handleEvent(PlatformScrollEvent); >+ float getProgress(); >+ SwipeDirection getDirection() { return m_direction; } >+ >+ private: >+ enum class State { >+ None, >+ Pending, >+ Scrolling, >+ Animating >+ }; >+ >+ void startAnimation(); >+ gboolean onAnimationTick(GdkFrameClock*); >+ void endAnimation(); >+ >+ State m_state { State::None }; >+ >+ SwipeDirection m_direction; >+ RefPtr<WebBackForwardListItem> m_targetItem; >+ unsigned m_tickCallbackID { 0 }; >+ >+ Seconds m_prevTime; >+ double m_velocity; >+ >+ Seconds m_startTime; >+ Seconds m_endTime; >+ >+ float m_progress { 0 }; >+ float m_startProgress; >+ float m_endProgress; >+ bool m_cancelled; >+ >+ ViewGestureController& m_viewGestureController; >+ WebPageProxy& m_webPageProxy; >+ }; >+ >+ SwipeProgressTracker m_swipeProgressTracker; >+ >+ cairo_pattern_t* m_currentSwipeSnapshotPattern { nullptr }; >+#endif >+ >+ bool m_isConnectedToProcess { false }; >+ >+ SnapshotRemovalTracker m_snapshotRemovalTracker; >+ WTF::Function<void()> m_loadCallback; >+}; >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/ViewGestureController.messages.in b/Source/WebKit/UIProcess/ViewGestureController.messages.in >new file mode 100644 >index 0000000000000000000000000000000000000000..bb1baf361949403416c8819ec275458c23c2fc9c >--- /dev/null >+++ b/Source/WebKit/UIProcess/ViewGestureController.messages.in >@@ -0,0 +1,29 @@ >+# Copyright (C) 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. >+ >+messages -> ViewGestureController { >+#if PLATFORM(MAC) >+ DidCollectGeometryForMagnificationGesture(WebCore::FloatRect visibleContentBounds, bool frameHandlesMagnificationGesture) >+ DidCollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin, WebCore::FloatRect renderRect, WebCore::FloatRect visibleContentBounds, bool fitEntireRect, double viewportMinimumScale, double viewportMaximumScale) >+ DidHitRenderTreeSizeThreshold() >+#endif >+} >diff --git a/Source/WebKit/UIProcess/ViewSnapshotStore.cpp b/Source/WebKit/UIProcess/ViewSnapshotStore.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..cc78fa307823026a1d5a8def4ffb2bfef54d6d7b >--- /dev/null >+++ b/Source/WebKit/UIProcess/ViewSnapshotStore.cpp >@@ -0,0 +1,115 @@ >+/* >+ * Copyright (C) 2014 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. >+ */ >+ >+#include "config.h" >+#include "ViewSnapshotStore.h" >+ >+#include "WebBackForwardList.h" >+#include "WebPageProxy.h" >+#include <wtf/NeverDestroyed.h> >+ >+#if PLATFORM(IOS_FAMILY) >+static const size_t maximumSnapshotCacheSize = 50 * (1024 * 1024); >+#else >+static const size_t maximumSnapshotCacheSize = 400 * (1024 * 1024); >+#endif >+ >+namespace WebKit { >+using namespace WebCore; >+ >+ViewSnapshotStore::ViewSnapshotStore() >+{ >+} >+ >+ViewSnapshotStore::~ViewSnapshotStore() >+{ >+ discardSnapshotImages(); >+} >+ >+ViewSnapshotStore& ViewSnapshotStore::singleton() >+{ >+ static NeverDestroyed<ViewSnapshotStore> store; >+ return store; >+} >+ >+void ViewSnapshotStore::didAddImageToSnapshot(ViewSnapshot& snapshot) >+{ >+ bool isNewEntry = m_snapshotsWithImages.add(&snapshot).isNewEntry; >+ ASSERT_UNUSED(isNewEntry, isNewEntry); >+ m_snapshotCacheSize += snapshot.imageSizeInBytes(); >+} >+ >+void ViewSnapshotStore::willRemoveImageFromSnapshot(ViewSnapshot& snapshot) >+{ >+ bool removed = m_snapshotsWithImages.remove(&snapshot); >+ ASSERT_UNUSED(removed, removed); >+ m_snapshotCacheSize -= snapshot.imageSizeInBytes(); >+} >+ >+void ViewSnapshotStore::pruneSnapshots(WebPageProxy& webPageProxy) >+{ >+ if (m_snapshotCacheSize <= maximumSnapshotCacheSize) >+ return; >+ >+ ASSERT(!m_snapshotsWithImages.isEmpty()); >+ >+ // FIXME: We have enough information to do smarter-than-LRU eviction (making use of the back-forward lists, etc.) >+ >+ m_snapshotsWithImages.first()->clearImage(); >+} >+ >+void ViewSnapshotStore::recordSnapshot(WebPageProxy& webPageProxy, WebBackForwardListItem& item) >+{ >+ if (webPageProxy.isShowingNavigationGestureSnapshot()) >+ return; >+ >+ pruneSnapshots(webPageProxy); >+ >+ webPageProxy.willRecordNavigationSnapshot(item); >+ >+ auto snapshot = webPageProxy.takeViewSnapshot(); >+ if (!snapshot) >+ return; >+ >+ snapshot->setRenderTreeSize(webPageProxy.renderTreeSize()); >+ snapshot->setDeviceScaleFactor(webPageProxy.deviceScaleFactor()); >+ snapshot->setBackgroundColor(webPageProxy.pageExtendedBackgroundColor()); >+ snapshot->setViewScrollPosition(WebCore::roundedIntPoint(webPageProxy.viewScrollPosition())); >+ >+ item.setSnapshot(WTFMove(snapshot)); >+} >+ >+void ViewSnapshotStore::discardSnapshotImages() >+{ >+ while (!m_snapshotsWithImages.isEmpty()) >+ m_snapshotsWithImages.first()->clearImage(); >+} >+ >+ViewSnapshot::~ViewSnapshot() >+{ >+ clearImage(); >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/ViewSnapshotStore.h b/Source/WebKit/UIProcess/ViewSnapshotStore.h >new file mode 100644 >index 0000000000000000000000000000000000000000..0a865adeb0fe40f86bb511e2afda2bbc83722d61 >--- /dev/null >+++ b/Source/WebKit/UIProcess/ViewSnapshotStore.h >@@ -0,0 +1,171 @@ >+/* >+ * Copyright (C) 2014 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. >+ */ >+ >+#pragma once >+ >+#include <WebCore/Color.h> >+#include <WebCore/IntPoint.h> >+#include <WebCore/IntSize.h> >+#if PLATFORM(COCOA) >+#include <WebCore/IOSurface.h> >+#elif PLATFORM(GTK) >+#include <WebCore/RefPtrCairo.h> >+#endif >+#include <wtf/ListHashSet.h> >+#include <wtf/Noncopyable.h> >+#include <wtf/RefCounted.h> >+#include <wtf/text/WTFString.h> >+ >+#if PLATFORM(COCOA) >+#if !defined(__OBJC__) >+typedef struct objc_object *id; >+#endif >+ >+OBJC_CLASS CAContext; >+ >+#if HAVE(IOSURFACE) >+namespace WebCore { >+class IOSurface; >+} >+#endif >+#endif >+ >+namespace WebKit { >+ >+class ViewSnapshotStore; >+class WebBackForwardListItem; >+class WebPageProxy; >+ >+class ViewSnapshot : public RefCounted<ViewSnapshot> { >+public: >+#if PLATFORM(COCOA) >+#if HAVE(IOSURFACE) >+ static Ref<ViewSnapshot> create(std::unique_ptr<WebCore::IOSurface>); >+#else >+ static Ref<ViewSnapshot> create(uint32_t slotID, WebCore::IntSize, size_t imageSizeInBytes); >+#endif >+#else >+ static Ref<ViewSnapshot> create(RefPtr<cairo_surface_t>&&); >+#endif >+ >+ ~ViewSnapshot(); >+ >+ void clearImage(); >+ bool hasImage() const; >+#if PLATFORM(COCOA) >+ id asLayerContents(); >+ RetainPtr<CGImageRef> asImageForTesting(); >+#endif >+ >+ void setRenderTreeSize(uint64_t renderTreeSize) { m_renderTreeSize = renderTreeSize; } >+ uint64_t renderTreeSize() const { return m_renderTreeSize; } >+ >+ void setBackgroundColor(WebCore::Color color) { m_backgroundColor = color; } >+ WebCore::Color backgroundColor() const { return m_backgroundColor; } >+ >+ void setViewScrollPosition(WebCore::IntPoint scrollPosition) { m_viewScrollPosition = scrollPosition; } >+ WebCore::IntPoint viewScrollPosition() const { return m_viewScrollPosition; } >+ >+ void setDeviceScaleFactor(float deviceScaleFactor) { m_deviceScaleFactor = deviceScaleFactor; } >+ float deviceScaleFactor() const { return m_deviceScaleFactor; } >+ >+#if PLATFORM(COCOA) >+#if HAVE(IOSURFACE) >+ WebCore::IOSurface* surface() const { return m_surface.get(); } >+ >+ size_t imageSizeInBytes() const { return m_surface ? m_surface->totalBytes() : 0; } >+ WebCore::IntSize size() const { return m_surface ? m_surface->size() : WebCore::IntSize(); } >+ >+ void setSurface(std::unique_ptr<WebCore::IOSurface>); >+ >+ WebCore::IOSurface::SurfaceState setVolatile(bool); >+#else >+ WebCore::IntSize size() const { return m_size; } >+ size_t imageSizeInBytes() const { return m_imageSizeInBytes; } >+#endif >+#else >+ cairo_surface_t* surface() const { return m_surface.get(); } >+ >+ size_t imageSizeInBytes() const; >+ WebCore::IntSize size() const; >+#endif >+ >+private: >+#if PLATFORM(COCOA) >+#if HAVE(IOSURFACE) >+ explicit ViewSnapshot(std::unique_ptr<WebCore::IOSurface>); >+ >+ std::unique_ptr<WebCore::IOSurface> m_surface; >+#else >+ explicit ViewSnapshot(uint32_t slotID, WebCore::IntSize, size_t imageSizeInBytes); >+ >+ uint32_t m_slotID; >+ size_t m_imageSizeInBytes; >+ WebCore::IntSize m_size; >+#endif >+#else >+ explicit ViewSnapshot(RefPtr<cairo_surface_t>&&); >+ >+ RefPtr<cairo_surface_t> m_surface { nullptr }; >+#endif >+ >+ uint64_t m_renderTreeSize; >+ float m_deviceScaleFactor; >+ WebCore::Color m_backgroundColor; >+ WebCore::IntPoint m_viewScrollPosition; // Scroll position at snapshot time. Integral to make comparison reliable. >+}; >+ >+class ViewSnapshotStore { >+ WTF_MAKE_NONCOPYABLE(ViewSnapshotStore); >+ friend class ViewSnapshot; >+public: >+ ViewSnapshotStore(); >+ ~ViewSnapshotStore(); >+ >+ static ViewSnapshotStore& singleton(); >+ >+ void recordSnapshot(WebPageProxy&, WebBackForwardListItem&); >+ >+ void discardSnapshotImages(); >+ >+ void setDisableSnapshotVolatilityForTesting(bool disable) { m_disableSnapshotVolatility = disable; } >+ bool disableSnapshotVolatilityForTesting() const { return m_disableSnapshotVolatility; } >+ >+#if !HAVE(IOSURFACE) && HAVE(CORE_ANIMATION_RENDER_SERVER) >+ static CAContext *snapshottingContext(); >+#endif >+ >+private: >+ void didAddImageToSnapshot(ViewSnapshot&); >+ void willRemoveImageFromSnapshot(ViewSnapshot&); >+ void pruneSnapshots(WebPageProxy&); >+ >+ size_t m_snapshotCacheSize { 0 }; >+ >+ ListHashSet<ViewSnapshot*> m_snapshotsWithImages; >+ bool m_disableSnapshotVolatility { false }; >+}; >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebBackForwardList.cpp b/Source/WebKit/UIProcess/WebBackForwardList.cpp >index f2d5a162c407213ca829164d94ea265b9dd1c5c8..7564f3c36cac6dee305a8d9625d30d10c690b8ac 100644 >--- a/Source/WebKit/UIProcess/WebBackForwardList.cpp >+++ b/Source/WebKit/UIProcess/WebBackForwardList.cpp >@@ -468,7 +468,7 @@ void WebBackForwardList::didRemoveItem(WebBackForwardListItem& backForwardListIt > m_page->backForwardRemovedItem(backForwardListItem.itemID()); > > backForwardListItem.setSuspendedPage(nullptr); >-#if PLATFORM(COCOA) >+#if PLATFORM(COCOA) || PLATFORM(GTK) > backForwardListItem.setSnapshot(nullptr); > #endif > } >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index 6a15c801beafdc6ad2d8d5fc42cd707c31d2fbf1..370f1011f0d13fe121a0e2e9559105f47fd3b50e 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -189,12 +189,15 @@ > #include "TouchBarMenuItemData.h" > #include "VideoFullscreenManagerProxy.h" > #include "VideoFullscreenManagerProxyMessages.h" >-#include "ViewSnapshotStore.h" > #include <WebCore/RunLoopObserver.h> > #include <WebCore/TextIndicatorWindow.h> > #include <wtf/MachSendRight.h> > #endif > >+#if PLATFORM(COCOA) || PLATFORM(GTK) >+#include "ViewSnapshotStore.h" >+#endif >+ > #if PLATFORM(GTK) > #include "WebSelectionData.h" > #endif >@@ -1348,7 +1351,7 @@ void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item) > if (!m_shouldRecordNavigationSnapshots) > return; > >-#if PLATFORM(COCOA) >+#if PLATFORM(COCOA) || PLATFORM(GTK) > ViewSnapshotStore::singleton().recordSnapshot(*this, item); > #else > UNUSED_PARAM(item); >@@ -7472,7 +7475,7 @@ void WebPageProxy::setEditableElementIsFocused(bool editableElementIsFocused) > > #endif // PLATFORM(MAC) > >-#if PLATFORM(COCOA) >+#if PLATFORM(COCOA) || PLATFORM(GTK) > RefPtr<ViewSnapshot> WebPageProxy::takeViewSnapshot() > { > return pageClient().takeViewSnapshot(); >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index a7f9c5d18cc3f56974b36c261b85f3668ed77248..6d094b2bec3d10086557962e13535ecb1f3a09ea 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -1223,7 +1223,7 @@ public: > void recordNavigationSnapshot(WebBackForwardListItem&); > void requestFocusedElementInformation(Function<void(const FocusedElementInformation&, CallbackBase::Error)>&&); > >-#if PLATFORM(COCOA) >+#if PLATFORM(COCOA) || PLATFORM(GTK) > RefPtr<ViewSnapshot> takeViewSnapshot(); > #endif > >diff --git a/Source/WebKit/UIProcess/gtk/ViewGestureControllerGtk.cpp b/Source/WebKit/UIProcess/gtk/ViewGestureControllerGtk.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..26082f6fdeb939dedd3d382e09106477b77be36e >--- /dev/null >+++ b/Source/WebKit/UIProcess/gtk/ViewGestureControllerGtk.cpp >@@ -0,0 +1,533 @@ >+/* >+ * Copyright (C) 2013, 2014 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. >+ */ >+ >+#include "config.h" >+#include "ViewGestureController.h" >+ >+#include "APINavigation.h" >+#include "DrawingAreaProxy.h" >+#include "WebBackForwardList.h" >+ >+namespace WebKit { >+using namespace WebCore; >+ >+static const Seconds swipeMinAnimationDuration = 100_ms; >+static const Seconds swipeMaxAnimationDuration = 400_ms; >+ >+static const float minimumHorizontalSwipeDistance = 15; >+static const float minimumScrollEventRatioForSwipe = 0.5; >+ >+static const double swipeOverlayShadowOpacity = 0.06; >+static const double swipeOverlayDimmingOpacity = 0.12; >+static const double swipeOverlayShadowWidth = 81; >+static const double swipeOverlayShadowGradientOffsets[] = { 0, 0.03125, 0.0625, 0.0938, 0.125, 0.1875, 0.25, 0.375, 0.4375, 0.5, 0.5625, 0.625, 0.6875, 0.75, 0.875, 1. }; >+static const double swipeOverlayShadowGradientAlpha[] = { 1, 0.99, 0.98, 0.95, 0.92, 0.82, 0.71, 0.46, 0.35, 0.25, 0.17, 0.11, 0.07, 0.04, 0.01, 0. }; >+ >+ViewGestureController::PendingSwipeTracker::PendingSwipeTracker(WebPageProxy& webPageProxy, ViewGestureController& viewGestureController) >+ : m_viewGestureController(viewGestureController) >+ , m_webPageProxy(webPageProxy) >+{ >+} >+ >+void ViewGestureController::platformTeardown() >+{ >+ m_swipeProgressTracker.reset(); >+ >+ if (m_activeGestureType == ViewGestureType::Swipe) >+ removeSwipeSnapshot(); >+} >+ >+static bool scrollEventCanInfluenceSwipe(GdkEventScroll* event) >+{ >+ GdkDevice* device = gdk_event_get_source_device(reinterpret_cast<GdkEvent*>(event)); >+ GdkInputSource source = gdk_device_get_source(device); >+ >+ // FIXME: Should it maybe be allowed on mice/trackpoints as well? The GDK_SCROLL_SMOOTH >+ // requirement already filters out most mice, and it works pretty well on a trackpoint >+ return event->direction == GDK_SCROLL_SMOOTH && source == GDK_SOURCE_TOUCHPAD; >+} >+ >+static bool deltaShouldCancelSwipe(float x, float y) >+{ >+ return std::abs(y) >= std::abs(x) * minimumScrollEventRatioForSwipe; >+} >+ >+bool ViewGestureController::PendingSwipeTracker::scrollEventCanBecomeSwipe(GdkEventScroll *event, ViewGestureController::SwipeDirection& potentialSwipeDirection) >+{ >+ if (!scrollEventCanInfluenceSwipe(event)) >+ return false; >+ >+ if (deltaShouldCancelSwipe(event->delta_x, event->delta_y)) >+ return false; >+ >+ bool isPinnedToLeft = m_shouldIgnorePinnedState || m_webPageProxy.isPinnedToLeftSide(); >+ bool isPinnedToRight = m_shouldIgnorePinnedState || m_webPageProxy.isPinnedToRightSide(); >+ >+ bool tryingToSwipeBack = event->delta_x < 0 && isPinnedToLeft; >+ bool tryingToSwipeForward = event->delta_x > 0 && isPinnedToRight; >+ if (m_webPageProxy.userInterfaceLayoutDirection() != WebCore::UserInterfaceLayoutDirection::LTR) >+ std::swap(tryingToSwipeBack, tryingToSwipeForward); >+ >+ if (!tryingToSwipeBack && !tryingToSwipeForward) >+ return false; >+ >+ potentialSwipeDirection = tryingToSwipeBack ? SwipeDirection::Back : SwipeDirection::Forward; >+ return m_viewGestureController.canSwipeInDirection(potentialSwipeDirection); >+} >+ >+bool ViewGestureController::handleScrollWheelEvent(GdkEventScroll* event) >+{ >+ return m_swipeProgressTracker.handleEvent(event) || m_pendingSwipeTracker.handleEvent(event); >+} >+ >+bool ViewGestureController::PendingSwipeTracker::handleEvent(GdkEventScroll *event) >+{ >+ if ( >+#if GTK_CHECK_VERSION(3, 20, 0) >+ event->is_stop >+#else >+ !event->delta_x && !event->delta_y >+#endif >+ ) { >+ reset("gesture ended"); >+ return false; >+ } >+ >+ if (m_state == State::None) { >+ if (!scrollEventCanBecomeSwipe(event, m_direction)) >+ return false; >+ >+ if (!m_shouldIgnorePinnedState && m_webPageProxy.willHandleHorizontalScrollEvents()) { >+ m_state = State::WaitingForWebCore; >+ LOG(ViewGestures, "Swipe Start Hysteresis - waiting for WebCore to handle event"); >+ } >+ } >+ >+ if (m_state == State::WaitingForWebCore) >+ return false; >+ >+ return tryToStartSwipe(event); >+} >+ >+void ViewGestureController::PendingSwipeTracker::eventWasNotHandledByWebCore(GdkEventScroll* event) >+{ >+ if (m_state != State::WaitingForWebCore) >+ return; >+ >+ LOG(ViewGestures, "Swipe Start Hysteresis - WebCore didn't handle event"); >+ m_state = State::None; >+ m_cumulativeDelta = FloatSize(); >+ tryToStartSwipe(event); >+} >+ >+bool ViewGestureController::PendingSwipeTracker::tryToStartSwipe(GdkEventScroll* event) >+{ >+ ASSERT(m_state != State::WaitingForWebCore); >+ >+ if (m_state == State::None) { >+ SwipeDirection direction; >+ if (!scrollEventCanBecomeSwipe(event, direction)) >+ return false; >+ } >+ >+ if (!scrollEventCanInfluenceSwipe(event)) >+ return false; >+ >+ m_cumulativeDelta += FloatSize(event->delta_x, event->delta_y) * Scrollbar::pixelsPerLineStep(); >+ LOG(ViewGestures, "Swipe Start Hysteresis - consumed event, cumulative delta (%0.2f, %0.2f)", m_cumulativeDelta.width(), m_cumulativeDelta.height()); >+ >+ if (deltaShouldCancelSwipe(m_cumulativeDelta.width(), m_cumulativeDelta.height())) { >+ reset("cumulative delta became too vertical"); >+ return false; >+ } >+ >+ if (std::abs(m_cumulativeDelta.width()) >= minimumHorizontalSwipeDistance) >+ m_viewGestureController.trackSwipeGesture(event, m_direction); >+ else >+ m_state = State::InsufficientMagnitude; >+ >+ return true; >+} >+ >+void ViewGestureController::PendingSwipeTracker::reset(const char* resetReasonForLogging) >+{ >+ if (m_state != State::None) >+ LOG(ViewGestures, "Swipe Start Hysteresis - reset; %s", resetReasonForLogging); >+ >+ m_state = State::None; >+ m_cumulativeDelta = FloatSize(); >+} >+ >+void ViewGestureController::trackSwipeGesture(GdkEventScroll* event, SwipeDirection direction) >+{ >+ ASSERT(m_activeGestureType == ViewGestureType::None); >+ >+ m_pendingSwipeTracker.reset("starting to track swipe"); >+ >+ m_webPageProxy.recordAutomaticNavigationSnapshot(); >+ >+ RefPtr<WebBackForwardListItem> targetItem = (direction == SwipeDirection::Back) ? m_webPageProxy.backForwardList().backItem() : m_webPageProxy.backForwardList().forwardItem(); >+ if (!targetItem) >+ return; >+ >+ m_swipeProgressTracker.startTracking(WTFMove(targetItem), direction); >+ m_swipeProgressTracker.handleEvent(event); >+} >+ >+bool ViewGestureController::isPhysicallySwipingLeft(SwipeDirection direction) const >+{ >+ bool isLTR = m_webPageProxy.userInterfaceLayoutDirection() == WebCore::UserInterfaceLayoutDirection::LTR; >+ bool isSwipingForward = direction == SwipeDirection::Forward; >+ return isLTR != isSwipingForward; >+} >+ >+ViewGestureController::SwipeProgressTracker::SwipeProgressTracker(WebPageProxy& webPageProxy, ViewGestureController& viewGestureController) >+ : m_viewGestureController(viewGestureController) >+ , m_webPageProxy(webPageProxy) >+{ >+} >+ >+void ViewGestureController::SwipeProgressTracker::startTracking(RefPtr<WebBackForwardListItem>&& targetItem, SwipeDirection direction) >+{ >+ if (m_state != State::None) >+ return; >+ >+ m_targetItem = targetItem; >+ m_direction = direction; >+ m_state = State::Pending; >+} >+ >+void ViewGestureController::SwipeProgressTracker::reset() >+{ >+ m_targetItem = nullptr; >+ m_state = State::None; >+ >+ if (m_tickCallbackID) { >+ GtkWidget* widget = m_viewGestureController.m_webPageProxy.viewWidget(); >+ gtk_widget_remove_tick_callback(widget, m_tickCallbackID); >+ m_tickCallbackID = 0; >+ } >+ >+ m_progress = 0; >+ m_startProgress = 0; >+ m_endProgress = 0; >+ >+ m_startTime = 0_ms; >+ m_endTime = 0_ms; >+ m_prevTime = 0_ms; >+ m_velocity = 0; >+ m_cancelled = false; >+} >+ >+bool ViewGestureController::SwipeProgressTracker::handleEvent(GdkEventScroll* event) >+{ >+ if (m_state == State::Pending) { >+ m_viewGestureController.beginSwipeGesture(m_targetItem.get(), m_direction); >+ m_state = State::Scrolling; >+ } >+ >+ // Don't allow scrolling during animation >+ if (m_state == State::Animating) >+ return true; >+ >+ if (m_state != State::Scrolling) >+ return false; >+ >+ if ( >+#if GTK_CHECK_VERSION(3, 20, 0) >+ event->is_stop >+#else >+ !event->delta_x && !event->delta_y >+#endif >+ ) { >+ startAnimation(); >+ return false; >+ } >+ >+ Seconds time = Seconds::fromMilliseconds(event->time); >+ m_velocity = -event->delta_x / (time - m_prevTime).milliseconds(); >+ >+ m_prevTime = time; >+ m_progress -= event->delta_x / Scrollbar::pixelsPerLineStep(); >+ >+ bool swipingLeft = m_viewGestureController.isPhysicallySwipingLeft(m_direction); >+ float maxProgress = swipingLeft ? 1 : 0; >+ float minProgress = !swipingLeft ? -1 : 0; >+ m_progress = std::min(std::max(m_progress, minProgress), maxProgress); >+ >+ m_viewGestureController.handleSwipeGesture(m_targetItem.get(), m_progress, m_direction); >+ >+ return true; >+} >+ >+float ViewGestureController::SwipeProgressTracker::getProgress() >+{ >+ return m_progress; >+} >+ >+void ViewGestureController::SwipeProgressTracker::startAnimation() >+{ >+ bool swipingLeft = m_viewGestureController.isPhysicallySwipingLeft(m_direction); >+ m_cancelled = swipingLeft ? (m_velocity <= 0) : (m_velocity >= 0); >+ >+ m_state = State::Animating; >+ m_viewGestureController.willEndSwipeGesture(*m_targetItem, m_cancelled); >+ >+ m_startProgress = m_progress; >+ if (m_cancelled) >+ m_endProgress = 0; >+ else >+ m_endProgress = swipingLeft ? 1 : -1; >+ >+ Seconds duration = Seconds::fromMilliseconds(std::abs((m_progress - m_endProgress) / m_velocity) * Scrollbar::pixelsPerLineStep()); >+ duration = std::min(std::max(duration, swipeMinAnimationDuration), swipeMaxAnimationDuration); >+ >+ GtkWidget* widget = m_viewGestureController.m_webPageProxy.viewWidget(); >+ m_startTime = Seconds::fromMicroseconds(gdk_frame_clock_get_frame_time(gtk_widget_get_frame_clock(widget))); >+ m_endTime = m_startTime + duration; >+ >+ m_tickCallbackID = gtk_widget_add_tick_callback(widget, [](GtkWidget*, GdkFrameClock* frameClock, gpointer userData) -> gboolean { >+ auto* tracker = static_cast<SwipeProgressTracker*>(userData); >+ return tracker->onAnimationTick(frameClock); >+ }, this, nullptr); >+} >+ >+static inline double easeOutCubic(double t) >+{ >+ double p = t - 1; >+ return p * p * p + 1; >+} >+ >+gboolean ViewGestureController::SwipeProgressTracker::onAnimationTick(GdkFrameClock* frameClock) >+{ >+ ASSERT(m_state == State::Animating); >+ ASSERT(m_endTime > m_startTime); >+ >+ Seconds frameTime = Seconds::fromMicroseconds(gdk_frame_clock_get_frame_time(frameClock)); >+ >+ double animationProgress = (frameTime - m_startTime) / (m_endTime - m_startTime); >+ if (animationProgress > 1) >+ animationProgress = 1; >+ >+ m_progress = m_startProgress + (m_endProgress - m_startProgress) * easeOutCubic(animationProgress); >+ >+ m_viewGestureController.handleSwipeGesture(m_targetItem.get(), m_progress, m_direction); >+ if (frameTime >= m_endTime) { >+ m_tickCallbackID = 0; >+ endAnimation(); >+ return G_SOURCE_REMOVE; >+ } >+ >+ return G_SOURCE_CONTINUE; >+} >+ >+void ViewGestureController::SwipeProgressTracker::endAnimation() >+{ >+ m_viewGestureController.endSwipeGesture(m_targetItem.get(), m_cancelled); >+} >+ >+void ViewGestureController::beginSwipeGesture(WebBackForwardListItem* targetItem, SwipeDirection direction) >+{ >+ ASSERT(targetItem); >+ >+ m_webPageProxy.navigationGestureDidBegin(); >+ >+ willBeginGesture(ViewGestureType::Swipe); >+ >+ ViewSnapshot* snapshot = targetItem->snapshot(); >+ if (snapshot) { >+ m_currentSwipeSnapshot = snapshot; >+ >+ FloatSize viewSize = FloatSize(m_webPageProxy.viewSize()); >+ if (snapshot->hasImage() && shouldUseSnapshotForSize(*snapshot, viewSize, 0)) >+ m_currentSwipeSnapshotPattern = cairo_pattern_create_for_surface(snapshot->surface()); >+ >+ Color color = snapshot->backgroundColor(); >+ if (color.isValid()) { >+ m_backgroundColorForCurrentSnapshot = color; >+ if (!m_currentSwipeSnapshotPattern) >+ m_currentSwipeSnapshotPattern = cairo_pattern_create_rgba(color.red(), color.green(), color.blue(), color.alpha()); >+ } >+ } >+ >+ if (!m_currentSwipeSnapshotPattern) >+ m_currentSwipeSnapshotPattern = cairo_pattern_create_rgb(1, 1, 1); >+} >+ >+void ViewGestureController::handleSwipeGesture(WebBackForwardListItem*, double, SwipeDirection) >+{ >+ gtk_widget_queue_draw(m_webPageProxy.viewWidget()); >+} >+ >+void ViewGestureController::willEndSwipeGesture(WebBackForwardListItem& targetItem, bool cancelled) >+{ >+ m_webPageProxy.navigationGestureWillEnd(!cancelled, targetItem); >+} >+ >+void ViewGestureController::endSwipeGesture(WebBackForwardListItem* targetItem, bool cancelled) >+{ >+ ASSERT(targetItem); >+ >+ if (cancelled) { >+ removeSwipeSnapshot(); >+ m_webPageProxy.navigationGestureDidEnd(false, *targetItem); >+ return; >+ } >+ >+ m_webPageProxy.navigationGestureDidEnd(true, *targetItem); >+ m_webPageProxy.goToBackForwardItem(*targetItem); >+ >+ auto* currentItem = m_webPageProxy.backForwardList().currentItem(); >+ // The main frame will not be navigated so hide the snapshot right away. >+ if (currentItem && currentItem->itemIsClone(*targetItem)) { >+ removeSwipeSnapshot(); >+ return; >+ } >+ >+ SnapshotRemovalTracker::Events desiredEvents = SnapshotRemovalTracker::VisuallyNonEmptyLayout >+ | SnapshotRemovalTracker::MainFrameLoad >+ | SnapshotRemovalTracker::SubresourceLoads >+ | SnapshotRemovalTracker::ScrollPositionRestoration; >+ m_snapshotRemovalTracker.start(desiredEvents, [this] { this->forceRepaintIfNeeded(); }); >+ >+ if (ViewSnapshot* snapshot = targetItem->snapshot()) >+ m_backgroundColorForCurrentSnapshot = snapshot->backgroundColor(); >+} >+ >+void ViewGestureController::forceRepaintIfNeeded() >+{ >+ if (m_activeGestureType != ViewGestureType::Swipe) >+ return; >+ >+ if (m_hasOutstandingRepaintRequest) >+ return; >+ >+ m_hasOutstandingRepaintRequest = true; >+ >+ uint64_t pageID = m_webPageProxy.pageID(); >+ GestureID gestureID = m_currentGestureID; >+ m_webPageProxy.forceRepaint(VoidCallback::create([pageID, gestureID] (CallbackBase::Error error) { >+ if (auto gestureController = controllerForGesture(pageID, gestureID)) >+ gestureController->removeSwipeSnapshot(); >+ })); >+} >+ >+bool ViewGestureController::shouldUseSnapshotForSize(ViewSnapshot& snapshot, FloatSize swipeLayerSize, float topContentInset) >+{ >+ float deviceScaleFactor = m_webPageProxy.deviceScaleFactor(); >+ if (snapshot.deviceScaleFactor() != deviceScaleFactor) >+ return false; >+ >+ FloatSize unobscuredSwipeLayerSizeInDeviceCoordinates = swipeLayerSize - FloatSize(0, topContentInset); >+ unobscuredSwipeLayerSizeInDeviceCoordinates.scale(deviceScaleFactor); >+ if (snapshot.size() != unobscuredSwipeLayerSizeInDeviceCoordinates) >+ return false; >+ >+ return true; >+} >+ >+void ViewGestureController::draw(cairo_t* cr, cairo_pattern_t* pageGroup) >+{ >+ bool swipingLeft = isPhysicallySwipingLeft(m_swipeProgressTracker.getDirection()); >+ float progress = m_swipeProgressTracker.getProgress(); >+ >+ double width = m_webPageProxy.drawingArea()->size().width(); >+ double height = m_webPageProxy.drawingArea()->size().height(); >+ >+ double swipingLayerOffset = (swipingLeft ? 0 : width) + floor(width * progress); >+ >+ double dimmingProgress = swipingLeft ? 1 - progress : -progress; >+ >+ double remainingSwipeDistance = dimmingProgress * width; >+ double shadowFadeDistance = swipeOverlayShadowWidth; >+ >+ double shadowOpacity = swipeOverlayShadowOpacity; >+ if (remainingSwipeDistance < shadowFadeDistance) >+ shadowOpacity = (remainingSwipeDistance / shadowFadeDistance) * swipeOverlayShadowOpacity; >+ >+ RefPtr<cairo_pattern_t> shadowPattern = adoptRef(cairo_pattern_create_linear(0, 0, -swipeOverlayShadowWidth, 0)); >+ for (int i = 0; i < 16; i++) { >+ double offset = swipeOverlayShadowGradientOffsets[i]; >+ double alpha = swipeOverlayShadowGradientAlpha[i] * shadowOpacity; >+ cairo_pattern_add_color_stop_rgba(shadowPattern.get(), offset, 0, 0, 0, alpha); >+ } >+ >+ cairo_save(cr); >+ >+ cairo_rectangle(cr, 0, 0, swipingLayerOffset, height); >+ cairo_set_source(cr, swipingLeft ? m_currentSwipeSnapshotPattern : pageGroup); >+ cairo_fill_preserve(cr); >+ >+ cairo_set_source_rgba(cr, 0, 0, 0, dimmingProgress * swipeOverlayDimmingOpacity); >+ cairo_fill(cr); >+ >+ cairo_translate(cr, swipingLayerOffset, 0); >+ >+ if (progress) { >+ cairo_rectangle(cr, -swipeOverlayShadowWidth, 0, swipeOverlayShadowWidth, height); >+ cairo_set_source(cr, shadowPattern.get()); >+ cairo_fill(cr); >+ } >+ >+ cairo_rectangle(cr, 0, 0, width - swipingLayerOffset, height); >+ cairo_set_source(cr, swipingLeft ? pageGroup : m_currentSwipeSnapshotPattern); >+ cairo_fill(cr); >+ >+ cairo_restore(cr); >+} >+ >+void ViewGestureController::removeSwipeSnapshot() >+{ >+ m_swipeProgressTracker.reset(); >+ m_snapshotRemovalTracker.reset(); >+ >+ m_hasOutstandingRepaintRequest = false; >+ >+ if (m_activeGestureType != ViewGestureType::Swipe) >+ return; >+ >+ cairo_pattern_destroy(m_currentSwipeSnapshotPattern); >+ m_currentSwipeSnapshotPattern = nullptr; >+ >+ m_currentSwipeSnapshot = nullptr; >+ >+ m_webPageProxy.navigationGestureSnapshotWasRemoved(); >+ >+ m_backgroundColorForCurrentSnapshot = Color(); >+ >+ didEndGesture(); >+} >+ >+bool ViewGestureController::beginSimulatedSwipeInDirectionForTesting(SwipeDirection) >+{ >+ return false; >+} >+ >+bool ViewGestureController::completeSimulatedSwipeInDirectionForTesting(SwipeDirection) >+{ >+ return false; >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/gtk/ViewSnapshotStoreGtk.cpp b/Source/WebKit/UIProcess/gtk/ViewSnapshotStoreGtk.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..bcff1a7d46558e09effb67e7d86976653cdff4de >--- /dev/null >+++ b/Source/WebKit/UIProcess/gtk/ViewSnapshotStoreGtk.cpp >@@ -0,0 +1,85 @@ >+/* >+ * Copyright (C) 2014 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. >+ */ >+ >+#include "config.h" >+#include "ViewSnapshotStore.h" >+ >+#include <WebCore/CairoUtilities.h> >+ >+namespace WebKit { >+using namespace WebCore; >+ >+Ref<ViewSnapshot> ViewSnapshot::create(RefPtr<cairo_surface_t>&& surface) >+{ >+ return adoptRef(*new ViewSnapshot(WTFMove(surface))); >+} >+ >+ViewSnapshot::ViewSnapshot(RefPtr<cairo_surface_t>&& surface) >+ : m_surface(WTFMove(surface)) >+{ >+ if (hasImage()) >+ ViewSnapshotStore::singleton().didAddImageToSnapshot(*this); >+} >+ >+bool ViewSnapshot::hasImage() const >+{ >+ return !!m_surface; >+} >+ >+void ViewSnapshot::clearImage() >+{ >+ if (!hasImage()) >+ return; >+ >+ ViewSnapshotStore::singleton().willRemoveImageFromSnapshot(*this); >+ >+ m_surface = nullptr; >+} >+ >+size_t ViewSnapshot::imageSizeInBytes() const >+{ >+ if (!m_surface) >+ return 0; >+ >+ cairo_surface_t* surface = m_surface.get(); >+ int stride = cairo_image_surface_get_stride(surface); >+ int height = cairo_image_surface_get_width(surface); >+ >+ return stride*height; >+} >+ >+WebCore::IntSize ViewSnapshot::size() const >+{ >+ if (!m_surface) >+ return WebCore::IntSize(); >+ >+ cairo_surface_t* surface = m_surface.get(); >+ int width = cairo_image_surface_get_width(surface); >+ int height = cairo_image_surface_get_height(surface); >+ >+ return WebCore::IntSize(width, height); >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/gtk/WebMemoryPressureHandlerGtk.cpp b/Source/WebKit/UIProcess/gtk/WebMemoryPressureHandlerGtk.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..0a69c6f015e920cb314fd2c893a386237fbe66cc >--- /dev/null >+++ b/Source/WebKit/UIProcess/gtk/WebMemoryPressureHandlerGtk.cpp >@@ -0,0 +1,51 @@ >+/* >+ * Copyright (C) 2014 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. >+ */ >+ >+#include "config.h" >+#include "WebMemoryPressureHandlerGtk.h" >+ >+#include "ViewSnapshotStore.h" >+#include "WebProcessPool.h" >+#include <wtf/MemoryPressureHandler.h> >+ >+namespace WebKit { >+ >+void installMemoryPressureHandler() >+{ >+ const char* disableMemoryPressureMonitor = getenv("WEBKIT_DISABLE_MEMORY_PRESSURE_MONITOR"); >+ if (disableMemoryPressureMonitor && !strcmp(disableMemoryPressureMonitor, "1")) >+ return; >+ >+ auto& memoryPressureHandler = MemoryPressureHandler::singleton(); >+ memoryPressureHandler.setLowMemoryHandler([] (Critical critical, Synchronous) { >+ ViewSnapshotStore::singleton().discardSnapshotImages(); >+ >+ for (auto* processPool : WebProcessPool::allProcessPools()) >+ processPool->handleMemoryPressureWarning(critical); >+ }); >+ memoryPressureHandler.install(); >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/gtk/WebMemoryPressureHandlerGtk.h b/Source/WebKit/UIProcess/gtk/WebMemoryPressureHandlerGtk.h >new file mode 100644 >index 0000000000000000000000000000000000000000..6855b0a8eb954871737af5ce4d978974607e9b8e >--- /dev/null >+++ b/Source/WebKit/UIProcess/gtk/WebMemoryPressureHandlerGtk.h >@@ -0,0 +1,32 @@ >+/* >+ * Copyright (C) 2014 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. >+ */ >+ >+#pragma once >+ >+namespace WebKit { >+ >+void installMemoryPressureHandler(); >+ >+} >diff --git a/Source/WebKit/UIProcess/gtk/WebProcessPoolGtk.cpp b/Source/WebKit/UIProcess/gtk/WebProcessPoolGtk.cpp >index 6b2357404e03ae3021ae880b63a8cec0ee86f0f6..9caa98c10e4e1edb3852e7507b3a5245b47f5ca9 100644 >--- a/Source/WebKit/UIProcess/gtk/WebProcessPoolGtk.cpp >+++ b/Source/WebKit/UIProcess/gtk/WebProcessPoolGtk.cpp >@@ -31,6 +31,7 @@ > #include "APIProcessPoolConfiguration.h" > #include "Logging.h" > #include "WebCookieManagerProxy.h" >+#include "WebMemoryPressureHandlerGtk.h" > #include "WebProcessCreationParameters.h" > #include "WebProcessMessages.h" > #include <JavaScriptCore/RemoteInspectorServer.h> >@@ -75,6 +76,8 @@ void WebProcessPool::platformInitialize() > g_unsetenv("WEBKIT_INSPECTOR_SERVER"); > } > #endif >+ >+ installMemoryPressureHandler(); > } > > void WebProcessPool::platformInitializeWebProcess(WebProcessCreationParameters& parameters) >diff --git a/Source/WebKit/UIProcess/mac/ViewSnapshotStore.h b/Source/WebKit/UIProcess/mac/ViewSnapshotStore.h >deleted file mode 100644 >index b06f1f4dbb2976ce98d6f1bf61fd7f16aee1bb2e..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/mac/ViewSnapshotStore.h >+++ /dev/null >@@ -1,149 +0,0 @@ >-/* >- * Copyright (C) 2014 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. >- */ >- >-#ifndef ViewSnapshotStore_h >-#define ViewSnapshotStore_h >- >-#include <WebCore/Color.h> >-#include <WebCore/IntPoint.h> >-#include <WebCore/IntSize.h> >-#include <WebCore/IOSurface.h> >-#include <wtf/ListHashSet.h> >-#include <wtf/Noncopyable.h> >-#include <wtf/RefCounted.h> >-#include <wtf/text/WTFString.h> >- >-#if !defined(__OBJC__) >-typedef struct objc_object *id; >-#endif >- >-OBJC_CLASS CAContext; >- >-#if HAVE(IOSURFACE) >-namespace WebCore { >-class IOSurface; >-} >-#endif >- >-namespace WebKit { >- >-class ViewSnapshotStore; >-class WebBackForwardListItem; >-class WebPageProxy; >- >-class ViewSnapshot : public RefCounted<ViewSnapshot> { >-public: >-#if HAVE(IOSURFACE) >- static Ref<ViewSnapshot> create(std::unique_ptr<WebCore::IOSurface>); >-#else >- static Ref<ViewSnapshot> create(uint32_t slotID, WebCore::IntSize, size_t imageSizeInBytes); >-#endif >- >- ~ViewSnapshot(); >- >- void clearImage(); >- bool hasImage() const; >- id asLayerContents(); >- RetainPtr<CGImageRef> asImageForTesting(); >- >- void setRenderTreeSize(uint64_t renderTreeSize) { m_renderTreeSize = renderTreeSize; } >- uint64_t renderTreeSize() const { return m_renderTreeSize; } >- >- void setBackgroundColor(WebCore::Color color) { m_backgroundColor = color; } >- WebCore::Color backgroundColor() const { return m_backgroundColor; } >- >- void setViewScrollPosition(WebCore::IntPoint scrollPosition) { m_viewScrollPosition = scrollPosition; } >- WebCore::IntPoint viewScrollPosition() const { return m_viewScrollPosition; } >- >- void setDeviceScaleFactor(float deviceScaleFactor) { m_deviceScaleFactor = deviceScaleFactor; } >- float deviceScaleFactor() const { return m_deviceScaleFactor; } >- >-#if HAVE(IOSURFACE) >- WebCore::IOSurface* surface() const { return m_surface.get(); } >- >- size_t imageSizeInBytes() const { return m_surface ? m_surface->totalBytes() : 0; } >- WebCore::IntSize size() const { return m_surface ? m_surface->size() : WebCore::IntSize(); } >- >- void setSurface(std::unique_ptr<WebCore::IOSurface>); >- >- WebCore::IOSurface::SurfaceState setVolatile(bool); >-#else >- WebCore::IntSize size() const { return m_size; } >- size_t imageSizeInBytes() const { return m_imageSizeInBytes; } >-#endif >- >-private: >-#if HAVE(IOSURFACE) >- explicit ViewSnapshot(std::unique_ptr<WebCore::IOSurface>); >- >- std::unique_ptr<WebCore::IOSurface> m_surface; >-#else >- explicit ViewSnapshot(uint32_t slotID, WebCore::IntSize, size_t imageSizeInBytes); >- >- uint32_t m_slotID; >- size_t m_imageSizeInBytes; >- WebCore::IntSize m_size; >-#endif >- >- uint64_t m_renderTreeSize; >- float m_deviceScaleFactor; >- WebCore::Color m_backgroundColor; >- WebCore::IntPoint m_viewScrollPosition; // Scroll position at snapshot time. Integral to make comparison reliable. >-}; >- >-class ViewSnapshotStore { >- WTF_MAKE_NONCOPYABLE(ViewSnapshotStore); >- friend class ViewSnapshot; >-public: >- ViewSnapshotStore(); >- ~ViewSnapshotStore(); >- >- static ViewSnapshotStore& singleton(); >- >- void recordSnapshot(WebPageProxy&, WebBackForwardListItem&); >- >- void discardSnapshotImages(); >- >- void setDisableSnapshotVolatilityForTesting(bool disable) { m_disableSnapshotVolatility = disable; } >- bool disableSnapshotVolatilityForTesting() const { return m_disableSnapshotVolatility; } >- >-#if !HAVE(IOSURFACE) && HAVE(CORE_ANIMATION_RENDER_SERVER) >- static CAContext *snapshottingContext(); >-#endif >- >-private: >- void didAddImageToSnapshot(ViewSnapshot&); >- void willRemoveImageFromSnapshot(ViewSnapshot&); >- void pruneSnapshots(WebPageProxy&); >- >- size_t m_snapshotCacheSize { 0 }; >- >- ListHashSet<ViewSnapshot*> m_snapshotsWithImages; >- bool m_disableSnapshotVolatility { false }; >-}; >- >-} // namespace WebKit >- >-#endif // ViewSnapshotStore_h >diff --git a/Source/WebKit/UIProcess/mac/ViewSnapshotStore.mm b/Source/WebKit/UIProcess/mac/ViewSnapshotStore.mm >deleted file mode 100644 >index 1fef6943e05c43e264c5cb5d2e7d2b7a59ca724c..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/mac/ViewSnapshotStore.mm >+++ /dev/null >@@ -1,249 +0,0 @@ >-/* >- * Copyright (C) 2014 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 "ViewSnapshotStore.h" >- >-#import "WebBackForwardList.h" >-#import "WebPageProxy.h" >-#import <CoreGraphics/CoreGraphics.h> >-#import <WebCore/IOSurface.h> >- >-#if PLATFORM(IOS_FAMILY) >-#import <pal/spi/cocoa/QuartzCoreSPI.h> >-#endif >- >-#if PLATFORM(IOS_FAMILY) >-static const size_t maximumSnapshotCacheSize = 50 * (1024 * 1024); >-#else >-static const size_t maximumSnapshotCacheSize = 400 * (1024 * 1024); >-#endif >- >-namespace WebKit { >-using namespace WebCore; >- >-ViewSnapshotStore::ViewSnapshotStore() >-{ >-} >- >-ViewSnapshotStore::~ViewSnapshotStore() >-{ >- discardSnapshotImages(); >-} >- >-ViewSnapshotStore& ViewSnapshotStore::singleton() >-{ >- static ViewSnapshotStore& store = *new ViewSnapshotStore; >- return store; >-} >- >-#if !HAVE(IOSURFACE) && HAVE(CORE_ANIMATION_RENDER_SERVER) >-CAContext *ViewSnapshotStore::snapshottingContext() >-{ >- static CAContext *context; >- static dispatch_once_t onceToken; >- dispatch_once(&onceToken, ^{ >- NSDictionary *options = @{ >- kCAContextDisplayName: @"WebKitSnapshotting", >- kCAContextIgnoresHitTest: @YES, >- kCAContextDisplayId : @20000 >- }; >- context = [[CAContext remoteContextWithOptions:options] retain]; >- }); >- >- return context; >-} >-#endif >- >-void ViewSnapshotStore::didAddImageToSnapshot(ViewSnapshot& snapshot) >-{ >- bool isNewEntry = m_snapshotsWithImages.add(&snapshot).isNewEntry; >- ASSERT_UNUSED(isNewEntry, isNewEntry); >- m_snapshotCacheSize += snapshot.imageSizeInBytes(); >-} >- >-void ViewSnapshotStore::willRemoveImageFromSnapshot(ViewSnapshot& snapshot) >-{ >- bool removed = m_snapshotsWithImages.remove(&snapshot); >- ASSERT_UNUSED(removed, removed); >- m_snapshotCacheSize -= snapshot.imageSizeInBytes(); >-} >- >-void ViewSnapshotStore::pruneSnapshots(WebPageProxy& webPageProxy) >-{ >- if (m_snapshotCacheSize <= maximumSnapshotCacheSize) >- return; >- >- ASSERT(!m_snapshotsWithImages.isEmpty()); >- >- // FIXME: We have enough information to do smarter-than-LRU eviction (making use of the back-forward lists, etc.) >- >- m_snapshotsWithImages.first()->clearImage(); >-} >- >-void ViewSnapshotStore::recordSnapshot(WebPageProxy& webPageProxy, WebBackForwardListItem& item) >-{ >- if (webPageProxy.isShowingNavigationGestureSnapshot()) >- return; >- >- pruneSnapshots(webPageProxy); >- >- webPageProxy.willRecordNavigationSnapshot(item); >- >- auto snapshot = webPageProxy.takeViewSnapshot(); >- if (!snapshot) >- return; >- >- snapshot->setRenderTreeSize(webPageProxy.renderTreeSize()); >- snapshot->setDeviceScaleFactor(webPageProxy.deviceScaleFactor()); >- snapshot->setBackgroundColor(webPageProxy.pageExtendedBackgroundColor()); >- snapshot->setViewScrollPosition(WebCore::roundedIntPoint(webPageProxy.viewScrollPosition())); >- >- item.setSnapshot(WTFMove(snapshot)); >-} >- >-void ViewSnapshotStore::discardSnapshotImages() >-{ >- while (!m_snapshotsWithImages.isEmpty()) >- m_snapshotsWithImages.first()->clearImage(); >-} >- >-#if HAVE(IOSURFACE) >-Ref<ViewSnapshot> ViewSnapshot::create(std::unique_ptr<WebCore::IOSurface> surface) >-{ >- return adoptRef(*new ViewSnapshot(WTFMove(surface))); >-} >-#else >-Ref<ViewSnapshot> ViewSnapshot::create(uint32_t slotID, IntSize size, size_t imageSizeInBytes) >-{ >- return adoptRef(*new ViewSnapshot(slotID, size, imageSizeInBytes)); >-} >-#endif >- >-#if HAVE(IOSURFACE) >-ViewSnapshot::ViewSnapshot(std::unique_ptr<WebCore::IOSurface> surface) >- : m_surface(WTFMove(surface)) >-#else >-ViewSnapshot::ViewSnapshot(uint32_t slotID, IntSize size, size_t imageSizeInBytes) >- : m_slotID(slotID) >- , m_imageSizeInBytes(imageSizeInBytes) >- , m_size(size) >-#endif >-{ >- if (hasImage()) >- ViewSnapshotStore::singleton().didAddImageToSnapshot(*this); >-} >- >-ViewSnapshot::~ViewSnapshot() >-{ >- clearImage(); >-} >- >-#if HAVE(IOSURFACE) >-void ViewSnapshot::setSurface(std::unique_ptr<WebCore::IOSurface> surface) >-{ >- ASSERT(!m_surface); >- if (!surface) { >- clearImage(); >- return; >- } >- >- m_surface = WTFMove(surface); >- ViewSnapshotStore::singleton().didAddImageToSnapshot(*this); >-} >-#endif >- >-bool ViewSnapshot::hasImage() const >-{ >-#if HAVE(IOSURFACE) >- return !!m_surface; >-#else >- return m_slotID; >-#endif >-} >- >-void ViewSnapshot::clearImage() >-{ >- if (!hasImage()) >- return; >- >- ViewSnapshotStore::singleton().willRemoveImageFromSnapshot(*this); >- >-#if HAVE(IOSURFACE) >- m_surface = nullptr; >-#else >-#if HAVE(CORE_ANIMATION_RENDER_SERVER) >- [ViewSnapshotStore::snapshottingContext() deleteSlot:m_slotID]; >-#endif >- m_slotID = 0; >- m_imageSizeInBytes = 0; >-#endif >-} >- >-#if HAVE(IOSURFACE) >-WebCore::IOSurface::SurfaceState ViewSnapshot::setVolatile(bool becomeVolatile) >-{ >- if (ViewSnapshotStore::singleton().disableSnapshotVolatilityForTesting()) >- return WebCore::IOSurface::SurfaceState::Valid; >- >- if (!m_surface) >- return WebCore::IOSurface::SurfaceState::Empty; >- >- return m_surface->setIsVolatile(becomeVolatile); >-} >-#endif >- >-id ViewSnapshot::asLayerContents() >-{ >-#if HAVE(IOSURFACE) >- if (!m_surface) >- return nullptr; >- >- if (setVolatile(false) != WebCore::IOSurface::SurfaceState::Valid) { >- clearImage(); >- return nullptr; >- } >- >- return m_surface->asLayerContents(); >-#else >- return [CAContext objectForSlot:m_slotID]; >-#endif >-} >- >-RetainPtr<CGImageRef> ViewSnapshot::asImageForTesting() >-{ >-#if HAVE(IOSURFACE) >- if (!m_surface) >- return nullptr; >- >- ASSERT(ViewSnapshotStore::singleton().disableSnapshotVolatilityForTesting()); >- return m_surface->createImage(); >-#else >- // FIXME: Implement this in the slot case. >- return nullptr; >-#endif >-} >- >-} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/mac/ViewSnapshotStoreMac.mm b/Source/WebKit/UIProcess/mac/ViewSnapshotStoreMac.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..35bc7c2eb990e8f41e87cc34d11c31f8b6d93d5e >--- /dev/null >+++ b/Source/WebKit/UIProcess/mac/ViewSnapshotStoreMac.mm >@@ -0,0 +1,168 @@ >+/* >+ * Copyright (C) 2014 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 "ViewSnapshotStore.h" >+ >+#import <CoreGraphics/CoreGraphics.h> >+#import <WebCore/IOSurface.h> >+ >+#if PLATFORM(IOS_FAMILY) >+#import <pal/spi/cocoa/QuartzCoreSPI.h> >+#endif >+ >+namespace WebKit { >+using namespace WebCore; >+ >+#if !HAVE(IOSURFACE) && HAVE(CORE_ANIMATION_RENDER_SERVER) >+CAContext *ViewSnapshotStore::snapshottingContext() >+{ >+ static CAContext *context; >+ static dispatch_once_t onceToken; >+ dispatch_once(&onceToken, ^{ >+ NSDictionary *options = @{ >+ kCAContextDisplayName: @"WebKitSnapshotting", >+ kCAContextIgnoresHitTest: @YES, >+ kCAContextDisplayId : @20000 >+ }; >+ context = [[CAContext remoteContextWithOptions:options] retain]; >+ }); >+ >+ return context; >+} >+#endif >+ >+#if HAVE(IOSURFACE) >+Ref<ViewSnapshot> ViewSnapshot::create(std::unique_ptr<WebCore::IOSurface> surface) >+{ >+ return adoptRef(*new ViewSnapshot(WTFMove(surface))); >+} >+#else >+Ref<ViewSnapshot> ViewSnapshot::create(uint32_t slotID, IntSize size, size_t imageSizeInBytes) >+{ >+ return adoptRef(*new ViewSnapshot(slotID, size, imageSizeInBytes)); >+} >+#endif >+ >+#if HAVE(IOSURFACE) >+ViewSnapshot::ViewSnapshot(std::unique_ptr<WebCore::IOSurface> surface) >+ : m_surface(WTFMove(surface)) >+#else >+ViewSnapshot::ViewSnapshot(uint32_t slotID, IntSize size, size_t imageSizeInBytes) >+ : m_slotID(slotID) >+ , m_imageSizeInBytes(imageSizeInBytes) >+ , m_size(size) >+#endif >+{ >+ if (hasImage()) >+ ViewSnapshotStore::singleton().didAddImageToSnapshot(*this); >+} >+ >+#if HAVE(IOSURFACE) >+void ViewSnapshot::setSurface(std::unique_ptr<WebCore::IOSurface> surface) >+{ >+ ASSERT(!m_surface); >+ if (!surface) { >+ clearImage(); >+ return; >+ } >+ >+ m_surface = WTFMove(surface); >+ ViewSnapshotStore::singleton().didAddImageToSnapshot(*this); >+} >+#endif >+ >+bool ViewSnapshot::hasImage() const >+{ >+#if HAVE(IOSURFACE) >+ return !!m_surface; >+#else >+ return m_slotID; >+#endif >+} >+ >+void ViewSnapshot::clearImage() >+{ >+ if (!hasImage()) >+ return; >+ >+ ViewSnapshotStore::singleton().willRemoveImageFromSnapshot(*this); >+ >+#if HAVE(IOSURFACE) >+ m_surface = nullptr; >+#else >+#if HAVE(CORE_ANIMATION_RENDER_SERVER) >+ [ViewSnapshotStore::snapshottingContext() deleteSlot:m_slotID]; >+#endif >+ m_slotID = 0; >+ m_imageSizeInBytes = 0; >+#endif >+} >+ >+#if HAVE(IOSURFACE) >+WebCore::IOSurface::SurfaceState ViewSnapshot::setVolatile(bool becomeVolatile) >+{ >+ if (ViewSnapshotStore::singleton().disableSnapshotVolatilityForTesting()) >+ return WebCore::IOSurface::SurfaceState::Valid; >+ >+ if (!m_surface) >+ return WebCore::IOSurface::SurfaceState::Empty; >+ >+ return m_surface->setIsVolatile(becomeVolatile); >+} >+#endif >+ >+id ViewSnapshot::asLayerContents() >+{ >+#if HAVE(IOSURFACE) >+ if (!m_surface) >+ return nullptr; >+ >+ if (setVolatile(false) != WebCore::IOSurface::SurfaceState::Valid) { >+ clearImage(); >+ return nullptr; >+ } >+ >+ return m_surface->asLayerContents(); >+#else >+ return [CAContext objectForSlot:m_slotID]; >+#endif >+} >+ >+RetainPtr<CGImageRef> ViewSnapshot::asImageForTesting() >+{ >+#if HAVE(IOSURFACE) >+ if (!m_surface) >+ return nullptr; >+ >+ ASSERT(ViewSnapshotStore::singleton().disableSnapshotVolatilityForTesting()); >+ return m_surface->createImage(); >+#else >+ // FIXME: Implement this in the slot case. >+ return nullptr; >+#endif >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UnifiedSources-input.xcfilelist b/Source/WebKit/UnifiedSources-input.xcfilelist >index 0dc7761202894eccc1d21135ce7d4494668a8210..93dd69fe23a30a0a895b71bfec64fa4dfc63e041 100644 >--- a/Source/WebKit/UnifiedSources-input.xcfilelist >+++ b/Source/WebKit/UnifiedSources-input.xcfilelist >@@ -504,7 +504,6 @@ $(SRCROOT)/UIProcess/Cocoa/UIDelegate.mm > $(SRCROOT)/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp > $(SRCROOT)/UIProcess/Cocoa/VersionChecks.mm > $(SRCROOT)/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm >-$(SRCROOT)/UIProcess/Cocoa/ViewGestureController.cpp > $(SRCROOT)/UIProcess/Cocoa/WKEditCommand.mm > $(SRCROOT)/UIProcess/Cocoa/WKFullKeyboardAccessWatcher.mm > $(SRCROOT)/UIProcess/Cocoa/WKReloadFrameErrorRecoveryAttempter.mm >@@ -578,6 +577,8 @@ $(SRCROOT)/UIProcess/UserMediaPermissionCheckProxy.cpp > $(SRCROOT)/UIProcess/UserMediaPermissionRequestManagerProxy.cpp > $(SRCROOT)/UIProcess/UserMediaPermissionRequestProxy.cpp > $(SRCROOT)/UIProcess/UserMediaProcessManager.cpp >+$(SRCROOT)/UIProcess/ViewGestureController.cpp >+$(SRCROOT)/UIProcess/ViewSnapshotStore.cpp > $(SRCROOT)/UIProcess/VisitedLinkStore.cpp > $(SRCROOT)/UIProcess/WKImagePreviewViewController.mm > $(SRCROOT)/UIProcess/WKInspectorHighlightView.mm >@@ -714,7 +715,7 @@ $(SRCROOT)/UIProcess/mac/ServicesController.mm > $(SRCROOT)/UIProcess/mac/TextCheckerMac.mm > $(SRCROOT)/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm > $(SRCROOT)/UIProcess/mac/ViewGestureControllerMac.mm >-$(SRCROOT)/UIProcess/mac/ViewSnapshotStore.mm >+$(SRCROOT)/UIProcess/mac/ViewSnapshotStoreMac.mm > $(SRCROOT)/UIProcess/mac/WKFullScreenWindowController.mm > $(SRCROOT)/UIProcess/mac/WKImmediateActionController.mm > $(SRCROOT)/UIProcess/mac/WKInspectorViewController.mm >diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >index 851b5e678ce2d5373bbd26caae2f54a44dde2708..8c6e0b9ac688f2f9bf26b99a17917797937c0a88 100644 >--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj >+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >@@ -618,6 +618,7 @@ > 2D6AB541192B1C4A003A9FD1 /* WKPDFPageNumberIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D6AB53F192B1C4A003A9FD1 /* WKPDFPageNumberIndicator.h */; }; > 2D6B371B18A967AD0042AE80 /* _WKThumbnailView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D6B371918A967AD0042AE80 /* _WKThumbnailView.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 2D6BF12421AF56E1001E79C9 /* PencilKitSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D6BF12221AF56E1001E79C9 /* PencilKitSoftLink.h */; }; >+ 2D6CD11B189058A500E5A4A0 /* ViewSnapshotStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D6CD11A189058A500E5A4A0 /* ViewSnapshotStore.cpp */; }; > 2D6CD119189058A500E5A4A0 /* ViewSnapshotStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D6CD117189058A500E5A4A0 /* ViewSnapshotStore.h */; }; > 2D72A1FA212BF46E00517A20 /* RemoteLayerTreeDrawingArea.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AB16ADB1648598400290D62 /* RemoteLayerTreeDrawingArea.mm */; }; > 2D7303791A7C2B7500F8F487 /* WKPageNavigationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D7303781A7C2B7500F8F487 /* WKPageNavigationClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -2466,6 +2467,7 @@ > 2D1087621D2C641B00B85F82 /* LoadParametersCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LoadParametersCocoa.mm; sourceTree = "<group>"; }; > 2D125C5C1857EA05003BA3CB /* ViewGestureController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewGestureController.h; sourceTree = "<group>"; }; > 2D125C5D1857EA05003BA3CB /* ViewGestureControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewGestureControllerMac.mm; sourceTree = "<group>"; }; >+ 2D6CD118189058A500E5A4A0 /* ViewSnapshotStoreMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewSnapshotStoreMac.mm; sourceTree = "<group>"; }; > 2D12DAB420662C73006F00FB /* WKAnimationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKAnimationDelegate.h; sourceTree = "<group>"; }; > 2D1B5D5A18586599006C6596 /* ViewGestureController.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = ViewGestureController.messages.in; sourceTree = "<group>"; }; > 2D1B5D5B185869C8006C6596 /* ViewGestureControllerMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ViewGestureControllerMessageReceiver.cpp; path = DerivedSources/WebKit2/ViewGestureControllerMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; >@@ -2541,7 +2543,7 @@ > 2D6BF12121AF56E1001E79C9 /* PencilKitSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PencilKitSoftLink.mm; path = ios/PencilKitSoftLink.mm; sourceTree = "<group>"; }; > 2D6BF12221AF56E1001E79C9 /* PencilKitSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PencilKitSoftLink.h; path = ios/PencilKitSoftLink.h; sourceTree = "<group>"; }; > 2D6CD117189058A500E5A4A0 /* ViewSnapshotStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewSnapshotStore.h; sourceTree = "<group>"; }; >- 2D6CD118189058A500E5A4A0 /* ViewSnapshotStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewSnapshotStore.mm; sourceTree = "<group>"; }; >+ 2D6CD11A189058A500E5A4A0 /* ViewSnapshotStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewSnapshotStore.cpp; sourceTree = "<group>"; }; > 2D7303781A7C2B7500F8F487 /* WKPageNavigationClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPageNavigationClient.h; sourceTree = "<group>"; }; > 2D790A9C1AD7050D00AB90B3 /* _WKLayoutMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKLayoutMode.h; sourceTree = "<group>"; }; > 2D790A9E1AD7164900AB90B3 /* WKLayoutMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKLayoutMode.h; sourceTree = "<group>"; }; >@@ -5335,9 +5337,6 @@ > 52D5A1AA1C57494E00DE34A3 /* VideoFullscreenManagerProxy.h */, > 52D5A1AB1C57494E00DE34A3 /* VideoFullscreenManagerProxy.messages.in */, > 52D5A1AC1C57494E00DE34A3 /* VideoFullscreenManagerProxy.mm */, >- 2DAF4FFA1B636181006013D6 /* ViewGestureController.cpp */, >- 2D125C5C1857EA05003BA3CB /* ViewGestureController.h */, >- 2D1B5D5A18586599006C6596 /* ViewGestureController.messages.in */, > 2D3EF4411917646300034184 /* WebMemoryPressureHandlerCocoa.h */, > 2D3EF4401917646300034184 /* WebMemoryPressureHandlerCocoa.mm */, > 1AC0273E196622D600C12B75 /* WebPageProxyCocoa.mm */, >@@ -7398,6 +7397,11 @@ > 4A410F3C19AF7B04002EBAB5 /* UserMediaPermissionRequestProxy.h */, > 074E75FC1DF2002400D318EC /* UserMediaProcessManager.cpp */, > 074E75FB1DF1FD1300D318EC /* UserMediaProcessManager.h */, >+ 2DAF4FFA1B636181006013D6 /* ViewGestureController.cpp */, >+ 2D125C5C1857EA05003BA3CB /* ViewGestureController.h */, >+ 2D1B5D5A18586599006C6596 /* ViewGestureController.messages.in */, >+ 2D6CD11A189058A500E5A4A0 /* ViewSnapshotStore.cpp */, >+ 2D6CD117189058A500E5A4A0 /* ViewSnapshotStore.h */, > 2DD5A7281EBF08D5009BA597 /* VisibleWebPageCounter.h */, > 1A0F29E1120B44420053D1B9 /* VisitedLinkStore.cpp */, > 1A0F29E2120B44420053D1B9 /* VisitedLinkStore.h */, >@@ -8196,8 +8200,7 @@ > CD491B111E73482100009066 /* UserMediaCaptureManagerProxy.h */, > CD491B141E7349F300009066 /* UserMediaCaptureManagerProxy.messages.in */, > 2D125C5D1857EA05003BA3CB /* ViewGestureControllerMac.mm */, >- 2D6CD117189058A500E5A4A0 /* ViewSnapshotStore.h */, >- 2D6CD118189058A500E5A4A0 /* ViewSnapshotStore.mm */, >+ 2D6CD118189058A500E5A4A0 /* ViewSnapshotStoreMac.mm */, > 728E86EF1795188C0087879E /* WebColorPickerMac.h */, > 728E86F01795188C0087879E /* WebColorPickerMac.mm */, > 51ACBB9E127A8F2C00D203B9 /* WebContextMenuProxyMac.h */, >@@ -11058,6 +11061,7 @@ > 3F418EFB1887BD97002795FD /* VideoFullscreenManagerProxyMessageReceiver.cpp in Sources */, > 2D1B5D5D185869C8006C6596 /* ViewGestureControllerMessageReceiver.cpp in Sources */, > 2D819BA11862800E001F03D1 /* ViewGestureGeometryCollectorMessageReceiver.cpp in Sources */, >+ 2D6CD11B189058A500E5A4A0 /* ViewShapshotStore.cpp in Sources */, > 2684055218B86ED60022C38B /* ViewUpdateDispatcherMessageReceiver.cpp in Sources */, > 1A60224C18C16B9F00C3E8C9 /* VisitedLinkStoreMessageReceiver.cpp in Sources */, > 1A8E7D3C18C15149005A702A /* VisitedLinkTableControllerMessageReceiver.cpp in Sources */, >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 1c2a54e926a8d87f796d90989a822af00b3b34df..3a4b0755dbdfb1ae14670f673fcba6bfaf7a37ac 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,13 @@ >+2019-02-04 Alexander Mikhaylenko <exalm7659@gmail.com> >+ >+ [GTK] Implement back/forward touchpad gesture >+ https://bugs.webkit.org/show_bug.cgi?id=193919 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp: >+ (testWebKitSettings): Add a test for 'allow-back-forward-navigation-gestures' property. >+ > 2019-02-03 Fujii Hironori <Hironori.Fujii@sony.com> > > [Win] WebKitTestRunners is failing to create the IndexedDB directory. >diff --git a/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp b/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp >index 3edd53ced97d32e9934adaa56bd612943788e49f..5133428b7850623b130b95cc21838242fbfe5b29 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp >+++ b/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp >@@ -348,6 +348,11 @@ static void testWebKitSettings(Test*, gconstpointer) > g_assert_cmpuint(webkit_settings_get_hardware_acceleration_policy(settings), ==, WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS); > webkit_settings_set_hardware_acceleration_policy(settings, WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND); > g_assert_cmpuint(webkit_settings_get_hardware_acceleration_policy(settings), ==, WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND); >+ >+ // Back-forward navigation gesture is disabled by default >+ g_assert_false(webkit_settings_get_allow_back_forward_navigation_gestures(settings)); >+ webkit_settings_set_allow_back_forward_navigation_gestures(settings, TRUE); >+ g_assert_true(webkit_settings_get_allow_back_forward_navigation_gestures(settings)); > #endif > > g_object_unref(G_OBJECT(settings));
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 193919
:
360363
|
360378
|
360724
|
360725
|
360726
|
360728
|
360745
|
360753
|
360755
|
360763
|
360765
|
360770
|
360780
|
360785
|
360789
|
360795
|
360800
|
360846
|
360848
|
360858
|
361024
|
361026
|
361027
|
361050
|
361056
|
361074
|
361084
|
361184
|
361185
|
361187
|
361188
|
361190
|
361287
|
361288
|
361512
|
361519
|
361522
|
361524
|
361527
|
361528