Skip to content

Instantly share code, notes, and snippets.

@kenchris
Created January 24, 2012 15:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenchris/1670648 to your computer and use it in GitHub Desktop.
Save kenchris/1670648 to your computer and use it in GitHub Desktop.
commit 3224d13233952589e49b119ba773ee1ab6c99692
Author: Kenneth Rohde Christiansen <kenneth@webkit.org>
Date: Mon Jan 23 16:06:02 2012 +0100
WIP: tap highlighting
diff --git a/Source/WebCore/Target.pri b/Source/WebCore/Target.pri
index 457db0c..45d9858 100644
--- a/Source/WebCore/Target.pri
+++ b/Source/WebCore/Target.pri
@@ -985,6 +985,7 @@ SOURCES += \
page/FrameView.cpp \
page/Geolocation.cpp \
page/GeolocationController.cpp \
+ page/GestureTapHighlighter.cpp \
page/GroupSettings.cpp \
page/History.cpp \
page/Location.cpp \
@@ -2044,6 +2045,7 @@ HEADERS += \
page/FrameView.h \
page/Geolocation.h \
page/Geoposition.h \
+ page/GestureTapHighlighter.h\
page/GroupSettings.h \
page/History.h \
page/Location.h \
diff --git a/Source/WebCore/page/GestureTapHighlighter.cpp b/Source/WebCore/page/GestureTapHighlighter.cpp
new file mode 100644
index 0000000..8751eb1
--- /dev/null
+++ b/Source/WebCore/page/GestureTapHighlighter.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GestureTapHighlighter.h"
+
+#include "Element.h"
+#include "Frame.h"
+#include "FrameView.h"
+
+#include "GraphicsContext.h"
+#include "GraphicsTypes.h"
+#include "Node.h"
+#include "Page.h"
+#include "RenderBoxModelObject.h"
+#include "RenderInline.h"
+#include "RenderObject.h"
+#include "RenderLayer.h"
+
+namespace WebCore {
+
+namespace{
+
+inline LayoutSize frameToMainFrameOffset(Frame* frame)
+{
+ LayoutPoint mainFramePoint = frame->page()->mainFrame()->view()->rootViewToContents(frame->view()->contentsToRootView(LayoutPoint()));
+ return toLayoutSize(mainFramePoint);
+}
+
+} // anonymous namespace
+
+namespace GestureTapHighlighter {
+
+void drawHighlight(GraphicsContext* context, Node* node)
+{
+ RenderObject* renderer = node->renderer();
+ Frame* containingFrame = node->document()->frame();
+
+ if (!renderer || !containingFrame || !context)
+ return;
+
+ LayoutSize mainFrameOffset = frameToMainFrameOffset(containingFrame);
+
+ // Don't translate the context if the frame is rendered in page coordinates.
+ FrameView* view = containingFrame->page()->mainFrame()->view();
+ if (!view->delegatesScrolling()) {
+ FloatRect visibleRect = view->visibleContentRect();
+ context->translate(-visibleRect.x(), -visibleRect.y());
+ }
+
+ if (renderer->isBox() || renderer->isRenderInline()) {
+ LayoutRect contentBox;
+ LayoutRect paddingBox;
+ LayoutRect borderBox;
+
+ if (renderer->isBox()) {
+ RenderBox* renderBox = toRenderBox(renderer);
+ contentBox = renderBox->contentBoxRect();
+ paddingBox = LayoutRect(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
+ contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
+ borderBox = LayoutRect(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
+ paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
+ } else {
+ RenderInline* renderInline = toRenderInline(renderer);
+ // RenderInline's bounding box includes paddings and borders, excludes margins.
+ borderBox = renderInline->linesBoundingBox();
+ }
+
+ RoundedRect rect(borderBox);
+ rect.expandRadii(10);
+ rect.inflateWithRadii(5);
+
+ AffineTransform trans;
+
+ LayoutPoint referencePoint;
+ while (renderer) {
+ RenderObject* nextContainer = renderer->container();
+ if (!nextContainer)
+ break;
+
+ LayoutSize containerOffset = renderer->offsetFromContainer(nextContainer, referencePoint);
+ TransformationMatrix t;
+ renderer->getTransformFromContainer(nextContainer, containerOffset, t);
+
+ trans = t.toAffineTransform() * trans;
+ referencePoint.move(containerOffset);
+ renderer = nextContainer;
+ }
+
+ rect.move(mainFrameOffset);
+
+ context->concatCTM(trans);
+ context->fillRoundedRect(rect, node->renderer()->style()->tapHighlightColor(), ColorSpaceDeviceRGB);
+ }
+}
+
+} // namespace GestureTapHighlighter
+
+} // namespace WebCore
diff --git a/Source/WebCore/page/GestureTapHighlighter.h b/Source/WebCore/page/GestureTapHighlighter.h
new file mode 100644
index 0000000..e8092f3
--- /dev/null
+++ b/Source/WebCore/page/GestureTapHighlighter.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GestureTapHighlighter_h
+#define GestureTapHighlighter_h
+
+namespace WebCore {
+
+class Color;
+class GraphicsContext;
+class Node;
+
+namespace GestureTapHighlighter {
+
+void drawHighlight(GraphicsContext*, Node*);
+
+} // namespace GestureTapHighlighter
+
+} // namespace WebCore
+
+#endif // DOMNodeHighlighter_h
diff --git a/Source/WebKit2/Target.pri b/Source/WebKit2/Target.pri
index 35983f0..7d6e7b0 100644
--- a/Source/WebKit2/Target.pri
+++ b/Source/WebKit2/Target.pri
@@ -348,6 +348,7 @@ HEADERS += \
WebProcess/WebPage/DrawingAreaImpl.h \
WebProcess/WebPage/EventDispatcher.h \
WebProcess/WebPage/FindController.h \
+ WebProcess/WebPage/TapHighlightController.h \
WebProcess/WebPage/PageOverlay.h \
WebProcess/WebPage/WebContextMenu.h \
WebProcess/WebPage/WebFrame.h \
@@ -701,6 +702,7 @@ SOURCES += \
WebProcess/WebPage/EncoderAdapter.cpp \
WebProcess/WebPage/EventDispatcher.cpp \
WebProcess/WebPage/FindController.cpp \
+ WebProcess/WebPage/TapHighlightController.cpp \
WebProcess/WebPage/LayerTreeHost.cpp \
WebProcess/WebPage/PageOverlay.cpp \
WebProcess/WebPage/TiledBackingStoreRemoteTile.cpp \
diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp
index 52ff6c0..1c3f131 100644
--- a/Source/WebKit2/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp
@@ -991,6 +991,16 @@ void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
} else
process()->send(Messages::WebPage::TouchEvent(event), m_pageID);
} else {
+#if PLATFORM(QT)
+ IntPoint activationPoint;
+ if (event.touchPoints().size() == 1) {
+ WebPlatformTouchPoint point = event.touchPoints().at(0);
+ if (point.state() == WebPlatformTouchPoint::TouchPressed)
+ activationPoint = point.position();
+ }
+
+ process()->send(Messages::WebPage::HighlightPotentialActivation(activationPoint), m_pageID);
+#endif
if (m_touchEventQueue.isEmpty()) {
bool isEventHandled = false;
m_pageClient->doneWithTouchEvent(event, isEventHandled);
diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp
index f557ee9..a275d4c 100644
--- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp
+++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp
@@ -97,6 +97,7 @@ QtWebPageEventHandler::QtWebPageEventHandler(WKPageRef pageRef, QQuickWebPage* q
, m_postponeTextInputStateChanged(false)
{
connect(qApp->inputPanel(), SIGNAL(visibleChanged()), this, SLOT(inputPanelVisibleChanged()));
+
}
QtWebPageEventHandler::~QtWebPageEventHandler()
diff --git a/Source/WebKit2/WebProcess/WebPage/TapHighlightController.cpp b/Source/WebKit2/WebProcess/WebPage/TapHighlightController.cpp
new file mode 100644
index 0000000..27bbebd
--- /dev/null
+++ b/Source/WebKit2/WebProcess/WebPage/TapHighlightController.cpp
@@ -0,0 +1,85 @@
+#include "config.h"
+#include "TapHighlightController.h"
+
+#include "ShareableBitmap.h"
+#include "WKPage.h"
+#include "WebCoreArgumentCoders.h"
+#include "WebPage.h"
+#include "WebPageProxyMessages.h"
+#include "WebProcess.h"
+#include <WebCore/FocusController.h>
+#include <WebCore/Frame.h>
+#include <WebCore/FrameView.h>
+#include <WebCore/GraphicsContext.h>
+#include <WebCore/Page.h>
+#include <WebCore/GestureTapHighlighter.h>
+
+#include <WebCore/DOMNodeHighlighter.h>
+
+using namespace std;
+using namespace WebCore;
+
+namespace WebKit {
+
+TapHighlightController::TapHighlightController(WebPage* webPage)
+ : m_webPage(webPage)
+ , m_overlay(0)
+ , m_node(0)
+{
+}
+
+TapHighlightController::~TapHighlightController()
+{
+}
+
+void TapHighlightController::highlight(Node* node)
+{
+ m_node = node;
+
+ if (!m_overlay) {
+ RefPtr<PageOverlay> overlay = PageOverlay::create(this);
+ m_overlay = overlay.get();
+ m_webPage->installPageOverlay(overlay.release());
+ } else
+ m_overlay->setNeedsDisplay();
+}
+
+void TapHighlightController::hideHighlight()
+{
+ if (m_overlay)
+ m_webPage->uninstallPageOverlay(m_overlay, true);
+ ASSERT(!m_overlay);
+}
+
+void TapHighlightController::pageOverlayDestroyed(PageOverlay*)
+{
+}
+
+void TapHighlightController::willMoveToWebPage(PageOverlay*, WebPage* webPage)
+{
+ if (webPage)
+ return;
+
+ // The page overlay is moving away from the web page, reset it.
+ ASSERT(m_overlay);
+ m_overlay = 0;
+}
+
+void TapHighlightController::didMoveToWebPage(PageOverlay*, WebPage*)
+{
+}
+
+void TapHighlightController::drawRect(PageOverlay* pageOverlay, GraphicsContext& graphicsContext, const IntRect& dirtyRect)
+{
+ if (!m_node)
+ return;
+
+ GestureTapHighlighter::drawHighlight(&graphicsContext, m_node);
+}
+
+bool TapHighlightController::mouseEvent(PageOverlay* pageOverlay, const WebMouseEvent& mouseEvent)
+{
+ return false;
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/TapHighlightController.h b/Source/WebKit2/WebProcess/WebPage/TapHighlightController.h
new file mode 100644
index 0000000..b7358c7
--- /dev/null
+++ b/Source/WebKit2/WebProcess/WebPage/TapHighlightController.h
@@ -0,0 +1,46 @@
+#ifndef TapHighlightController_h
+#define TapHighlightController_h
+
+#include "PageOverlay.h"
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+#include "Timer.h"
+
+namespace WebCore {
+ class Frame;
+ class IntRect;
+ class Node;
+}
+
+namespace WebKit {
+
+class WebPage;
+
+class TapHighlightController : private PageOverlay::Client {
+ WTF_MAKE_NONCOPYABLE(TapHighlightController);
+
+public:
+ explicit TapHighlightController(WebPage*);
+ virtual ~TapHighlightController();
+
+ void highlight(WebCore::Node*);
+ void hideHighlight();
+
+private:
+ // PageOverlay::Client.
+ virtual void pageOverlayDestroyed(PageOverlay*);
+ virtual void willMoveToWebPage(PageOverlay*, WebPage*);
+ virtual void didMoveToWebPage(PageOverlay*, WebPage*);
+ virtual bool mouseEvent(PageOverlay*, const WebMouseEvent&);
+ virtual void drawRect(PageOverlay*, WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect);
+
+private:
+ WebPage* m_webPage;
+ PageOverlay* m_overlay;
+ WebCore::Node* m_node;
+};
+
+} // namespace WebKit
+
+#endif // TapHighlightController_h
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
index 365d578..ce204e7 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
@@ -192,6 +192,9 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
#endif
, m_setCanStartMediaTimer(WebProcess::shared().runLoop(), this, &WebPage::setCanStartMediaTimerFired)
, m_findController(this)
+#if PLATFORM(QT)
+ , m_tapHighlightController(this)
+#endif
, m_geolocationPermissionRequestManager(this)
, m_pageID(pageID)
, m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel)
@@ -1420,6 +1423,27 @@ void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& session
}
#if ENABLE(TOUCH_EVENTS)
+#if PLATFORM(QT)
+void WebPage::highlightPotentialActivation(const IntPoint& point)
+{
+ Node* activationNode = 0;
+ Frame* mainframe = m_page->mainFrame();
+
+ if (point != IntPoint::zero()) {
+ HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
+ activationNode = result.innerNode();
+
+ if (!activationNode->isFocusable())
+ activationNode = activationNode->enclosingLinkEventParentOrSelf();
+ }
+
+ if (activationNode)
+ tapHighlightController().highlight(activationNode);
+ else
+ tapHighlightController().hideHighlight();
+}
+#endif
+
static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
{
Frame* frame = page->mainFrame();
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.h b/Source/WebKit2/WebProcess/WebPage/WebPage.h
index 40072cf..473d93b 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.h
@@ -41,6 +41,7 @@
#include "InjectedBundlePageResourceLoadClient.h"
#include "InjectedBundlePageUIClient.h"
#include "MessageSender.h"
+#include "TapHighlightController.h"
#include "Plugin.h"
#include "SandboxExtension.h"
#include "ShareableBitmap.h"
@@ -315,6 +316,10 @@ public:
static const WebEvent* currentEvent();
FindController& findController() { return m_findController; }
+#if PLATFORM(QT)
+ TapHighlightController& tapHighlightController() { return m_tapHighlightController; }
+#endif
+
GeolocationPermissionRequestManager& geolocationPermissionRequestManager() { return m_geolocationPermissionRequestManager; }
NotificationPermissionRequestManager* notificationPermissionRequestManager();
@@ -538,6 +543,9 @@ private:
#if ENABLE(TOUCH_EVENTS)
void touchEvent(const WebTouchEvent&);
void touchEventSyncForTesting(const WebTouchEvent&, bool& handled);
+#if PLATFORM(QT)
+ void highlightPotentialActivation(const WebCore::IntPoint&);
+#endif
#endif
void contextMenuHidden() { m_isShowingContextMenu = false; }
@@ -700,6 +708,9 @@ private:
#endif
FindController m_findController;
+#if PLATFORM(QT)
+ TapHighlightController m_tapHighlightController;
+#endif
RefPtr<PageOverlay> m_pageOverlay;
RefPtr<WebPage> m_underlayPage;
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
index 5a3bb45..6ef0b8b 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
@@ -40,6 +40,9 @@ messages -> WebPage {
#if ENABLE(TOUCH_EVENTS)
TouchEvent(WebKit::WebTouchEvent event)
TouchEventSyncForTesting(WebKit::WebTouchEvent event) -> (bool handled)
+#if PLATFORM(QT)
+ HighlightPotentialActivation(WebCore::IntPoint point)
+#endif
#endif
ContextMenuHidden()
diff --git a/transformtest.html b/transformtest.html
new file mode 100644
index 0000000..feabdf2
--- /dev/null
+++ b/transformtest.html
@@ -0,0 +1,11 @@
+<h1>
+<input style='position:absolute; left:10px; top:10px;' type='text'>
+<input style='position:absolute; left:0px; top:300px; -webkit-transform:skew(30deg) rotate(-40deg) scale(1.2);' type='text'>
+<input style='position:absolute; left:100px; top:100px; -webkit-transform: rotate(-20deg) scale(1.5);' type='button' value='hest#1'>
+<div style='position:absolute; left:400px; top:200px; -webkit-transform:rotate(10deg);'><a href='#'>hest#2</a></div>
+<div style='position:absolute; left:300px; top:100px; -webkit-transform:rotate(70deg);'><div style=' -webkit-transform:rotate(10deg);'><a href='#'>hest#3</a></div></div>
+<div style='-webkit-transform:rotate(70deg); width:200px'><div style='position:absolute; left:400px; top:-100px; -webkit-transform:rotate(10deg);'><a href='#'>hest#4</a></div></div>
+<div><div style='position:absolute; left:400px; top:400px; -webkit-transform:rotate(10deg);'><a href='#'>hest#4a</a></div></div>
+<a href='#' style='position:absolute;left:500px'>hest#5</a>
+<div style='position:absolute;left:640px'><a href='#'>hest#6</a>
+</h1>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment