Input elements with type=range do not have default touch handlers.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Jul 2012 01:47:58 +0000 (01:47 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Jul 2012 01:47:58 +0000 (01:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=88807

Patch by Kevin Ellis <kevers@chromium.org> on 2012-07-10
Reviewed by Antonio Gomes.

Source/WebCore:

This patch adds support for touch event handling on input elements
and dragging a slider with touch start and move events.  Previously,
manipulating a slider on a touch screen required generation of
synthetic mouse events.

Tests: fast/events/touch/touch-slider-no-js-touch-listener.html
       fast/events/touch/touch-slider.html

* dom/Event.cpp:
(WebCore::Event::isTouchEvent):
(WebCore):
* dom/Event.h:
(Event):
* dom/Touch.cpp:
(WebCore::Touch::Touch):
* dom/Touch.h:
(WebCore::Touch::absoluteLocation):
(Touch):
* dom/TouchEvent.cpp:
(WebCore::TouchEvent::isTouchEvent):
(WebCore):
* dom/TouchEvent.h:
(TouchEvent):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::HTMLInputElement):
(WebCore::HTMLInputElement::~HTMLInputElement):
(WebCore::HTMLInputElement::updateType):
(WebCore::HTMLInputElement::defaultEventHandler):
* html/HTMLInputElement.h:
(HTMLInputElement):
* html/InputType.cpp:
(WebCore):
(WebCore::InputType::handleTouchEvent):
(WebCore::InputType::hasTouchEventHandler):
* html/InputType.h:
(WebCore):
(ClickHandlingState):
(InputType):
* html/RangeInputType.cpp:
(WebCore):
(WebCore::RangeInputType::handleTouchEvent):
(WebCore::RangeInputType::hasTouchEventHandler):
* html/RangeInputType.h:
(RangeInputType):
* html/shadow/SliderThumbElement.h:
(SliderThumbElement):

Source/WebKit/chromium:

Adds flag to enable native handling of touch events for input elements
with type=range.

* features.gypi:

LayoutTests:

Add automated test for manipulating an input slider via touch
events.

* fast/events/touch/script-tests/touch-slider-no-js-touch-listener.js: Added.
(checkPosition):
* fast/events/touch/script-tests/touch-slider.js: Added.
(onTouchStart):
(onTouchEnd):
(onKeyDown):
(checkPosition):
* fast/events/touch/touch-slider-expected.txt: Added.
* fast/events/touch/touch-slider-no-js-touch-listener-expected.txt: Added.
* fast/events/touch/touch-slider-no-js-touch-listener.html: Added.
* fast/events/touch/touch-slider.html: Added.
* platform/chromium/fast/events/touch/touch-slider-expected.txt: Added.
* platform/chromium/fast/events/touch/touch-slider-no-js-touch-listener-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@122286 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/events/touch/script-tests/touch-slider-no-js-touch-listener.js [new file with mode: 0644]
LayoutTests/fast/events/touch/script-tests/touch-slider.js [new file with mode: 0644]
LayoutTests/fast/events/touch/touch-slider-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/touch/touch-slider-no-js-touch-listener-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/touch/touch-slider-no-js-touch-listener.html [new file with mode: 0644]
LayoutTests/fast/events/touch/touch-slider.html [new file with mode: 0644]
LayoutTests/platform/chromium/fast/events/touch/touch-slider-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/fast/events/touch/touch-slider-no-js-touch-listener-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Event.cpp
Source/WebCore/dom/Event.h
Source/WebCore/dom/Touch.cpp
Source/WebCore/dom/Touch.h
Source/WebCore/dom/TouchEvent.cpp
Source/WebCore/dom/TouchEvent.h
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLInputElement.h
Source/WebCore/html/InputType.cpp
Source/WebCore/html/InputType.h
Source/WebCore/html/RangeInputType.cpp
Source/WebCore/html/RangeInputType.h
Source/WebCore/html/shadow/SliderThumbElement.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/features.gypi

index b23ccd9..5b77ab7 100644 (file)
@@ -1,3 +1,27 @@
+2012-07-10  Kevin Ellis  <kevers@chromium.org>
+
+        Input elements with type=range do not have default touch handlers.
+        https://bugs.webkit.org/show_bug.cgi?id=88807
+
+        Reviewed by Antonio Gomes.
+
+        Add automated test for manipulating an input slider via touch
+        events.
+
+        * fast/events/touch/script-tests/touch-slider-no-js-touch-listener.js: Added.
+        (checkPosition):
+        * fast/events/touch/script-tests/touch-slider.js: Added.
+        (onTouchStart):
+        (onTouchEnd):
+        (onKeyDown):
+        (checkPosition):
+        * fast/events/touch/touch-slider-expected.txt: Added.
+        * fast/events/touch/touch-slider-no-js-touch-listener-expected.txt: Added.
+        * fast/events/touch/touch-slider-no-js-touch-listener.html: Added.
+        * fast/events/touch/touch-slider.html: Added.
+        * platform/chromium/fast/events/touch/touch-slider-expected.txt: Added.
+        * platform/chromium/fast/events/touch/touch-slider-no-js-touch-listener-expected.txt: Added.
+
 2012-07-10  Kenneth Russell  <kbr@google.com>
 
         Line directive test in fast/canvas/webgl/glsl-conformance.html is incorrect
diff --git a/LayoutTests/fast/events/touch/script-tests/touch-slider-no-js-touch-listener.js b/LayoutTests/fast/events/touch/script-tests/touch-slider-no-js-touch-listener.js
new file mode 100644 (file)
index 0000000..454fafb
--- /dev/null
@@ -0,0 +1,59 @@
+var div = document.createElement("div");
+div.style.width = "200%";
+var slider = document.createElement("input");
+slider.setAttribute("type", "range");
+slider.style.width = "200px";
+slider.style.height = "30px";
+
+document.body.insertBefore(div, document.getElementById('console'));
+div.appendChild(slider);
+
+
+var checkPosition = (function() {
+
+  var nCheck = 0;
+
+  var expectedPositions = [50, 0];
+
+  return function() {
+    shouldBeEqualToString("slider.value", String(expectedPositions[nCheck++]));
+  };
+
+})();
+
+function onKeyDown() {
+    checkPosition();
+    layoutTestController.notifyDone();
+    isSuccessfullyParsed();
+}
+
+document.addEventListener('keydown', onKeyDown);
+
+description("Tests to ensure that touch events are delivered to an input element with type=range even when there are no touch event handlers in Javascript. This test is only expected to pass if ENABLE_TOUCH_SLIDER is defined.");
+
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+}
+
+if (window.eventSender) {
+    var x = slider.offsetLeft;
+    var y = slider.offsetTop + slider.clientHeight/2;
+    var w = slider.clientWidth;
+
+    checkPosition();
+
+    eventSender.clearTouchPoints();
+    eventSender.addTouchPoint(x + w/2, y);
+    eventSender.touchStart();
+
+    eventSender.updateTouchPoint(0, x, y);
+    eventSender.touchMove();
+
+    eventSender.releaseTouchPoint(0);
+    eventSender.touchEnd();
+
+    eventSender.keyDown(' ');
+
+} else {
+    debug('This test requires DRT.');
+}
diff --git a/LayoutTests/fast/events/touch/script-tests/touch-slider.js b/LayoutTests/fast/events/touch/script-tests/touch-slider.js
new file mode 100644 (file)
index 0000000..6391dd0
--- /dev/null
@@ -0,0 +1,120 @@
+var div = document.createElement("div");
+div.style.width = "200%";
+var slider1 = document.createElement("input");
+slider1.id = "slider1";
+slider1.setAttribute("type", "range");
+slider1.style.width = "200px";
+slider1.style.height = "30px";
+var slider2 = document.createElement("input");
+slider2.id = "slider2";
+slider2.setAttribute("type", "range");
+slider2.style.width = "30px";
+slider2.style.height = "200px";
+slider2.style.setProperty("-webkit-appearance", "slider-vertical");
+var slider3 = document.createElement("input");
+slider3.id = "slider3";
+slider3.setAttribute("type", "range");
+slider3.style.width = "200px";
+slider3.style.height = "30px";
+slider3.style.setProperty("-webkit-transform", "rotate(-90deg)");
+slider3.style.setProperty("margin", "120px 0");
+
+document.body.insertBefore(div, document.getElementById('console'));
+div.appendChild(slider1);
+div.appendChild(slider2);
+div.appendChild(slider3);
+
+var onTouchStart = (function() {
+
+    var slider = [slider1, slider2, slider3];
+    var nCheck = 0;
+
+    return function() {
+        shouldBeEqualToString("event.touches[0].target.id", slider[nCheck++].id);
+        checkPosition();
+    }
+
+})();
+
+function onTouchMove() {
+    checkPosition();
+}
+
+function onTouchEnd() {
+    checkPosition();
+}
+
+function onKeyDown() {
+    isSuccessfullyParsed();
+    layoutTestController.notifyDone();
+}
+
+var sliderValue = 0;
+
+var checkPosition = (function() {
+
+    var nCheck = 0;
+    var slider = [slider1, slider2, slider3];
+    var expectedPositions = [50, 50, 0, 100, 50];
+    var sliderIndex = 0;
+
+    return function() {
+        sliderValue = slider[sliderIndex].value;
+        shouldBeEqualToString("sliderValue", String(expectedPositions[nCheck++]));
+        if (nCheck % expectedPositions.length == 0) {
+            sliderIndex++;
+            nCheck = 0;
+        }
+    };
+
+})();
+
+function runTest(slider, rotated) {
+
+    var w = slider.clientWidth;
+    var h = slider.clientHeight;
+    var x = slider.offsetLeft + w/2;
+    var y = slider.offsetTop + h/2;
+
+    if (rotated) {
+      w = slider.clientHeight;
+      h = slider.clientWidth;
+    }
+
+    eventSender.clearTouchPoints();
+    eventSender.addTouchPoint(x, y);
+    eventSender.touchStart();
+
+    eventSender.updateTouchPoint(0, x - w/2, y + h/2);
+    eventSender.touchMove();
+
+    eventSender.updateTouchPoint(0, x + w/2, y - h/2);
+    eventSender.touchMove();
+
+    eventSender.updateTouchPoint(0, x, y);
+    eventSender.touchMove();
+
+    eventSender.releaseTouchPoint(0);
+    eventSender.touchEnd();
+}
+
+document.addEventListener("touchstart", onTouchStart, false);
+document.addEventListener("touchmove", onTouchMove, false);
+document.addEventListener("touchend", onTouchEnd, false);
+document.addEventListener("keydown", onKeyDown, false);
+
+description("Tests that the touch events originating on an input element with type=range update the slider position. This test is only expected to pass if ENABLE_TOUCH_SLIDER is defined.");
+
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+}
+
+if (window.eventSender) {
+    runTest(slider1, false);
+    runTest(slider2, false);
+    runTest(slider3, true);
+
+    eventSender.keyDown(' ');
+} else {
+    debug('This test requires DRT.');
+}
diff --git a/LayoutTests/fast/events/touch/touch-slider-expected.txt b/LayoutTests/fast/events/touch/touch-slider-expected.txt
new file mode 100644 (file)
index 0000000..ad31218
--- /dev/null
@@ -0,0 +1,28 @@
+Tests that the touch events originating on an input element with type=range update the slider position. This test is only expected to pass if ENABLE_TOUCH_SLIDER is defined.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+PASS event.touches[0].target.id is "slider1"
+PASS sliderValue is "50"
+PASS sliderValue is "50"
+FAIL sliderValue should be 0. Was 50.
+FAIL sliderValue should be 100. Was 50.
+PASS sliderValue is "50"
+PASS event.touches[0].target.id is "slider2"
+PASS sliderValue is "50"
+PASS sliderValue is "50"
+FAIL sliderValue should be 0. Was 50.
+FAIL sliderValue should be 100. Was 50.
+PASS sliderValue is "50"
+PASS event.touches[0].target.id is "slider3"
+PASS sliderValue is "50"
+PASS sliderValue is "50"
+FAIL sliderValue should be 0. Was 50.
+FAIL sliderValue should be 100. Was 50.
+PASS sliderValue is "50"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/touch/touch-slider-no-js-touch-listener-expected.txt b/LayoutTests/fast/events/touch/touch-slider-no-js-touch-listener-expected.txt
new file mode 100644 (file)
index 0000000..f4bc762
--- /dev/null
@@ -0,0 +1,12 @@
+Tests to ensure that touch events are delivered to an input element with type=range even when there are no touch event handlers in Javascript. This test is only expected to pass if ENABLE_TOUCH_SLIDER is defined.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+PASS slider.value is "50"
+FAIL slider.value should be 0. Was 50.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/touch/touch-slider-no-js-touch-listener.html b/LayoutTests/fast/events/touch/touch-slider-no-js-touch-listener.html
new file mode 100644 (file)
index 0000000..d55b866
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../js/resources/js-test-pre.js"></script>
+<!--
+  Touch tests that involve the ontouchstart, ontouchmove, ontouchend or ontouchcancel callbacks
+  should be written in an asynchronous fashion so they can be run on mobile platforms like Android.
+  You will need to invoke isSuccessfullyParsed() in your test script when the test completes.
+-->
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/touch-slider-no-js-touch-listener.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/touch/touch-slider.html b/LayoutTests/fast/events/touch/touch-slider.html
new file mode 100644 (file)
index 0000000..8c7d516
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../js/resources/js-test-pre.js"></script>
+<!--
+  Touch tests that involve the ontouchstart, ontouchmove, ontouchend or ontouchcancel callbacks
+  should be written in an asynchronous fashion so they can be run on mobile platforms like Android.
+  You will need to invoke isSuccessfullyParsed() in your test script when the test completes.
+-->
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/touch-slider.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/platform/chromium/fast/events/touch/touch-slider-expected.txt b/LayoutTests/platform/chromium/fast/events/touch/touch-slider-expected.txt
new file mode 100644 (file)
index 0000000..55141f4
--- /dev/null
@@ -0,0 +1,28 @@
+Tests that the touch events originating on an input element with type=range update the slider position. This test is only expected to pass if ENABLE_TOUCH_SLIDER is defined.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+PASS event.touches[0].target.id is "slider1"
+PASS sliderValue is "50"
+PASS sliderValue is "50"
+PASS sliderValue is "0"
+PASS sliderValue is "100"
+PASS sliderValue is "50"
+PASS event.touches[0].target.id is "slider2"
+PASS sliderValue is "50"
+PASS sliderValue is "50"
+PASS sliderValue is "0"
+PASS sliderValue is "100"
+PASS sliderValue is "50"
+PASS event.touches[0].target.id is "slider3"
+PASS sliderValue is "50"
+PASS sliderValue is "50"
+PASS sliderValue is "0"
+PASS sliderValue is "100"
+PASS sliderValue is "50"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/chromium/fast/events/touch/touch-slider-no-js-touch-listener-expected.txt b/LayoutTests/platform/chromium/fast/events/touch/touch-slider-no-js-touch-listener-expected.txt
new file mode 100644 (file)
index 0000000..3f41b11
--- /dev/null
@@ -0,0 +1,12 @@
+Tests to ensure that touch events are delivered to an input element with type=range even when there are no touch event handlers in Javascript. This test is only expected to pass if ENABLE_TOUCH_SLIDER is defined.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+PASS slider.value is "50"
+PASS slider.value is "0"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
index 65f296d..f142ea6 100644 (file)
@@ -1,3 +1,57 @@
+2012-07-10  Kevin Ellis  <kevers@chromium.org>
+
+        Input elements with type=range do not have default touch handlers.
+        https://bugs.webkit.org/show_bug.cgi?id=88807
+
+        Reviewed by Antonio Gomes.
+
+        This patch adds support for touch event handling on input elements
+        and dragging a slider with touch start and move events.  Previously,
+        manipulating a slider on a touch screen required generation of
+        synthetic mouse events.
+
+        Tests: fast/events/touch/touch-slider-no-js-touch-listener.html
+               fast/events/touch/touch-slider.html
+
+        * dom/Event.cpp:
+        (WebCore::Event::isTouchEvent):
+        (WebCore):
+        * dom/Event.h:
+        (Event):
+        * dom/Touch.cpp:
+        (WebCore::Touch::Touch):
+        * dom/Touch.h:
+        (WebCore::Touch::absoluteLocation):
+        (Touch):
+        * dom/TouchEvent.cpp:
+        (WebCore::TouchEvent::isTouchEvent):
+        (WebCore):
+        * dom/TouchEvent.h:
+        (TouchEvent):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::HTMLInputElement):
+        (WebCore::HTMLInputElement::~HTMLInputElement):
+        (WebCore::HTMLInputElement::updateType):
+        (WebCore::HTMLInputElement::defaultEventHandler):
+        * html/HTMLInputElement.h:
+        (HTMLInputElement):
+        * html/InputType.cpp:
+        (WebCore):
+        (WebCore::InputType::handleTouchEvent):
+        (WebCore::InputType::hasTouchEventHandler):
+        * html/InputType.h:
+        (WebCore):
+        (ClickHandlingState):
+        (InputType):
+        * html/RangeInputType.cpp:
+        (WebCore):
+        (WebCore::RangeInputType::handleTouchEvent):
+        (WebCore::RangeInputType::hasTouchEventHandler):
+        * html/RangeInputType.h:
+        (RangeInputType):
+        * html/shadow/SliderThumbElement.h:
+        (SliderThumbElement):
+
 2012-07-10  Pravin D  <pravind.2k4@gmail.com>
 
         Re-factoring recalcColumn in AutoTableLayout.cpp for readability
