diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2017-03-26 13:55:39 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-03-26 18:56:55 +0000 |
commit | eaaf1391d58f17bde794d6c8634e092209898941 (patch) | |
tree | ff3702a6509dc9333ffd7515cf078cf69478fcc3 | |
parent | fdcba363c7e7e01790ba4b946e4f53f8600d8a20 (diff) | |
download | qtwebkit-eaaf1391d58f17bde794d6c8634e092209898941.tar.gz |
Import WebKit commit 17e8bfb1ff30314a838b9bf641c112f63a11dba4
Change-Id: Ib6549e44a04300c7b7b07ddc9094b823b37f3183
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
65 files changed, 1477 insertions, 50 deletions
diff --git a/Source/WebCore/PlatformQt.cmake b/Source/WebCore/PlatformQt.cmake index 2e649507d..5d2d01cc9 100644 --- a/Source/WebCore/PlatformQt.cmake +++ b/Source/WebCore/PlatformQt.cmake @@ -26,7 +26,10 @@ list(APPEND WebCore_INCLUDE_DIRECTORIES "${THIRDPARTY_DIR}/ANGLE/include/KHR" "${WEBCORE_DIR}/Modules/gamepad" "${WEBCORE_DIR}/bridge/qt" + "${WEBCORE_DIR}/dom/qt" + "${WEBCORE_DIR}/editing/qt" "${WEBCORE_DIR}/history/qt" + "${WEBCORE_DIR}/page/qt" "${WEBCORE_DIR}/platform/qt" "${WEBCORE_DIR}/platform/audio/qt" "${WEBCORE_DIR}/platform/graphics/egl" @@ -53,10 +56,13 @@ list(APPEND WebCore_SOURCES bridge/qt/qt_pixmapruntime.cpp bridge/qt/qt_runtime.cpp + dom/qt/GestureEvent.cpp + editing/qt/EditorQt.cpp page/qt/DragControllerQt.cpp page/qt/EventHandlerQt.cpp + page/qt/TouchAdjustment.cpp platform/KillRingNone.cpp diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp index 34495b5c7..be23d49f2 100644 --- a/Source/WebCore/dom/Node.cpp +++ b/Source/WebCore/dom/Node.cpp @@ -75,6 +75,10 @@ #include <wtf/text/CString.h> #include <wtf/text/StringBuilder.h> +#if ENABLE(QT_GESTURE_EVENTS) +#include "GestureEvent.h" +#endif + #if ENABLE(INDIE_UI) #include "UIRequestEvent.h" #endif @@ -2149,6 +2153,25 @@ bool Node::dispatchDOMActivateEvent(int detail, PassRefPtr<Event> underlyingEven return event->defaultHandled(); } +#if ENABLE(QT_GESTURE_EVENTS) +bool Node::dispatchGestureEvent(const PlatformGestureEvent& event) +{ + RefPtr<GestureEvent> gestureEvent = GestureEvent::create(document().defaultView(), event); + if (!gestureEvent.get()) + return false; + + if (!is<Element>(*this)) + return false; + if (downcast<Element>(*this).isDisabledFormControl()) + return false; + + EventDispatcher::dispatchEvent(this, *gestureEvent); + + ASSERT(!gestureEvent->defaultPrevented()); + return gestureEvent->defaultHandled() || gestureEvent->defaultPrevented(); +} +#endif + #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS) bool Node::dispatchTouchEvent(TouchEvent& event) { diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h index 842bd8775..480655e32 100644 --- a/Source/WebCore/dom/Node.h +++ b/Source/WebCore/dom/Node.h @@ -75,6 +75,10 @@ class SVGQualifiedName; class ShadowRoot; class TagCollection; +#if ENABLE(QT_GESTURE_EVENTS) +class PlatformGestureEvent; +#endif + #if ENABLE(INDIE_UI) class UIRequestEvent; #endif @@ -534,6 +538,9 @@ public: void dispatchSubtreeModifiedEvent(); bool dispatchDOMActivateEvent(int detail, PassRefPtr<Event> underlyingEvent); +#if ENABLE(QT_GESTURE_EVENTS) + bool dispatchGestureEvent(const PlatformGestureEvent&); +#endif #if ENABLE(TOUCH_EVENTS) virtual bool allowsDoubleTapGesture() const { return true; } #endif diff --git a/Source/WebCore/dom/qt/GestureEvent.cpp b/Source/WebCore/dom/qt/GestureEvent.cpp new file mode 100644 index 000000000..12dddf1cd --- /dev/null +++ b/Source/WebCore/dom/qt/GestureEvent.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GestureEvent.h" + +#if ENABLE(QT_GESTURE_EVENTS) + +#include "Element.h" +#include <wtf/text/AtomicString.h> + +namespace WebCore { + +RefPtr<GestureEvent> GestureEvent::create(AbstractView* view, const PlatformGestureEvent& event) +{ + AtomicString eventType; + switch (event.type()) { + case PlatformEvent::GestureTap: + eventType = eventNames().gesturetapEvent; break; + case PlatformEvent::GestureLongPress: + default: + return 0; + } + return adoptRef(new GestureEvent(eventType, event.timestamp(), view, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(), event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey())); +} + +EventInterface GestureEvent::eventInterface() const +{ + // FIXME: This makes it so we never wrap GestureEvents in the right bindings. + return EventInterfaceType; +} + +GestureEvent::GestureEvent(const AtomicString& type, double timestamp, AbstractView* view, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey) + : MouseRelatedEvent(type, true, true, timestamp, view, 0, IntPoint(screenX, screenY), IntPoint(clientX, clientY) +#if ENABLE(POINTER_LOCK) + , IntPoint(0, 0) +#endif + , ctrlKey, altKey, shiftKey, metaKey) +{ +} + +} // namespace WebCore + +#endif // ENABLE(QT_GESTURE_EVENTS) diff --git a/Source/WebCore/dom/qt/GestureEvent.h b/Source/WebCore/dom/qt/GestureEvent.h new file mode 100644 index 000000000..518923744 --- /dev/null +++ b/Source/WebCore/dom/qt/GestureEvent.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GestureEvent_h +#define GestureEvent_h + +#if ENABLE(QT_GESTURE_EVENTS) + +#include "EventNames.h" +#include "Frame.h" +#include "FrameView.h" +#include "MouseRelatedEvent.h" +#include "PlatformEvent.h" +#include "PlatformGestureEvent.h" + +namespace WebCore { + +class GestureEvent : public MouseRelatedEvent { +public: + virtual ~GestureEvent() { } + + static RefPtr<GestureEvent> create(AbstractView*, const PlatformGestureEvent&); + + EventInterface eventInterface() const override; + +private: + GestureEvent(const AtomicString& type, double timestamp, AbstractView*, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey); +}; + +} // namespace WebCore + +#endif // ENABLE(QT_GESTURE_EVENTS) + +#endif // GestureEvent_h diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp index e8aa9dfb3..a40b4bfab 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp @@ -105,6 +105,15 @@ #include "StyleCachedImageSet.h" #endif +#if ENABLE(QT_GESTURE_EVENTS) +#include "PlatformGestureEvent.h" +#include "ScrollAnimator.h" +#endif + +#if ENABLE(TOUCH_ADJUSTMENT) +#include "TouchAdjustment.h" +#endif + #if ENABLE(IOS_TOUCH_EVENTS) #include "PlatformTouchEventIOS.h" #endif @@ -347,7 +356,7 @@ static inline bool handleWheelEventInAppropriateEnclosingBox(Node* startNode, Wh return false; } -#if (ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)) +#if (ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)) || ENABLE(QT_GESTURE_EVENTS) static inline bool shouldGesturesTriggerActive() { // If the platform we're on supports GestureTapDown and GestureTapCancel then we'll @@ -2704,6 +2713,169 @@ void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEv #endif } +#if ENABLE(QT_GESTURE_EVENTS) +bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) +{ + Node* eventTarget = 0; + Scrollbar* scrollbar = 0; + + IntPoint adjustedPoint = gestureEvent.position(); + HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent; + if (gestureEvent.type() == PlatformEvent::GestureTap) { + // The mouseup event synthesized for this gesture will clear the active state of the + // targeted node, so performing a ReadOnly hit test here is fine. + hitType |= HitTestRequest::ReadOnly; + } else + hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; + + if (!shouldGesturesTriggerActive()) + hitType |= HitTestRequest::ReadOnly; + + if ((!scrollbar && !eventTarget) || !(hitType & HitTestRequest::ReadOnly)) { + IntPoint hitTestPoint = m_frame.view()->windowToContents(adjustedPoint); + HitTestResult result = hitTestResultAtPoint(hitTestPoint, hitType | HitTestRequest::AllowFrameScrollbars); + eventTarget = result.targetNode(); + if (!scrollbar) + scrollbar = result.scrollbar(); + } + + if (scrollbar) { + bool eventSwallowed = scrollbar->gestureEvent(gestureEvent); + if (eventSwallowed) + return true; + } + + if (eventTarget) { + bool eventSwallowed = eventTarget->dispatchGestureEvent(gestureEvent); + if (eventSwallowed) + return true; + } + + // FIXME: A more general scroll system (https://bugs.webkit.org/show_bug.cgi?id=80596) will + // eliminate the need for this. + TemporaryChange<PlatformEvent::Type> baseEventType(m_baseEventType, gestureEvent.type()); + + switch (gestureEvent.type()) { + case PlatformEvent::GestureTap: + return handleGestureTap(gestureEvent); + case PlatformEvent::GestureLongPress: + return handleGestureLongPress(gestureEvent); + default: + ASSERT_NOT_REACHED(); + } + + return false; +} + +bool EventHandler::handleGestureTap(const PlatformGestureEvent& gestureEvent) +{ + // FIXME: Refactor this code to not hit test multiple times. We use the adjusted position to ensure that the correct node is targeted by the later redundant hit tests. + IntPoint adjustedPoint = gestureEvent.position(); +#if ENABLE(TOUCH_ADJUSTMENT) + adjustGesturePosition(gestureEvent, adjustedPoint); +#endif + + PlatformMouseEvent fakeMouseMove(adjustedPoint, gestureEvent.globalPosition(), + NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0, + gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp(), ForceAtClick); + mouseMoved(fakeMouseMove); + + int tapCount = 1; + + bool defaultPrevented = false; + PlatformMouseEvent fakeMouseDown(adjustedPoint, gestureEvent.globalPosition(), + LeftButton, PlatformEvent::MousePressed, tapCount, + gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp(), ForceAtClick); + defaultPrevented |= handleMousePressEvent(fakeMouseDown); + + PlatformMouseEvent fakeMouseUp(adjustedPoint, gestureEvent.globalPosition(), + LeftButton, PlatformEvent::MouseReleased, tapCount, + gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp(), ForceAtClick); + defaultPrevented |= handleMouseReleaseEvent(fakeMouseUp); + + return defaultPrevented; +} + +bool EventHandler::handleGestureLongPress(const PlatformGestureEvent& gestureEvent) +{ + return handleGestureForTextSelectionOrContextMenu(gestureEvent); +} + +bool EventHandler::handleGestureForTextSelectionOrContextMenu(const PlatformGestureEvent& gestureEvent) +{ +#if ENABLE(CONTEXT_MENUS) + return sendContextMenuEventForGesture(gestureEvent); +#else + return false; +#endif +} +#endif // ENABLE(QT_GESTURE_EVENTS) + +#if ENABLE(TOUCH_ADJUSTMENT) +bool EventHandler::shouldApplyTouchAdjustment(const PlatformGestureEvent& event) const +{ + if (!m_frame.settings().touchAdjustmentEnabled()) + return false; + return !event.area().isEmpty(); +} + + +bool EventHandler::bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode) +{ + IntPoint hitTestPoint = m_frame.view()->windowToContents(touchCenter); + HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, touchRadius); + + IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius); + + // FIXME: Should be able to handle targetNode being a shadow DOM node to avoid performing uncessary hit tests + // in the case where further processing on the node is required. Returning the shadow ancestor prevents a + // regression in touchadjustment/html-label.html. Some refinement is required to testing/internals to + // handle targetNode being a shadow DOM node. + bool success = findBestClickableCandidate(targetNode, targetPoint, touchCenter, touchRect, result.rectBasedTestResult()); + if (success && targetNode) + targetNode = targetNode->deprecatedShadowAncestorNode(); + return success; +} + +bool EventHandler::bestContextMenuNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode) +{ + IntPoint hitTestPoint = m_frame.view()->windowToContents(touchCenter); + HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, touchRadius); + + IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius); + return findBestContextMenuCandidate(targetNode, targetPoint, touchCenter, touchRect, result.rectBasedTestResult()); +} + +bool EventHandler::bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode) +{ + IntPoint hitTestPoint = m_frame.view()->windowToContents(touchCenter); + HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent, touchRadius); + + IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius); + return findBestZoomableArea(targetNode, targetArea, touchCenter, touchRect, result.rectBasedTestResult()); +} + +bool EventHandler::adjustGesturePosition(const PlatformGestureEvent& gestureEvent, IntPoint& adjustedPoint) +{ + if (!shouldApplyTouchAdjustment(gestureEvent)) + return false; + + Node* targetNode = 0; + switch (gestureEvent.type()) { + case PlatformEvent::GestureTap: + bestClickableNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode); + break; + case PlatformEvent::GestureLongPress: + bestContextMenuNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode); + break; + default: + // FIXME: Implement handling for other types as needed. + ASSERT_NOT_REACHED(); + } + return targetNode; +} +#endif + #if ENABLE(CONTEXT_MENUS) bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event) { @@ -2811,6 +2983,29 @@ bool EventHandler::sendContextMenuEventForKey() return !dispatchMouseEvent(eventNames().contextmenuEvent, targetNode, true, 0, platformMouseEvent, false); } + +#if ENABLE(QT_GESTURE_EVENTS) +bool EventHandler::sendContextMenuEventForGesture(const PlatformGestureEvent& event) +{ +#if OS(WINDOWS) + PlatformEvent::Type eventType = PlatformEvent::MouseReleased; +#else + PlatformEvent::Type eventType = PlatformEvent::MousePressed; +#endif + + IntPoint adjustedPoint = event.position(); +#if ENABLE(TOUCH_ADJUSTMENT) + adjustGesturePosition(event, adjustedPoint); +#endif + PlatformMouseEvent mouseEvent(adjustedPoint, event.globalPosition(), RightButton, eventType, 1, false, false, false, false, WTF::currentTime(), ForceAtClick); + // To simulate right-click behavior, we send a right mouse down and then + // context menu event. + handleMousePressEvent(mouseEvent); + return sendContextMenuEvent(mouseEvent); + // We do not need to send a corresponding mouse release because in case of + // right-click, the context menu takes capture and consumes all events. +} +#endif // ENABLE(QT_GESTURE_EVENTS) #endif // ENABLE(CONTEXT_MENUS) void EventHandler::scheduleHoverStateUpdate() diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h index f666a1b40..a11e042ee 100644 --- a/Source/WebCore/page/EventHandler.h +++ b/Source/WebCore/page/EventHandler.h @@ -96,6 +96,11 @@ class Widget; struct DragState; +#if ENABLE(QT_GESTURE_EVENTS) +class PlatformGestureEvent; +class RenderObject; +#endif + #if ENABLE(DRAG_SUPPORT) extern const int LinkDragHysteresis; extern const int ImageDragHysteresis; @@ -217,6 +222,12 @@ public: typedef HashSet<RefPtr<EventTarget>> EventTargetSet; #endif +#if ENABLE(QT_GESTURE_EVENTS) + bool handleGestureEvent(const PlatformGestureEvent&); + bool handleGestureTap(const PlatformGestureEvent&); + bool handleGestureLongPress(const PlatformGestureEvent&); +#endif + #if ENABLE(IOS_TOUCH_EVENTS) bool dispatchTouchEvent(const PlatformTouchEvent&, const AtomicString&, const EventTargetTouchMap&, float, float); bool dispatchSimulatedTouchEvent(IntPoint location); @@ -233,9 +244,22 @@ public: void defaultTouchEventHandler(Node*, TouchEvent*); #endif +#if ENABLE(TOUCH_ADJUSTMENT) + bool shouldApplyTouchAdjustment(const PlatformGestureEvent&) const; + + bool bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode); + bool bestContextMenuNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode); + bool bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode); + + bool adjustGesturePosition(const PlatformGestureEvent&, IntPoint& adjustedPoint); +#endif + #if ENABLE(CONTEXT_MENUS) WEBCORE_EXPORT bool sendContextMenuEvent(const PlatformMouseEvent&); bool sendContextMenuEventForKey(); +#if ENABLE(QT_GESTURE_EVENTS) + bool sendContextMenuEventForGesture(const PlatformGestureEvent&); +#endif #endif void setMouseDownMayStartAutoscroll() { m_mouseDownMayStartAutoscroll = true; } @@ -451,6 +475,10 @@ private: bool isKeyEventAllowedInFullScreen(const PlatformKeyboardEvent&) const; #endif +#if ENABLE(QT_GESTURE_EVENTS) + bool handleGestureForTextSelectionOrContextMenu(const PlatformGestureEvent&); +#endif + void setLastKnownMousePosition(const PlatformMouseEvent&); #if ENABLE(CURSOR_VISIBILITY) diff --git a/Source/WebCore/page/Settings.in b/Source/WebCore/page/Settings.in index 24f7e40ec..84a9f0cd0 100644 --- a/Source/WebCore/page/Settings.in +++ b/Source/WebCore/page/Settings.in @@ -154,6 +154,11 @@ imageSubsamplingEnabled initial=defaultImageSubsamplingEnabled wantsBalancedSetDefersLoadingBehavior initial=false requestAnimationFrameEnabled initial=true +# For touch adjustment to apply, the compile option TOUCH_ADJUSTMENT must also be enabled. +# This setting adds a means to dynamically disable the feature at runtime on systems with +# support for touch adjustment. +touchAdjustmentEnabled initial=true + fixedPositionCreatesStackingContext initial=defaultFixedPositionCreatesStackingContext syncXHRInDocumentsEnabled initial=true cookieEnabled initial=true diff --git a/Source/WebCore/page/qt/TouchAdjustment.cpp b/Source/WebCore/page/qt/TouchAdjustment.cpp new file mode 100644 index 000000000..5c393efb5 --- /dev/null +++ b/Source/WebCore/page/qt/TouchAdjustment.cpp @@ -0,0 +1,503 @@ +/* + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "TouchAdjustment.h" + +#include "ContainerNode.h" +#include "Editor.h" +#include "FloatPoint.h" +#include "FloatQuad.h" +#include "Frame.h" +#include "FrameView.h" +#include "HTMLFrameOwnerElement.h" +#include "HTMLInputElement.h" +#include "HTMLLabelElement.h" +#include "HTMLNames.h" +#include "IntPoint.h" +#include "IntSize.h" +#include "Node.h" +#include "NodeRenderStyle.h" +#include "RenderBox.h" +#include "RenderObject.h" +#include "RenderStyle.h" +#include "RenderText.h" +#include "RenderView.h" +#include "ShadowRoot.h" +#include "Text.h" +#include "TextBreakIterator.h" + +namespace WebCore { + +namespace TouchAdjustment { + +const float zeroTolerance = 1e-6f; + +// Class for remembering absolute quads of a target node and what node they represent. +class SubtargetGeometry { +public: + SubtargetGeometry(Node* node, const FloatQuad& quad) + : m_node(node) + , m_quad(quad) + { } + + Node* node() const { return m_node; } + FloatQuad quad() const { return m_quad; } + IntRect boundingBox() const { return m_quad.enclosingBoundingBox(); } + +private: + Node* m_node; + FloatQuad m_quad; +}; + +typedef Vector<SubtargetGeometry> SubtargetGeometryList; +typedef bool (*NodeFilter)(Node*); +typedef void (*AppendSubtargetsForNode)(Node*, SubtargetGeometryList&); +typedef float (*DistanceFunction)(const IntPoint&, const IntRect&, const SubtargetGeometry&); + +// Takes non-const Node* because isContentEditable is a non-const function. +bool nodeRespondsToTapGesture(Node* node) +{ + if (node->willRespondToMouseClickEvents() || node->willRespondToMouseMoveEvents()) + return true; + // Accept nodes that has a CSS effect when touched. + if (node->isElementNode()) { + Element* element = downcast<Element>(node); + if (element->isMouseFocusable()) + return true; + if (element->childrenAffectedByActive() || element->childrenAffectedByHover()) + return true; + } + if (RenderStyle* renderStyle = node->renderStyle()) { + if (renderStyle->affectedByActive() || renderStyle->affectedByHover()) + return true; + } + return false; +} + +bool nodeIsZoomTarget(Node* node) +{ + if (node->isTextNode() || node->isShadowRoot()) + return false; + + ASSERT(node->renderer()); + return node->renderer()->isBox(); +} + +bool providesContextMenuItems(Node* node) +{ + // This function tries to match the nodes that receive special context-menu items in + // ContextMenuController::populate(), and should be kept uptodate with those. + ASSERT(node->renderer() || node->isShadowRoot()); + if (!node->renderer()) + return false; + if (node->isContentEditable()) + return true; + if (node->isLink()) + return true; + if (node->renderer()->isImage()) + return true; + if (node->renderer()->isMedia()) + return true; + if (node->renderer()->canBeSelectionLeaf()) { + // If the context menu gesture will trigger a selection all selectable nodes are valid targets. + if (node->renderer()->frame().editor().behavior().shouldSelectOnContextualMenuClick()) + return true; + // Only the selected part of the renderer is a valid target, but this will be corrected in + // appendContextSubtargetsForNode. + if (node->renderer()->selectionState() != RenderObject::SelectionNone) + return true; + } + return false; +} + +static inline void appendQuadsToSubtargetList(Vector<FloatQuad>& quads, Node* node, SubtargetGeometryList& subtargets) +{ + Vector<FloatQuad>::const_iterator it = quads.begin(); + const Vector<FloatQuad>::const_iterator end = quads.end(); + for (; it != end; ++it) + subtargets.append(SubtargetGeometry(node, *it)); +} + +static inline void appendBasicSubtargetsForNode(Node* node, SubtargetGeometryList& subtargets) +{ + // Node guaranteed to have renderer due to check in node filter. + ASSERT(node->renderer()); + + Vector<FloatQuad> quads; + node->renderer()->absoluteQuads(quads); + + appendQuadsToSubtargetList(quads, node, subtargets); +} + +static inline void appendContextSubtargetsForNode(Node* node, SubtargetGeometryList& subtargets) +{ + // This is a variant of appendBasicSubtargetsForNode that adds special subtargets for + // selected or auto-selectable parts of text nodes. + ASSERT(node->renderer()); + + if (!node->isTextNode()) + return appendBasicSubtargetsForNode(node, subtargets); + + Text* textNode = static_cast<WebCore::Text*>(node); + RenderText* textRenderer = textNode->renderer(); + + if (textRenderer->frame().editor().behavior().shouldSelectOnContextualMenuClick()) { + // Make subtargets out of every word. + String textValue = textNode->data(); + TextBreakIterator* wordIterator = wordBreakIterator(StringView(textValue)); + int lastOffset = textBreakFirst(wordIterator); + if (lastOffset == -1) + return; + int offset; + while ((offset = textBreakNext(wordIterator)) != -1) { + if (isWordTextBreak(wordIterator)) { + Vector<FloatQuad> quads = textRenderer->absoluteQuadsForRange(lastOffset, offset); + appendQuadsToSubtargetList(quads, textNode, subtargets); + } + lastOffset = offset; + } + } else { + if (textRenderer->selectionState() == RenderObject::SelectionNone) + return appendBasicSubtargetsForNode(node, subtargets); + // If selected, make subtargets out of only the selected part of the text. + int startPos, endPos; + switch (textRenderer->selectionState()) { + case RenderObject::SelectionInside: + startPos = 0; + endPos = textRenderer->textLength(); + break; + case RenderObject::SelectionStart: + textRenderer->selectionStartEnd(startPos, endPos); + endPos = textRenderer->textLength(); + break; + case RenderObject::SelectionEnd: + textRenderer->selectionStartEnd(startPos, endPos); + startPos = 0; + break; + case RenderObject::SelectionBoth: + textRenderer->selectionStartEnd(startPos, endPos); + break; + default: + ASSERT_NOT_REACHED(); + return; + } + Vector<FloatQuad> quads = textRenderer->absoluteQuadsForRange(startPos, endPos); + appendQuadsToSubtargetList(quads, textNode, subtargets); + } +} + +static inline void appendZoomableSubtargets(Node* node, SubtargetGeometryList& subtargets) +{ + RenderBox* renderer = downcast<RenderBox>(node->renderer()); + ASSERT(renderer); + + Vector<FloatQuad> quads; + FloatRect borderBoxRect = renderer->borderBoxRect(); + FloatRect contentBoxRect = renderer->contentBoxRect(); + quads.append(renderer->localToAbsoluteQuad(borderBoxRect)); + if (borderBoxRect != contentBoxRect) + quads.append(renderer->localToAbsoluteQuad(contentBoxRect)); + // FIXME: For RenderBlocks, add column boxes and content boxes cleared for floats. + + Vector<FloatQuad>::const_iterator it = quads.begin(); + const Vector<FloatQuad>::const_iterator end = quads.end(); + for (; it != end; ++it) + subtargets.append(SubtargetGeometry(node, *it)); +} + +static inline Node* parentShadowHostOrOwner(const Node* node) +{ + if (Node* ancestor = node->parentOrShadowHostNode()) + return ancestor; + if (node->isDocumentNode()) + return downcast<Document>(node)->ownerElement(); + return 0; +} + +// Compiles a list of subtargets of all the relevant target nodes. +void compileSubtargetList(const NodeListHashSet& intersectedNodes, SubtargetGeometryList& subtargets, NodeFilter nodeFilter, AppendSubtargetsForNode appendSubtargetsForNode) +{ + // Find candidates responding to tap gesture events in O(n) time. + HashMap<Node*, Node*> responderMap; + HashSet<Node*> ancestorsToRespondersSet; + Vector<Node*> candidates; + HashSet<Node*> editableAncestors; + + // A node matching the NodeFilter is called a responder. Candidate nodes must either be a + // responder or have an ancestor that is a responder. + // This iteration tests all ancestors at most once by caching earlier results. + NodeListHashSet::const_iterator end = intersectedNodes.end(); + for (NodeListHashSet::const_iterator it = intersectedNodes.begin(); it != end; ++it) { + Node* const node = it->get(); + Vector<Node*> visitedNodes; + Node* respondingNode = 0; + for (Node* visitedNode = node; visitedNode; visitedNode = visitedNode->parentOrShadowHostNode()) { + // Check if we already have a result for a common ancestor from another candidate. + respondingNode = responderMap.get(visitedNode); + if (respondingNode) + break; + visitedNodes.append(visitedNode); + // Check if the node filter applies, which would mean we have found a responding node. + if (nodeFilter(visitedNode)) { + respondingNode = visitedNode; + // Continue the iteration to collect the ancestors of the responder, which we will need later. + for (visitedNode = parentShadowHostOrOwner(visitedNode); visitedNode; visitedNode = parentShadowHostOrOwner(visitedNode)) { + HashSet<Node*>::AddResult addResult = ancestorsToRespondersSet.add(visitedNode); + if (!addResult.isNewEntry) + break; + } + break; + } + } + // Insert the detected responder for all the visited nodes. + for (unsigned j = 0; j < visitedNodes.size(); j++) + responderMap.add(visitedNodes[j], respondingNode); + + if (respondingNode) + candidates.append(node); + } + + // We compile the list of component absolute quads instead of using the bounding rect + // to be able to perform better hit-testing on inline links on line-breaks. + unsigned length = candidates.size(); + for (unsigned i = 0; i < length; i++) { + Node* candidate = candidates[i]; + // Skip nodes who's responders are ancestors of other responders. This gives preference to + // the inner-most event-handlers. So that a link is always preferred even when contained + // in an element that monitors all click-events. + Node* respondingNode = responderMap.get(candidate); + ASSERT(respondingNode); + if (ancestorsToRespondersSet.contains(respondingNode)) + continue; + // Consolidate bounds for editable content. + if (editableAncestors.contains(candidate)) + continue; + if (candidate->isContentEditable()) { + Node* replacement = candidate; + Node* parent = candidate->parentOrShadowHostNode(); + while (parent && parent->isContentEditable()) { + replacement = parent; + if (editableAncestors.contains(replacement)) { + replacement = 0; + break; + } + editableAncestors.add(replacement); + parent = parent->parentOrShadowHostNode(); + } + candidate = replacement; + } + if (candidate) + appendSubtargetsForNode(candidate, subtargets); + } +} + +// Compiles a list of zoomable subtargets. +void compileZoomableSubtargets(const NodeListHashSet& intersectedNodes, SubtargetGeometryList& subtargets) +{ + NodeListHashSet::const_iterator end = intersectedNodes.end(); + for (NodeListHashSet::const_iterator it = intersectedNodes.begin(); it != end; ++it) { + Node* const candidate = it->get(); + if (nodeIsZoomTarget(candidate)) + appendZoomableSubtargets(candidate, subtargets); + } +} + +// This returns quotient of the target area and its intersection with the touch area. +// This will prioritize largest intersection and smallest area, while balancing the two against each other. +float zoomableIntersectionQuotient(const IntPoint& touchHotspot, const IntRect& touchArea, const SubtargetGeometry& subtarget) +{ + IntRect rect = subtarget.boundingBox(); + + // Convert from frame coordinates to window coordinates. + rect = subtarget.node()->document().view()->contentsToWindow(rect); + + // Check the rectangle is meaningful zoom target. It should at least contain the hotspot. + if (!rect.contains(touchHotspot)) + return std::numeric_limits<float>::infinity(); + IntRect intersection = rect; + intersection.intersect(touchArea); + + // Return the quotient of the intersection. + return rect.size().area() / (float)intersection.size().area(); +} + +// Uses a hybrid of distance to adjust and intersect ratio, normalizing each score between 0 and 1 +// and combining them. The distance to adjust works best for disambiguating clicks on targets such +// as links, where the width may be significantly larger than the touch width. Using area of overlap +// in such cases can lead to a bias towards shorter links. Conversely, percentage of overlap can +// provide strong confidence in tapping on a small target, where the overlap is often quite high, +// and works well for tightly packed controls. +float hybridDistanceFunction(const IntPoint& touchHotspot, const IntRect& touchRect, const SubtargetGeometry& subtarget) +{ + IntRect rect = subtarget.boundingBox(); + + // Convert from frame coordinates to window coordinates. + rect = subtarget.node()->document().view()->contentsToWindow(rect); + + float radiusSquared = 0.25f * (touchRect.size().diagonalLengthSquared()); + float distanceToAdjustScore = rect.distanceSquaredToPoint(touchHotspot) / radiusSquared; + + int maxOverlapWidth = std::min(touchRect.width(), rect.width()); + int maxOverlapHeight = std::min(touchRect.height(), rect.height()); + float maxOverlapArea = std::max(maxOverlapWidth * maxOverlapHeight, 1); + rect.intersect(touchRect); + float intersectArea = rect.size().area(); + float intersectionScore = 1 - intersectArea / maxOverlapArea; + + float hybridScore = intersectionScore + distanceToAdjustScore; + + return hybridScore; +} + +FloatPoint contentsToWindow(FrameView *view, FloatPoint pt) +{ + int x = static_cast<int>(pt.x() + 0.5f); + int y = static_cast<int>(pt.y() + 0.5f); + IntPoint adjusted = view->contentsToWindow(IntPoint(x, y)); + return FloatPoint(adjusted.x(), adjusted.y()); +} + +// Adjusts 'point' to the nearest point inside rect, and leaves it unchanged if already inside. +void adjustPointToRect(FloatPoint& point, const FloatRect& rect) +{ + if (point.x() < rect.x()) + point.setX(rect.x()); + else if (point.x() > rect.maxX()) + point.setX(rect.maxX()); + + if (point.y() < rect.y()) + point.setY(rect.y()); + else if (point.y() > rect.maxY()) + point.setY(rect.maxY()); +} + +bool snapTo(const SubtargetGeometry& geom, const IntPoint& touchPoint, const IntRect& touchArea, IntPoint& adjustedPoint) +{ + FrameView* view = geom.node()->document().view(); + FloatQuad quad = geom.quad(); + + if (quad.isRectilinear()) { + IntRect contentBounds = geom.boundingBox(); + // Convert from frame coordinates to window coordinates. + IntRect bounds = view->contentsToWindow(contentBounds); + if (bounds.contains(touchPoint)) { + adjustedPoint = touchPoint; + return true; + } + if (bounds.intersects(touchArea)) { + bounds.intersect(touchArea); + adjustedPoint = bounds.center(); + return true; + } + return false; + } + + // The following code tries to adjust the point to place inside a both the touchArea and the non-rectilinear quad. + // FIXME: This will return the point inside the touch area that is the closest to the quad center, but does not + // guarantee that the point will be inside the quad. Corner-cases exist where the quad will intersect but this + // will fail to adjust the point to somewhere in the intersection. + + // Convert quad from content to window coordinates. + FloatPoint p1 = contentsToWindow(view, quad.p1()); + FloatPoint p2 = contentsToWindow(view, quad.p2()); + FloatPoint p3 = contentsToWindow(view, quad.p3()); + FloatPoint p4 = contentsToWindow(view, quad.p4()); + quad = FloatQuad(p1, p2, p3, p4); + + if (quad.containsPoint(touchPoint)) { + adjustedPoint = touchPoint; + return true; + } + + // Pull point towards the center of the element. + FloatPoint center = quad.center(); + + adjustPointToRect(center, touchArea); + adjustedPoint = roundedIntPoint(center); + + return quad.containsPoint(adjustedPoint); +} + +// A generic function for finding the target node with the lowest distance metric. A distance metric here is the result +// of a distance-like function, that computes how well the touch hits the node. +// Distance functions could for instance be distance squared or area of intersection. +bool findNodeWithLowestDistanceMetric(Node*& targetNode, IntPoint& targetPoint, IntRect& targetArea, const IntPoint& touchHotspot, const IntRect& touchArea, SubtargetGeometryList& subtargets, DistanceFunction distanceFunction) +{ + targetNode = 0; + float bestDistanceMetric = std::numeric_limits<float>::infinity(); + SubtargetGeometryList::const_iterator it = subtargets.begin(); + const SubtargetGeometryList::const_iterator end = subtargets.end(); + IntPoint adjustedPoint; + + for (; it != end; ++it) { + Node* node = it->node(); + float distanceMetric = distanceFunction(touchHotspot, touchArea, *it); + if (distanceMetric < bestDistanceMetric) { + if (snapTo(*it, touchHotspot, touchArea, adjustedPoint)) { + targetPoint = adjustedPoint; + targetArea = it->boundingBox(); + targetNode = node; + bestDistanceMetric = distanceMetric; + } + } else if (distanceMetric - bestDistanceMetric < zeroTolerance) { + if (snapTo(*it, touchHotspot, touchArea, adjustedPoint)) { + if (node->isDescendantOf(targetNode)) { + // Try to always return the inner-most element. + targetPoint = adjustedPoint; + targetNode = node; + targetArea = it->boundingBox(); + } + } + } + } + + if (targetNode) + targetArea = targetNode->document().view()->contentsToWindow(targetArea); + + return targetNode; +} + +} // namespace TouchAdjustment + +bool findBestClickableCandidate(Node*& targetNode, IntPoint &targetPoint, const IntPoint &touchHotspot, const IntRect &touchArea, const NodeListHashSet& nodeList) +{ + IntRect targetArea; + TouchAdjustment::SubtargetGeometryList subtargets; + TouchAdjustment::compileSubtargetList(nodeList, subtargets, TouchAdjustment::nodeRespondsToTapGesture, TouchAdjustment::appendBasicSubtargetsForNode); + return TouchAdjustment::findNodeWithLowestDistanceMetric(targetNode, targetPoint, targetArea, touchHotspot, touchArea, subtargets, TouchAdjustment::hybridDistanceFunction); +} + +bool findBestContextMenuCandidate(Node*& targetNode, IntPoint &targetPoint, const IntPoint &touchHotspot, const IntRect &touchArea, const NodeListHashSet& nodeList) +{ + IntRect targetArea; + TouchAdjustment::SubtargetGeometryList subtargets; + TouchAdjustment::compileSubtargetList(nodeList, subtargets, TouchAdjustment::providesContextMenuItems, TouchAdjustment::appendContextSubtargetsForNode); + return TouchAdjustment::findNodeWithLowestDistanceMetric(targetNode, targetPoint, targetArea, touchHotspot, touchArea, subtargets, TouchAdjustment::hybridDistanceFunction); +} + +bool findBestZoomableArea(Node*& targetNode, IntRect& targetArea, const IntPoint& touchHotspot, const IntRect& touchArea, const NodeListHashSet& nodeList) +{ + IntPoint targetPoint; + TouchAdjustment::SubtargetGeometryList subtargets; + TouchAdjustment::compileZoomableSubtargets(nodeList, subtargets); + return TouchAdjustment::findNodeWithLowestDistanceMetric(targetNode, targetPoint, targetArea, touchHotspot, touchArea, subtargets, TouchAdjustment::zoomableIntersectionQuotient); +} + +} // namespace WebCore diff --git a/Source/WebCore/page/qt/TouchAdjustment.h b/Source/WebCore/page/qt/TouchAdjustment.h new file mode 100644 index 000000000..06ac00813 --- /dev/null +++ b/Source/WebCore/page/qt/TouchAdjustment.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef TouchAdjustment_h +#define TouchAdjustment_h + +#include "IntPoint.h" +#include "IntRect.h" +#include "Node.h" +#include "NodeList.h" +#include <wtf/Vector.h> + +namespace WebCore { + +typedef ListHashSet<RefPtr<Node> > NodeListHashSet; + +bool findBestClickableCandidate(Node*& targetNode, IntPoint& targetPoint, const IntPoint& touchHotspot, const IntRect& touchArea, const NodeListHashSet&); +bool findBestContextMenuCandidate(Node*& targetNode, IntPoint& targetPoint, const IntPoint& touchHotspot, const IntRect& touchArea, const NodeListHashSet&); +bool findBestZoomableArea(Node*& targetNode, IntRect& targetArea, const IntPoint& touchHotspot, const IntRect& touchArea, const NodeListHashSet&); +// FIXME: Implement the similar functions for other gestures here as well. + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/MainThreadSharedTimer.h b/Source/WebCore/platform/MainThreadSharedTimer.h index f7a0c91da..a8421c3fa 100644 --- a/Source/WebCore/platform/MainThreadSharedTimer.h +++ b/Source/WebCore/platform/MainThreadSharedTimer.h @@ -50,6 +50,10 @@ public: // need to call this from non-member functions at the moment. void fired(); +#if PLATFORM(QT) + bool hasFiredFunction() const { return bool(m_firedFunction); } +#endif + private: MainThreadSharedTimer(); diff --git a/Source/WebCore/platform/PlatformEvent.h b/Source/WebCore/platform/PlatformEvent.h index 6e263122f..402052dc4 100644 --- a/Source/WebCore/platform/PlatformEvent.h +++ b/Source/WebCore/platform/PlatformEvent.h @@ -51,6 +51,12 @@ public: // PlatformWheelEvent Wheel, +#if ENABLE(QT_GESTURE_EVENTS) + // PlatformGestureEvent + GestureTap, + GestureLongPress, +#endif + #if ENABLE(TOUCH_EVENTS) // PlatformTouchEvent TouchStart, diff --git a/Source/WebCore/platform/Scrollbar.cpp b/Source/WebCore/platform/Scrollbar.cpp index 05bf16a29..617d9a0e1 100644 --- a/Source/WebCore/platform/Scrollbar.cpp +++ b/Source/WebCore/platform/Scrollbar.cpp @@ -35,6 +35,10 @@ #include "ScrollbarTheme.h" #include <algorithm> +#if ENABLE(QT_GESTURE_EVENTS) +#include "PlatformGestureEvent.h" +#endif + #if PLATFORM(GTK) // The position of the scrollbar thumb affects the appearance of the steppers, so // when the thumb moves, we have to invalidate them for painting. @@ -319,6 +323,24 @@ void Scrollbar::setPressedPart(ScrollbarPart part) theme().invalidatePart(*this, m_hoveredPart); } +#if ENABLE(QT_GESTURE_EVENTS) +bool Scrollbar::gestureEvent(const PlatformGestureEvent& evt) +{ + bool handled = false; + switch (evt.type()) { + case PlatformEvent::GestureTap: + if (m_pressedPart != ThumbPart && m_pressedPart != NoPart) + handled = m_scrollableArea.scroll(pressedPartScrollDirection(), pressedPartScrollGranularity()); + break; + default: + break; + } + setPressedPart(NoPart); + m_pressedPos = 0; + return handled; +} +#endif + #if !PLATFORM(IOS) bool Scrollbar::mouseMoved(const PlatformMouseEvent& evt) { diff --git a/Source/WebCore/platform/Scrollbar.h b/Source/WebCore/platform/Scrollbar.h index 2491b9c74..ad29b502f 100644 --- a/Source/WebCore/platform/Scrollbar.h +++ b/Source/WebCore/platform/Scrollbar.h @@ -40,6 +40,10 @@ class PlatformMouseEvent; class ScrollableArea; class ScrollbarTheme; +#if ENABLE(QT_GESTURE_EVENTS) +class PlatformGestureEvent; +#endif + class Scrollbar : public Widget { public: // Must be implemented by platforms that can't simply use the Scrollbar base class. Right now the only platform that is not using the base class is GTK. @@ -96,6 +100,10 @@ public: bool isWindowActive() const; +#if ENABLE(QT_GESTURE_EVENTS) + bool gestureEvent(const PlatformGestureEvent&); +#endif + // These methods are used for platform scrollbars to give :hover feedback. They will not get called // when the mouse went down in a scrollbar, since it is assumed the scrollbar will start // grabbing all events in that case anyway. diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h index 2038416a8..71efb55e0 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h @@ -22,15 +22,23 @@ #define TextureMapperShaderProgram_h #if USE(TEXTURE_MAPPER_GL) + #include "GraphicsContext3D.h" #include "TransformationMatrix.h" #include <wtf/HashMap.h> +#include <wtf/NeverDestroyed.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> #include <wtf/text/AtomicStringHash.h> namespace WebCore { -#define TEXMAP_DECLARE_VARIABLE(Accessor, Name, Type) GC3Duint Accessor##Location() { static const AtomicString name(Name); return getLocation(name, Type); } + +#define TEXMAP_DECLARE_VARIABLE(Accessor, Name, Type) \ + GC3Duint Accessor##Location() { \ + static NeverDestroyed<const AtomicString> name(Name, AtomicString::ConstructFromLiteral); \ + return getLocation(name.get(), Type); \ + } + #define TEXMAP_DECLARE_UNIFORM(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "u_"#Accessor, UniformVariable) #define TEXMAP_DECLARE_ATTRIBUTE(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "a_"#Accessor, AttribVariable) #define TEXMAP_DECLARE_SAMPLER(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "s_"#Accessor, UniformVariable) diff --git a/Source/WebCore/platform/qt/MainThreadSharedTimerQt.cpp b/Source/WebCore/platform/qt/MainThreadSharedTimerQt.cpp index 11c507d66..7aae3f1de 100644 --- a/Source/WebCore/platform/qt/MainThreadSharedTimerQt.cpp +++ b/Source/WebCore/platform/qt/MainThreadSharedTimerQt.cpp @@ -33,7 +33,6 @@ #include <QBasicTimer> #include <QCoreApplication> -#include <QDebug> #include <QPointer> #include <wtf/CurrentTime.h> @@ -104,7 +103,8 @@ void SharedTimerQt::timerEvent(QTimerEvent* ev) return; m_timer.stop(); - MainThreadSharedTimer::singleton().fired(); + if (MainThreadSharedTimer::singleton().hasFiredFunction()) + MainThreadSharedTimer::singleton().fired(); } void MainThreadSharedTimer::setFireInterval(double interval) diff --git a/Source/WebCore/platform/qt/PlatformGestureEvent.h b/Source/WebCore/platform/qt/PlatformGestureEvent.h new file mode 100644 index 000000000..1beac6a68 --- /dev/null +++ b/Source/WebCore/platform/qt/PlatformGestureEvent.h @@ -0,0 +1,60 @@ +/* + * 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 COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PlatformGestureEvent_h +#define PlatformGestureEvent_h + +#if ENABLE(QT_GESTURE_EVENTS) + +#include "FloatPoint.h" +#include "IntPoint.h" +#include "IntSize.h" +#include "PlatformEvent.h" + +namespace WebCore { + +class PlatformGestureEvent : public PlatformEvent { +public: + PlatformGestureEvent() + : PlatformEvent(PlatformEvent::GestureTap) + { + } + + const IntPoint& position() const { return m_position; } // PlatformWindow coordinates. + const IntPoint& globalPosition() const { return m_globalPosition; } // Screen coordinates. + + const IntSize& area() const { return m_area; } + +protected: + IntPoint m_position; + IntPoint m_globalPosition; + IntSize m_area; +}; + +} // namespace WebCore + +#endif // ENABLE(QT_GESTURE_EVENTS) + +#endif // PlatformGestureEvent_h diff --git a/Source/WebCore/platform/qt/WidgetQt.cpp b/Source/WebCore/platform/qt/WidgetQt.cpp index f3f04b157..0d1669941 100644 --- a/Source/WebCore/platform/qt/WidgetQt.cpp +++ b/Source/WebCore/platform/qt/WidgetQt.cpp @@ -42,7 +42,6 @@ #include "FrameView.h" #include <QCoreApplication> -#include <QDebug> #include <QPaintEngine> #include <QPainter> diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp index e4db91695..b46112a22 100644 --- a/Source/WebCore/testing/Internals.cpp +++ b/Source/WebCore/testing/Internals.cpp @@ -145,6 +145,10 @@ #include "DeviceProximityController.h" #endif +#if ENABLE(TOUCH_ADJUSTMENT) +#include "WebKitPoint.h" +#endif + #if ENABLE(MOUSE_CURSOR_SCALE) #include <wtf/dtoa.h> #endif @@ -1483,6 +1487,105 @@ void Internals::setDelegatesScrolling(bool enabled, ExceptionCode& ec) document->view()->setDelegatesScrolling(enabled); } +#if ENABLE(TOUCH_ADJUSTMENT) +PassRefPtr<WebKitPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, ExceptionCode& ec) +{ + Document* document = contextDocument(); + if (!document || !document->frame()) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + IntSize radius(width / 2, height / 2); + IntPoint point(x + radius.width(), y + radius.height()); + + Node* targetNode; + IntPoint adjustedPoint; + + bool foundNode = document->frame()->eventHandler().bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode); + if (foundNode) + return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y()); + + return 0; +} + +Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, ExceptionCode& ec) +{ + Document* document = contextDocument(); + if (!document || !document->frame()) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + IntSize radius(width / 2, height / 2); + IntPoint point(x + radius.width(), y + radius.height()); + + Node* targetNode; + IntPoint adjustedPoint; + document->frame()->eventHandler().bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode); + return targetNode; +} + +PassRefPtr<WebKitPoint> Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, ExceptionCode& ec) +{ + Document* document = contextDocument(); + if (!document || !document->frame()) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + IntSize radius(width / 2, height / 2); + IntPoint point(x + radius.width(), y + radius.height()); + + Node* targetNode = 0; + IntPoint adjustedPoint; + + bool foundNode = document->frame()->eventHandler().bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode); + if (foundNode) + return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y()); + + return WebKitPoint::create(x, y); +} + +Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, ExceptionCode& ec) +{ + Document* document = contextDocument(); + if (!document || !document->frame()) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + IntSize radius(width / 2, height / 2); + IntPoint point(x + radius.width(), y + radius.height()); + + Node* targetNode = 0; + IntPoint adjustedPoint; + document->frame()->eventHandler().bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode); + return targetNode; +} + +PassRefPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, ExceptionCode& ec) +{ + Document* document = contextDocument(); + if (!document || !document->frame()) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + IntSize radius(width / 2, height / 2); + IntPoint point(x + radius.width(), y + radius.height()); + + Node* targetNode; + IntRect zoomableArea; + bool foundNode = document->frame()->eventHandler().bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode); + if (foundNode) + return ClientRect::create(zoomableArea); + + return 0; +} +#endif + + int Internals::lastSpellCheckRequestSequence(ExceptionCode& ec) { Document* document = contextDocument(); diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h index 67a0193cd..95ed9357d 100644 --- a/Source/WebCore/testing/Internals.h +++ b/Source/WebCore/testing/Internals.h @@ -64,6 +64,7 @@ class Page; class Range; class RenderedDocumentMarker; class ScriptExecutionContext; +class WebKitPoint; class SerializedScriptValue; class SourceBuffer; class TimeRanges; @@ -193,6 +194,13 @@ public: RefPtr<Range> rangeForDictionaryLookupAtLocation(int x, int y, ExceptionCode&); void setDelegatesScrolling(bool enabled, ExceptionCode&); +#if ENABLE(TOUCH_ADJUSTMENT) + PassRefPtr<WebKitPoint> touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, ExceptionCode&); + Node* touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, ExceptionCode&); + PassRefPtr<WebKitPoint> touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, ExceptionCode&); + Node* touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, ExceptionCode&); + PassRefPtr<ClientRect> bestZoomableAreaForTouchPoint(long x, long y, long width, long height, ExceptionCode&); +#endif int lastSpellCheckRequestSequence(ExceptionCode&); int lastSpellCheckProcessedSequence(ExceptionCode&); diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl index 8043d6752..12cbad516 100644 --- a/Source/WebCore/testing/Internals.idl +++ b/Source/WebCore/testing/Internals.idl @@ -174,6 +174,13 @@ enum AutoFillButtonType { [RaisesException] Range rangeForDictionaryLookupAtLocation(long x, long y); [RaisesException] void setDelegatesScrolling(boolean enabled); +#if defined(ENABLE_TOUCH_ADJUSTMENT) && ENABLE_TOUCH_ADJUSTMENT + [RaisesException] WebKitPoint touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height); + [RaisesException] Node touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height); + [RaisesException] WebKitPoint touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height); + [RaisesException] Node touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height); + [RaisesException] ClientRect bestZoomableAreaForTouchPoint(long x, long y, long width, long height); +#endif [RaisesException] long lastSpellCheckRequestSequence(); [RaisesException] long lastSpellCheckProcessedSequence(); diff --git a/Source/WebKit/PlatformQt.cmake b/Source/WebKit/PlatformQt.cmake index 61fb76047..7e319fade 100644 --- a/Source/WebKit/PlatformQt.cmake +++ b/Source/WebKit/PlatformQt.cmake @@ -653,9 +653,6 @@ if (MSVC) string(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replace_CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}) set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${replace_CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /INCREMENTAL:NO") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS") - list(APPEND WebKit_INCLUDE_DIRECTORIES ${DERIVED_SOURCES_WEBKIT_DIR} ) diff --git a/Source/WebKit/qt/Api/qwebfullscreenrequest.h b/Source/WebKit/qt/Api/qwebfullscreenrequest.h index b86418c19..280e89caa 100644 --- a/Source/WebKit/qt/Api/qwebfullscreenrequest.h +++ b/Source/WebKit/qt/Api/qwebfullscreenrequest.h @@ -68,7 +68,10 @@ private: QScopedPointer<QWebFullScreenRequestPrivate> d; }; +QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(QWebFullScreenRequest, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + Q_DECLARE_METATYPE(QWebFullScreenRequest) #endif diff --git a/Source/WebKit/qt/Api/qwebhistory.cpp b/Source/WebKit/qt/Api/qwebhistory.cpp index 6c5934156..64e607af9 100644 --- a/Source/WebKit/qt/Api/qwebhistory.cpp +++ b/Source/WebKit/qt/Api/qwebhistory.cpp @@ -37,7 +37,6 @@ #include <wtf/text/WTFString.h> #include <QSharedData> -#include <QDebug> #include <QJsonObject> static const int HistoryStreamVersion = 3; diff --git a/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp b/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp index 1ba5a8aa1..b45fb6b2a 100644 --- a/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp +++ b/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp @@ -82,7 +82,6 @@ #include "qwebpluginfactory.h" #include "qwebsettings.h" #include <QCoreApplication> -#include <QDebug> #include <QFileInfo> #include <QMouseEvent> #include <QNetworkReply> diff --git a/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.cpp b/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.cpp index 62b2f38be..de90866c6 100644 --- a/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.cpp +++ b/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.cpp @@ -64,7 +64,7 @@ #include <QFileInfo> #include <QNetworkRequest> -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) #include "PlatformGestureEvent.h" #include "WebEventConversion.h" #endif @@ -165,7 +165,7 @@ bool QWebFrameAdapter::hasView() const return frame && frame->view(); } -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) void QWebFrameAdapter::handleGestureEvent(QGestureEventFacade* gestureEvent) { ASSERT(frame && frame->view()); diff --git a/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.h b/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.h index 42e02459d..c445a3240 100644 --- a/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.h +++ b/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.h @@ -47,8 +47,8 @@ QT_BEGIN_NAMESPACE class QPoint; QT_END_NAMESPACE -#if ENABLE(GESTURE_EVENTS) -class QGestureEventFacade; +#if ENABLE(QT_GESTURE_EVENTS) +struct QGestureEventFacade; #endif class QWebFrame; class QWebFrameData; @@ -133,7 +133,7 @@ public: void load(const QNetworkRequest&, QNetworkAccessManager::Operation = QNetworkAccessManager::GetOperation, const QByteArray& body = QByteArray()); bool hasView() const; -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) void handleGestureEvent(QGestureEventFacade*); #endif QWebFrameAdapter* createFrame(QWebFrameData*); diff --git a/Source/WebKit/qt/WebCoreSupport/QWebPageAdapter.cpp b/Source/WebKit/qt/WebCoreSupport/QWebPageAdapter.cpp index ee3339594..4d2b30d37 100644 --- a/Source/WebKit/qt/WebCoreSupport/QWebPageAdapter.cpp +++ b/Source/WebKit/qt/WebCoreSupport/QWebPageAdapter.cpp @@ -454,7 +454,7 @@ void QWebPageAdapter::adjustPointForClicking(QMouseEvent* ev) { #if ENABLE(TOUCH_ADJUSTMENT) QtPlatformPlugin platformPlugin; - OwnPtr<QWebTouchModifier> touchModifier = platformPlugin.createTouchModifier(); + std::unique_ptr<QWebTouchModifier> touchModifier = platformPlugin.createTouchModifier(); if (!touchModifier) return; @@ -468,7 +468,7 @@ void QWebPageAdapter::adjustPointForClicking(QMouseEvent* ev) if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) return; - FrameView* view = page->mainFrame()->view(); + FrameView* view = page->mainFrame().view(); ASSERT(view); if (view->scrollbarAtPoint(ev->pos())) return; diff --git a/Source/WebKit/qt/WebCoreSupport/WebEventConversion.cpp b/Source/WebKit/qt/WebCoreSupport/WebEventConversion.cpp index cf10a113e..ee847787c 100644 --- a/Source/WebKit/qt/WebCoreSupport/WebEventConversion.cpp +++ b/Source/WebKit/qt/WebCoreSupport/WebEventConversion.cpp @@ -22,7 +22,7 @@ #include "config.h" #include "WebEventConversion.h" -//#include "PlatformGestureEvent.h" FIXME: GestureEvents were removed in r157316 +#include "PlatformGestureEvent.h" #include "PlatformMouseEvent.h" #include "PlatformTouchEvent.h" #include "PlatformTouchPoint.h" @@ -240,7 +240,7 @@ WebKitPlatformTouchPoint::WebKitPlatformTouchPoint(const QTouchEvent::TouchPoint } #endif -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) class WebKitPlatformGestureEvent : public PlatformGestureEvent { public: WebKitPlatformGestureEvent(QGestureEventFacade*); @@ -281,7 +281,7 @@ PlatformTouchEvent convertTouchEvent(QTouchEvent* event) } #endif -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) PlatformGestureEvent convertGesture(QGestureEventFacade* event) { return WebKitPlatformGestureEvent(event); diff --git a/Source/WebKit/qt/WebCoreSupport/WebEventConversion.h b/Source/WebKit/qt/WebCoreSupport/WebEventConversion.h index 0cf8cd849..3cb7a3093 100644 --- a/Source/WebKit/qt/WebCoreSupport/WebEventConversion.h +++ b/Source/WebKit/qt/WebCoreSupport/WebEventConversion.h @@ -49,7 +49,7 @@ class PlatformTouchEvent; PlatformTouchEvent convertTouchEvent(QTouchEvent*); #endif -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) class PlatformGestureEvent; PlatformGestureEvent convertGesture(QGestureEventFacade*); #endif diff --git a/Source/WebKit/qt/WidgetApi/qwebpage.cpp b/Source/WebKit/qt/WidgetApi/qwebpage.cpp index 009842830..5bb2f315d 100644 --- a/Source/WebKit/qt/WidgetApi/qwebpage.cpp +++ b/Source/WebKit/qt/WidgetApi/qwebpage.cpp @@ -31,6 +31,7 @@ #include "QtFallbackWebPopup.h" #include "QtPlatformPlugin.h" #include "UndoStepQt.h" +#include "WebEventConversion.h" #include "qwebframe.h" #include "qwebframe_p.h" @@ -48,7 +49,6 @@ #include <QBitArray> #include <QClipboard> #include <QColorDialog> -#include <QDebug> #include <QDesktopWidget> #include <QDragEnterEvent> #include <QDragLeaveEvent> @@ -976,7 +976,7 @@ bool QWebPagePrivate::gestureEvent(QGestureEvent* event) return false; // QGestureEvents can contain updates for multiple gestures. bool handled = false; -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) // QGestureEvent lives in Widgets, we'll need a dummy struct to mule the info it contains to the "other side" QGestureEventFacade gestureFacade; @@ -1000,7 +1000,7 @@ bool QWebPagePrivate::gestureEvent(QGestureEvent* event) frame->handleGestureEvent(&gestureFacade); handled = true; } -#endif // ENABLE(GESTURE_EVENTS) +#endif // ENABLE(QT_GESTURE_EVENTS) event->setAccepted(handled); return handled; @@ -3064,7 +3064,7 @@ bool QWebPage::extension(Extension extension, const ExtensionOption *option, Ext if (extension == ChooseMultipleFilesExtension) { // FIXME: do not ignore suggestedFiles QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames; - QStringList names = QFileDialog::getOpenFileNames(view(), QString::null); + QStringList names = QFileDialog::getOpenFileNames(view(), QString()); static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names; return true; } @@ -3139,9 +3139,9 @@ QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFil { Q_UNUSED(parentFrame); #ifndef QT_NO_FILEDIALOG - return QFileDialog::getOpenFileName(view(), QString::null, suggestedFile); + return QFileDialog::getOpenFileName(view(), QString(), suggestedFile); #else - return QString::null; + return QString(); #endif } diff --git a/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index f792befcd..17bc703fc 100644 --- a/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -30,7 +30,6 @@ #include <QComboBox> #include <QPaintEngine> #include <QPicture> -#include <QRegExp> #include <QNetworkRequest> #include <QNetworkReply> #include <QTextCodec> diff --git a/Source/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp b/Source/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp index f4571cf74..1612eb7b9 100644 --- a/Source/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp +++ b/Source/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp @@ -25,7 +25,6 @@ #include <qwebframe.h> #include <qwebelement.h> #include <qwebhistoryinterface.h> -#include <QDebug> class tst_QWebHistoryInterface : public QObject { diff --git a/Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index bef98fee6..67fe242f9 100644 --- a/Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -28,6 +28,7 @@ #include <QMenu> #include <QMimeDatabase> #include <QPushButton> +#include <QRegExp> #include <QStateMachine> #include <QStyle> #include <QtTest/QtTest> diff --git a/Source/WebKit/qt/tests/qwebsecurityorigin/tst_qwebsecurityorigin.cpp b/Source/WebKit/qt/tests/qwebsecurityorigin/tst_qwebsecurityorigin.cpp index 835f243f7..a15838274 100644 --- a/Source/WebKit/qt/tests/qwebsecurityorigin/tst_qwebsecurityorigin.cpp +++ b/Source/WebKit/qt/tests/qwebsecurityorigin/tst_qwebsecurityorigin.cpp @@ -19,7 +19,6 @@ */ -#include <QDebug> #include <QNetworkReply> #include <QtTest> #include <qwebframe.h> diff --git a/Source/WebKit2/Platform/qt/LoggingQt.cpp b/Source/WebKit2/Platform/qt/LoggingQt.cpp index 6f7951857..fd7809cce 100644 --- a/Source/WebKit2/Platform/qt/LoggingQt.cpp +++ b/Source/WebKit2/Platform/qt/LoggingQt.cpp @@ -28,8 +28,6 @@ #include "config.h" #include "Logging.h" -#include <QDebug> - namespace WebKit { #if !LOG_DISABLED diff --git a/Source/WebKit2/PlatformQt.cmake b/Source/WebKit2/PlatformQt.cmake index 38080b1a4..3d74594f0 100644 --- a/Source/WebKit2/PlatformQt.cmake +++ b/Source/WebKit2/PlatformQt.cmake @@ -75,6 +75,7 @@ list(APPEND WebKit2_SOURCES Shared/qt/ShareableBitmapQt.cpp Shared/qt/WebCoreArgumentCodersQt.cpp Shared/qt/WebEventFactoryQt.cpp + Shared/qt/WebGestureEvent.cpp Shared/unix/ChildProcessMain.cpp diff --git a/Source/WebKit2/PluginProcess/qt/PluginProcessMainQt.cpp b/Source/WebKit2/PluginProcess/qt/PluginProcessMainQt.cpp index 8de65216b..96e676d6e 100644 --- a/Source/WebKit2/PluginProcess/qt/PluginProcessMainQt.cpp +++ b/Source/WebKit2/PluginProcess/qt/PluginProcessMainQt.cpp @@ -31,7 +31,6 @@ #include "NetscapePluginModule.h" #include "PluginProcess.h" #include "WebKit2Initialize.h" -#include <QDebug> #include <QGuiApplication> #include <QStringList> #include <QtGlobal> diff --git a/Source/WebKit2/Shared/WebEvent.h b/Source/WebKit2/Shared/WebEvent.h index 4bfa0d822..c7548203a 100644 --- a/Source/WebKit2/Shared/WebEvent.h +++ b/Source/WebKit2/Shared/WebEvent.h @@ -71,6 +71,11 @@ public: RawKeyDown, Char, +#if ENABLE(QT_GESTURE_EVENTS) + // WebGestureEvent + GestureSingleTap, +#endif + #if ENABLE(TOUCH_EVENTS) // WebTouchEvent TouchStart, @@ -290,6 +295,31 @@ private: bool m_isSystemKey; }; + +#if ENABLE(QT_GESTURE_EVENTS) +// FIXME: Move this class to its own header file. +class WebGestureEvent : public WebEvent { +public: + WebGestureEvent() { } + WebGestureEvent(Type, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, Modifiers, double timestamp, const WebCore::IntSize& area); + + const WebCore::IntPoint position() const { return m_position; } + const WebCore::IntPoint globalPosition() const { return m_globalPosition; } + const WebCore::IntSize area() const { return m_area; } + + void encode(IPC::ArgumentEncoder&) const; + static bool decode(IPC::ArgumentDecoder&, WebGestureEvent&); + +private: + static bool isGestureEventType(Type); + + WebCore::IntPoint m_position; + WebCore::IntPoint m_globalPosition; + WebCore::IntSize m_area; +}; +#endif // ENABLE(QT_GESTURE_EVENTS) + + #if ENABLE(TOUCH_EVENTS) #if PLATFORM(IOS) class WebPlatformTouchPoint { diff --git a/Source/WebKit2/Shared/WebEventConversion.cpp b/Source/WebKit2/Shared/WebEventConversion.cpp index eeb74413f..f401a53bd 100644 --- a/Source/WebKit2/Shared/WebEventConversion.cpp +++ b/Source/WebKit2/Shared/WebEventConversion.cpp @@ -223,6 +223,46 @@ WebCore::PlatformKeyboardEvent platform(const WebKeyboardEvent& webEvent) return WebKit2PlatformKeyboardEvent(webEvent); } +#if ENABLE(QT_GESTURE_EVENTS) +class WebKit2PlatformGestureEvent : public WebCore::PlatformGestureEvent { +public: + WebKit2PlatformGestureEvent(const WebGestureEvent& webEvent) + { + // PlatformEvent + switch (webEvent.type()) { + case WebEvent::GestureSingleTap: + m_type = WebCore::PlatformEvent::GestureTap; + break; + default: + ASSERT_NOT_REACHED(); + } + + m_modifiers = 0; + if (webEvent.shiftKey()) + m_modifiers |= ShiftKey; + if (webEvent.controlKey()) + m_modifiers |= CtrlKey; + if (webEvent.altKey()) + m_modifiers |= AltKey; + if (webEvent.metaKey()) + m_modifiers |= MetaKey; + + m_timestamp = webEvent.timestamp(); + + // PlatformGestureEvent + m_position = webEvent.position(); + m_globalPosition = webEvent.globalPosition(); + + m_area = webEvent.area(); + } +}; + +WebCore::PlatformGestureEvent platform(const WebGestureEvent& webEvent) +{ + return WebKit2PlatformGestureEvent(webEvent); +} +#endif + #if ENABLE(TOUCH_EVENTS) #if PLATFORM(IOS) diff --git a/Source/WebKit2/Shared/WebEventConversion.h b/Source/WebKit2/Shared/WebEventConversion.h index 827f4f7b2..ea0aad421 100644 --- a/Source/WebKit2/Shared/WebEventConversion.h +++ b/Source/WebKit2/Shared/WebEventConversion.h @@ -41,12 +41,20 @@ #include <WebKitAdditions/PlatformGestureEventMac.h> #endif +#if ENABLE(QT_GESTURE_EVENTS) +#include <WebCore/PlatformGestureEvent.h> +#endif + namespace WebKit { class WebMouseEvent; class WebWheelEvent; class WebKeyboardEvent; +#if ENABLE(QT_GESTURE_EVENTS) +class WebGestureEvent; +#endif + #if ENABLE(TOUCH_EVENTS) class WebTouchEvent; class WebTouchPoint; @@ -60,6 +68,10 @@ WebCore::PlatformMouseEvent platform(const WebMouseEvent&); WebCore::PlatformWheelEvent platform(const WebWheelEvent&); WebCore::PlatformKeyboardEvent platform(const WebKeyboardEvent&); +#if ENABLE(QT_GESTURE_EVENTS) +WebCore::PlatformGestureEvent platform(const WebGestureEvent&); +#endif + #if ENABLE(TOUCH_EVENTS) WebCore::PlatformTouchEvent platform(const WebTouchEvent&); #if !ENABLE(IOS_TOUCH_EVENTS) diff --git a/Source/WebKit2/Shared/qt/WebGestureEvent.cpp b/Source/WebKit2/Shared/qt/WebGestureEvent.cpp new file mode 100644 index 000000000..340658267 --- /dev/null +++ b/Source/WebKit2/Shared/qt/WebGestureEvent.cpp @@ -0,0 +1,76 @@ +/* + * 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 "WebEvent.h" + +#if ENABLE(QT_GESTURE_EVENTS) + +#include "Arguments.h" +#include "WebCoreArgumentCoders.h" + +using namespace WebCore; + +namespace WebKit { + +WebGestureEvent::WebGestureEvent(Type type, const IntPoint& position, const IntPoint& globalPosition, Modifiers modifiers, double timestamp, const IntSize& area/*, const FloatPoint& delta*/) + : WebEvent(type, modifiers, timestamp) + , m_position(position) + , m_globalPosition(globalPosition) + , m_area(area) +{ + ASSERT(isGestureEventType(type)); +} + +void WebGestureEvent::encode(IPC::ArgumentEncoder& encoder) const +{ + WebEvent::encode(encoder); + + encoder << m_position; + encoder << m_globalPosition; + encoder << m_area; +} + +bool WebGestureEvent::decode(IPC::ArgumentDecoder& decoder, WebGestureEvent& t) +{ + if (!WebEvent::decode(decoder, t)) + return false; + if (!decoder.decode(t.m_position)) + return false; + if (!decoder.decode(t.m_globalPosition)) + return false; + if (!decoder.decode(t.m_area)) + return false; + return true; +} + +bool WebGestureEvent::isGestureEventType(Type type) +{ + return type == GestureSingleTap; +} + +} // namespace WebKit + +#endif // ENABLE(QT_GESTURE_EVENTS) diff --git a/Source/WebKit2/UIProcess/PageClient.h b/Source/WebKit2/UIProcess/PageClient.h index edb0897b0..86dae0c2a 100644 --- a/Source/WebKit2/UIProcess/PageClient.h +++ b/Source/WebKit2/UIProcess/PageClient.h @@ -66,6 +66,10 @@ class WebContextMenuProxy; class WebEditCommandProxy; class WebPopupMenuProxy; +#if ENABLE(QT_GESTURE_EVENTS) +class WebGestureEvent; +#endif + #if ENABLE(TOUCH_EVENTS) class NativeWebTouchEvent; #endif @@ -223,6 +227,9 @@ public: #endif virtual void doneWithKeyEvent(const NativeWebKeyboardEvent&, bool wasEventHandled) = 0; +#if ENABLE(QT_GESTURE_EVENTS) + virtual void doneWithGestureEvent(const WebGestureEvent&, bool wasEventHandled) = 0; +#endif #if ENABLE(TOUCH_EVENTS) virtual void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled) = 0; #endif diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp index 3e221a920..9b2033f32 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp @@ -1929,6 +1929,19 @@ void WebPageProxy::findPlugin(const String& mimeType, uint32_t processType, cons #endif // ENABLE(NETSCAPE_PLUGIN_API) +#if ENABLE(QT_GESTURE_EVENTS) +void WebPageProxy::handleGestureEvent(const WebGestureEvent& event) +{ + if (!isValid()) + return; + + m_gestureEventQueue.append(event); + + m_process->responsivenessTimer().start(); + m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0); +} +#endif + #if ENABLE(TOUCH_EVENTS) bool WebPageProxy::shouldStartTrackingTouchEvents(const WebTouchEvent& touchStartEvent) const @@ -4588,6 +4601,9 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) case WebEvent::KeyUp: case WebEvent::RawKeyDown: case WebEvent::Char: +#if ENABLE(QT_GESTURE_EVENTS) + case WebEvent::GestureSingleTap: +#endif #if ENABLE(TOUCH_EVENTS) case WebEvent::TouchStart: case WebEvent::TouchMove: @@ -4613,6 +4629,16 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) break; case WebEvent::MouseDown: break; +#if ENABLE(QT_GESTURE_EVENTS) + case WebEvent::GestureSingleTap: { + WebGestureEvent event = m_gestureEventQueue.first(); + MESSAGE_CHECK(type == event.type()); + + m_gestureEventQueue.removeFirst(); + m_pageClient.doneWithGestureEvent(event, handled); + break; + } +#endif case WebEvent::MouseUp: m_currentlyProcessedMouseDownEvent = nullptr; break; @@ -5147,6 +5173,9 @@ void WebPageProxy::resetStateAfterProcessExited() m_pendingLearnOrIgnoreWordMessageCount = 0; // Can't expect DidReceiveEvent notifications from a crashed web process. +#if ENABLE(QT_GESTURE_EVENTS) + m_gestureEventQueue.clear(); +#endif m_keyEventQueue.clear(); m_wheelEventQueue.clear(); m_currentlyProcessedWheelEvents.clear(); diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h index fb39d86f4..a404e8664 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.h +++ b/Source/WebKit2/UIProcess/WebPageProxy.h @@ -224,6 +224,10 @@ struct PlatformPopupMenuData; struct PrintInfo; struct WebPopupItem; +#if ENABLE(QT_GESTURE_EVENTS) +class WebGestureEvent; +#endif + #if ENABLE(VIBRATION) class WebVibrationProxy; #endif @@ -630,6 +634,10 @@ public: void handleGestureEvent(const NativeWebGestureEvent&); #endif +#if ENABLE(QT_GESTURE_EVENTS) + void handleGestureEvent(const WebGestureEvent&); +#endif + #if ENABLE(IOS_TOUCH_EVENTS) void handleTouchEventSynchronously(const NativeWebTouchEvent&); void handleTouchEventAsynchronously(const NativeWebTouchEvent&); @@ -1689,6 +1697,9 @@ private: DownloadID m_syncNavigationActionPolicyDownloadID; bool m_shouldSuppressAppLinksInNextNavigationPolicyDecision { false }; +#if ENABLE(QT_GESTURE_EVENTS) + Deque<WebGestureEvent> m_gestureEventQueue; +#endif Deque<NativeWebKeyboardEvent> m_keyEventQueue; Deque<NativeWebWheelEvent> m_wheelEventQueue; Deque<std::unique_ptr<Vector<NativeWebWheelEvent>>> m_currentlyProcessedWheelEvents; diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp index 1b62c94ba..d5afa7996 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp @@ -251,7 +251,7 @@ void QtPageClient::handleWillSetInputMethodState() m_eventHandler->handleWillSetInputMethodState(); } -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) void QtPageClient::doneWithGestureEvent(const WebGestureEvent& event, bool wasEventHandled) { ASSERT(m_eventHandler); diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.h b/Source/WebKit2/UIProcess/qt/QtPageClient.h index 393629731..a30b25dd3 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.h +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.h @@ -93,7 +93,7 @@ public: void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&) override; void updateTextInputState() override; void handleWillSetInputMethodState() override; -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) void doneWithGestureEvent(const WebGestureEvent&, bool wasEventHandled) override; #endif #if ENABLE(TOUCH_EVENTS) diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp index 9b620fb9d..b56f475cc 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp @@ -261,12 +261,12 @@ void QtWebPageEventHandler::deactivateTapHighlight() void QtWebPageEventHandler::handleSingleTapEvent(const QTouchEvent::TouchPoint& point) { -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) deactivateTapHighlight(); m_postponeTextInputStateChanged = true; QTransform fromItemTransform = m_webPage->transformFromItem(); - WebGestureEvent gesture(WebEvent::GestureSingleTap, fromItemTransform.map(point.pos()).toPoint(), point.screenPos().toPoint(), WebEvent::Modifiers(0), 0, IntSize(point.rect().size().toSize()), FloatPoint(0, 0)); + WebGestureEvent gesture(WebEvent::GestureSingleTap, fromItemTransform.map(point.pos()).toPoint(), point.screenPos().toPoint(), WebEvent::Modifiers(0), 0, IntSize(point.rect().size().toSize())); m_webPageProxy->handleGestureEvent(gesture); #endif } @@ -448,7 +448,7 @@ void QtWebPageEventHandler::handleWillSetInputMethodState() void QtWebPageEventHandler::doneWithGestureEvent(const WebGestureEvent& event, bool wasEventHandled) { -#if ENABLE(GESTURE_EVENTS) +#if ENABLE(QT_GESTURE_EVENTS) if (event.type() != WebEvent::GestureSingleTap) return; diff --git a/Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp b/Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp index 3418d8b0c..ee7d32600 100644 --- a/Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp +++ b/Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp @@ -488,6 +488,9 @@ bool NetscapePluginX11::handleMouseEvent(const WebMouseEvent& event) case WebEvent::KeyUp: case WebEvent::RawKeyDown: case WebEvent::Char: +#if ENABLE(QT_GESTURE_EVENTS) + case WebEvent::GestureSingleTap: +#endif #if ENABLE(TOUCH_EVENTS) case WebEvent::TouchStart: case WebEvent::TouchMove: diff --git a/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/WebPageCoordinatedGraphics.cpp b/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/WebPageCoordinatedGraphics.cpp index 345648baa..a3335430a 100644 --- a/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/WebPageCoordinatedGraphics.cpp +++ b/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/WebPageCoordinatedGraphics.cpp @@ -45,6 +45,26 @@ using namespace WebCore; namespace WebKit { #if USE(COORDINATED_GRAPHICS_MULTIPROCESS) + +#if ENABLE(TOUCH_ADJUSTMENT) +void WebPage::findZoomableAreaForPoint(const IntPoint& point, const IntSize& area) +{ + Node* node = 0; + IntRect zoomableArea; + bool foundAreaForTouchPoint = m_mainFrame->coreFrame()->eventHandler().bestZoomableAreaForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), zoomableArea, node); + + if (!foundAreaForTouchPoint) + return; + + ASSERT(node); + + if (node->document().view()) + zoomableArea = node->document().view()->contentsToWindow(zoomableArea); + + send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea)); +} + +#else void WebPage::findZoomableAreaForPoint(const IntPoint& point, const IntSize& area) { UNUSED_PARAM(area); @@ -85,6 +105,8 @@ void WebPage::findZoomableAreaForPoint(const IntPoint& point, const IntSize& are send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea)); } +#endif // ENABLE(TOUCH_ADJUSTMENT) + #endif } // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp index b96398ed3..cac0abfbc 100644 --- a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp +++ b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp @@ -144,7 +144,7 @@ void EventDispatcher::wheelEvent(uint64_t pageID, const WebWheelEvent& wheelEven }); } -#if ENABLE(MAC_GESTURE_EVENTS) +#if ENABLE(MAC_GESTURE_EVENTS) || ENABLE(QT_GESTURE_EVENTS) void EventDispatcher::gestureEvent(uint64_t pageID, const WebKit::WebGestureEvent& gestureEvent) { RefPtr<EventDispatcher> eventDispatcher = this; @@ -224,7 +224,7 @@ void EventDispatcher::dispatchWheelEvent(uint64_t pageID, const WebWheelEvent& w webPage->wheelEvent(wheelEvent); } -#if ENABLE(MAC_GESTURE_EVENTS) +#if ENABLE(MAC_GESTURE_EVENTS) || ENABLE(QT_GESTURE_EVENTS) void EventDispatcher::dispatchGestureEvent(uint64_t pageID, const WebGestureEvent& gestureEvent) { ASSERT(RunLoop::isMain()); diff --git a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h index 8374a83fe..3b088e927 100644 --- a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h +++ b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h @@ -81,7 +81,7 @@ private: #if ENABLE(IOS_TOUCH_EVENTS) void touchEvent(uint64_t pageID, const WebTouchEvent&); #endif -#if ENABLE(MAC_GESTURE_EVENTS) +#if ENABLE(MAC_GESTURE_EVENTS) || ENABLE(QT_GESTURE_EVENTS) void gestureEvent(uint64_t pageID, const WebGestureEvent&); #endif @@ -91,7 +91,7 @@ private: #if ENABLE(IOS_TOUCH_EVENTS) void dispatchTouchEvents(); #endif -#if ENABLE(MAC_GESTURE_EVENTS) +#if ENABLE(MAC_GESTURE_EVENTS) || ENABLE(QT_GESTURE_EVENTS) void dispatchGestureEvent(uint64_t pageID, const WebGestureEvent&); #endif diff --git a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in index 5e1543c98..8044fc614 100644 --- a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in +++ b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in @@ -25,7 +25,7 @@ messages -> EventDispatcher { #if ENABLE(IOS_TOUCH_EVENTS) TouchEvent(uint64_t pageID, WebKit::WebTouchEvent event) #endif -#if ENABLE(MAC_GESTURE_EVENTS) +#if ENABLE(MAC_GESTURE_EVENTS) || ENABLE(QT_GESTURE_EVENTS) GestureEvent(uint64_t pageID, WebKit::WebGestureEvent event) #endif } diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp index 2cd709f22..6eafa5123 100644 --- a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp +++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp @@ -2368,7 +2368,7 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent) } #endif -#if ENABLE(MAC_GESTURE_EVENTS) +#if ENABLE(MAC_GESTURE_EVENTS) || ENABLE(QT_GESTURE_EVENTS) static bool handleGestureEvent(const WebGestureEvent& event, Page* page) { if (!page->mainFrame().view()) diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.h b/Source/WebKit2/WebProcess/WebPage/WebPage.h index 8be9a42a9..a41239ac6 100644 --- a/Source/WebKit2/WebProcess/WebPage/WebPage.h +++ b/Source/WebKit2/WebProcess/WebPage/WebPage.h @@ -210,6 +210,10 @@ struct WebPreferencesStore; class RemoteLayerTreeTransaction; #endif +#if ENABLE(QT_GESTURE_EVENTS) +class WebGestureEvent; +#endif + #if ENABLE(TOUCH_EVENTS) class WebTouchEvent; #endif @@ -811,7 +815,7 @@ public: void wheelEventHandlersChanged(bool); void recomputeShortCircuitHorizontalWheelEventsState(); -#if ENABLE(MAC_GESTURE_EVENTS) +#if ENABLE(MAC_GESTURE_EVENTS) || ENABLE(QT_GESTURE_EVENTS) void gestureEvent(const WebGestureEvent&); #endif diff --git a/Source/cmake/OptionsCommon.cmake b/Source/cmake/OptionsCommon.cmake index ddaa23327..6a32559a0 100644 --- a/Source/cmake/OptionsCommon.cmake +++ b/Source/cmake/OptionsCommon.cmake @@ -44,6 +44,33 @@ if (WIN32 AND COMPILER_IS_GCC_OR_CLANG) add_definitions(-D__USE_MINGW_ANSI_STDIO=1) endif () +# Ensure that the default include system directories are added to the list of CMake implicit includes. +# This workarounds an issue that happens when using GCC 6 and using system includes (-isystem). +# For more details check: https://bugs.webkit.org/show_bug.cgi?id=161697 +macro(DETERMINE_GCC_SYSTEM_INCLUDE_DIRS _lang _compiler _flags _result) + file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/dummy" "\n") + separate_arguments(_buildFlags UNIX_COMMAND "${_flags}") + execute_process(COMMAND ${_compiler} ${_buildFlags} -v -E -x ${_lang} -dD dummy + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/CMakeFiles OUTPUT_QUIET + ERROR_VARIABLE _gccOutput) + file(REMOVE "${CMAKE_BINARY_DIR}/CMakeFiles/dummy") + if ("${_gccOutput}" MATCHES "> search starts here[^\n]+\n *(.+) *\n *End of (search) list") + set(${_result} ${CMAKE_MATCH_1}) + string(REPLACE "\n" " " ${_result} "${${_result}}") + separate_arguments(${_result}) + endif () +endmacro() + +if (CMAKE_COMPILER_IS_GNUCC) + DETERMINE_GCC_SYSTEM_INCLUDE_DIRS("c" "${CMAKE_C_COMPILER}" "${CMAKE_C_FLAGS}" SYSTEM_INCLUDE_DIRS) + set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES} ${SYSTEM_INCLUDE_DIRS}) +endif () + +if (CMAKE_COMPILER_IS_GNUCXX) + DETERMINE_GCC_SYSTEM_INCLUDE_DIRS("c++" "${CMAKE_CXX_COMPILER}" "${CMAKE_CXX_FLAGS}" SYSTEM_INCLUDE_DIRS) + set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES} ${SYSTEM_INCLUDE_DIRS}) +endif () + # Detect Cortex-A53 core if CPU is ARM64 and OS is Linux. # Query /proc/cpuinfo for each available core and check reported CPU part number: 0xd03 signals Cortex-A53. # (see Main ID Register in ARM Cortex-A53 MPCore Processor Technical Reference Manual) diff --git a/Source/cmake/OptionsQt.cmake b/Source/cmake/OptionsQt.cmake index 8f06820c5..d57e9133c 100644 --- a/Source/cmake/OptionsQt.cmake +++ b/Source/cmake/OptionsQt.cmake @@ -110,6 +110,9 @@ else () set(ENABLE_NETSCAPE_PLUGIN_API_DEFAULT OFF) endif () +# Public options specific to the Qt port. Do not add any options here unless +# there is a strong reason we should support changing the value of the option, +# and the option is not relevant to any other WebKit ports. WEBKIT_OPTION_DEFINE(USE_GSTREAMER "Use GStreamer implementation of MediaPlayer" PUBLIC ${USE_GSTREAMER_DEFAULT}) WEBKIT_OPTION_DEFINE(USE_LIBHYPHEN "Use automatic hyphenation with LibHyphen" PUBLIC ${USE_LIBHYPHEN_DEFAULT}) WEBKIT_OPTION_DEFINE(USE_MEDIA_FOUNDATION "Use MediaFoundation implementation of MediaPlayer" PUBLIC OFF) @@ -118,6 +121,7 @@ WEBKIT_OPTION_DEFINE(USE_WOFF2 "Include support of WOFF2 fonts format" PUBLIC ON WEBKIT_OPTION_DEFINE(ENABLE_INSPECTOR_UI "Include Inspector UI into resources" PUBLIC ON) WEBKIT_OPTION_DEFINE(ENABLE_OPENGL "Whether to use OpenGL." PUBLIC ON) WEBKIT_OPTION_DEFINE(ENABLE_PRINT_SUPPORT "Enable support for printing web pages" PUBLIC ON) +WEBKIT_OPTION_DEFINE(ENABLE_QT_GESTURE_EVENTS "Enable support for gesture events (required for mouse in WK2)" PUBLIC ON) WEBKIT_OPTION_DEFINE(ENABLE_X11_TARGET "Whether to enable support for the X11 windowing target." PUBLIC ${ENABLE_X11_TARGET_DEFAULT}) option(GENERATE_DOCUMENTATION "Generate HTML and QCH documentation" OFF) @@ -125,6 +129,11 @@ cmake_dependent_option(ENABLE_TEST_SUPPORT "Build tools for running layout tests "DEVELOPER_MODE" OFF) option(USE_STATIC_RUNTIME "Use static runtime (MSVC only)" OFF) +# Private options specific to the Qt port. Changing these options is +# completely unsupported. They are intended for use only by WebKit developers. +WEBKIT_OPTION_DEFINE(ENABLE_TOUCH_ADJUSTMENT "Whether to use touch adjustment" PRIVATE ON) + + # Public options shared with other WebKit ports. There must be strong reason # to support changing the value of the option. WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ACCELERATED_2D_CANVAS PUBLIC ON) diff --git a/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp index e9c39f9b2..e72ee703a 100644 --- a/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp +++ b/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp @@ -64,6 +64,7 @@ #include <QPrinter> #endif #include <QProgressBar> +#include <QRegExp> #include <QUndoStack> #include <QUrl> #include <limits.h> diff --git a/Tools/DumpRenderTree/qt/EventSenderQt.cpp b/Tools/DumpRenderTree/qt/EventSenderQt.cpp index 666a2475e..563286526 100644 --- a/Tools/DumpRenderTree/qt/EventSenderQt.cpp +++ b/Tools/DumpRenderTree/qt/EventSenderQt.cpp @@ -576,7 +576,7 @@ void EventSender::gestureTap(int x, int y) m_gestures.clear(); m_gestures.append(&m_tapGesture); QGestureEvent event(m_gestures); - sendEvent(m_page, &event); + sendEvent(m_page->view(), &event); } void EventSender::gestureLongPress(int x, int y) @@ -585,7 +585,7 @@ void EventSender::gestureLongPress(int x, int y) m_gestures.clear(); m_gestures.append(&m_tapAndHoldGesture); QGestureEvent event(m_gestures); - sendEvent(m_page, &event); + sendEvent(m_page->view(), &event); } #endif diff --git a/Tools/MiniBrowser/qt/main.cpp b/Tools/MiniBrowser/qt/main.cpp index 4c8cd92ab..b688aa7ef 100644 --- a/Tools/MiniBrowser/qt/main.cpp +++ b/Tools/MiniBrowser/qt/main.cpp @@ -35,7 +35,6 @@ #include <QDir> #include <QLatin1String> -#include <QRegExp> int main(int argc, char** argv) { diff --git a/Tools/QtTestBrowser/CMakeLists.txt b/Tools/QtTestBrowser/CMakeLists.txt index 485cd0ca1..ab625f6e5 100644 --- a/Tools/QtTestBrowser/CMakeLists.txt +++ b/Tools/QtTestBrowser/CMakeLists.txt @@ -67,3 +67,7 @@ include_directories(SYSTEM ${QtTestBrowser_SYSTEM_INCLUDE_DIRECTORIES}) add_executable(QtTestBrowser ${QtTestBrowser_SOURCES}) target_link_libraries(QtTestBrowser ${QtTestBrowser_LIBRARIES}) set_target_properties(QtTestBrowser PROPERTIES FOLDER "Tools") + +if (${CMAKE_BUILD_TYPE} MATCHES "Release") + set_target_properties(QtTestBrowser PROPERTIES WIN32_EXECUTABLE ON) +endif () diff --git a/Tools/QtTestBrowser/qttestbrowser.cpp b/Tools/QtTestBrowser/qttestbrowser.cpp index 4ec7425b1..24ca97a7a 100644 --- a/Tools/QtTestBrowser/qttestbrowser.cpp +++ b/Tools/QtTestBrowser/qttestbrowser.cpp @@ -47,6 +47,7 @@ WindowOptions windowOptions; #include <QFile> #include <QFileInfo> #include <QFontDatabase> +#include <QRegExp> int launcherMain(const QApplication& app) { diff --git a/Tools/Scripts/update-qtwebkit-win-libs b/Tools/Scripts/update-qtwebkit-win-libs index 8227ba933..da813f855 100644 --- a/Tools/Scripts/update-qtwebkit-win-libs +++ b/Tools/Scripts/update-qtwebkit-win-libs @@ -35,7 +35,7 @@ use FindBin; my $file = "qtwebkit-libs-win"; my $zipFile = "$file.zip"; -my $winQtLibsURL = "https://dl.dropboxusercontent.com/u/30021413/$zipFile"; +my $winQtLibsURL = "https://github.com/Vitallium/qtwebkit-libs-win/releases/download/2015/$zipFile"; my $command = "$FindBin::Bin/update-webkit-dependency"; system("perl", $command, $winQtLibsURL, ".") == 0 or die; diff --git a/Tools/qmake/mkspecs/features/functions.prf b/Tools/qmake/mkspecs/features/functions.prf index 3a775dcfd..3e0d40610 100644 --- a/Tools/qmake/mkspecs/features/functions.prf +++ b/Tools/qmake/mkspecs/features/functions.prf @@ -51,6 +51,8 @@ defineReplace(appleSdkVersion) { } defineTest(isPlatformSupported) { + !qtHaveModule(widgets): skipBuild("QtWidgets module is required to build QtWebKit.") + cross_compile: skipBuild("cross-compilation of QtWebKit with qmake is not supported yet") requiredPrograms = cmake gperf python perl bison ruby flex diff --git a/Tools/qmake/projects/run_cmake.pro b/Tools/qmake/projects/run_cmake.pro index 1b8742c4a..e0c615b0a 100644 --- a/Tools/qmake/projects/run_cmake.pro +++ b/Tools/qmake/projects/run_cmake.pro @@ -70,7 +70,7 @@ build_pass|!debug_and_release { QMAKE_MAC_SDK_PATH = $$system("/usr/bin/xcodebuild -sdk $${QMAKE_MAC_SDK} -version Path 2>/dev/null") } exists($$QMAKE_MAC_SDK_PATH): CMAKE_CONFIG += CMAKE_OSX_SYSROOT=$$QMAKE_MAC_SDK_PATH - !isEmpty($$QMAKE_MACOSX_DEPLOYMENT_TARGET): CMAKE_CONFIG += CMAKE_OSX_DEPLOYMENT_TARGET=$$QMAKE_MACOSX_DEPLOYMENT_TARGET + !isEmpty(QMAKE_MACOSX_DEPLOYMENT_TARGET): CMAKE_CONFIG += CMAKE_OSX_DEPLOYMENT_TARGET=$$QMAKE_MACOSX_DEPLOYMENT_TARGET } equals(QMAKE_HOST.os, Windows) { |