Touch support is reported even when the device doesn't have a touch screen
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 May 2019 08:34:35 +0000 (08:34 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 May 2019 08:34:35 +0000 (08:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=139681

Reviewed by Michael Catanzaro.

Source/WebCore:

Add screenHasTouchDevice() and screenIsTouchPrimaryInputDevice() to PlatformScreen and use it to decide whether
to expose touch events functionality or not.

* bindings/js/WebCoreBuiltinNames.h:
* css/MediaQueryEvaluator.cpp:
(WebCore::hoverEvaluate): Use screenIsTouchPrimaryInputDevice() when touch events are enabled at build time.
(WebCore::anyHoverEvaluate): Use screenHasTouchDevice() when touch events are enabled at build time.
(WebCore::pointerEvaluate): Use screenIsTouchPrimaryInputDevice() when touch events are enabled at build time.
(WebCore::anyPointerEvaluate): Use screenHasTouchDevice() when touch events are enabled at build time.
* dom/GlobalEventHandlers.idl: Make touch event attributes enabled at runtime.
* page/RuntimeEnabledFeatures.cpp:
(WebCore::RuntimeEnabledFeatures::touchEventsEnabled const): Return whether touch events are enabled.
* page/RuntimeEnabledFeatures.h:
(WebCore::RuntimeEnabledFeatures::setTouchEventsEnabled): Force touch events to be enabled or disabled.
* platform/PlatformScreen.h:
(WebCore::screenHasTouchDevice): Just return true when touch events are enabled at build time for non-gtk ports.
(WebCore::screenIsTouchPrimaryInputDevice): Ditto.
* platform/gtk/PlatformScreenGtk.cpp:
(WebCore::screenHasTouchDevice):
(WebCore::screenIsTouchPrimaryInputDevice):
(WebCore::isTouchDevice):
(WebCore::deviceAddedCallback):
(WebCore::deviceRemovedCallback):

LayoutTests:

Remove expectations for tests that are passing now.

* platform/gtk/TestExpectations:

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

LayoutTests/ChangeLog
LayoutTests/platform/gtk/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/WebCoreBuiltinNames.h
Source/WebCore/css/MediaQueryEvaluator.cpp
Source/WebCore/dom/GlobalEventHandlers.idl
Source/WebCore/page/RuntimeEnabledFeatures.cpp
Source/WebCore/page/RuntimeEnabledFeatures.h
Source/WebCore/platform/PlatformScreen.h
Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
Source/WebCore/platform/wpe/PlatformScreenWPE.cpp

index 47d45f8..b2d158a 100644 (file)
@@ -1,3 +1,14 @@
+2019-05-27  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        Touch support is reported even when the device doesn't have a touch screen
+        https://bugs.webkit.org/show_bug.cgi?id=139681
+
+        Reviewed by Michael Catanzaro.
+
+        Remove expectations for tests that are passing now.
+
+        * platform/gtk/TestExpectations:
+
 2019-05-26  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics: Downgrade document.referrer to the referrer's eTLD+1 if the page was navigated to with a prevalent resource referrer containing link decoration
index 2f568ba..562b6db 100644 (file)
@@ -820,17 +820,6 @@ webkit.org/b/141423 fast/css/font-shorthand-from-longhands.html [ Failure ]
 webkit.org/b/141423 fast/css/font-shorthand-line-height.html [ Failure ]
 webkit.org/b/141423 fast/css/getComputedStyle/computed-style-font.html [ Failure ]
 
-#Pointer and hover media queries.
-webkit.org/b/141466 fast/media/mq-any-hover-matchMedia.html [ Failure ]
-webkit.org/b/141466 fast/media/mq-any-hover-styling.html [ Failure ]
-webkit.org/b/141466 fast/media/mq-any-pointer-matchMedia.html [ Failure ]
-webkit.org/b/141466 fast/media/mq-any-pointer-styling.html [ Failure ]
-webkit.org/b/141466 fast/media/mq-hover-matchMedia.html [ Failure ]
-webkit.org/b/141466 fast/media/mq-hover-styling.html [ Failure ]
-webkit.org/b/141466 fast/media/mq-pointer-matchMedia.html [ Failure ]
-webkit.org/b/141466 fast/media/mq-pointer-styling.html [ Failure ]
-webkit.org/b/141466 fast/media/mq-pointer.html [ Failure ]
-
 webkit.org/b/116259 http/tests/cache/willsendrequest-returns-null-for-memory-cache-load.html [ Failure ]
 
 webkit.org/b/141467 fast/multicol/pagination/LeftToRight-tb-hittest.html [ Failure ]
index 61d819f..bb6aaca 100644 (file)
@@ -1,3 +1,34 @@
+2019-05-27  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        Touch support is reported even when the device doesn't have a touch screen
+        https://bugs.webkit.org/show_bug.cgi?id=139681
+
+        Reviewed by Michael Catanzaro.
+
+        Add screenHasTouchDevice() and screenIsTouchPrimaryInputDevice() to PlatformScreen and use it to decide whether
+        to expose touch events functionality or not.
+
+        * bindings/js/WebCoreBuiltinNames.h:
+        * css/MediaQueryEvaluator.cpp:
+        (WebCore::hoverEvaluate): Use screenIsTouchPrimaryInputDevice() when touch events are enabled at build time.
+        (WebCore::anyHoverEvaluate): Use screenHasTouchDevice() when touch events are enabled at build time.
+        (WebCore::pointerEvaluate): Use screenIsTouchPrimaryInputDevice() when touch events are enabled at build time.
+        (WebCore::anyPointerEvaluate): Use screenHasTouchDevice() when touch events are enabled at build time.
+        * dom/GlobalEventHandlers.idl: Make touch event attributes enabled at runtime.
+        * page/RuntimeEnabledFeatures.cpp:
+        (WebCore::RuntimeEnabledFeatures::touchEventsEnabled const): Return whether touch events are enabled.
+        * page/RuntimeEnabledFeatures.h:
+        (WebCore::RuntimeEnabledFeatures::setTouchEventsEnabled): Force touch events to be enabled or disabled.
+        * platform/PlatformScreen.h:
+        (WebCore::screenHasTouchDevice): Just return true when touch events are enabled at build time for non-gtk ports.
+        (WebCore::screenIsTouchPrimaryInputDevice): Ditto.
+        * platform/gtk/PlatformScreenGtk.cpp:
+        (WebCore::screenHasTouchDevice):
+        (WebCore::screenIsTouchPrimaryInputDevice):
+        (WebCore::isTouchDevice):
+        (WebCore::deviceAddedCallback):
+        (WebCore::deviceRemovedCallback):
+
 2019-05-26  Simon Fraser  <simon.fraser@apple.com>
 
         Move VelocityData to WebCore
index 0a3fa83..f5b5322 100644 (file)
@@ -276,6 +276,11 @@ namespace WebCore {
     macro(matchingElementInFlatTree) \
     macro(mediaStreamTrackConstraints) \
     macro(openDatabase) \
+    macro(ontouchcancel) \
+    macro(ontouchend) \
+    macro(ontouchmove) \
+    macro(ontouchstart) \
+    macro(ontouchforcechange) \
     macro(onvrdisplayactivate) \
     macro(onvrdisplayblur) \
     macro(onvrdisplayconnect) \
index 527052b..6ee00de 100644 (file)
@@ -693,7 +693,7 @@ static bool hoverEvaluate(CSSValue* value, const CSSToLengthConversionData&, Fra
 {
     if (!is<CSSPrimitiveValue>(value)) {
 #if ENABLE(TOUCH_EVENTS)
-        return false;
+        return !screenIsTouchPrimaryInputDevice();
 #else
         return true;
 #endif
@@ -701,15 +701,28 @@ static bool hoverEvaluate(CSSValue* value, const CSSToLengthConversionData&, Fra
 
     auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
 #if ENABLE(TOUCH_EVENTS)
-    return keyword == CSSValueNone;
-#else
-    return keyword == CSSValueHover;
+    if (screenIsTouchPrimaryInputDevice())
+        return keyword == CSSValueNone;
 #endif
+    return keyword == CSSValueHover;
 }
 
-static bool anyHoverEvaluate(CSSValue* value, const CSSToLengthConversionData& cssToLengthConversionData, Frame& frame, MediaFeaturePrefix prefix)
+static bool anyHoverEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix)
 {
-    return hoverEvaluate(value, cssToLengthConversionData, frame, prefix);
+    if (!is<CSSPrimitiveValue>(value)) {
+#if ENABLE(TOUCH_EVENTS)
+        return !screenHasTouchDevice();
+#else
+        return true;
+#endif
+    }
+
+    auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
+#if ENABLE(TOUCH_EVENTS)
+    if (screenHasTouchDevice())
+        return keyword == CSSValueNone;
+#endif
+    return keyword == CSSValueHover;
 }
 
 static bool pointerEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix)
@@ -719,15 +732,23 @@ static bool pointerEvaluate(CSSValue* value, const CSSToLengthConversionData&, F
 
     auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
 #if ENABLE(TOUCH_EVENTS)
-    return keyword == CSSValueCoarse;
-#else
-    return keyword == CSSValueFine;
+    if (screenIsTouchPrimaryInputDevice())
+        return keyword == CSSValueCoarse;
 #endif
+    return keyword == CSSValueFine;
 }
 
-static bool anyPointerEvaluate(CSSValue* value, const CSSToLengthConversionData& cssToLengthConversionData, Frame& frame, MediaFeaturePrefix prefix)
+static bool anyPointerEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix)
 {
-    return pointerEvaluate(value, cssToLengthConversionData, frame, prefix);
+    if (!is<CSSPrimitiveValue>(value))
+        return true;
+
+    auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
+#if ENABLE(TOUCH_EVENTS)
+    if (screenHasTouchDevice())
+        return keyword == CSSValueCoarse;
+#endif
+    return keyword == CSSValueFine;
 }
 
 static bool prefersDarkInterfaceEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
index 54a7f28..770aa9c 100644 (file)
 
     [NotEnumerable] attribute EventHandler onsearch;
     [NotEnumerable] attribute EventHandler onwheel;
-    [NotEnumerable, Conditional=TOUCH_EVENTS] attribute EventHandler ontouchcancel;
-    [NotEnumerable, Conditional=TOUCH_EVENTS] attribute EventHandler ontouchend;
-    [NotEnumerable, Conditional=TOUCH_EVENTS] attribute EventHandler ontouchmove;
-    [NotEnumerable, Conditional=TOUCH_EVENTS] attribute EventHandler ontouchstart;
-    [NotEnumerable, Conditional=TOUCH_EVENTS] attribute EventHandler ontouchforcechange;
+    [NotEnumerable, Conditional=TOUCH_EVENTS, EnabledAtRuntime=TouchEvents] attribute EventHandler ontouchcancel;
+    [NotEnumerable, Conditional=TOUCH_EVENTS, EnabledAtRuntime=TouchEvents] attribute EventHandler ontouchend;
+    [NotEnumerable, Conditional=TOUCH_EVENTS, EnabledAtRuntime=TouchEvents] attribute EventHandler ontouchmove;
+    [NotEnumerable, Conditional=TOUCH_EVENTS, EnabledAtRuntime=TouchEvents] attribute EventHandler ontouchstart;
+    [NotEnumerable, Conditional=TOUCH_EVENTS, EnabledAtRuntime=TouchEvents] attribute EventHandler ontouchforcechange;
     [NotEnumerable, Conditional=MOUSE_FORCE_EVENTS] attribute EventHandler onwebkitmouseforcechanged;
     [NotEnumerable, Conditional=MOUSE_FORCE_EVENTS] attribute EventHandler onwebkitmouseforcedown;
     [NotEnumerable, Conditional=MOUSE_FORCE_EVENTS] attribute EventHandler onwebkitmouseforcewillbegin;
index 159a92a..e09b20e 100644 (file)
@@ -33,6 +33,7 @@
 #include "RuntimeEnabledFeatures.h"
 
 #include "MediaPlayer.h"
+#include "PlatformScreen.h"
 #include <JavaScriptCore/Options.h>
 #include <wtf/NeverDestroyed.h>
 
@@ -63,4 +64,11 @@ bool RuntimeEnabledFeatures::spectreGadgetsEnabled() const
     return JSC::Options::enableSpectreGadgets();
 }
 
+#if ENABLE(TOUCH_EVENTS)
+bool RuntimeEnabledFeatures::touchEventsEnabled() const
+{
+    return m_touchEventsEnabled.valueOr(screenHasTouchDevice());
+}
+#endif
+
 } // namespace WebCore
index 3b49857..a40c762 100644 (file)
@@ -347,6 +347,8 @@ public:
 #if ENABLE(TOUCH_EVENTS)
     bool mouseEventsSimulationEnabled() const { return m_mouseEventsSimulationEnabled; }
     void setMouseEventsSimulationEnabled(bool isEnabled) { m_mouseEventsSimulationEnabled = isEnabled; }
+    bool touchEventsEnabled() const;
+    void setTouchEventsEnabled(bool isEnabled) { m_touchEventsEnabled = isEnabled; }
 #endif
     
     bool referrerPolicyAttributeEnabled() const { return m_referrerPolicyAttributeEnabled; }
@@ -531,6 +533,7 @@ private:
 
 #if ENABLE(TOUCH_EVENTS)
     bool m_mouseEventsSimulationEnabled { false };
+    Optional<bool> m_touchEventsEnabled;
 #endif
 
     bool m_isITPDatabaseEnabled { false };
index c6990f7..3fd7471 100644 (file)
@@ -122,4 +122,14 @@ WEBCORE_EXPORT float screenScaleFactor(UIScreen * = nullptr);
 
 #endif
 
+#if ENABLE(TOUCH_EVENTS)
+#if PLATFORM(GTK) || PLATFORM(WPE)
+bool screenHasTouchDevice();
+bool screenIsTouchPrimaryInputDevice();
+#else
+bool screenHasTouchDevice() { return true; }
+bool screenIsTouchPrimaryInputDevice() { return true; }
+#endif
+#endif
+
 } // namespace WebCore