index c9a45dc..761313c 100644 (file)
@@ -126,6 +126,11 @@ bool Event::isKeyboardEvent() const
     return false;
 }
 
+bool Event::isTouchEvent() const
+{
+    return false;
+}
+
 bool Event::isDragEvent() const
 {
     return false;
index 36ed9a6..d298d90 100644 (file)
@@ -120,6 +120,7 @@ namespace WebCore {
         virtual bool isUIEvent() const;
         virtual bool isMouseEvent() const;
         virtual bool isKeyboardEvent() const;
+        virtual bool isTouchEvent() const;
 
         // Drag events are a subset of mouse events.
         virtual bool isDragEvent() const;
index cf721df..a6bda25 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "Touch.h"
 
+#include "DOMWindow.h"
 #include "Frame.h"
 #include "FrameView.h"
 
@@ -68,6 +69,10 @@ Touch::Touch(Frame* frame, EventTarget* target, unsigned identifier, int screenX
     , m_rotationAngle(rotationAngle)
     , m_force(force)
 {
+    float scaleFactor = frame->pageZoomFactor() * frame->frameScaleFactor();
+    float x = pageX * scaleFactor;
+    float y = pageY * scaleFactor;
+    m_absoluteLocation = roundedLayoutPoint(FloatPoint(x, y));
 }
 
 } // namespace WebCore
index f4c9e80..1e80253 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(TOUCH_EVENTS)
 
 #include "EventTarget.h"
+#include "LayoutTypes.h"
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
@@ -59,6 +60,7 @@ public:
     int webkitRadiusY() const { return m_radiusY; }
     float webkitRotationAngle() const { return m_rotationAngle; }
     float webkitForce() const { return m_force; }
+    const LayoutPoint& absoluteLocation() const { return m_absoluteLocation; }
 
 private:
     Touch(Frame* frame, EventTarget* target, unsigned identifier,
@@ -77,6 +79,7 @@ private:
     int m_radiusY;
     float m_rotationAngle;
     float m_force;
+    LayoutPoint m_absoluteLocation;
 };
 
 } // namespace WebCore
index bfd6360..a58f1dc 100644 (file)
@@ -94,6 +94,11 @@ const AtomicString& TouchEvent::interfaceName() const
     return eventNames().interfaceForTouchEvent;
 }
 
