summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/WebProcess/WebPage
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage')
-rw-r--r--Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp144
-rw-r--r--Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h1
-rw-r--r--Source/WebKit2/WebProcess/WebPage/FindController.cpp49
-rw-r--r--Source/WebKit2/WebProcess/WebPage/LayerTreeHost.cpp14
-rw-r--r--Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h20
-rw-r--r--Source/WebKit2/WebProcess/WebPage/PageOverlay.cpp63
-rw-r--r--Source/WebKit2/WebProcess/WebPage/PageOverlay.h25
-rw-r--r--Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp3
-rw-r--r--Source/WebKit2/WebProcess/WebPage/WebFrame.cpp30
-rw-r--r--Source/WebKit2/WebProcess/WebPage/WebFrame.h2
-rw-r--r--Source/WebKit2/WebProcess/WebPage/WebPage.cpp202
-rw-r--r--Source/WebKit2/WebProcess/WebPage/WebPage.h78
-rw-r--r--Source/WebKit2/WebProcess/WebPage/WebPage.messages.in28
-rw-r--r--Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.h1
-rw-r--r--Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp29
-rw-r--r--Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h49
-rw-r--r--Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h64
-rw-r--r--Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm66
-rw-r--r--Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp270
-rw-r--r--Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h84
-rw-r--r--Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp125
-rw-r--r--Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm451
-rw-r--r--Source/WebKit2/WebProcess/WebPage/win/LayerTreeHostWin.cpp44
-rw-r--r--Source/WebKit2/WebProcess/WebPage/win/WebPageWin.cpp94
24 files changed, 1552 insertions, 384 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
index 47acc7a..6272fb5 100644
--- a/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
@@ -42,6 +42,7 @@
#endif
using namespace WebCore;
+using namespace std;
namespace WebKit {
@@ -159,7 +160,8 @@ void DrawingAreaImpl::forceRepaint()
if (m_layerTreeHost) {
m_layerTreeHost->forceRepaint();
- return;
+ if (!m_layerTreeHost->participatesInDisplay())
+ return;
}
m_isWaitingForDidUpdate = false;
@@ -190,6 +192,13 @@ void DrawingAreaImpl::setPageOverlayNeedsDisplay(const IntRect& rect)
setNeedsDisplay(rect);
}
+void DrawingAreaImpl::setLayerHostNeedsDisplay()
+{
+ ASSERT(m_layerTreeHost);
+ ASSERT(m_layerTreeHost->participatesInDisplay());
+ scheduleDisplay();
+}
+
void DrawingAreaImpl::layerHostDidFlushLayers()
{
ASSERT(m_layerTreeHost);
@@ -201,8 +210,12 @@ void DrawingAreaImpl::layerHostDidFlushLayers()
return;
}
- if (!m_layerTreeHost)
+ if (!m_layerTreeHost || m_layerTreeHost->participatesInDisplay()) {
+ // When the layer tree host participates in display, we never tell the UI process about
+ // accelerated compositing. From the UI process's point of view, we're still just sending
+ // it a series of bitmaps in Update messages.
return;
+ }
#if USE(ACCELERATED_COMPOSITING)
m_webPage->send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(m_backingStoreStateID, m_layerTreeHost->layerTreeContext()));
@@ -301,13 +314,13 @@ void DrawingAreaImpl::sendDidUpdateBackingStoreState()
UpdateInfo updateInfo;
- if (!m_isPaintingSuspended && !m_layerTreeHost)
+ if (!m_isPaintingSuspended && (!m_layerTreeHost || m_layerTreeHost->participatesInDisplay()))
display(updateInfo);
#if USE(ACCELERATED_COMPOSITING)
LayerTreeContext layerTreeContext;
- if (m_isPaintingSuspended || m_layerTreeHost) {
+ if (m_isPaintingSuspended || (m_layerTreeHost && !m_layerTreeHost->participatesInDisplay())) {
updateInfo.viewSize = m_webPage->size();
if (m_layerTreeHost) {
@@ -318,6 +331,7 @@ void DrawingAreaImpl::sendDidUpdateBackingStoreState()
// message back to the UI process, but the updated layer tree context
// will be sent back in the DidUpdateBackingStoreState message.
m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(false);
+ m_layerTreeHost->forceRepaint();
}
}
@@ -329,7 +343,7 @@ void DrawingAreaImpl::didUpdate()
{
// We might get didUpdate messages from the UI process even after we've
// entered accelerated compositing mode. Ignore them.
- if (m_layerTreeHost)
+ if (m_layerTreeHost && !m_layerTreeHost->participatesInDisplay())
return;
m_isWaitingForDidUpdate = false;
@@ -342,14 +356,24 @@ void DrawingAreaImpl::suspendPainting()
{
ASSERT(!m_isPaintingSuspended);
+ if (m_layerTreeHost)
+ m_layerTreeHost->pauseRendering();
+
m_isPaintingSuspended = true;
m_displayTimer.stop();
}
void DrawingAreaImpl::resumePainting()
{
- ASSERT(m_isPaintingSuspended);
-
+ if (!m_isPaintingSuspended) {
+ // FIXME: We can get a call to resumePainting when painting is not suspended.
+ // This happens when sending a synchronous message to create a new page. See <rdar://problem/8976531>.
+ return;
+ }
+
+ if (m_layerTreeHost)
+ m_layerTreeHost->resumeRendering();
+
m_isPaintingSuspended = false;
// FIXME: We shouldn't always repaint everything here.
@@ -372,8 +396,11 @@ void DrawingAreaImpl::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLay
m_dirtyRegion = Region();
m_scrollRect = IntRect();
m_scrollOffset = IntSize();
- m_displayTimer.stop();
- m_isWaitingForDidUpdate = false;
+
+ if (!m_layerTreeHost->participatesInDisplay()) {
+ m_displayTimer.stop();
+ m_isWaitingForDidUpdate = false;
+ }
}
void DrawingAreaImpl::exitAcceleratedCompositingMode()
@@ -385,6 +412,8 @@ void DrawingAreaImpl::exitAcceleratedCompositingMode()
ASSERT(m_layerTreeHost);
+ bool wasParticipatingInDisplay = m_layerTreeHost->participatesInDisplay();
+
m_layerTreeHost->invalidate();
m_layerTreeHost = nullptr;
m_dirtyRegion = m_webPage->bounds();
@@ -404,9 +433,16 @@ void DrawingAreaImpl::exitAcceleratedCompositingMode()
display(updateInfo);
#if USE(ACCELERATED_COMPOSITING)
- // Send along a complete update of the page so we can paint the contents right after we exit the
- // accelerated compositing mode, eliminiating flicker.
- m_webPage->send(Messages::DrawingAreaProxy::ExitAcceleratedCompositingMode(m_backingStoreStateID, updateInfo));
+ if (wasParticipatingInDisplay) {
+ // When the layer tree host participates in display, we never tell the UI process about
+ // accelerated compositing. From the UI process's point of view, we're still just sending
+ // it a series of bitmaps in Update messages.
+ m_webPage->send(Messages::DrawingAreaProxy::Update(m_backingStoreStateID, updateInfo));
+ } else {
+ // Send along a complete update of the page so we can paint the contents right after we exit the
+ // accelerated compositing mode, eliminiating flicker.
+ m_webPage->send(Messages::DrawingAreaProxy::ExitAcceleratedCompositingMode(m_backingStoreStateID, updateInfo));
+ }
#endif
}
@@ -420,14 +456,19 @@ void DrawingAreaImpl::exitAcceleratedCompositingModeSoon()
void DrawingAreaImpl::scheduleDisplay()
{
+ ASSERT(!m_layerTreeHost || m_layerTreeHost->participatesInDisplay());
+
if (m_isWaitingForDidUpdate)
return;
if (m_isPaintingSuspended)
return;
- if (m_dirtyRegion.isEmpty())
- return;
+ if (m_layerTreeHost) {
+ if (!m_layerTreeHost->needsDisplay())
+ return;
+ } else if (m_dirtyRegion.isEmpty())
+ return;
if (m_displayTimer.isActive())
return;
@@ -440,7 +481,8 @@ void DrawingAreaImpl::displayTimerFired()
static const double minimumFrameInterval = 1.0 / 60.0;
double timeSinceLastDisplay = currentTime() - m_lastDisplayTime;
- double timeUntilNextDisplay = minimumFrameInterval - timeSinceLastDisplay;
+ double timeUntilLayerTreeHostNeedsDisplay = m_layerTreeHost && m_layerTreeHost->participatesInDisplay() ? m_layerTreeHost->timeUntilNextDisplay() : 0;
+ double timeUntilNextDisplay = max(minimumFrameInterval - timeSinceLastDisplay, timeUntilLayerTreeHostNeedsDisplay);
if (timeUntilNextDisplay > 0) {
m_displayTimer.startOneShot(timeUntilNextDisplay);
@@ -452,14 +494,17 @@ void DrawingAreaImpl::displayTimerFired()
void DrawingAreaImpl::display()
{
- ASSERT(!m_layerTreeHost);
+ ASSERT(!m_layerTreeHost || m_layerTreeHost->participatesInDisplay());
ASSERT(!m_isWaitingForDidUpdate);
ASSERT(!m_inUpdateBackingStoreState);
if (m_isPaintingSuspended)
return;
- if (m_dirtyRegion.isEmpty())
+ if (m_layerTreeHost) {
+ if (!m_layerTreeHost->needsDisplay())
+ return;
+ } else if (m_dirtyRegion.isEmpty())
return;
if (m_shouldSendDidUpdateBackingStoreState) {
@@ -470,7 +515,7 @@ void DrawingAreaImpl::display()
UpdateInfo updateInfo;
display(updateInfo);
- if (m_layerTreeHost) {
+ if (m_layerTreeHost && !m_layerTreeHost->participatesInDisplay()) {
// The call to update caused layout which turned on accelerated compositing.
// Don't send an Update message in this case.
return;
@@ -504,7 +549,7 @@ static bool shouldPaintBoundsRect(const IntRect& bounds, const Vector<IntRect>&
void DrawingAreaImpl::display(UpdateInfo& updateInfo)
{
ASSERT(!m_isPaintingSuspended);
- ASSERT(!m_layerTreeHost);
+ ASSERT(!m_layerTreeHost || m_layerTreeHost->participatesInDisplay());
ASSERT(!m_webPage->size().isEmpty());
// FIXME: It would be better if we could avoid painting altogether when there is a custom representation.
@@ -516,44 +561,49 @@ void DrawingAreaImpl::display(UpdateInfo& updateInfo)
m_webPage->layoutIfNeeded();
- // The layout may have put the page into accelerated compositing mode, in which case the
- // LayerTreeHost is now in charge of displaying.
- if (m_layerTreeHost)
+ // The layout may have put the page into accelerated compositing mode. If the LayerTreeHost is
+ // in charge of displaying, we have nothing more to do.
+ if (m_layerTreeHost && !m_layerTreeHost->participatesInDisplay())
return;
- IntRect bounds = m_dirtyRegion.bounds();
- ASSERT(m_webPage->bounds().contains(bounds));
+ updateInfo.viewSize = m_webPage->size();
+
+ if (m_layerTreeHost)
+ m_layerTreeHost->display(updateInfo);
+ else {
+ IntRect bounds = m_dirtyRegion.bounds();
+ ASSERT(m_webPage->bounds().contains(bounds));
- RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(bounds.size(), ShareableBitmap::SupportsAlpha);
- if (!bitmap->createHandle(updateInfo.bitmapHandle))
- return;
+ RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(bounds.size(), ShareableBitmap::SupportsAlpha);
+ if (!bitmap->createHandle(updateInfo.bitmapHandle))
+ return;
- Vector<IntRect> rects = m_dirtyRegion.rects();
+ Vector<IntRect> rects = m_dirtyRegion.rects();
- if (shouldPaintBoundsRect(bounds, rects)) {
- rects.clear();
- rects.append(bounds);
- }
+ if (shouldPaintBoundsRect(bounds, rects)) {
+ rects.clear();
+ rects.append(bounds);
+ }
- updateInfo.scrollRect = m_scrollRect;
- updateInfo.scrollOffset = m_scrollOffset;
+ updateInfo.scrollRect = m_scrollRect;
+ updateInfo.scrollOffset = m_scrollOffset;
- m_dirtyRegion = Region();
- m_scrollRect = IntRect();
- m_scrollOffset = IntSize();
+ m_dirtyRegion = Region();
+ m_scrollRect = IntRect();
+ m_scrollOffset = IntSize();
- OwnPtr<GraphicsContext> graphicsContext = bitmap->createGraphicsContext();
-
- updateInfo.viewSize = m_webPage->size();
- updateInfo.updateRectBounds = bounds;
+ OwnPtr<GraphicsContext> graphicsContext = bitmap->createGraphicsContext();
+
+ updateInfo.updateRectBounds = bounds;
- graphicsContext->translate(-bounds.x(), -bounds.y());
+ graphicsContext->translate(-bounds.x(), -bounds.y());
- for (size_t i = 0; i < rects.size(); ++i) {
- m_webPage->drawRect(*graphicsContext, rects[i]);
- if (m_webPage->hasPageOverlay())
- m_webPage->drawPageOverlay(*graphicsContext, rects[i]);
- updateInfo.updateRects.append(rects[i]);
+ for (size_t i = 0; i < rects.size(); ++i) {
+ m_webPage->drawRect(*graphicsContext, rects[i]);
+ if (m_webPage->hasPageOverlay())
+ m_webPage->drawPageOverlay(*graphicsContext, rects[i]);
+ updateInfo.updateRects.append(rects[i]);
+ }
}
// Layout can trigger more calls to setNeedsDisplay and we don't want to process them
diff --git a/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h
index 9e93869..471ba56 100644
--- a/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h
+++ b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h
@@ -40,6 +40,7 @@ public:
static PassOwnPtr<DrawingAreaImpl> create(WebPage*, const WebPageCreationParameters&);
virtual ~DrawingAreaImpl();
+ void setLayerHostNeedsDisplay();
void layerHostDidFlushLayers();
private:
diff --git a/Source/WebKit2/WebProcess/WebPage/FindController.cpp b/Source/WebKit2/WebProcess/WebPage/FindController.cpp
index 3e7b268..49f5786 100644
--- a/Source/WebKit2/WebProcess/WebPage/FindController.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/FindController.cpp
@@ -38,6 +38,7 @@
#include <WebCore/GraphicsContext.h>
#include <WebCore/Page.h>
+using namespace std;
using namespace WebCore;
namespace WebKit {
@@ -64,9 +65,16 @@ FindController::~FindController()
void FindController::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
{
- unsigned matchCount = m_webPage->corePage()->markAllMatchesForText(string, core(options), false, maxMatchCount);
+ if (maxMatchCount == numeric_limits<unsigned>::max())
+ --maxMatchCount;
+
+ unsigned matchCount = m_webPage->corePage()->markAllMatchesForText(string, core(options), false, maxMatchCount + 1);
m_webPage->corePage()->unmarkAllTextMatches();
+ // Check if we have more matches than allowed.
+ if (matchCount > maxMatchCount)
+ matchCount = static_cast<unsigned>(kWKMoreThanMaximumMatchCount);
+
m_webPage->send(Messages::WebPageProxy::DidCountStringMatches(string, matchCount));
}
@@ -102,6 +110,9 @@ void FindController::findString(const String& string, FindOptions options, unsig
shouldShowOverlay = options & FindOptionsShowOverlay;
if (shouldShowOverlay) {
+ if (maxMatchCount == numeric_limits<unsigned>::max())
+ --maxMatchCount;
+
unsigned matchCount = m_webPage->corePage()->markAllMatchesForText(string, core(options), false, maxMatchCount + 1);
// Check if we have more matches than allowed.
@@ -122,7 +133,7 @@ void FindController::findString(const String& string, FindOptions options, unsig
if (!shouldShowOverlay) {
if (m_findPageOverlay) {
// Get rid of the overlay.
- m_webPage->uninstallPageOverlay(m_findPageOverlay);
+ m_webPage->uninstallPageOverlay(m_findPageOverlay, false);
}
ASSERT(!m_findPageOverlay);
@@ -142,7 +153,7 @@ void FindController::findString(const String& string, FindOptions options, unsig
void FindController::hideFindUI()
{
if (m_findPageOverlay)
- m_webPage->uninstallPageOverlay(m_findPageOverlay);
+ m_webPage->uninstallPageOverlay(m_findPageOverlay, true);
hideFindIndicator();
}
@@ -259,27 +270,39 @@ static const float shadowOffsetY = 1.0;
static const float shadowBlurRadius = 2.0;
static const float whiteFrameThickness = 1.0;
-static const int overlayBackgroundRed = 25;
-static const int overlayBackgroundGreen = 25;
-static const int overlayBackgroundBlue = 25;
-static const int overlayBackgroundAlpha = 63;
+static const float overlayBackgroundRed = 0.1;
+static const float overlayBackgroundGreen = 0.1;
+static const float overlayBackgroundBlue = 0.1;
+static const float overlayBackgroundAlpha = 0.25;
+
+static Color overlayBackgroundColor(float fractionFadedIn)
+{
+ return Color(overlayBackgroundRed, overlayBackgroundGreen, overlayBackgroundBlue, overlayBackgroundAlpha * fractionFadedIn);
+}
-static Color overlayBackgroundColor()
+static Color holeShadowColor(float fractionFadedIn)
{
- return Color(overlayBackgroundRed, overlayBackgroundGreen, overlayBackgroundBlue, overlayBackgroundAlpha);
+ return Color(0.0f, 0.0f, 0.0f, fractionFadedIn);
}
-void FindController::drawRect(PageOverlay*, GraphicsContext& graphicsContext, const IntRect& dirtyRect)
+static Color holeFillColor(float fractionFadedIn)
{
+ return Color(1.0f, 1.0f, 1.0f, fractionFadedIn);
+}
+
+void FindController::drawRect(PageOverlay* pageOverlay, GraphicsContext& graphicsContext, const IntRect& dirtyRect)
+{
+ float fractionFadedIn = pageOverlay->fractionFadedIn();
+
Vector<IntRect> rects = rectsForTextMatches();
// Draw the background.
- graphicsContext.fillRect(dirtyRect, overlayBackgroundColor(), ColorSpaceSRGB);
+ graphicsContext.fillRect(dirtyRect, overlayBackgroundColor(fractionFadedIn), ColorSpaceSRGB);
graphicsContext.save();
- graphicsContext.setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowBlurRadius, Color::black, ColorSpaceSRGB);
+ graphicsContext.setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowBlurRadius, holeShadowColor(fractionFadedIn), ColorSpaceSRGB);
- graphicsContext.setFillColor(Color::white, ColorSpaceSRGB);
+ graphicsContext.setFillColor(holeFillColor(fractionFadedIn), ColorSpaceSRGB);
// Draw white frames around the holes.
for (size_t i = 0; i < rects.size(); ++i) {
diff --git a/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.cpp b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.cpp
index 737e195..24cbcc6 100644
--- a/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.cpp
@@ -26,8 +26,12 @@
#include "config.h"
#include "LayerTreeHost.h"
+#if USE(CA)
#if PLATFORM(MAC)
-#include "LayerTreeHostCA.h"
+#include "LayerTreeHostCAMac.h"
+#elif PLATFORM(WIN)
+#include "LayerTreeHostCAWin.h"
+#endif
#endif
#if !PLATFORM(MAC) && !PLATFORM(WIN)
@@ -41,10 +45,12 @@ namespace WebKit {
PassRefPtr<LayerTreeHost> LayerTreeHost::create(WebPage* webPage)
{
#if PLATFORM(MAC)
- return LayerTreeHostCA::create(webPage);
-#endif
-
+ return LayerTreeHostCAMac::create(webPage);
+#elif PLATFORM(WIN) && HAVE(WKQCA)
+ return LayerTreeHostCAWin::create(webPage);
+#else
return 0;
+#endif
}
LayerTreeHost::LayerTreeHost(WebPage* webPage)
diff --git a/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h
index bbb94e8..004bdb7 100644
--- a/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h
+++ b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h
@@ -38,6 +38,7 @@ namespace WebCore {
namespace WebKit {
class LayerTreeContext;
+class UpdateInfo;
class WebPage;
class LayerTreeHost : public RefCounted<LayerTreeHost> {
@@ -45,6 +46,8 @@ public:
static PassRefPtr<LayerTreeHost> create(WebPage*);
virtual ~LayerTreeHost();
+ static bool supportsAcceleratedCompositing();
+
virtual const LayerTreeContext& layerTreeContext() = 0;
virtual void scheduleLayerFlush() = 0;
virtual void setShouldNotifyAfterNextScheduledLayerFlush(bool) = 0;
@@ -60,12 +63,29 @@ public:
virtual void didUninstallPageOverlay() = 0;
virtual void setPageOverlayNeedsDisplay(const WebCore::IntRect&) = 0;
+ virtual void pauseRendering() { }
+ virtual void resumeRendering() { }
+
+ // If a derived class overrides this function to return true, the derived class must also
+ // override the functions beneath it.
+ virtual bool participatesInDisplay() { return false; }
+ virtual bool needsDisplay() { ASSERT_NOT_REACHED(); return false; }
+ virtual double timeUntilNextDisplay() { ASSERT_NOT_REACHED(); return 0; }
+ virtual void display(UpdateInfo&) { ASSERT_NOT_REACHED(); }
+
protected:
explicit LayerTreeHost(WebPage*);
WebPage* m_webPage;
};
+#if !PLATFORM(WIN)
+inline bool LayerTreeHost::supportsAcceleratedCompositing()
+{
+ return true;
+}
+#endif
+
} // namespace WebKit
#endif // LayerTreeHost_h
diff --git a/Source/WebKit2/WebProcess/WebPage/PageOverlay.cpp b/Source/WebKit2/WebProcess/WebPage/PageOverlay.cpp
index 67c1165..d4b1b41 100644
--- a/Source/WebKit2/WebProcess/WebPage/PageOverlay.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/PageOverlay.cpp
@@ -27,6 +27,7 @@
#include "PageOverlay.h"
#include "WebPage.h"
+#include "WebProcess.h"
#include <WebCore/Frame.h>
#include <WebCore/FrameView.h>
#include <WebCore/GraphicsContext.h>
@@ -37,6 +38,9 @@ using namespace WebCore;
namespace WebKit {
+static const double fadeAnimationDuration = 0.2;
+static const double fadeAnimationFrameRate = 30;
+
PassRefPtr<PageOverlay> PageOverlay::create(Client* client)
{
return adoptRef(new PageOverlay(client));
@@ -45,6 +49,11 @@ PassRefPtr<PageOverlay> PageOverlay::create(Client* client)
PageOverlay::PageOverlay(Client* client)
: m_client(client)
, m_webPage(0)
+ , m_fadeAnimationTimer(WebProcess::shared().runLoop(), this, &PageOverlay::fadeAnimationTimerFired)
+ , m_fadeAnimationStartTime(0.0)
+ , m_fadeAnimationDuration(fadeAnimationDuration)
+ , m_fadeAnimationType(NoAnimation)
+ , m_fractionFadedIn(1.0)
{
}
@@ -54,7 +63,7 @@ PageOverlay::~PageOverlay()
IntRect PageOverlay::bounds() const
{
- FrameView* frameView = webPage()->corePage()->mainFrame()->view();
+ FrameView* frameView = m_webPage->corePage()->mainFrame()->view();
int width = frameView->width();
int height = frameView->height();
@@ -73,6 +82,8 @@ void PageOverlay::setPage(WebPage* webPage)
m_client->willMoveToWebPage(this, webPage);
m_webPage = webPage;
m_client->didMoveToWebPage(this, webPage);
+
+ m_fadeAnimationTimer.stop();
}
void PageOverlay::setNeedsDisplay(const IntRect& dirtyRect)
@@ -112,4 +123,54 @@ bool PageOverlay::mouseEvent(const WebMouseEvent& mouseEvent)
return m_client->mouseEvent(this, mouseEvent);
}
+void PageOverlay::startFadeInAnimation()
+{
+ m_fractionFadedIn = 0.0;
+ m_fadeAnimationType = FadeInAnimation;
+
+ startFadeAnimation();
+}
+
+void PageOverlay::startFadeOutAnimation()
+{
+ m_fractionFadedIn = 1.0;
+ m_fadeAnimationType = FadeOutAnimation;
+
+ startFadeAnimation();
+}
+
+void PageOverlay::startFadeAnimation()
+{
+ m_fadeAnimationStartTime = currentTime();
+
+ // Start the timer
+ m_fadeAnimationTimer.startRepeating(1 / fadeAnimationFrameRate);
+}
+
+void PageOverlay::fadeAnimationTimerFired()
+{
+ float animationProgress = (currentTime() - m_fadeAnimationStartTime) / m_fadeAnimationDuration;
+
+ if (animationProgress >= 1.0)
+ animationProgress = 1.0;
+
+ double sine = sin(piOverTwoFloat * animationProgress);
+ float fadeAnimationValue = sine * sine;
+
+ m_fractionFadedIn = (m_fadeAnimationType == FadeInAnimation) ? fadeAnimationValue : 1 - fadeAnimationValue;
+ setNeedsDisplay();
+
+ if (animationProgress == 1.0) {
+ m_fadeAnimationTimer.stop();
+
+ bool wasFadingOut = m_fadeAnimationType == FadeOutAnimation;
+ m_fadeAnimationType = NoAnimation;
+
+ if (wasFadingOut) {
+ // If this was a fade out, go ahead and uninstall the page overlay.
+ m_webPage->uninstallPageOverlay(this, false);
+ }
+ }
+}
+
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/PageOverlay.h b/Source/WebKit2/WebProcess/WebPage/PageOverlay.h
index 6f1f70f..1f61ceb 100644
--- a/Source/WebKit2/WebProcess/WebPage/PageOverlay.h
+++ b/Source/WebKit2/WebProcess/WebPage/PageOverlay.h
@@ -27,6 +27,7 @@
#define PageOverlay_h
#include "APIObject.h"
+#include "RunLoop.h"
#include <wtf/PassRefPtr.h>
namespace WebCore {
@@ -65,20 +66,38 @@ public:
void drawRect(WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect);
bool mouseEvent(const WebMouseEvent&);
+ void startFadeInAnimation();
+ void startFadeOutAnimation();
+
+ float fractionFadedIn() const { return m_fractionFadedIn; }
+
protected:
explicit PageOverlay(Client*);
- WebPage* webPage() const { return m_webPage; }
-
private:
// APIObject
virtual Type type() const { return APIType; }
WebCore::IntRect bounds() const;
- Client* m_client;
+ void startFadeAnimation();
+ void fadeAnimationTimerFired();
+ Client* m_client;
WebPage* m_webPage;
+
+ RunLoop::Timer<PageOverlay> m_fadeAnimationTimer;
+ double m_fadeAnimationStartTime;
+ double m_fadeAnimationDuration;
+
+ enum FadeAnimationType {
+ NoAnimation,
+ FadeInAnimation,
+ FadeOutAnimation,
+ };
+
+ FadeAnimationType m_fadeAnimationType;
+ float m_fractionFadedIn;
};
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp b/Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp
index 35058de..cbed180 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp
@@ -82,7 +82,8 @@ void WebContextMenu::show()
contextMenuState.absoluteImageURLString = controller->hitTestResult().absoluteImageURL().string();
contextMenuState.absoluteLinkURLString = controller->hitTestResult().absoluteLinkURL().string();
- // Notify the UIProcess.
+ // Mark the WebPage has having a shown context menu then notify the UIProcess.
+ m_page->contextMenuShowing();
m_page->send(Messages::WebPageProxy::ShowContextMenu(view->contentsToWindow(controller->hitTestResult().point()), contextMenuState, proposedMenu, InjectedBundleUserMessageEncoder(userData.get())));
}
diff --git a/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp b/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp
index 574634f..0d550c9 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp
@@ -512,6 +512,30 @@ IntSize WebFrame::scrollOffset() const
return view->scrollOffset();
}
+bool WebFrame::hasHorizontalScrollbar() const
+{
+ if (!m_coreFrame)
+ return false;
+
+ FrameView* view = m_coreFrame->view();
+ if (!view)
+ return false;
+
+ return view->horizontalScrollbar();
+}
+
+bool WebFrame::hasVerticalScrollbar() const
+{
+ if (!m_coreFrame)
+ return false;
+
+ FrameView* view = m_coreFrame->view();
+ if (!view)
+ return false;
+
+ return view->verticalScrollbar();
+}
+
bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha)
{
if (!m_coreFrame)
@@ -550,6 +574,9 @@ WebFrame* WebFrame::frameForContext(JSContextRef context)
JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world)
{
+ if (!m_coreFrame)
+ return 0;
+
JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld());
ExecState* exec = globalObject->globalExec();
@@ -559,6 +586,9 @@ JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, Inj
JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, InjectedBundleScriptWorld* world)
{
+ if (!m_coreFrame)
+ return 0;
+
JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld());
ExecState* exec = globalObject->globalExec();
diff --git a/Source/WebKit2/WebProcess/WebPage/WebFrame.h b/Source/WebKit2/WebProcess/WebPage/WebFrame.h
index 3c63cf3..b6e1e13 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebFrame.h
+++ b/Source/WebKit2/WebProcess/WebPage/WebFrame.h
@@ -93,6 +93,8 @@ public:
WebCore::IntRect visibleContentBounds() const;
WebCore::IntRect visibleContentBoundsExcludingScrollbars() const;
WebCore::IntSize scrollOffset() const;
+ bool hasHorizontalScrollbar() const;
+ bool hasVerticalScrollbar() const;
bool getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha);
static WebFrame* frameForContext(JSContextRef);
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
index d5f3724..7707965 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
@@ -32,6 +32,7 @@
#include "DrawingArea.h"
#include "InjectedBundle.h"
#include "InjectedBundleBackForwardList.h"
+#include "LayerTreeHost.h"
#include "MessageID.h"
#include "NetscapePlugin.h"
#include "PageOverlay.h"
@@ -66,8 +67,8 @@
#include "WebPopupMenu.h"
#include "WebPreferencesStore.h"
#include "WebProcess.h"
-#include "WebProcessProxyMessageKinds.h"
#include "WebProcessProxyMessages.h"
+#include <JavaScriptCore/APICast.h>
#include <WebCore/AbstractDatabase.h>
#include <WebCore/ArchiveResource.h>
#include <WebCore/Chrome.h>
@@ -77,18 +78,23 @@
#include <WebCore/DocumentMarkerController.h>
#include <WebCore/DragController.h>
#include <WebCore/DragData.h>
+#include <WebCore/EditingBehavior.h>
#include <WebCore/EventHandler.h>
#include <WebCore/FocusController.h>
+#include <WebCore/FormState.h>
#include <WebCore/Frame.h>
+#include <WebCore/FrameLoadRequest.h>
#include <WebCore/FrameLoaderTypes.h>
#include <WebCore/FrameView.h>
+#include <WebCore/HTMLFormElement.h>
#include <WebCore/HistoryItem.h>
#include <WebCore/KeyboardEvent.h>
+#include <WebCore/MouseEvent.h>
#include <WebCore/Page.h>
#include <WebCore/PlatformKeyboardEvent.h>
#include <WebCore/PrintContext.h>
-#include <WebCore/RenderTreeAsText.h>
#include <WebCore/RenderLayer.h>
+#include <WebCore/RenderTreeAsText.h>
#include <WebCore/RenderView.h>
#include <WebCore/ReplaceSelectionCommand.h>
#include <WebCore/ResourceRequest.h>
@@ -110,9 +116,10 @@
#endif
#if ENABLE(PLUGIN_PROCESS)
-// FIXME: This is currently Mac-specific!
+#if PLATFORM(MAC)
#include "MachPort.h"
#endif
+#endif
#if PLATFORM(QT)
#include "HitTestResult.h"
@@ -151,6 +158,7 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
#if PLATFORM(MAC)
, m_windowIsVisible(false)
, m_isSmartInsertDeleteEnabled(parameters.isSmartInsertDeleteEnabled)
+ , m_keyboardEventBeingInterpreted(0)
#elif PLATFORM(WIN)
, m_nativeWindow(parameters.nativeWindow)
#endif
@@ -163,6 +171,10 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
, m_userSpaceScaleFactor(parameters.userSpaceScaleFactor)
, m_cachedMainFrameIsPinnedToLeftSide(false)
, m_cachedMainFrameIsPinnedToRightSide(false)
+ , m_isShowingContextMenu(false)
+#if PLATFORM(WIN)
+ , m_gestureReachedScrollingLimit(false)
+#endif
{
ASSERT(m_pageID);
@@ -282,6 +294,13 @@ void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
m_uiClient.initialize(client);
}
+#if ENABLE(FULLSCREEN_API)
+void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient* client)
+{
+ m_fullScreenClient.initialize(client);
+}
+#endif
+
PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
{
String pluginPath;
@@ -302,6 +321,22 @@ PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
#endif
}
+EditorState WebPage::editorState() const
+{
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+ ASSERT(frame);
+
+ EditorState result;
+ result.selectionIsNone = frame->selection()->isNone();
+ result.selectionIsRange = frame->selection()->isRange();
+ result.isContentEditable = frame->selection()->isContentEditable();
+ result.isContentRichlyEditable = frame->selection()->isContentRichlyEditable();
+ result.isInPasswordField = frame->selection()->isInPasswordField();
+ result.hasComposition = frame->editor()->hasComposition();
+
+ return result;
+}
+
String WebPage::renderTreeExternalRepresentation() const
{
return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
@@ -440,6 +475,20 @@ void WebPage::loadPlainTextString(const String& string)
loadData(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL());
}
+void WebPage::linkClicked(const String& url, const WebMouseEvent& event)
+{
+ Frame* frame = m_page->mainFrame();
+ if (!frame)
+ return;
+
+ RefPtr<Event> coreEvent;
+ if (event.type() != WebEvent::NoType)
+ coreEvent = MouseEvent::create(eventNames().clickEvent, frame->document()->defaultView(), platform(event), 0, 0);
+
+ frame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(url)),
+ false, false, coreEvent.get(), 0, SendReferrer);
+}
+
void WebPage::stopLoadingFrame(uint64_t frameID)
{
WebFrame* frame = WebProcess::shared().webFrame(frameID);
@@ -697,22 +746,38 @@ void WebPage::setFixedLayoutSize(const IntSize& size)
void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay)
{
- if (m_pageOverlay)
- pageOverlay->setPage(0);
+ bool shouldFadeIn = true;
+
+ if (m_pageOverlay) {
+ m_pageOverlay->setPage(0);
+
+ if (pageOverlay) {
+ // We're installing a page overlay when a page overlay is already active.
+ // In this case we don't want to fade in the new overlay.
+ shouldFadeIn = false;
+ }
+ }
m_pageOverlay = pageOverlay;
m_pageOverlay->setPage(this);
- m_drawingArea->didInstallPageOverlay();
+ if (shouldFadeIn)
+ m_pageOverlay->startFadeInAnimation();
+ m_drawingArea->didInstallPageOverlay();
m_pageOverlay->setNeedsDisplay();
}
-void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay)
+void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay, bool fadeOut)
{
if (pageOverlay != m_pageOverlay)
return;
+ if (fadeOut) {
+ m_pageOverlay->startFadeOutAnimation();
+ return;
+ }
+
m_pageOverlay->setPage(0);
m_pageOverlay = nullptr;
@@ -804,35 +869,6 @@ WebContextMenu* WebPage::contextMenu()
return m_contextMenu.get();
}
-void WebPage::getLocationAndLengthFromRange(Range* range, uint64_t& location, uint64_t& length)
-{
- location = notFound;
- length = 0;
-
- if (!range || !range->startContainer())
- return;
-
- Element* selectionRoot = range->ownerDocument()->frame()->selection()->rootEditableElement();
- Element* scope = selectionRoot ? selectionRoot : range->ownerDocument()->documentElement();
-
- // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
- // that is not inside the current editable region. These checks ensure we don't produce
- // potentially invalid data when responding to such requests.
- if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
- return;
- if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
- return;
-
- RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
- ASSERT(testRange->startContainer() == scope);
- location = TextIterator::rangeLength(testRange.get());
-
- ExceptionCode ec;
- testRange->setEnd(range->endContainer(), range->endOffset(), ec);
- ASSERT(testRange->startContainer() == scope);
- length = TextIterator::rangeLength(testRange.get()) - location;
-}
-
// Events
static const WebEvent* g_currentEvent = 0;
@@ -913,6 +949,12 @@ static bool handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page)
void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
{
+ // Don't try to handle any pending mouse events if a context menu is showing.
+ if (m_isShowingContextMenu) {
+ send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false));
+ return;
+ }
+
bool handled = false;
if (m_pageOverlay) {
@@ -962,6 +1004,7 @@ void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
CurrentEvent currentEvent(keyboardEvent);
bool handled = handleKeyEvent(keyboardEvent, m_page.get());
+ // FIXME: Platform default behaviors should be performed during normal DOM event dispatch (in most cases, in default keydown event handler).
if (!handled)
handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
@@ -1142,8 +1185,9 @@ void WebPage::viewWillEndLiveResize()
void WebPage::setFocused(bool isFocused)
{
- if (!isFocused)
+ if (!isFocused && m_page->focusController()->focusedOrMainFrame()->editor()->behavior().shouldClearSelectionWhenLosingWebPageFocus())
m_page->focusController()->focusedOrMainFrame()->selection()->clear();
+
m_page->focusController()->setFocused(isFocused);
}
@@ -1240,7 +1284,8 @@ void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID
JSLock lock(SilenceAssertionsOnly);
if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) {
- if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue)))
+ if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(),
+ toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0)))
dataReference = CoreIPC::DataReference(serializedResultValue->data().data(), serializedResultValue->data().size());
}
@@ -1360,6 +1405,7 @@ void WebPage::updatePreferences(const WebPreferencesStore& store)
settings->setJavaScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
+ settings->setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey()));
settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
@@ -1391,17 +1437,11 @@ void WebPage::updatePreferences(const WebPreferencesStore& store)
settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
+ settings->setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey())));
-#if PLATFORM(WIN)
- // Temporarily turn off accelerated compositing until we have a good solution for rendering it.
- settings->setAcceleratedCompositingEnabled(false);
- settings->setAcceleratedDrawingEnabled(false);
- settings->setCanvasUsesAcceleratedDrawing(false);
-#else
- settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()));
- settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()));
- settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()));
-#endif
+ settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
+ settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
+ settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()) && LayerTreeHost::supportsAcceleratedCompositing());
settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey()));
@@ -1441,7 +1481,7 @@ WebFullScreenManager* WebPage::fullScreenManager()
}
#endif
-#if !PLATFORM(MAC)
+#if !PLATFORM(GTK) && !PLATFORM(MAC)
bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
{
Node* node = evt->target()->toNode();
@@ -1504,7 +1544,7 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint cli
}
}
#else
-void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags)
+void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags, const SandboxExtension::Handle& sandboxExtensionHandle)
{
if (!m_page) {
send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone));
@@ -1525,10 +1565,23 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint cli
m_page->dragController()->dragExited(&dragData);
break;
- case DragControllerActionPerformDrag:
+ case DragControllerActionPerformDrag: {
+ ASSERT(!m_pendingDropSandboxExtension);
+
+ m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle);
+
m_page->dragController()->performDrag(&dragData);
+
+ // If we started loading a local file, the sandbox extension tracker would have adopted this
+ // pending drop sandbox extension. If not, we'll play it safe and invalidate it.
+ if (m_pendingDropSandboxExtension) {
+ m_pendingDropSandboxExtension->invalidate();
+ m_pendingDropSandboxExtension = nullptr;
+ }
+
break;
-
+ }
+
default:
ASSERT_NOT_REACHED();
}
@@ -1550,6 +1603,11 @@ void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint glob
m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
}
+void WebPage::willPerformLoadDragDestinationAction()
+{
+ m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release());
+}
+
WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
{
return m_editCommandMap.get(commandID).get();
@@ -1734,8 +1792,9 @@ void WebPage::didChangeScrollOffsetForMainFrame()
Frame* frame = m_page->mainFrame();
IntPoint scrollPosition = frame->view()->scrollPosition();
IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
+ IntPoint minimumScrollPosition = frame->view()->minimumScrollPosition();
- bool isPinnedToLeftSide = (scrollPosition.x() <= 0);
+ bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x());
bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x());
if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide) {
@@ -1877,18 +1936,28 @@ void WebPage::SandboxExtensionTracker::invalidate()
}
}
+void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension)
+{
+ setPendingProvisionalSandboxExtension(pendingDropSandboxExtension);
+}
+
void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
{
ASSERT(frame->isMainFrame());
+ setPendingProvisionalSandboxExtension(SandboxExtension::create(handle));
+}
+
+void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension)
+{
// If we get two beginLoad calls in succession, without a provisional load starting, then
// m_pendingProvisionalSandboxExtension will be non-null. Invalidate and null out the extension if that is the case.
if (m_pendingProvisionalSandboxExtension) {
m_pendingProvisionalSandboxExtension->invalidate();
m_pendingProvisionalSandboxExtension = nullptr;
}
-
- m_pendingProvisionalSandboxExtension = SandboxExtension::create(handle);
+
+ m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension;
}
static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
@@ -1907,8 +1976,7 @@ static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
if (!documentLoader || !provisionalDocumentLoader)
return false;
- if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile()
- && provisionalDocumentLoader->triggeringAction().type() == NavigationTypeLinkClicked)
+ if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile())
return true;
return false;
@@ -1953,7 +2021,6 @@ void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
if (!frame->isMainFrame())
return;
- ASSERT(!m_pendingProvisionalSandboxExtension);
if (!m_provisionalSandboxExtension)
return;
@@ -2058,7 +2125,7 @@ void WebPage::drawRectToPDF(uint64_t frameID, const WebCore::IntRect& rect, uint
if (coreFrame) {
ASSERT(coreFrame->document()->printing());
-#if PLATFORM(CG)
+#if USE(CG)
// FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
@@ -2090,7 +2157,7 @@ void WebPage::drawPagesToPDF(uint64_t frameID, uint32_t first, uint32_t count, u
if (coreFrame) {
ASSERT(coreFrame->document()->printing());
-#if PLATFORM(CG)
+#if USE(CG)
// FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
@@ -2159,4 +2226,19 @@ void WebPage::handleCorrectionPanelResult(const String& result)
}
#endif
+void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
+{
+ mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
+}
+
+void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
+{
+ mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
+}
+
+void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time)
+{
+ mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time));
+}
+
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.h b/Source/WebKit2/WebProcess/WebPage/WebPage.h
index 8e4e71c..7828b45 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.h
@@ -34,6 +34,7 @@
#include "InjectedBundlePageContextMenuClient.h"
#include "InjectedBundlePageEditorClient.h"
#include "InjectedBundlePageFormClient.h"
+#include "InjectedBundlePageFullScreenClient.h"
#include "InjectedBundlePageLoaderClient.h"
#include "InjectedBundlePagePolicyClient.h"
#include "InjectedBundlePageResourceLoadClient.h"
@@ -81,6 +82,7 @@ namespace WebCore {
class ResourceRequest;
class SharedBuffer;
class VisibleSelection;
+ struct KeypressCommand;
}
namespace WebKit {
@@ -103,6 +105,8 @@ class WebOpenPanelResultListener;
class WebPageGroupProxy;
class WebPopupMenu;
class WebWheelEvent;
+struct AttributedString;
+struct EditorState;
struct PrintInfo;
struct WebPageCreationParameters;
struct WebPreferencesStore;
@@ -159,9 +163,12 @@ public:
void layoutIfNeeded();
// -- Called from WebCore clients.
-#if !PLATFORM(MAC)
+#if PLATFORM(MAC)
+ bool handleEditingKeyboardEvent(WebCore::KeyboardEvent*, bool saveCommands);
+#elif !PLATFORM(GTK)
bool handleEditingKeyboardEvent(WebCore::KeyboardEvent*);
#endif
+
void show();
String userAgent() const { return m_userAgent; }
WebCore::IntRect windowResizerRect() const;
@@ -189,6 +196,9 @@ public:
void initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient*);
void initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient*);
void initializeInjectedBundleUIClient(WKBundlePageUIClient*);
+#if ENABLE(FULLSCREEN_API)
+ void initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient*);
+#endif
InjectedBundlePageContextMenuClient& injectedBundleContextMenuClient() { return m_contextMenuClient; }
InjectedBundlePageEditorClient& injectedBundleEditorClient() { return m_editorClient; }
@@ -197,12 +207,17 @@ public:
InjectedBundlePagePolicyClient& injectedBundlePolicyClient() { return m_policyClient; }
InjectedBundlePageResourceLoadClient& injectedBundleResourceLoadClient() { return m_resourceLoadClient; }
InjectedBundlePageUIClient& injectedBundleUIClient() { return m_uiClient; }
+#if ENABLE(FULLSCREEN_API)
+ InjectedBundlePageFullScreenClient& injectedBundleFullScreenClient() { return m_fullScreenClient; }
+#endif
bool findStringFromInjectedBundle(const String&, FindOptions);
WebFrame* mainFrame() const { return m_mainFrame.get(); }
PassRefPtr<Plugin> createPlugin(const Plugin::Parameters&);
+ EditorState editorState() const;
+
String renderTreeExternalRepresentation() const;
void executeEditingCommand(const String& commandName, const String& argument);
bool isEditingCommandEnabled(const String& commandName);
@@ -240,14 +255,13 @@ public:
bool windowIsVisible() const { return m_windowIsVisible; }
const WebCore::IntRect& windowFrameInScreenCoordinates() const { return m_windowFrameInScreenCoordinates; }
const WebCore::IntRect& viewFrameInWindowCoordinates() const { return m_viewFrameInWindowCoordinates; }
- bool interceptEditingKeyboardEvent(WebCore::KeyboardEvent*, bool);
#elif PLATFORM(WIN)
HWND nativeWindow() const { return m_nativeWindow; }
#endif
bool windowIsFocused() const;
void installPageOverlay(PassRefPtr<PageOverlay>);
- void uninstallPageOverlay(PageOverlay*);
+ void uninstallPageOverlay(PageOverlay*, bool fadeOut);
bool hasPageOverlay() const { return m_pageOverlay; }
WebCore::IntRect windowToScreen(const WebCore::IntRect&);
@@ -285,10 +299,14 @@ public:
void invalidate();
void beginLoad(WebFrame*, const SandboxExtension::Handle& handle);
+ void willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension);
void didStartProvisionalLoad(WebFrame*);
void didCommitProvisionalLoad(WebFrame*);
void didFailProvisionalLoad(WebFrame*);
+
private:
+ void setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension>);
+
RefPtr<SandboxExtension> m_pendingProvisionalSandboxExtension;
RefPtr<SandboxExtension> m_provisionalSandboxExtension;
RefPtr<SandboxExtension> m_committedSandboxExtension;
@@ -296,8 +314,6 @@ public:
SandboxExtensionTracker& sandboxExtensionTracker() { return m_sandboxExtensionTracker; }
- static void getLocationAndLengthFromRange(WebCore::Range*, uint64_t& location, uint64_t& length);
-
#if PLATFORM(MAC)
void registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elemenToken, const CoreIPC::DataReference& windowToken);
AccessibilityWebPageObject* accessibilityRemoteObject();
@@ -305,16 +321,29 @@ public:
void sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput);
+ void setComposition(const String& text, Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, EditorState& newState);
+ void confirmComposition(EditorState& newState);
+ void insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, bool& handled, EditorState& newState);
void getMarkedRange(uint64_t& location, uint64_t& length);
+ void getSelectedRange(uint64_t& location, uint64_t& length);
+ void getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString&);
void characterIndexForPoint(const WebCore::IntPoint point, uint64_t& result);
void firstRectForCharacterRange(uint64_t location, uint64_t length, WebCore::IntRect& resultRect);
+ void executeKeypressCommands(const Vector<WebCore::KeypressCommand>&, bool& handled, EditorState& newState);
void writeSelectionToPasteboard(const WTF::String& pasteboardName, const WTF::Vector<WTF::String>& pasteboardTypes, bool& result);
void readSelectionFromPasteboard(const WTF::String& pasteboardName, bool& result);
+ void shouldDelayWindowOrderingEvent(const WebKit::WebMouseEvent&, bool& result);
+ void acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent&, bool& result);
+ bool performNonEditingBehaviorForSelector(const String&);
#elif PLATFORM(WIN)
void confirmComposition(const String& compositionString);
void setComposition(const WTF::String& compositionString, const WTF::Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition);
void firstRectForCharacterInSelectedRange(const uint64_t characterPosition, WebCore::IntRect& resultRect);
void getSelectedText(WTF::String&);
+
+ void gestureWillBegin(const WebCore::IntPoint&, bool& canBeginPanning);
+ void gestureDidScroll(const WebCore::IntSize&);
+ void gestureDidEnd();
#endif
// FIXME: This a dummy message, to avoid breaking the build for platforms that don't require
@@ -335,10 +364,12 @@ public:
#if PLATFORM(WIN)
void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap&, uint32_t flags);
#else
- void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WTF::String& dragStorageName, uint32_t flags);
+ void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WTF::String& dragStorageName, uint32_t flags, const SandboxExtension::Handle&);
#endif
void dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation);
+ void willPerformLoadDragDestinationAction();
+
void beginPrinting(uint64_t frameID, const PrintInfo&);
void endPrinting();
void computePagesForPrinting(uint64_t frameID, const PrintInfo&, uint64_t callbackID);
@@ -365,6 +396,9 @@ public:
void forceRepaintWithoutCallback();
+ void unmarkAllMisspellings();
+ void unmarkAllBadGrammar();
+
#if PLATFORM(MAC)
void setDragSource(NSObject *);
#endif
@@ -373,6 +407,12 @@ public:
void handleCorrectionPanelResult(const String&);
#endif
+ void simulateMouseDown(int button, WebCore::IntPoint, int clickCount, WKEventModifiers, double time);
+ void simulateMouseUp(int button, WebCore::IntPoint, int clickCount, WKEventModifiers, double time);
+ void simulateMouseMotion(WebCore::IntPoint, double time);
+
+ void contextMenuShowing() { m_isShowingContextMenu = true; }
+
private:
WebPage(uint64_t pageID, const WebPageCreationParameters&);
@@ -383,9 +423,15 @@ private:
void didReceiveWebPageMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
CoreIPC::SyncReplyMode didReceiveSyncWebPageMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, CoreIPC::ArgumentEncoder*);
+#if !PLATFORM(MAC)
static const char* interpretKeyEvent(const WebCore::KeyboardEvent*);
+#endif
bool performDefaultBehaviorForKeyEvent(const WebKeyboardEvent&);
+#if PLATFORM(MAC)
+ bool executeKeypressCommandsInternal(const Vector<WebCore::KeypressCommand>&, WebCore::KeyboardEvent*);
+#endif
+
String sourceForFrame(WebFrame*);
void loadData(PassRefPtr<WebCore::SharedBuffer>, const String& MIMEType, const String& encodingName, const WebCore::KURL& baseURL, const WebCore::KURL& failingURL);
@@ -399,6 +445,7 @@ private:
void loadHTMLString(const String& htmlString, const String& baseURL);
void loadAlternateHTMLString(const String& htmlString, const String& baseURL, const String& unreachableURL);
void loadPlainTextString(const String&);
+ void linkClicked(const String& url, const WebMouseEvent&);
void reload(bool reloadFromOrigin);
void goForward(uint64_t, const SandboxExtension::Handle&);
void goBack(uint64_t, const SandboxExtension::Handle&);
@@ -420,6 +467,7 @@ private:
#if ENABLE(TOUCH_EVENTS)
void touchEvent(const WebTouchEvent&);
#endif
+ void contextMenuHidden() { m_isShowingContextMenu = false; }
static void scroll(WebCore::Page*, WebCore::ScrollDirection, WebCore::ScrollGranularity);
static void logicalScroll(WebCore::Page*, WebCore::ScrollLogicalDirection, WebCore::ScrollGranularity);
@@ -486,8 +534,6 @@ private:
void advanceToNextMisspelling(bool startBeforeSelection);
void changeSpellingToWord(const String& word);
- void unmarkAllMisspellings();
- void unmarkAllBadGrammar();
#if PLATFORM(MAC)
void uppercaseWord();
void lowercaseWord();
@@ -545,9 +591,14 @@ private:
RetainPtr<AccessibilityWebPageObject> m_mockAccessibilityElement;
RetainPtr<NSObject> m_dragSource;
+
+ WebCore::KeyboardEvent* m_keyboardEventBeingInterpreted;
+
#elif PLATFORM(WIN)
// Our view's window (in the UI process).
HWND m_nativeWindow;
+
+ RefPtr<WebCore::Node> m_gestureTargetNode;
#endif
HashMap<uint64_t, RefPtr<WebEditCommand> > m_editCommandMap;
@@ -561,6 +612,9 @@ private:
InjectedBundlePagePolicyClient m_policyClient;
InjectedBundlePageResourceLoadClient m_resourceLoadClient;
InjectedBundlePageUIClient m_uiClient;
+#if ENABLE(FULLSCREEN_API)
+ InjectedBundlePageFullScreenClient m_fullScreenClient;
+#endif
#if ENABLE(TILED_BACKING_STORE)
WebCore::IntSize m_resizesToContentsLayoutSize;
@@ -585,6 +639,8 @@ private:
SandboxExtensionTracker m_sandboxExtensionTracker;
uint64_t m_pageID;
+ RefPtr<SandboxExtension> m_pendingDropSandboxExtension;
+
bool m_canRunBeforeUnloadConfirmPanel;
bool m_canRunModal;
@@ -594,6 +650,12 @@ private:
bool m_cachedMainFrameIsPinnedToLeftSide;
bool m_cachedMainFrameIsPinnedToRightSide;
+
+ bool m_isShowingContextMenu;
+
+#if PLATFORM(WIN)
+ bool m_gestureReachedScrollingLimit;
+#endif
};
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
index 69bd54d..673e8d6 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
@@ -42,6 +42,8 @@ messages -> WebPage {
TouchEvent(WebKit::WebTouchEvent event)
#endif
+ ContextMenuHidden()
+
ScrollBy(uint32_t scrollDirection, uint32_t scrollGranularity)
GoBack(uint64_t backForwardItemID, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
@@ -52,6 +54,7 @@ messages -> WebPage {
LoadPlainTextString(WTF::String string)
LoadURL(WTF::String url, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
LoadURLRequest(WebCore::ResourceRequest request, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
+ LinkClicked(WTF::String url, WebKit::WebMouseEvent event)
Reload(bool reloadFromOrigin)
StopLoading()
@@ -119,7 +122,7 @@ messages -> WebPage {
PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, HashMap<UINT,Vector<String>> dataMap, uint32_t flags)
#endif
#if !PLATFORM(WIN)
- PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, WTF::String dragStorageName, uint32_t flags)
+ PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, WTF::String dragStorageName, uint32_t flags, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
#endif
DragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
@@ -140,8 +143,6 @@ messages -> WebPage {
# Spelling and grammar.
AdvanceToNextMisspelling(bool startBeforeSelection)
ChangeSpellingToWord(WTF::String word)
- UnmarkAllMisspellings()
- UnmarkAllBadGrammar()
#if PLATFORM(MAC)
UppercaseWord();
LowercaseWord();
@@ -179,18 +180,33 @@ messages -> WebPage {
SetWindowIsVisible(bool windowIsVisible)
WindowAndViewFramesChanged(WebCore::IntRect windowFrameInScreenCoordinates, WebCore::IntRect viewFrameInWindowCoordinates, WebCore::IntPoint accessibilityViewCoordinates)
- GetMarkedRange() -> (uint64_t location, uint64_t length)
- CharacterIndexForPoint(WebCore::IntPoint point) -> (uint64_t result)
- FirstRectForCharacterRange(uint64_t location, uint64_t length) -> (WebCore::IntRect resultRect)
RegisterUIProcessAccessibilityTokens(CoreIPC::DataReference elemenToken, CoreIPC::DataReference windowToken)
WriteSelectionToPasteboard(WTF::String pasteboardName, WTF::Vector<WTF::String> pasteboardTypes) -> (bool result)
ReadSelectionFromPasteboard(WTF::String pasteboardName) -> (bool result)
+
+ # Text input.
+ SetComposition(WTF::String text, WTF::Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd) -> (WebKit::EditorState newState)
+ ConfirmComposition() -> (WebKit::EditorState newState)
+ InsertText(WTF::String text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd) -> (bool handled, WebKit::EditorState newState)
+ GetMarkedRange() -> (uint64_t location, uint64_t length)
+ GetSelectedRange() -> (uint64_t location, uint64_t length)
+ GetAttributedSubstringFromRange(uint64_t location, uint64_t length) -> (WebKit::AttributedString result)
+ CharacterIndexForPoint(WebCore::IntPoint point) -> (uint64_t result)
+ FirstRectForCharacterRange(uint64_t location, uint64_t length) -> (WebCore::IntRect resultRect)
+ ExecuteKeypressCommands(Vector<WebCore::KeypressCommand> savedCommands) -> (bool handled, WebKit::EditorState newState)
+ ShouldDelayWindowOrderingEvent(WebKit::WebMouseEvent event) -> (bool result)
+ AcceptsFirstMouse(int eventNumber, WebKit::WebMouseEvent event) -> (bool result)
#endif
#if PLATFORM(WIN)
+ // FIXME: Unify with Mac counterparts.
ConfirmComposition(WTF::String compositionString)
SetComposition(WTF::String compositionString, WTF::Vector<WebCore::CompositionUnderline> underlines, uint64_t cursorPosition)
FirstRectForCharacterInSelectedRange(uint64_t characterPosition) -> (WebCore::IntRect resultRect)
GetSelectedText() -> (WTF::String text)
+
+ GestureWillBegin(WebCore::IntPoint point) -> (bool canBeginPanning)
+ GestureDidScroll(WebCore::IntSize size)
+ GestureDidEnd()
#endif
#if PLATFORM(QT)
FindZoomableAreaForPoint(WebCore::IntPoint point)
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.h b/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.h
index 55cf629..91e6c5c 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.h
+++ b/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.h
@@ -42,6 +42,7 @@ public:
const String& identifier() const { return m_data.identifer; }
uint64_t pageGroupID() const { return m_data.pageGroupID; }
bool isVisibleToInjectedBundle() const { return m_data.visibleToInjectedBundle; }
+ bool isVisibleToHistoryClient() const { return m_data.visibleToHistoryClient; }
private:
WebPageGroupProxy(const WebPageGroupData& data)
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp b/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp
index 2460607..42a2dc9 100644
--- a/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp
@@ -31,39 +31,41 @@
#include "WebProcess.h"
#include <WebCore/Frame.h>
#include <WebCore/FrameView.h>
+#include <WebCore/GraphicsLayerCA.h>
#include <WebCore/Page.h>
+#include <WebCore/PlatformCALayer.h>
#include <WebCore/Settings.h>
using namespace WebCore;
namespace WebKit {
-PassRefPtr<LayerTreeHostCA> LayerTreeHostCA::create(WebPage* webPage)
-{
- return adoptRef(new LayerTreeHostCA(webPage));
-}
-
LayerTreeHostCA::LayerTreeHostCA(WebPage* webPage)
: LayerTreeHost(webPage)
, m_isValid(true)
, m_notifyAfterScheduledLayerFlush(false)
{
+}
+void LayerTreeHostCA::initialize()
+{
// Create a root layer.
m_rootLayer = GraphicsLayer::create(this);
#ifndef NDEBUG
m_rootLayer->setName("LayerTreeHost root layer");
#endif
m_rootLayer->setDrawsContent(false);
- m_rootLayer->setSize(webPage->size());
+ m_rootLayer->setSize(m_webPage->size());
+ static_cast<GraphicsLayerCA*>(m_rootLayer.get())->platformCALayer()->setGeometryFlipped(true);
m_nonCompositedContentLayer = GraphicsLayer::create(this);
+ static_cast<GraphicsLayerCA*>(m_nonCompositedContentLayer.get())->setAllowTiledLayer(false);
#ifndef NDEBUG
m_nonCompositedContentLayer->setName("LayerTreeHost non-composited content");
#endif
m_nonCompositedContentLayer->setDrawsContent(true);
m_nonCompositedContentLayer->setContentsOpaque(m_webPage->drawsBackground() && !m_webPage->drawsTransparentBackground());
- m_nonCompositedContentLayer->setSize(webPage->size());
+ m_nonCompositedContentLayer->setSize(m_webPage->size());
if (m_webPage->corePage()->settings()->acceleratedDrawingEnabled())
m_nonCompositedContentLayer->setAcceleratesDrawing(true);
@@ -72,7 +74,7 @@ LayerTreeHostCA::LayerTreeHostCA(WebPage* webPage)
if (m_webPage->hasPageOverlay())
createPageOverlayLayer();
- platformInitialize();
+ platformInitialize(m_layerTreeContext);
scheduleLayerFlush();
}
@@ -81,10 +83,6 @@ LayerTreeHostCA::~LayerTreeHostCA()
{
ASSERT(!m_isValid);
ASSERT(!m_rootLayer);
-#if PLATFORM(MAC)
- ASSERT(!m_flushPendingLayerChangesRunLoopObserver);
- ASSERT(!m_remoteLayerClient);
-#endif
}
const LayerTreeContext& LayerTreeHostCA::layerTreeContext()
@@ -109,7 +107,6 @@ void LayerTreeHostCA::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
void LayerTreeHostCA::invalidate()
{
ASSERT(m_isValid);
- platformInvalidate();
m_rootLayer = nullptr;
m_isValid = false;
}
@@ -138,16 +135,12 @@ void LayerTreeHostCA::sizeDidChange(const IntSize& newSize)
scheduleLayerFlush();
flushPendingLayerChanges();
-
- platformSizeDidChange();
}
void LayerTreeHostCA::forceRepaint()
{
scheduleLayerFlush();
flushPendingLayerChanges();
-
- platformForceRepaint();
}
void LayerTreeHostCA::didInstallPageOverlay()
@@ -218,8 +211,6 @@ void LayerTreeHostCA::performScheduledLayerFlush()
void LayerTreeHostCA::didPerformScheduledLayerFlush()
{
- platformDidPerformScheduledLayerFlush();
-
if (m_notifyAfterScheduledLayerFlush) {
// Let the drawing area know that we've done a flush of the layer changes.
static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers();
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h b/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h
index ba4e33a..3a62d15 100644
--- a/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h
+++ b/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h
@@ -31,35 +31,36 @@
#include <WebCore/GraphicsLayerClient.h>
#include <wtf/OwnPtr.h>
-#if PLATFORM(MAC)
-#include <wtf/RetainPtr.h>
-#endif
-
-#if PLATFORM(MAC)
-typedef struct __WKCARemoteLayerClientRef* WKCARemoteLayerClientRef;
-#endif
-
namespace WebKit {
class LayerTreeHostCA : public LayerTreeHost, WebCore::GraphicsLayerClient {
public:
- static PassRefPtr<LayerTreeHostCA> create(WebPage*);
- ~LayerTreeHostCA();
+ virtual ~LayerTreeHostCA();
-private:
+protected:
explicit LayerTreeHostCA(WebPage*);
+ WebCore::GraphicsLayer* rootLayer() const { return m_rootLayer.get(); }
+
+ void initialize();
+ void performScheduledLayerFlush();
+
+ // LayerTreeHost.
+ virtual void invalidate();
+ virtual void sizeDidChange(const WebCore::IntSize& newSize);
+ virtual void forceRepaint();
+
+ // LayerTreeHostCA
+ virtual void didPerformScheduledLayerFlush();
+
+private:
// LayerTreeHost.
virtual const LayerTreeContext& layerTreeContext();
- virtual void scheduleLayerFlush();
virtual void setShouldNotifyAfterNextScheduledLayerFlush(bool);
virtual void setRootCompositingLayer(WebCore::GraphicsLayer*);
- virtual void invalidate();
virtual void setNonCompositedContentsNeedDisplay(const WebCore::IntRect&);
virtual void scrollNonCompositedContents(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset);
- virtual void sizeDidChange(const WebCore::IntSize& newSize);
- virtual void forceRepaint();
virtual void didInstallPageOverlay();
virtual void didUninstallPageOverlay();
@@ -72,23 +73,14 @@ private:
virtual bool showDebugBorders() const;
virtual bool showRepaintCounter() const;
- void platformInitialize();
- void platformInvalidate();
- void platformSizeDidChange();
- void platformForceRepaint();
+ // LayerTreeHostCA
+ virtual void platformInitialize(LayerTreeContext&) = 0;
- void performScheduledLayerFlush();
- void didPerformScheduledLayerFlush();
- void platformDidPerformScheduledLayerFlush();
bool flushPendingLayerChanges();
void createPageOverlayLayer();
void destroyPageOverlayLayer();
-#if PLATFORM(MAC)
- static void flushPendingLayerChangesRunLoopObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*);
-#endif
-
// The context for this layer tree.
LayerTreeContext m_layerTreeContext;
@@ -107,11 +99,6 @@ private:
// The page overlay layer. Will be null if there's no page overlay.
OwnPtr<WebCore::GraphicsLayer> m_pageOverlayLayer;
-
-#if PLATFORM(MAC)
- RetainPtr<WKCARemoteLayerClientRef> m_remoteLayerClient;
- RetainPtr<CFRunLoopObserverRef> m_flushPendingLayerChangesRunLoopObserver;
-#endif
};
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h b/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h
new file mode 100644
index 0000000..e3a0160
--- /dev/null
+++ b/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 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 LayerTreeHostCAMac_h
+#define LayerTreeHostCAMac_h
+
+#include "LayerTreeHostCA.h"
+#include <wtf/RetainPtr.h>
+
+typedef struct __WKCARemoteLayerClientRef* WKCARemoteLayerClientRef;
+
+namespace WebKit {
+
+class LayerTreeHostCAMac : public LayerTreeHostCA {
+public:
+ static PassRefPtr<LayerTreeHostCAMac> create(WebPage*);
+ virtual ~LayerTreeHostCAMac();
+
+private:
+ explicit LayerTreeHostCAMac(WebPage*);
+
+ // LayerTreeHost.
+ virtual void scheduleLayerFlush();
+ virtual void invalidate();
+ virtual void sizeDidChange(const WebCore::IntSize& newSize);
+ virtual void forceRepaint();
+ virtual void pauseRendering();
+ virtual void resumeRendering();
+
+ // LayerTreeHostCA
+ virtual void platformInitialize(LayerTreeContext&);
+ virtual void didPerformScheduledLayerFlush();
+
+ static void flushPendingLayerChangesRunLoopObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*);
+
+ RetainPtr<WKCARemoteLayerClientRef> m_remoteLayerClient;
+ RetainPtr<CFRunLoopObserverRef> m_flushPendingLayerChangesRunLoopObserver;
+};
+
+} // namespace WebKit
+
+#endif // LayerTreeHostCAMac_h
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm b/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm
index 50776d7..69cfa44 100644
--- a/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm
+++ b/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm
@@ -24,32 +24,50 @@
*/
#import "config.h"
-#import "LayerTreeHostCA.h"
+#import "LayerTreeHostCAMac.h"
#import "WebProcess.h"
#import <QuartzCore/CATransaction.h>
#import <WebCore/GraphicsLayer.h>
#import <WebKitSystemInterface.h>
+using namespace WebCore;
+
@interface CATransaction (Details)
+ (void)synchronize;
@end
namespace WebKit {
-void LayerTreeHostCA::platformInitialize()
+PassRefPtr<LayerTreeHostCAMac> LayerTreeHostCAMac::create(WebPage* webPage)
+{
+ RefPtr<LayerTreeHostCAMac> host = adoptRef(new LayerTreeHostCAMac(webPage));
+ host->initialize();
+ return host.release();
+}
+
+LayerTreeHostCAMac::LayerTreeHostCAMac(WebPage* webPage)
+ : LayerTreeHostCA(webPage)
+{
+}
+
+LayerTreeHostCAMac::~LayerTreeHostCAMac()
+{
+ ASSERT(!m_flushPendingLayerChangesRunLoopObserver);
+ ASSERT(!m_remoteLayerClient);
+}
+
+void LayerTreeHostCAMac::platformInitialize(LayerTreeContext& layerTreeContext)
{
mach_port_t serverPort = WebProcess::shared().compositingRenderServerPort();
m_remoteLayerClient = WKCARemoteLayerClientMakeWithServerPort(serverPort);
- [m_rootLayer->platformLayer() setGeometryFlipped:YES];
+ WKCARemoteLayerClientSetLayer(m_remoteLayerClient.get(), rootLayer()->platformLayer());
- WKCARemoteLayerClientSetLayer(m_remoteLayerClient.get(), m_rootLayer->platformLayer());
-
- m_layerTreeContext.contextID = WKCARemoteLayerClientGetClientId(m_remoteLayerClient.get());
+ layerTreeContext.contextID = WKCARemoteLayerClientGetClientId(m_remoteLayerClient.get());
}
-void LayerTreeHostCA::scheduleLayerFlush()
+void LayerTreeHostCAMac::scheduleLayerFlush()
{
CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
@@ -67,7 +85,7 @@ void LayerTreeHostCA::scheduleLayerFlush()
CFRunLoopAddObserver(currentRunLoop, m_flushPendingLayerChangesRunLoopObserver.get(), kCFRunLoopCommonModes);
}
-void LayerTreeHostCA::platformInvalidate()
+void LayerTreeHostCAMac::invalidate()
{
if (m_flushPendingLayerChangesRunLoopObserver) {
CFRunLoopObserverInvalidate(m_flushPendingLayerChangesRunLoopObserver.get());
@@ -76,34 +94,54 @@ void LayerTreeHostCA::platformInvalidate()
WKCARemoteLayerClientInvalidate(m_remoteLayerClient.get());
m_remoteLayerClient = nullptr;
+
+ LayerTreeHostCA::invalidate();
}
-void LayerTreeHostCA::platformSizeDidChange()
+void LayerTreeHostCAMac::sizeDidChange(const IntSize& newSize)
{
+ LayerTreeHostCA::sizeDidChange(newSize);
[CATransaction flush];
[CATransaction synchronize];
}
-void LayerTreeHostCA::platformForceRepaint()
+void LayerTreeHostCAMac::forceRepaint()
{
+ LayerTreeHostCA::forceRepaint();
[CATransaction flush];
[CATransaction synchronize];
-}
+}
+
+void LayerTreeHostCAMac::pauseRendering()
+{
+ CALayer* root = rootLayer()->platformLayer();
+ [root setValue:(id)kCFBooleanTrue forKey:@"NSCAViewRenderPaused"];
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"NSCAViewRenderDidPauseNotification" object:nil userInfo:[NSDictionary dictionaryWithObject:root forKey:@"layer"]];
+}
-void LayerTreeHostCA::flushPendingLayerChangesRunLoopObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity, void* context)
+void LayerTreeHostCAMac::resumeRendering()
+{
+ CALayer* root = rootLayer()->platformLayer();
+ [root setValue:(id)kCFBooleanFalse forKey:@"NSCAViewRenderPaused"];
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"NSCAViewRenderDidResumeNotification" object:nil userInfo:[NSDictionary dictionaryWithObject:root forKey:@"layer"]];
+}
+
+void LayerTreeHostCAMac::flushPendingLayerChangesRunLoopObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity, void* context)
{
// This gets called outside of the normal event loop so wrap in an autorelease pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- static_cast<LayerTreeHostCA*>(context)->performScheduledLayerFlush();
+ static_cast<LayerTreeHostCAMac*>(context)->performScheduledLayerFlush();
[pool drain];
}
-void LayerTreeHostCA::platformDidPerformScheduledLayerFlush()
+void LayerTreeHostCAMac::didPerformScheduledLayerFlush()
{
// We successfully flushed the pending layer changes, remove the run loop observer.
ASSERT(m_flushPendingLayerChangesRunLoopObserver);
CFRunLoopObserverInvalidate(m_flushPendingLayerChangesRunLoopObserver.get());
m_flushPendingLayerChangesRunLoopObserver = 0;
+
+ LayerTreeHostCA::didPerformScheduledLayerFlush();
}
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
index 81db03e..699a1fe 100644
--- a/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
@@ -24,46 +24,276 @@
*/
#include "config.h"
-#include "LayerTreeHostCA.h"
+#include "LayerTreeHostCAWin.h"
-#include <WebCore/NotImplemented.h>
+#if HAVE(WKQCA)
+
+#include "DrawingAreaImpl.h"
+#include "ShareableBitmap.h"
+#include "UpdateInfo.h"
+#include "WebPage.h"
+#include <WebCore/GraphicsLayerCA.h>
+#include <WebCore/LayerChangesFlusher.h>
+#include <WebCore/PlatformCALayer.h>
+#include <WebCore/WebCoreInstanceHandle.h>
+#include <WebKitQuartzCoreAdditions/WKCACFImage.h>
+#include <WebKitQuartzCoreAdditions/WKCACFView.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/Threading.h>
+
+#ifdef DEBUG_ALL
+#pragma comment(lib, "WebKitQuartzCoreAdditions_debug")
+#else
+#pragma comment(lib, "WebKitQuartzCoreAdditions")
+#endif
+
+using namespace WebCore;
namespace WebKit {
-void LayerTreeHostCA::platformInitialize()
+static HWND dummyWindow;
+static LPCWSTR dummyWindowClass = L"LayerTreeHostCAWindowClass";
+static size_t validLayerTreeHostCount;
+
+static void registerDummyWindowClass()
+{
+ static bool didRegister;
+ if (didRegister)
+ return;
+ didRegister = true;
+
+ WNDCLASSW wndClass = {0};
+ wndClass.lpszClassName = dummyWindowClass;
+ wndClass.lpfnWndProc = ::DefWindowProcW;
+ wndClass.hInstance = instanceHandle();
+
+ ::RegisterClassW(&wndClass);
+}
+
+// This window is never shown. It is only needed so that D3D can determine the display mode, etc.
+static HWND createDummyWindow()
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
+ registerDummyWindowClass();
+ return ::CreateWindowW(dummyWindowClass, 0, WS_POPUP, 0, 0, 10, 10, 0, 0, instanceHandle(), 0);
}
-void LayerTreeHostCA::scheduleLayerFlush()
+bool LayerTreeHostCAWin::supportsAcceleratedCompositing()
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
+ static bool initialized;
+ static bool supportsAcceleratedCompositing;
+ if (initialized)
+ return supportsAcceleratedCompositing;
+ initialized = true;
+
+ ASSERT(!dummyWindow);
+ dummyWindow = createDummyWindow();
+ RetainPtr<WKCACFViewRef> view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationImage));
+ CGRect fakeBounds = CGRectMake(0, 0, 10, 10);
+ WKCACFViewUpdate(view.get(), dummyWindow, &fakeBounds);
+
+ supportsAcceleratedCompositing = WKCACFViewCanDraw(view.get());
+
+ WKCACFViewUpdate(view.get(), 0, 0);
+ ::DestroyWindow(dummyWindow);
+ dummyWindow = 0;
+
+ return supportsAcceleratedCompositing;
}
-void LayerTreeHostCA::platformInvalidate()
+PassRefPtr<LayerTreeHostCAWin> LayerTreeHostCAWin::create(WebPage* webPage)
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
+ RefPtr<LayerTreeHostCAWin> host = adoptRef(new LayerTreeHostCAWin(webPage));
+ host->initialize();
+ return host.release();
}
-void LayerTreeHostCA::platformSizeDidChange()
+LayerTreeHostCAWin::LayerTreeHostCAWin(WebPage* webPage)
+ : LayerTreeHostCA(webPage)
+ , m_isFlushingLayerChanges(false)
+ , m_nextDisplayTime(0)
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
}
-void LayerTreeHostCA::platformForceRepaint()
+LayerTreeHostCAWin::~LayerTreeHostCAWin()
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
}
-void LayerTreeHostCA::platformDidPerformScheduledLayerFlush()
+void LayerTreeHostCAWin::platformInitialize(LayerTreeContext&)
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
+ ++validLayerTreeHostCount;
+ if (!dummyWindow)
+ dummyWindow = createDummyWindow();
+
+ m_view.adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationImage));
+ WKCACFViewSetContextUserData(m_view.get(), static_cast<AbstractCACFLayerTreeHost*>(this));
+ WKCACFViewSetLayer(m_view.get(), rootLayer()->platformLayer());
+ WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this);
+
+ CGRect bounds = m_webPage->bounds();
+ WKCACFViewUpdate(m_view.get(), dummyWindow, &bounds);
+}
+
+void LayerTreeHostCAWin::invalidate()
+{
+ LayerChangesFlusher::shared().cancelPendingFlush(this);
+
+ WKCACFViewUpdate(m_view.get(), 0, 0);
+ WKCACFViewSetContextUserData(m_view.get(), 0);
+ WKCACFViewSetLayer(m_view.get(), 0);
+ WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0);
+
+ LayerTreeHostCA::invalidate();
+
+ if (--validLayerTreeHostCount)
+ return;
+ ::DestroyWindow(dummyWindow);
+ dummyWindow = 0;
+}
+
+void LayerTreeHostCAWin::scheduleLayerFlush()
+{
+ LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
+}
+
+bool LayerTreeHostCAWin::participatesInDisplay()
+{
+ return true;
+}
+
+bool LayerTreeHostCAWin::needsDisplay()
+{
+ return timeUntilNextDisplay() <= 0;
+}
+
+double LayerTreeHostCAWin::timeUntilNextDisplay()
+{
+ return m_nextDisplayTime - currentTime();
+}
+
+static IntSize size(WKCACFImageRef image)
+{
+ return IntSize(WKCACFImageGetWidth(image), WKCACFImageGetHeight(image));
+}
+
+static PassRefPtr<ShareableBitmap> toShareableBitmap(WKCACFImageRef image)
+{
+ size_t fileMappingSize;
+ HANDLE mapping = WKCACFImageCopyFileMapping(image, &fileMappingSize);
+ if (!mapping)
+ return 0;
+
+ RefPtr<SharedMemory> sharedMemory = SharedMemory::adopt(mapping, fileMappingSize, SharedMemory::ReadWrite);
+ if (!sharedMemory) {
+ ::CloseHandle(mapping);
+ return 0;
+ }
+
+ // WKCACFImage never has an alpha channel.
+ return ShareableBitmap::create(size(image), 0, sharedMemory.release());
+}
+
+void LayerTreeHostCAWin::display(UpdateInfo& updateInfo)
+{
+ CGPoint imageOrigin;
+ CFTimeInterval nextDrawTime;
+ RetainPtr<WKCACFImageRef> image(AdoptCF, WKCACFViewCopyDrawnImage(m_view.get(), &imageOrigin, &nextDrawTime));
+ m_nextDisplayTime = nextDrawTime - CACurrentMediaTime() + currentTime();
+ if (!image)
+ return;
+ RefPtr<ShareableBitmap> bitmap = toShareableBitmap(image.get());
+ if (!bitmap)
+ return;
+ if (!bitmap->createHandle(updateInfo.bitmapHandle))
+ return;
+ updateInfo.updateRectBounds = IntRect(IntPoint(imageOrigin.x, m_webPage->size().height() - imageOrigin.y - bitmap->size().height()), bitmap->size());
+ updateInfo.updateRects.append(updateInfo.updateRectBounds);
+}
+
+void LayerTreeHostCAWin::sizeDidChange(const IntSize& newSize)
+{
+ LayerTreeHostCA::sizeDidChange(newSize);
+ CGRect bounds = CGRectMake(0, 0, newSize.width(), newSize.height());
+ WKCACFViewUpdate(m_view.get(), dummyWindow, &bounds);
+ WKCACFViewFlushContext(m_view.get());
+}
+
+void LayerTreeHostCAWin::forceRepaint()
+{
+ LayerTreeHostCA::forceRepaint();
+ WKCACFViewFlushContext(m_view.get());
+}
+
+void LayerTreeHostCAWin::contextDidChangeCallback(WKCACFViewRef view, void* info)
+{
+ // This should only be called on a background thread when no changes have actually
+ // been committed to the context, eg. when a video frame has been added to an image
+ // queue, so return without triggering animations etc.
+ if (!isMainThread())
+ return;
+
+ LayerTreeHostCAWin* host = static_cast<LayerTreeHostCAWin*>(info);
+ ASSERT_ARG(view, view == host->m_view);
+ host->contextDidChange();
+}
+
+void LayerTreeHostCAWin::contextDidChange()
+{
+ // Send currentTime to the pending animations. This function is called by CACF in a callback
+ // which occurs after the drawInContext calls. So currentTime is very close to the time
+ // the animations actually start
+ double currentTime = WTF::currentTime();
+
+ HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end();
+ for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it)
+ (*it)->animationStarted(currentTime);
+
+ m_pendingAnimatedLayers.clear();
+
+ m_nextDisplayTime = 0;
+ static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->setLayerHostNeedsDisplay();
+}
+
+PlatformCALayer* LayerTreeHostCAWin::rootLayer() const
+{
+ return static_cast<GraphicsLayerCA*>(LayerTreeHostCA::rootLayer())->platformCALayer();
+}
+
+void LayerTreeHostCAWin::addPendingAnimatedLayer(PassRefPtr<PlatformCALayer> layer)
+{
+ m_pendingAnimatedLayers.add(layer);
+}
+
+void LayerTreeHostCAWin::layerTreeDidChange()
+{
+ if (m_isFlushingLayerChanges) {
+ // The layer tree is changing as a result of flushing GraphicsLayer changes to their
+ // underlying PlatformCALayers. We'll flush those changes to the context as part of that
+ // process, so there's no need to schedule another flush here.
+ return;
+ }
+
+ // The layer tree is changing as a result of someone modifying a PlatformCALayer that doesn't
+ // have a corresponding GraphicsLayer. Schedule a flush since we won't schedule one through the
+ // normal GraphicsLayer mechanisms.
+ LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
+}
+
+void LayerTreeHostCAWin::flushPendingLayerChangesNow()
+{
+ RefPtr<LayerTreeHostCA> protector(this);
+
+ m_isFlushingLayerChanges = true;
+
+ // Flush changes stored up in GraphicsLayers to their underlying PlatformCALayers, if
+ // requested.
+ performScheduledLayerFlush();
+
+ // Flush changes stored up in PlatformCALayers to the context so they will be rendered.
+ WKCACFViewFlushContext(m_view.get());
+
+ m_isFlushingLayerChanges = false;
}
} // namespace WebKit
+
+#endif // HAVE(WKQCA)
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h
new file mode 100644
index 0000000..2232b08
--- /dev/null
+++ b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2011 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 LayerTreeHostCAWin_h
+#define LayerTreeHostCAWin_h
+
+#include "HeaderDetection.h"
+
+#if HAVE(WKQCA)
+
+#include "LayerTreeHostCA.h"
+#include <WebCore/AbstractCACFLayerTreeHost.h>
+#include <wtf/HashSet.h>
+#include <wtf/RetainPtr.h>
+
+typedef struct _WKCACFView* WKCACFViewRef;
+
+namespace WebKit {
+
+class LayerTreeHostCAWin : public LayerTreeHostCA, private WebCore::AbstractCACFLayerTreeHost {
+public:
+ static bool supportsAcceleratedCompositing();
+
+ static PassRefPtr<LayerTreeHostCAWin> create(WebPage*);
+ virtual ~LayerTreeHostCAWin();
+
+private:
+ explicit LayerTreeHostCAWin(WebPage*);
+
+ static void contextDidChangeCallback(WKCACFViewRef, void* info);
+ void contextDidChange();
+
+ // LayerTreeHost
+ virtual void invalidate();
+ virtual void forceRepaint();
+ virtual void sizeDidChange(const WebCore::IntSize& newSize);
+ virtual void scheduleLayerFlush();
+ virtual bool participatesInDisplay();
+ virtual bool needsDisplay();
+ virtual double timeUntilNextDisplay();
+ virtual void display(UpdateInfo&);
+
+ // LayerTreeHostCA
+ virtual void platformInitialize(LayerTreeContext&);
+
+ // AbstractCACFLayerTreeHost
+ virtual WebCore::PlatformCALayer* rootLayer() const;
+ virtual void addPendingAnimatedLayer(PassRefPtr<WebCore::PlatformCALayer>);
+ virtual void layerTreeDidChange();
+ virtual void flushPendingLayerChangesNow();
+
+ RetainPtr<WKCACFViewRef> m_view;
+ HashSet<RefPtr<WebCore::PlatformCALayer> > m_pendingAnimatedLayers;
+ bool m_isFlushingLayerChanges;
+ double m_nextDisplayTime;
+};
+
+} // namespace WebKit
+
+#endif // HAVE(WKQCA)
+
+#endif // LayerTreeHostCAWin_h
diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp
new file mode 100644
index 0000000..57c9977
--- /dev/null
+++ b/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 "WebPage.h"
+
+#include "NotImplemented.h"
+#include "WebEvent.h"
+#include "WindowsKeyboardCodes.h"
+#include <WebCore/FocusController.h>
+#include <WebCore/Frame.h>
+#include <WebCore/KeyboardEvent.h>
+#include <WebCore/Page.h>
+#include <WebCore/PlatformKeyboardEvent.h>
+#include <WebCore/Settings.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+void WebPage::platformInitialize()
+{
+ notImplemented();
+}
+
+void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
+{
+ notImplemented();
+}
+
+static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
+{
+ page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
+}
+
+bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
+{
+ if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown)
+ return false;
+
+ switch (keyboardEvent.windowsVirtualKeyCode()) {
+ case VK_BACK:
+ if (keyboardEvent.shiftKey())
+ m_page->goForward();
+ else
+ m_page->goBack();
+ break;
+ case VK_SPACE:
+ scroll(m_page.get(), keyboardEvent.shiftKey() ? ScrollUp : ScrollDown, ScrollByPage);
+ break;
+ case VK_LEFT:
+ scroll(m_page.get(), ScrollLeft, ScrollByLine);
+ break;
+ case VK_RIGHT:
+ scroll(m_page.get(), ScrollRight, ScrollByLine);
+ break;
+ case VK_UP:
+ scroll(m_page.get(), ScrollUp, ScrollByLine);
+ break;
+ case VK_DOWN:
+ scroll(m_page.get(), ScrollDown, ScrollByLine);
+ break;
+ case VK_HOME:
+ scroll(m_page.get(), ScrollUp, ScrollByDocument);
+ break;
+ case VK_END:
+ scroll(m_page.get(), ScrollDown, ScrollByDocument);
+ break;
+ case VK_PRIOR:
+ scroll(m_page.get(), ScrollUp, ScrollByPage);
+ break;
+ case VK_NEXT:
+ scroll(m_page.get(), ScrollDown, ScrollByPage);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool WebPage::platformHasLocalDataForURL(const WebCore::KURL&)
+{
+ // FIXME: Implement
+ notImplemented();
+ return false;
+}
+
+String WebPage::cachedResponseMIMETypeForURL(const WebCore::KURL&)
+{
+ // FIXME: Implement
+ return String();
+}
+
+bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest&)
+{
+ // FIXME: Implement
+ return true;
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm
index 8d81889..d7b352c 100644
--- a/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm
+++ b/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm
@@ -27,10 +27,13 @@
#import "WebPage.h"
#import "AccessibilityWebPageObject.h"
+#import "AttributedString.h"
#import "DataReference.h"
+#import "EditorState.h"
#import "PluginView.h"
#import "WebCoreArgumentCoders.h"
#import "WebEvent.h"
+#import "WebEventConversion.h"
#import "WebFrame.h"
#import "WebPageProxyMessages.h"
#import "WebProcess.h"
@@ -39,6 +42,7 @@
#import <WebCore/Frame.h>
#import <WebCore/FrameView.h>
#import <WebCore/HitTestResult.h>
+#import <WebCore/HTMLConverter.h>
#import <WebCore/KeyboardEvent.h>
#import <WebCore/Page.h>
#import <WebCore/PlatformKeyboardEvent.h>
@@ -53,6 +57,8 @@ using namespace WebCore;
namespace WebKit {
+static PassRefPtr<Range> convertToRange(Frame*, NSRange);
+
void WebPage::platformInitialize()
{
m_page->addSchedulePair(SchedulePair::create([NSRunLoop currentRunLoop], kCFRunLoopCommonModes));
@@ -77,68 +83,131 @@ void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
{
}
-bool WebPage::interceptEditingKeyboardEvent(KeyboardEvent* evt, bool shouldSaveCommand)
+typedef HashMap<String, String> SelectorNameMap;
+
+// Map selectors into Editor command names.
+// This is not needed for any selectors that have the same name as the Editor command.
+static const SelectorNameMap* createSelectorExceptionMap()
+{
+ SelectorNameMap* map = new HashMap<String, String>;
+
+ map->add("insertNewlineIgnoringFieldEditor:", "InsertNewline");
+ map->add("insertParagraphSeparator:", "InsertNewline");
+ map->add("insertTabIgnoringFieldEditor:", "InsertTab");
+ map->add("pageDown:", "MovePageDown");
+ map->add("pageDownAndModifySelection:", "MovePageDownAndModifySelection");
+ map->add("pageUp:", "MovePageUp");
+ map->add("pageUpAndModifySelection:", "MovePageUpAndModifySelection");
+
+ return map;
+}
+
+static String commandNameForSelectorName(const String& selectorName)
+{
+ // Check the exception map first.
+ static const SelectorNameMap* exceptionMap = createSelectorExceptionMap();
+ SelectorNameMap::const_iterator it = exceptionMap->find(selectorName);
+ if (it != exceptionMap->end())
+ return it->second;
+
+ // Remove the trailing colon.
+ // No need to capitalize the command name since Editor command names are not case sensitive.
+ size_t selectorNameLength = selectorName.length();
+ if (selectorNameLength < 2 || selectorName[selectorNameLength - 1] != ':')
+ return String();
+ return selectorName.left(selectorNameLength - 1);
+}
+
+static Frame* frameForEvent(KeyboardEvent* event)
{
- Node* node = evt->target()->toNode();
+ Node* node = event->target()->toNode();
ASSERT(node);
Frame* frame = node->document()->frame();
ASSERT(frame);
+ return frame;
+}
+
+bool WebPage::executeKeypressCommandsInternal(const Vector<WebCore::KeypressCommand>& commands, KeyboardEvent* event)
+{
+ Frame* frame = frameForEvent(event);
+ ASSERT(frame->page() == corePage());
+
+ bool eventWasHandled = false;
+ for (size_t i = 0; i < commands.size(); ++i) {
+ if (commands[i].commandName == "insertText:") {
+ ASSERT(!frame->editor()->hasComposition());
+
+ if (!frame->editor()->canEdit())
+ continue;
+
+ // An insertText: might be handled by other responders in the chain if we don't handle it.
+ // One example is space bar that results in scrolling down the page.
+ eventWasHandled |= frame->editor()->insertText(commands[i].text, event);
+ } else {
+ Editor::Command command = frame->editor()->command(commandNameForSelectorName(commands[i].commandName));
+ if (command.isSupported()) {
+ bool commandExecutedByEditor = command.execute(event);
+ eventWasHandled |= commandExecutedByEditor;
+ if (!commandExecutedByEditor) {
+ bool performedNonEditingBehavior = event->keyEvent()->type() == PlatformKeyboardEvent::RawKeyDown && performNonEditingBehaviorForSelector(commands[i].commandName);
+ eventWasHandled |= performedNonEditingBehavior;
+ }
+ } else {
+ bool commandWasHandledByUIProcess = false;
+ WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::ExecuteSavedCommandBySelector(commands[i].commandName),
+ Messages::WebPageProxy::ExecuteSavedCommandBySelector::Reply(commandWasHandledByUIProcess), m_pageID);
+ eventWasHandled |= commandWasHandledByUIProcess;
+ }
+ }
+ }
+ return eventWasHandled;
+}
+
+bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* event, bool saveCommands)
+{
+ ASSERT(!saveCommands || event->keypressCommands().isEmpty()); // Save commands once for each event.
+
+ Frame* frame = frameForEvent(event);
- const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
- if (!keyEvent)
+ const PlatformKeyboardEvent* platformEvent = event->keyEvent();
+ if (!platformEvent)
return false;
- const Vector<KeypressCommand>& commands = evt->keypressCommands();
- bool hasKeypressCommand = !commands.isEmpty();
-
+ Vector<KeypressCommand>& commands = event->keypressCommands();
+
+ if ([platformEvent->macEvent() type] == NSFlagsChanged)
+ return false;
+
bool eventWasHandled = false;
- if (shouldSaveCommand || !hasKeypressCommand) {
- Vector<KeypressCommand> commandsList;
- Vector<CompositionUnderline> underlines;
- unsigned start;
- unsigned end;
- if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::InterpretKeyEvent(keyEvent->type()),
- Messages::WebPageProxy::InterpretKeyEvent::Reply(commandsList, start, end, underlines),
- m_pageID, CoreIPC::Connection::NoTimeout))
+ if (saveCommands) {
+ KeyboardEvent* oldEvent = m_keyboardEventBeingInterpreted;
+ m_keyboardEventBeingInterpreted = event;
+ bool sendResult = WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::InterpretQueuedKeyEvent(editorState()),
+ Messages::WebPageProxy::InterpretQueuedKeyEvent::Reply(eventWasHandled, commands), m_pageID);
+ m_keyboardEventBeingInterpreted = oldEvent;
+ if (!sendResult)
+ return false;
+
+ // An input method may make several actions per keypress. For example, pressing Return with Korean IM both confirms it and sends a newline.
+ // IM-like actions are handled immediately (so the return value from UI process is true), but there are saved commands that
+ // should be handled like normal text input after DOM event dispatch.
+ if (!event->keypressCommands().isEmpty())
return false;
- if (commandsList.isEmpty())
- return eventWasHandled;
-
- if (commandsList[0].commandName == "setMarkedText") {
- frame->editor()->setComposition(commandsList[0].text, underlines, start, end);
- eventWasHandled = true;
- } else if (commandsList[0].commandName == "insertText" && frame->editor()->hasComposition()) {
- frame->editor()->confirmComposition(commandsList[0].text);
- eventWasHandled = true;
- } else if (commandsList[0].commandName == "unmarkText") {
- frame->editor()->confirmComposition();
- eventWasHandled = true;
- } else {
- for (size_t i = 0; i < commandsList.size(); i++)
- evt->keypressCommands().append(commandsList[i]);
- }
} else {
- size_t size = commands.size();
- // Are there commands that would just cause text insertion if executed via Editor?
+ // Are there commands that could just cause text insertion if executed via Editor?
// WebKit doesn't have enough information about mode to decide how they should be treated, so we leave it upon WebCore
// to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
// (e.g. Tab that inserts a Tab character, or Enter).
bool haveTextInsertionCommands = false;
- for (size_t i = 0; i < size; ++i) {
- if (frame->editor()->command(commands[i].commandName).isTextInsertion())
+ for (size_t i = 0; i < commands.size(); ++i) {
+ if (frame->editor()->command(commandNameForSelectorName(commands[i].commandName)).isTextInsertion())
haveTextInsertionCommands = true;
}
- if (!haveTextInsertionCommands || keyEvent->type() == PlatformKeyboardEvent::Char) {
- for (size_t i = 0; i < size; ++i) {
- if (commands[i].commandName == "insertText") {
- // Don't insert null or control characters as they can result in unexpected behaviour
- if (evt->charCode() < ' ')
- return false;
- eventWasHandled = frame->editor()->insertText(commands[i].text, evt);
- } else
- if (frame->editor()->command(commands[i].commandName).isSupported())
- eventWasHandled = frame->editor()->command(commands[i].commandName).execute(evt);
- }
+ // If there are no text insertion commands, default keydown handler is the right time to execute the commands.
+ // Keypress (Char event) handler is the latest opportunity to execute.
+ if (!haveTextInsertionCommands || platformEvent->type() == PlatformKeyboardEvent::Char) {
+ eventWasHandled = executeKeypressCommandsInternal(event->keypressCommands(), event);
+ event->keypressCommands().clear();
}
}
return eventWasHandled;
@@ -152,6 +221,54 @@ void WebPage::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdenti
}
}
+void WebPage::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, EditorState& newState)
+{
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+
+ if (frame->selection()->isContentEditable()) {
+ RefPtr<Range> replacementRange;
+ if (replacementRangeStart != NSNotFound) {
+ replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart));
+ frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY));
+ }
+
+ frame->editor()->setComposition(text, underlines, selectionStart, selectionEnd);
+ }
+
+ newState = editorState();
+}
+
+void WebPage::confirmComposition(EditorState& newState)
+{
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+
+ frame->editor()->confirmComposition();
+
+ newState = editorState();
+}
+
+void WebPage::insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, bool& handled, EditorState& newState)
+{
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+
+ RefPtr<Range> replacementRange;
+ if (replacementRangeStart != NSNotFound) {
+ replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart));
+ frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY));
+ }
+
+ if (!frame->editor()->hasComposition()) {
+ // An insertText: might be handled by other responders in the chain if we don't handle it.
+ // One example is space bar that results in scrolling down the page.
+ handled = frame->editor()->insertText(text, m_keyboardEventBeingInterpreted);
+ } else {
+ handled = true;
+ frame->editor()->confirmComposition(text);
+ }
+
+ newState = editorState();
+}
+
void WebPage::getMarkedRange(uint64_t& location, uint64_t& length)
{
location = NSNotFound;
@@ -159,38 +276,59 @@ void WebPage::getMarkedRange(uint64_t& location, uint64_t& length)
Frame* frame = m_page->focusController()->focusedOrMainFrame();
if (!frame)
return;
-
- getLocationAndLengthFromRange(frame->editor()->compositionRange().get(), location, length);
-}
+ RefPtr<Range> range = frame->editor()->compositionRange();
+ size_t locationSize;
+ size_t lengthSize;
+ if (range && TextIterator::locationAndLengthFromRange(range.get(), locationSize, lengthSize)) {
+ location = static_cast<uint64_t>(locationSize);
+ length = static_cast<uint64_t>(lengthSize);
+ }
+}
-static PassRefPtr<Range> characterRangeAtPositionForPoint(Frame* frame, const VisiblePosition& position, const IntPoint& point)
+void WebPage::getSelectedRange(uint64_t& location, uint64_t& length)
{
- if (position.isNull())
- return 0;
+ location = NSNotFound;
+ length = 0;
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+ if (!frame)
+ return;
- VisiblePosition previous = position.previous();
- if (previous.isNotNull()) {
- RefPtr<Range> previousCharacterRange = makeRange(previous, position);
- IntRect rect = frame->editor()->firstRectForRange(previousCharacterRange.get());
- if (rect.contains(point))
- return previousCharacterRange.release();
- }
-
- VisiblePosition next = position.next();
- if (next.isNotNull()) {
- RefPtr<Range> nextCharacterRange = makeRange(position, next);
- IntRect rect = frame->editor()->firstRectForRange(nextCharacterRange.get());
- if (rect.contains(point))
- return nextCharacterRange.release();
+ size_t locationSize;
+ size_t lengthSize;
+ RefPtr<Range> range = frame->selection()->toNormalizedRange();
+ if (range && TextIterator::locationAndLengthFromRange(range.get(), locationSize, lengthSize)) {
+ location = static_cast<uint64_t>(locationSize);
+ length = static_cast<uint64_t>(lengthSize);
}
-
- return 0;
}
-static PassRefPtr<Range> characterRangeAtPoint(Frame* frame, const IntPoint& point)
+void WebPage::getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString& result)
{
- return characterRangeAtPositionForPoint(frame, frame->visiblePositionForPoint(point), point);
+ NSRange nsRange = NSMakeRange(location, length - location);
+
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+ if (!frame)
+ return;
+
+ if (frame->selection()->isNone() || !frame->selection()->isContentEditable() || frame->selection()->isInPasswordField())
+ return;
+
+ RefPtr<Range> range = convertToRange(frame, nsRange);
+ if (!range)
+ return;
+
+ result.string = [WebHTMLConverter editingAttributedStringFromRange:range.get()];
+ NSAttributedString* attributedString = result.string.get();
+
+ // [WebHTMLConverter editingAttributedStringFromRange:] insists on inserting a trailing
+ // whitespace at the end of the string which breaks the ATOK input method. <rdar://problem/5400551>
+ // To work around this we truncate the resultant string to the correct length.
+ if ([attributedString length] > nsRange.length) {
+ ASSERT([attributedString length] == nsRange.length + 1);
+ ASSERT([[attributedString string] characterAtIndex:nsRange.length] == '\n' || [[attributedString string] characterAtIndex:nsRange.length] == ' ');
+ result.string = [attributedString attributedSubstringFromRange:NSMakeRange(0, nsRange.length)];
+ }
}
void WebPage::characterIndexForPoint(IntPoint point, uint64_t& index)
@@ -203,15 +341,17 @@ void WebPage::characterIndexForPoint(IntPoint point, uint64_t& index)
HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(point, false);
frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame();
- RefPtr<Range> range = characterRangeAtPoint(frame, result.point());
+ RefPtr<Range> range = frame->rangeForPoint(result.point());
if (!range)
return;
- uint64_t length;
- getLocationAndLengthFromRange(range.get(), index, length);
+ size_t location;
+ size_t length;
+ if (TextIterator::locationAndLengthFromRange(range.get(), location, length))
+ index = static_cast<uint64_t>(location);
}
-static PassRefPtr<Range> convertToRange(Frame* frame, NSRange nsrange)
+PassRefPtr<Range> convertToRange(Frame* frame, NSRange nsrange)
{
if (nsrange.location > INT_MAX)
return 0;
@@ -246,6 +386,12 @@ void WebPage::firstRectForCharacterRange(uint64_t location, uint64_t length, Web
resultRect = frame->view()->contentsToWindow(rect);
}
+void WebPage::executeKeypressCommands(const Vector<WebCore::KeypressCommand>& commands, bool& handled, EditorState& newState)
+{
+ handled = executeKeypressCommandsInternal(commands, m_keyboardEventBeingInterpreted);
+ newState = editorState();
+}
+
static bool isPositionInRange(const VisiblePosition& position, Range* range)
{
RefPtr<Range> positionRange = makeRange(position, position);
@@ -284,12 +430,12 @@ void WebPage::performDictionaryLookupAtLocation(const FloatPoint& floatPoint)
frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame();
IntPoint translatedPoint = frame->view()->windowToContents(point);
- VisiblePosition position = frame->visiblePositionForPoint(translatedPoint);
// Don't do anything if there is no character at the point.
- if (!characterRangeAtPositionForPoint(frame, position, translatedPoint))
+ if (!frame->rangeForPoint(translatedPoint))
return;
+ VisiblePosition position = frame->visiblePositionForPoint(translatedPoint);
VisibleSelection selection = m_page->focusController()->focusedOrMainFrame()->selection()->selection();
if (shouldUseSelection(position, selection)) {
performDictionaryLookupForSelection(DictionaryPopupInfo::HotKey, frame, selection);
@@ -378,96 +524,54 @@ void WebPage::performDictionaryLookupForRange(DictionaryPopupInfo::Type type, Fr
dictionaryPopupInfo.type = type;
dictionaryPopupInfo.origin = FloatPoint(rangeRect.x(), rangeRect.y());
dictionaryPopupInfo.fontInfo.fontAttributeDictionary = fontDescriptorAttributes;
+#if !defined(BUILDING_ON_SNOW_LEOPARD)
dictionaryPopupInfo.options = (CFDictionaryRef)options;
+#endif
send(Messages::WebPageProxy::DidPerformDictionaryLookup(rangeText, dictionaryPopupInfo));
}
-bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
+bool WebPage::performNonEditingBehaviorForSelector(const String& selector)
{
- if (keyboardEvent.type() != WebEvent::KeyDown)
- return false;
-
- // FIXME: This should be in WebCore.
-
- switch (keyboardEvent.windowsVirtualKeyCode()) {
- case VK_BACK:
- if (keyboardEvent.shiftKey())
- m_page->goForward();
- else
- m_page->goBack();
- break;
- case VK_SPACE:
- if (keyboardEvent.shiftKey())
- logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage);
- else
- logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage);
- break;
- case VK_PRIOR:
- logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage);
- break;
- case VK_NEXT:
- logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage);
- break;
- case VK_HOME:
- logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByDocument);
- break;
- case VK_END:
- logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByDocument);
- break;
- case VK_UP:
- if (keyboardEvent.shiftKey())
- return false;
- if (keyboardEvent.metaKey()) {
- scroll(m_page.get(), ScrollUp, ScrollByDocument);
- scroll(m_page.get(), ScrollLeft, ScrollByDocument);
- } else if (keyboardEvent.altKey() || keyboardEvent.controlKey())
- scroll(m_page.get(), ScrollUp, ScrollByPage);
- else
- scroll(m_page.get(), ScrollUp, ScrollByLine);
- break;
- case VK_DOWN:
- if (keyboardEvent.shiftKey())
- return false;
- if (keyboardEvent.metaKey()) {
- scroll(m_page.get(), ScrollDown, ScrollByDocument);
- scroll(m_page.get(), ScrollLeft, ScrollByDocument);
- } else if (keyboardEvent.altKey() || keyboardEvent.controlKey())
- scroll(m_page.get(), ScrollDown, ScrollByPage);
- else
- scroll(m_page.get(), ScrollDown, ScrollByLine);
- break;
- case VK_LEFT:
- if (keyboardEvent.shiftKey())
- return false;
- if (keyboardEvent.metaKey())
- m_page->goBack();
- else {
- if (keyboardEvent.altKey() || keyboardEvent.controlKey())
- scroll(m_page.get(), ScrollLeft, ScrollByPage);
- else
- scroll(m_page.get(), ScrollLeft, ScrollByLine);
- }
- break;
- case VK_RIGHT:
- if (keyboardEvent.shiftKey())
- return false;
- if (keyboardEvent.metaKey())
- m_page->goForward();
- else {
- if (keyboardEvent.altKey() || keyboardEvent.controlKey())
- scroll(m_page.get(), ScrollRight, ScrollByPage);
- else
- scroll(m_page.get(), ScrollRight, ScrollByLine);
- }
- break;
- default:
+ // FIXME: All these selectors have corresponding Editor commands, but the commands only work in editable content.
+ // Should such non-editing behaviors be implemented in Editor or EventHandler::defaultArrowEventHandler() perhaps?
+ if (selector == "moveUp:")
+ scroll(m_page.get(), ScrollUp, ScrollByLine);
+ else if (selector == "moveToBeginningOfParagraph:")
+ scroll(m_page.get(), ScrollUp, ScrollByPage);
+ else if (selector == "moveToBeginningOfDocument:") {
+ scroll(m_page.get(), ScrollUp, ScrollByDocument);
+ scroll(m_page.get(), ScrollLeft, ScrollByDocument);
+ } else if (selector == "moveDown:")
+ scroll(m_page.get(), ScrollDown, ScrollByLine);
+ else if (selector == "moveToEndOfParagraph:")
+ scroll(m_page.get(), ScrollDown, ScrollByPage);
+ else if (selector == "moveToEndOfDocument:") {
+ scroll(m_page.get(), ScrollDown, ScrollByDocument);
+ scroll(m_page.get(), ScrollLeft, ScrollByDocument);
+ } else if (selector == "moveLeft:")
+ scroll(m_page.get(), ScrollLeft, ScrollByLine);
+ else if (selector == "moveWordLeft:")
+ scroll(m_page.get(), ScrollLeft, ScrollByPage);
+ else if (selector == "moveToLeftEndOfLine:")
+ m_page->goBack();
+ else if (selector == "moveRight:")
+ scroll(m_page.get(), ScrollRight, ScrollByLine);
+ else if (selector == "moveWordRight:")
+ scroll(m_page.get(), ScrollRight, ScrollByPage);
+ else if (selector == "moveToRightEndOfLine:")
+ m_page->goForward();
+ else
return false;
- }
return true;
}
+bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent&)
+{
+ return false;
+}
+
void WebPage::registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elementToken, const CoreIPC::DataReference& windowToken)
{
#if !defined(BUILDING_ON_SNOW_LEOPARD)
@@ -484,6 +588,10 @@ void WebPage::registerUIProcessAccessibilityTokens(const CoreIPC::DataReference&
void WebPage::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes, bool& result)
{
Frame* frame = m_page->focusController()->focusedOrMainFrame();
+ if (!frame || frame->selection()->isNone()) {
+ result = false;
+ return;
+ }
frame->editor()->writeSelectionToPasteboard(pasteboardName, pasteboardTypes);
result = true;
}
@@ -491,6 +599,10 @@ void WebPage::writeSelectionToPasteboard(const String& pasteboardName, const Vec
void WebPage::readSelectionFromPasteboard(const String& pasteboardName, bool& result)
{
Frame* frame = m_page->focusController()->focusedOrMainFrame();
+ if (!frame || frame->selection()->isNone()) {
+ result = false;
+ return;
+ }
frame->editor()->readSelectionFromPasteboard(pasteboardName);
result = true;
}
@@ -548,10 +660,39 @@ void WebPage::setDragSource(NSObject *dragSource)
void WebPage::platformDragEnded()
{
+ // The draggedImage method releases its responder; we retain here to balance that.
+ [m_dragSource.get() retain];
// The drag source we care about here is NSFilePromiseDragSource, which doesn't look at
// the arguments. It's OK to just pass arbitrary constant values, so we just pass all zeroes.
[m_dragSource.get() draggedImage:nil endedAt:NSZeroPoint operation:NSDragOperationNone];
m_dragSource = nullptr;
}
+void WebPage::shouldDelayWindowOrderingEvent(const WebKit::WebMouseEvent& event, bool& result)
+{
+ result = false;
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+ if (!frame)
+ return;
+
+ HitTestResult hitResult = frame->eventHandler()->hitTestResultAtPoint(event.position(), true);
+ if (hitResult.isSelected())
+ result = frame->eventHandler()->eventMayStartDrag(platform(event));
+}
+
+void WebPage::acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent& event, bool& result)
+{
+ result = false;
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+ if (!frame)
+ return;
+
+ HitTestResult hitResult = frame->eventHandler()->hitTestResultAtPoint(event.position(), true);
+ frame->eventHandler()->setActivationEventNumber(eventNumber);
+ if (hitResult.isSelected())
+ result = frame->eventHandler()->eventMayStartDrag(platform(event));
+ else
+ result = !!hitResult.scrollbar();
+}
+
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/win/LayerTreeHostWin.cpp b/Source/WebKit2/WebProcess/WebPage/win/LayerTreeHostWin.cpp
new file mode 100644
index 0000000..57c04bb
--- /dev/null
+++ b/Source/WebKit2/WebProcess/WebPage/win/LayerTreeHostWin.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 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 "LayerTreeHost.h"
+
+#if USE(CA)
+#include "LayerTreeHostCAWin.h"
+#endif
+
+namespace WebKit {
+
+bool LayerTreeHost::supportsAcceleratedCompositing()
+{
+#if USE(CA) && HAVE(WKQCA)
+ return LayerTreeHostCAWin::supportsAcceleratedCompositing();
+#else
+ return false;
+#endif
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/win/WebPageWin.cpp b/Source/WebKit2/WebProcess/WebPage/win/WebPageWin.cpp
index 41bb219..9c7206a 100644
--- a/Source/WebKit2/WebProcess/WebPage/win/WebPageWin.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/win/WebPageWin.cpp
@@ -28,17 +28,22 @@
#include "FontSmoothingLevel.h"
#include "WebEvent.h"
+#include "WebPageProxyMessages.h"
#include "WebPreferencesStore.h"
#include <WebCore/FocusController.h>
#include <WebCore/FontRenderingMode.h>
#include <WebCore/Frame.h>
#include <WebCore/FrameView.h>
+#include <WebCore/HitTestRequest.h>
+#include <WebCore/HitTestResult.h>
#include <WebCore/KeyboardEvent.h>
#include <WebCore/Page.h>
#include <WebCore/PlatformKeyboardEvent.h>
+#include <WebCore/RenderLayer.h>
+#include <WebCore/RenderView.h>
#include <WebCore/ResourceHandle.h>
#include <WebCore/Settings.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include <WebKitSystemInterface/WebKitSystemInterface.h>
#endif
#include <WinUser.h>
@@ -62,7 +67,7 @@ void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store)
{
FontSmoothingLevel fontSmoothingLevel = static_cast<FontSmoothingLevel>(store.getUInt32ValueForKey(WebPreferencesKey::fontSmoothingLevelKey()));
-#if PLATFORM(CG)
+#if USE(CG)
FontSmoothingLevel adjustedLevel = fontSmoothingLevel;
if (adjustedLevel == FontSmoothingLevelWindows)
adjustedLevel = FontSmoothingLevelMedium;
@@ -351,4 +356,89 @@ void WebPage::getSelectedText(String& text)
text = selectedRange->text();
}
+void WebPage::gestureWillBegin(const WebCore::IntPoint& point, bool& canBeginPanning)
+{
+ m_gestureReachedScrollingLimit = false;
+
+ bool hitScrollbar = false;
+
+ HitTestRequest request(HitTestRequest::ReadOnly);
+ for (Frame* childFrame = m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) {
+ ScrollView* scollView = childFrame->view();
+ if (!scollView)
+ break;
+
+ RenderView* renderView = childFrame->document()->renderView();
+ if (!renderView)
+ break;
+
+ RenderLayer* layer = renderView->layer();
+ if (!layer)
+ break;
+
+ HitTestResult result = scollView->windowToContents(point);
+ layer->hitTest(request, result);
+ m_gestureTargetNode = result.innerNode();
+
+ if (!hitScrollbar)
+ hitScrollbar = result.scrollbar();
+ }
+
+ if (hitScrollbar) {
+ canBeginPanning = false;
+ return;
+ }
+
+ if (!m_gestureTargetNode) {
+ canBeginPanning = false;
+ return;
+ }
+
+ for (RenderObject* renderer = m_gestureTargetNode->renderer(); renderer; renderer = renderer->parent()) {
+ if (renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) {
+ canBeginPanning = true;
+ return;
+ }
+ }
+
+ canBeginPanning = false;
+}
+
+static bool scrollbarAtTopOrBottomOfDocument(Scrollbar* scrollbar)
+{
+ ASSERT_ARG(scrollbar, scrollbar);
+ return !scrollbar->currentPos() || scrollbar->currentPos() >= scrollbar->maximum();
+}
+
+void WebPage::gestureDidScroll(const IntSize& size)
+{
+ ASSERT_ARG(size, !size.isZero());
+
+ if (!m_gestureTargetNode || !m_gestureTargetNode->renderer() || !m_gestureTargetNode->renderer()->enclosingLayer())
+ return;
+
+ Scrollbar* verticalScrollbar = 0;
+ if (Frame* frame = m_page->mainFrame()) {
+ if (ScrollView* view = frame->view())
+ verticalScrollbar = view->verticalScrollbar();
+ }
+
+ m_gestureTargetNode->renderer()->enclosingLayer()->scrollByRecursively(size.width(), size.height());
+ bool gestureReachedScrollingLimit = verticalScrollbar && scrollbarAtTopOrBottomOfDocument(verticalScrollbar);
+
+ // FIXME: We really only want to update this state if the state was updated via scrolling the main frame,
+ // not scrolling something in a main frame when the main frame had already reached its scrolling limit.
+
+ if (gestureReachedScrollingLimit == m_gestureReachedScrollingLimit)
+ return;
+
+ send(Messages::WebPageProxy::SetGestureReachedScrollingLimit(gestureReachedScrollingLimit));
+ m_gestureReachedScrollingLimit = gestureReachedScrollingLimit;
+}
+
+void WebPage::gestureDidEnd()
+{
+ m_gestureTargetNode = nullptr;
+}
+
} // namespace WebKit