index 395dfe5..1129b4b 100644 (file)
@@ -41,7 +41,9 @@
 #include <cmath>
 #include <gtk/gtk.h>
 #include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
 #include <wtf/NeverDestroyed.h>
+#include <wtf/glib/GUniquePtr.h>
 
 namespace WebCore {
 
@@ -195,4 +197,112 @@ bool screenSupportsExtendedColor(Widget*)
     return false;
 }
 
+#if ENABLE(TOUCH_EVENTS)
+#ifdef GTK_API_VERSION_2
+bool screenHasTouchDevice()
+{
+    return false;
+}
+
+bool screenIsTouchPrimaryInputDevice()
+{
+    return false;
+}
+#else // GTK_API_VERSION_2
+#if !GTK_CHECK_VERSION(3, 20, 0)
+static void deviceAddedCallback(GdkDeviceManager*, GdkDevice*);
+static void deviceRemovedCallback(GdkDeviceManager*, GdkDevice*);
+
+static HashSet<GdkDevice*>& touchDevices()
+{
+    static LazyNeverDestroyed<HashSet<GdkDevice*>> touchDeviceSet;
+    static std::once_flag onceKey;
+    std::call_once(onceKey, [] {
+        touchDeviceSet.construct();
+
+        auto* display = gdk_display_get_default();
+        if (!display)
+            return;
+
+        auto* deviceManager = gdk_display_get_device_manager(display);
+        if (!deviceManager)
+            return;
+
+        GUniquePtr<GList> devices(gdk_device_manager_list_devices(deviceManager, GDK_DEVICE_TYPE_SLAVE));
+        for (GList* it = devices.get(); it; it = g_list_next(it)) {
+            auto* device = GDK_DEVICE(it->data);
+            if (gdk_device_get_source(device) == GDK_SOURCE_TOUCHSCREEN)
+                touchDeviceSet->add(device);
+        }
+
+        g_signal_connect(deviceManager, "device-added", G_CALLBACK(deviceAddedCallback), nullptr);
+        g_signal_connect(deviceManager, "device-removed", G_CALLBACK(deviceRemovedCallback), nullptr);
+    });
+
+    return touchDeviceSet;
+}
+
+static inline bool isTouchDevice(GdkDevice* device)
+{
+    return gdk_device_get_device_type(device) == GDK_DEVICE_TYPE_SLAVE && gdk_device_get_source(device) == GDK_SOURCE_TOUCHSCREEN;
+}
+
+static void deviceAddedCallback(GdkDeviceManager*, GdkDevice* device)
+{
+    if (!isTouchDevice(device))
+        return;
+
+    ASSERT(!touchDevices().contains(device));
+    touchDevices().add(device);
+}
+
+static void deviceRemovedCallback(GdkDeviceManager*, GdkDevice* device)
+{
+    if (!isTouchDevice(device))
+        return;
+
+    ASSERT(touchDevices().contains(device));
+    touchDevices().remove(device);
+}
+#endif // !GTK_CHECK_VERSION(3, 20, 0)
+
+bool screenHasTouchDevice()
+{
+#if GTK_CHECK_VERSION(3, 20, 0)
+    auto* display = gdk_display_get_default();
+    if (!display)
+        return true;
+
+    auto* seat = gdk_display_get_default_seat(display);
+    return seat ? gdk_seat_get_capabilities(seat) & GDK_SEAT_CAPABILITY_TOUCH : true;
+#else
+    return !touchDevices().isEmpty();
+#endif
+}
+
+bool screenIsTouchPrimaryInputDevice()
+{
+    auto* display = gdk_display_get_default();
+    if (!display)
+        return true;
+
+#if GTK_CHECK_VERSION(3, 20, 0)
+    auto* seat = gdk_display_get_default_seat(display);
+    if (!seat)
+        return true;
+
+    auto* device = gdk_seat_get_pointer(seat);
+#else
+    auto* deviceManager = gdk_display_get_device_manager(display);
+    if (!deviceManager)
+        return true;
+
+    auto* device = gdk_device_manager_get_client_pointer(deviceManager);
+#endif
+
+    return device ? gdk_device_get_source(device) == GDK_SOURCE_TOUCHSCREEN : true;
+}
+#endif // !GTK_API_VERSION_2
+#endif // ENABLE(TOUCH_EVENTS)
+
 } // namespace WebCore
index 904ebce..6b859de 100644 (file)
@@ -86,4 +86,16 @@ bool screenSupportsExtendedColor(Widget*)
     return false;
 }
 
+#if ENABLE(TOUCH_EVENTS)
+bool screenHasTouchDevice()
+{
+    return true;
+}
+
+bool screenIsTouchPrimaryInputDevice()
+{
+    return true;
+}
+#endif
+
 } // namespace WebCore