+bool TouchEvent::isTouchEvent() const
+{
+    return true;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(TOUCH_EVENTS)
index 297e340..b2e5b2e 100644 (file)
@@ -69,6 +69,7 @@ public:
     void setTouchHold(bool touchHold) { m_touchHold = touchHold; }
     bool isTouchHold() const { return m_touchHold; }
 #endif
+    virtual bool isTouchEvent() const OVERRIDE;
 
     virtual const AtomicString& interfaceName() const;
 
index e773284..e1373d7 100644 (file)
 #include "RuntimeEnabledFeatures.h"
 #endif
 
+#if ENABLE(TOUCH_EVENTS)
+#include "TouchEvent.h"
+#endif
+
 using namespace std;
 
 namespace WebCore {
@@ -98,6 +102,7 @@ HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* docum
     , m_valueAttributeWasUpdatedAfterParsing(false)
     , m_wasModifiedByUser(false)
     , m_canReceiveDroppedFiles(false)
+    , m_hasTouchEventHandler(false)
     , m_inputType(InputType::createText(this))
 {
     ASSERT(hasTagName(inputTag) || hasTagName(isindexTag));
@@ -130,6 +135,10 @@ HTMLInputElement::~HTMLInputElement()
     // We should unregister it to avoid accessing a deleted object.
     if (isRadioButton())
         document()->formController()->checkedRadioButtons().removeButton(this);
+#if ENABLE(TOUCH_EVENTS)
+    if (m_hasTouchEventHandler)
+        document()->didRemoveTouchEventHandler();
+#endif
 }
 
 const AtomicString& HTMLInputElement::name() const
@@ -401,6 +410,18 @@ void HTMLInputElement::updateType()
     m_inputType = newType.release();
     m_inputType->createShadowSubtree();
 
+#if ENABLE(TOUCH_EVENTS)
+    bool hasTouchEventHandler = m_inputType->hasTouchEventHandler();
+    if (hasTouchEventHandler != m_hasTouchEventHandler) {
+      if (hasTouchEventHandler) {
+        document()->didAddTouchEventHandler();
+        document()->addListenerType(Document::TOUCH_LISTENER);
+      } else
+        document()->didRemoveTouchEventHandler();
+      m_hasTouchEventHandler = hasTouchEventHandler;
+    }
+#endif
+
     setNeedsWillValidateCheck();
 
     bool willStoreValue = m_inputType->storesValueSeparateFromAttribute();
@@ -1038,6 +1059,14 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
             return;
     }
 
+#if ENABLE(TOUCH_EVENTS)
+    if (evt->isTouchEvent()) {
+        m_inputType->handleTouchEvent(static_cast<TouchEvent*>(evt));
+        if (evt->defaultHandled())
+            return;
+    }
+#endif
+
     if (evt->isKeyboardEvent() && evt->type() == eventNames().keydownEvent) {
         m_inputType->handleKeydownEvent(static_cast<KeyboardEvent*>(evt));
         if (evt->defaultHandled())
index 1ec5ef0..e10825c 100644 (file)
@@ -390,6 +390,7 @@ private:
     bool m_valueAttributeWasUpdatedAfterParsing : 1;
     bool m_wasModifiedByUser : 1;
     bool m_canReceiveDroppedFiles : 1;
+    bool m_hasTouchEventHandler: 1;
     OwnPtr<InputType> m_inputType;
 };
 
index 30602a0..2530e9e 100644 (file)
@@ -417,6 +417,12 @@ void InputType::handleWheelEvent(WheelEvent*)
 {
 }
 
+#if ENABLE(TOUCH_EVENTS)
+void InputType::handleTouchEvent(TouchEvent*)
+{
+}
+#endif
+
 void InputType::forwardEvent(Event*)
 {
 }
@@ -873,6 +879,13 @@ void InputType::subtreeHasChanged()
 {
 }
 
+#if ENABLE(TOUCH_EVENTS)
+bool InputType::hasTouchEventHandler() const
+{
+    return false;
+}
+#endif
+
 String InputType::defaultToolTip() const
 {
     return String();
index 451303d..fa41ff8 100644 (file)
@@ -61,12 +61,14 @@ class Node;
 class RenderArena;
 class RenderObject;
 class RenderStyle;
+class TouchEvent;
 class WheelEvent;
 
 typedef int ExceptionCode;
 
 struct ClickHandlingState {
     WTF_MAKE_FAST_ALLOCATED;
+  
 public:
     bool checked;
     bool indeterminate;
@@ -190,6 +192,9 @@ public:
     virtual void handleKeyupEvent(KeyboardEvent*);
     virtual void handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*);
     virtual void handleWheelEvent(WheelEvent*);
+#if ENABLE(TOUCH_EVENTS)
+    virtual void handleTouchEvent(TouchEvent*);
+#endif
     virtual void forwardEvent(Event*);
     // Helpers for event handlers.
     virtual bool shouldSubmitImplicitly(Event*);
@@ -202,6 +207,9 @@ public:
     virtual void accessKeyAction(bool sendMouseEvents);
     virtual bool canBeSuccessfulSubmitButton();
     virtual void subtreeHasChanged();
+#if ENABLE(TOUCH_EVENTS)
+    virtual bool hasTouchEventHandler() const;
+#endif
 
     // Shadow tree handling
 
index fd11cba..10c7576 100644 (file)
 #include <wtf/MathExtras.h>
 #include <wtf/PassOwnPtr.h>
 
+#if ENABLE(TOUCH_EVENTS)
+#include "Touch.h"
+#include "TouchEvent.h"
+#include "TouchList.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -134,6 +140,34 @@ void RangeInputType::handleMouseDownEvent(MouseEvent* event)
     thumb->dragFrom(event->absoluteLocation());
 }
 
+#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_SLIDER)
+void RangeInputType::handleTouchEvent(TouchEvent* event)
+{
+    if (element()->disabled() || element()->readOnly())
+        return;
+
+    if (event->type() == eventNames().touchendEvent) {
+        event->setDefaultHandled();
+        return;
+    }
+
+    TouchList* touches = event->targetTouches();
+    if (touches->length() == 1) {
+        Touch* touch = touches->item(0);
+        SliderThumbElement* thumb = sliderThumbElementOf(element());
+        thumb->setPositionFromPoint(touch->absoluteLocation());
+        event->setDefaultHandled();
+    }
+}
+
+bool RangeInputType::hasTouchEventHandler() const
+{
+    return true;
+}
+#endif
+#endif
+
 void RangeInputType::handleKeydownEvent(KeyboardEvent* event)
 {
     if (element()->disabled() || element()->readOnly())
index ff8f402..0983b3d 100644 (file)
@@ -51,6 +51,12 @@ private:
     virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE;
     virtual bool isSteppable() const OVERRIDE;
     virtual void handleMouseDownEvent(MouseEvent*) OVERRIDE;
+#if ENABLE(TOUCH_EVENTS)
+#if ENABLE(TOUCH_SLIDER)
+    virtual void handleTouchEvent(TouchEvent*) OVERRIDE;
+    virtual bool hasTouchEventHandler() const OVERRIDE;
+#endif
+#endif
     virtual void handleKeydownEvent(KeyboardEvent*) OVERRIDE;
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) const OVERRIDE;
     virtual void createShadowSubtree() OVERRIDE;
index e2d8b66..36d6418 100644 (file)
@@ -57,6 +57,7 @@ public:
     virtual void detach();
     virtual const AtomicString& shadowPseudoId() const;
     HTMLInputElement* hostInput() const;
+    void setPositionFromPoint(const LayoutPoint&);
 
 private:
     SliderThumbElement(Document*);
@@ -67,7 +68,6 @@ private:
     virtual Node* focusDelegate();
     void startDragging();
     void stopDragging();
-    void setPositionFromPoint(const LayoutPoint&);
 
     bool m_inDragMode;
 };
index 3674426..a5bbe2e 100644 (file)
@@ -1,3 +1,15 @@
+2012-07-10  Kevin Ellis  <kevers@chromium.org>
+
+        Input elements with type=range do not have default touch handlers.
+        https://bugs.webkit.org/show_bug.cgi?id=88807
+
+        Reviewed by Antonio Gomes.
+
+        Adds flag to enable native handling of touch events for input elements
+        with type=range.
+
+        * features.gypi:
+
 2012-07-10  Adam Klein  <adamk@chromium.org>
 
         [Chromium] REGRESSION(r121909): m_currentInputEvent never set
index ec09ff8..e978a6d 100644 (file)
@@ -97,6 +97,7 @@
       'ENABLE_TOUCH_ADJUSTMENT=1',
       'ENABLE_TOUCH_EVENTS=<(enable_touch_events)',
       'ENABLE_TOUCH_ICON_LOADING=<(enable_touch_icon_loading)',
+      'ENABLE_TOUCH_SLIDER=1',
       'ENABLE_V8_SCRIPT_DEBUG_SERVER=1',
       'ENABLE_VIDEO=1',
       'ENABLE_VIDEO_TRACK=1',