Changeset 268793 in webkit
- Timestamp:
- Oct 21, 2020, 5:36:18 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 23 edited
-
ChangeLog (modified) (1 diff)
-
Source/WebDriver/Actions.h (modified) (3 diffs)
-
Source/WebDriver/ChangeLog (modified) (1 diff)
-
Source/WebDriver/Session.cpp (modified) (4 diffs)
-
Source/WebDriver/WebDriverService.cpp (modified) (5 diffs)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/UIProcess/Automation/Automation.json (modified) (2 diffs)
-
Source/WebKit/UIProcess/Automation/SimulatedInputDispatcher.cpp (modified) (2 diffs)
-
Source/WebKit/UIProcess/Automation/SimulatedInputDispatcher.h (modified) (4 diffs)
-
Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp (modified) (10 diffs)
-
Source/WebKit/UIProcess/Automation/WebAutomationSession.h (modified) (4 diffs)
-
Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp (modified) (2 diffs)
-
Source/WebKit/UIProcess/Automation/wpe/WebAutomationSessionWPE.cpp (modified) (1 diff)
-
Source/WebKit/UIProcess/WebPageProxy.cpp (modified) (2 diffs)
-
Source/WebKit/UIProcess/WebPageProxy.h (modified) (1 diff)
-
Source/WebKit/config.h (modified) (1 diff)
-
Source/cmake/OptionsGTK.cmake (modified) (1 diff)
-
Source/cmake/OptionsWPE.cmake (modified) (1 diff)
-
Source/cmake/WebKitFeatures.cmake (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/Scripts/webkitperl/FeatureList.pm (modified) (2 diffs)
-
WebDriverTests/ChangeLog (modified) (1 diff)
-
WebDriverTests/TestExpectations.json (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ChangeLog
r268751 r268793 1 2020-10-21 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 WebDriver: add support for wheel actions 4 https://bugs.webkit.org/show_bug.cgi?id=217174 5 6 Reviewed by Brian Burg. 7 8 Enable WEBDRIVER_WHEEL_INTERACTIONS for GTK and WPE ports. 9 10 * Source/cmake/OptionsGTK.cmake: 11 * Source/cmake/OptionsWPE.cmake: 12 * Source/cmake/WebKitFeatures.cmake: 13 1 14 2020-10-20 Michael Catanzaro <mcatanzaro@gnome.org> 2 15 -
trunk/Source/WebDriver/Actions.h
r239427 r268793 34 34 35 35 struct InputSource { 36 enum class Type { None, Key, Pointer };36 enum class Type { None, Key, Pointer, Wheel }; 37 37 38 38 Type type; … … 52 52 53 53 struct Action { 54 enum class Type { None, Key, Pointer };55 enum class Subtype { Pause, PointerUp, PointerDown, PointerMove, PointerCancel, KeyUp, KeyDown };54 enum class Type { None, Key, Pointer, Wheel }; 55 enum class Subtype { Pause, PointerUp, PointerDown, PointerMove, PointerCancel, KeyUp, KeyDown, Scroll }; 56 56 57 57 Action(const String& id, Type type, Subtype subtype) … … 72 72 Optional<int64_t> x; 73 73 Optional<int64_t> y; 74 Optional<int64_t> deltaX; 75 Optional<int64_t> deltaY; 74 76 75 77 Optional<String> key; -
trunk/Source/WebDriver/ChangeLog
r268717 r268793 1 2020-10-21 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 WebDriver: add support for wheel actions 4 https://bugs.webkit.org/show_bug.cgi?id=217174 5 6 Reviewed by Brian Burg. 7 8 Handle wheel actions. 9 10 * Actions.h: 11 * Session.cpp: 12 (WebDriver::automationSourceType): Handle InputSource::Type::Wheel. 13 (WebDriver::Session::performActions): Handle Action::Type::Wheel. 14 * WebDriverService.cpp: 15 (WebDriver::processKeyAction): Assert if Action::Subtype::Scroll. 16 (WebDriver::processPointerMoveAction): Move this code to a helper to be used by both pointer move and scroll actions. 17 (WebDriver::processPointerAction): Use processPointerMoveAction(). 18 (WebDriver::processWheelAction): Call processPointerMoveAction() and process the scroll delta too. 19 (WebDriver::processInputActionSequence): Handle InputSource::Type::Wheel. 20 1 21 2020-10-20 Carlos Garcia Campos <cgarcia@igalia.com> 2 22 -
trunk/Source/WebDriver/Session.cpp
r268717 r268793 2620 2620 case InputSource::Type::Key: 2621 2621 return "Keyboard"; 2622 case InputSource::Type::Wheel: 2623 return "Wheel"; 2622 2624 } 2623 2625 RELEASE_ASSERT_NOT_REACHED(); … … 2710 2712 case Action::Subtype::KeyUp: 2711 2713 case Action::Subtype::KeyDown: 2714 case Action::Subtype::Scroll: 2712 2715 ASSERT_NOT_REACHED(); 2713 2716 } … … 2744 2747 case Action::Subtype::PointerMove: 2745 2748 case Action::Subtype::PointerCancel: 2749 case Action::Subtype::Scroll: 2746 2750 ASSERT_NOT_REACHED(); 2747 2751 } … … 2756 2760 } 2757 2761 break; 2762 case Action::Type::Wheel: 2763 switch (action.subtype) { 2764 case Action::Subtype::Scroll: { 2765 state->setString("origin"_s, automationOriginType(action.origin->type)); 2766 auto location = JSON::Object::create(); 2767 location->setInteger("x"_s, action.x.value()); 2768 location->setInteger("y"_s, action.y.value()); 2769 state->setObject("location"_s, WTFMove(location)); 2770 2771 auto delta = JSON::Object::create(); 2772 delta->setInteger("width"_s, action.deltaX.value()); 2773 delta->setInteger("height"_s, action.deltaY.value()); 2774 state->setObject("delta"_s, WTFMove(delta)); 2775 2776 if (action.origin->type == PointerOrigin::Type::Element) 2777 state->setString("nodeHandle"_s, action.origin->elementID.value()); 2778 FALLTHROUGH; 2779 } 2780 case Action::Subtype::Pause: 2781 if (action.duration) 2782 state->setDouble("duration"_s, action.duration.value()); 2783 break; 2784 case Action::Subtype::PointerUp: 2785 case Action::Subtype::PointerDown: 2786 case Action::Subtype::PointerMove: 2787 case Action::Subtype::PointerCancel: 2788 case Action::Subtype::KeyUp: 2789 case Action::Subtype::KeyDown: 2790 ASSERT_NOT_REACHED(); 2791 } 2758 2792 } 2759 2793 states->pushObject(WTFMove(state)); -
trunk/Source/WebDriver/WebDriverService.cpp
r267919 r268793 1910 1910 case Action::Subtype::PointerMove: 1911 1911 case Action::Subtype::PointerCancel: 1912 case Action::Subtype::Scroll: 1912 1913 ASSERT_NOT_REACHED(); 1913 1914 } … … 1930 1931 1931 1932 return MouseButton::None; 1933 } 1934 1935 static bool processPointerMoveAction(JSON::Object& actionItem, Action& action, Optional<String>& errorMessage) 1936 { 1937 if (auto durationValue = actionItem.getValue("duration"_s)) { 1938 auto duration = unsignedValue(*durationValue); 1939 if (!duration) { 1940 errorMessage = String("The parameter 'duration' is invalid in action"); 1941 return false; 1942 } 1943 action.duration = duration.value(); 1944 } 1945 1946 if (auto originValue = actionItem.getValue("origin"_s)) { 1947 if (auto originObject = originValue->asObject()) { 1948 auto elementID = originObject->getString(Session::webElementIdentifier()); 1949 if (!elementID) { 1950 errorMessage = String("The parameter 'origin' is not a valid web element object in action"); 1951 return false; 1952 } 1953 action.origin = PointerOrigin { PointerOrigin::Type::Element, elementID }; 1954 } else { 1955 auto origin = originValue->asString(); 1956 if (origin == "viewport") 1957 action.origin = PointerOrigin { PointerOrigin::Type::Viewport, WTF::nullopt }; 1958 else if (origin == "pointer") 1959 action.origin = PointerOrigin { PointerOrigin::Type::Pointer, WTF::nullopt }; 1960 else { 1961 errorMessage = String("The parameter 'origin' is invalid in action"); 1962 return false; 1963 } 1964 } 1965 } else 1966 action.origin = PointerOrigin { PointerOrigin::Type::Viewport, WTF::nullopt }; 1967 1968 if (auto xValue = actionItem.getValue("x"_s)) { 1969 auto x = valueAsNumberInRange(*xValue, INT_MIN); 1970 if (!x) { 1971 errorMessage = String("The paramater 'x' is invalid for action"); 1972 return false; 1973 } 1974 action.x = x.value(); 1975 } 1976 1977 if (auto yValue = actionItem.getValue("y"_s)) { 1978 auto y = valueAsNumberInRange(*yValue, INT_MIN); 1979 if (!y) { 1980 errorMessage = String("The paramater 'y' is invalid for action"); 1981 return false; 1982 } 1983 action.y = y.value(); 1984 } 1985 1986 return true; 1932 1987 } 1933 1988 … … 1974 2029 break; 1975 2030 } 1976 case Action::Subtype::PointerMove: { 1977 if (auto durationValue = actionItem.getValue("duration"_s)) { 1978 auto duration = unsignedValue(*durationValue); 1979 if (!duration) { 1980 errorMessage = String("The parameter 'duration' is invalid in pointer move action"); 1981 return WTF::nullopt; 1982 } 1983 action.duration = duration.value(); 1984 } 1985 1986 if (auto originValue = actionItem.getValue("origin"_s)) { 1987 if (auto originObject = originValue->asObject()) { 1988 auto elementID = originObject->getString(Session::webElementIdentifier()); 1989 if (!elementID) { 1990 errorMessage = String("The parameter 'origin' is not a valid web element object in pointer move action"); 1991 return WTF::nullopt; 1992 } 1993 action.origin = PointerOrigin { PointerOrigin::Type::Element, elementID }; 1994 } else { 1995 auto origin = originValue->asString(); 1996 if (origin == "viewport") 1997 action.origin = PointerOrigin { PointerOrigin::Type::Viewport, WTF::nullopt }; 1998 else if (origin == "pointer") 1999 action.origin = PointerOrigin { PointerOrigin::Type::Pointer, WTF::nullopt }; 2000 else { 2001 errorMessage = String("The parameter 'origin' is invalid in pointer move action"); 2002 return WTF::nullopt; 2003 } 2004 } 2005 } else 2006 action.origin = PointerOrigin { PointerOrigin::Type::Viewport, WTF::nullopt }; 2007 2008 if (auto xValue = actionItem.getValue("x"_s)) { 2009 auto x = valueAsNumberInRange(*xValue, INT_MIN); 2010 if (!x) { 2011 errorMessage = String("The paramater 'x' is invalid for pointer move action"); 2012 return WTF::nullopt; 2013 } 2014 action.x = x.value(); 2015 } 2016 2017 if (auto yValue = actionItem.getValue("y"_s)) { 2018 auto y = valueAsNumberInRange(*yValue, INT_MIN); 2019 if (!y) { 2020 errorMessage = String("The paramater 'y' is invalid for pointer move action"); 2021 return WTF::nullopt; 2022 } 2023 action.y = y.value(); 2024 } 2031 case Action::Subtype::PointerMove: 2032 if (!processPointerMoveAction(actionItem, action, errorMessage)) 2033 return WTF::nullopt; 2025 2034 break; 2026 }2027 2035 case Action::Subtype::PointerCancel: 2028 2036 break; 2029 2037 case Action::Subtype::KeyUp: 2030 2038 case Action::Subtype::KeyDown: 2039 case Action::Subtype::Scroll: 2040 ASSERT_NOT_REACHED(); 2041 } 2042 2043 return action; 2044 } 2045 2046 static Optional<Action> processWheelAction(const String& id, JSON::Object& actionItem, Optional<String>& errorMessage) 2047 { 2048 Action::Subtype actionSubtype; 2049 auto subtype = actionItem.getString("type"_s); 2050 if (subtype == "pause") 2051 actionSubtype = Action::Subtype::Pause; 2052 else if (subtype == "scroll") 2053 actionSubtype = Action::Subtype::Scroll; 2054 else { 2055 errorMessage = String("The parameter 'type' of wheel action is invalid"); 2056 return WTF::nullopt; 2057 } 2058 2059 Action action(id, Action::Type::Wheel, actionSubtype); 2060 2061 switch (actionSubtype) { 2062 case Action::Subtype::Pause: 2063 if (!processPauseAction(actionItem, action, errorMessage)) 2064 return WTF::nullopt; 2065 break; 2066 case Action::Subtype::Scroll: 2067 if (!processPointerMoveAction(actionItem, action, errorMessage)) 2068 return WTF::nullopt; 2069 2070 if (auto deltaXValue = actionItem.getValue("deltaX"_s)) { 2071 auto deltaX = valueAsNumberInRange(*deltaXValue, INT_MIN); 2072 if (!deltaX) { 2073 errorMessage = String("The paramater 'deltaX' is invalid for action"); 2074 return WTF::nullopt; 2075 } 2076 action.deltaX = deltaX.value(); 2077 } 2078 2079 if (auto deltaYValue = actionItem.getValue("deltaY"_s)) { 2080 auto deltaY = valueAsNumberInRange(*deltaYValue, INT_MIN); 2081 if (!deltaY) { 2082 errorMessage = String("The paramater 'deltaY' is invalid for action"); 2083 return WTF::nullopt; 2084 } 2085 action.deltaY = deltaY.value(); 2086 } 2087 break; 2088 case Action::Subtype::KeyUp: 2089 case Action::Subtype::KeyDown: 2090 case Action::Subtype::PointerUp: 2091 case Action::Subtype::PointerDown: 2092 case Action::Subtype::PointerMove: 2093 case Action::Subtype::PointerCancel: 2031 2094 ASSERT_NOT_REACHED(); 2032 2095 } … … 2081 2144 else if (type == "pointer") 2082 2145 inputSourceType = InputSource::Type::Pointer; 2146 else if (type == "wheel") 2147 inputSourceType = InputSource::Type::Wheel; 2083 2148 else if (type == "none") 2084 2149 inputSourceType = InputSource::Type::None; … … 2137 2202 else if (inputSourceType == InputSource::Type::Pointer) 2138 2203 action = processPointerAction(id, parameters.value(), *actionItem, errorMessage); 2204 else if (inputSourceType == InputSource::Type::Wheel) 2205 action = processWheelAction(id, *actionItem, errorMessage); 2139 2206 if (!action) 2140 2207 return WTF::nullopt; -
trunk/Source/WebKit/ChangeLog
r268758 r268793 1 2020-10-21 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 WebDriver: add support for wheel actions 4 https://bugs.webkit.org/show_bug.cgi?id=217174 5 6 Reviewed by Brian Burg. 7 8 * UIProcess/Automation/Automation.json: Add scroll delta to action state. 9 * UIProcess/Automation/SimulatedInputDispatcher.cpp: 10 (WebKit::SimulatedInputSourceState::emptyStateForSourceType): Initialize scrollDelta for wheel actions. 11 (WebKit::SimulatedInputDispatcher::transitionInputSourceToState): Handle SimulatedInputSourceType::Wheel. 12 * UIProcess/Automation/SimulatedInputDispatcher.h: 13 * UIProcess/Automation/WebAutomationSession.cpp: 14 (WebKit::WebAutomationSession::WebAutomationSession): Add SimulatedInputSourceType::Wheel. 15 (WebKit::WebAutomationSession::terminate): Handle pending wheel events. 16 (WebKit::WebAutomationSession::willShowJavaScriptDialog): Ditto. 17 (WebKit::WebAutomationSession::wheelEventsFlushedForPage): Ditto. 18 (WebKit::WebAutomationSession::willClosePage): Ditto. 19 (WebKit::WebAutomationSession::isSimulatingUserInteraction const): Return true if there are pending wheel events too. 20 (WebKit::WebAutomationSession::simulateWheelInteraction): Handle the wheel action. 21 (WebKit::simulatedInputSourceTypeFromProtocolSourceType): Handle Inspector::Protocol::Automation::InputSourceType::Wheel. 22 (WebKit::WebAutomationSession::performInteractionSequence): Initialize the scroll delta for wheel action. 23 * UIProcess/Automation/WebAutomationSession.h: 24 * UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp: 25 (WebKit::WebAutomationSession::platformSimulateWheelInteraction): Synthesize a wheel event. 26 * UIProcess/Automation/wpe/WebAutomationSessionWPE.cpp: 27 (WebKit::WebAutomationSession::platformSimulateWheelInteraction): Ditto. 28 * UIProcess/WebPageProxy.cpp: 29 (WebKit::WebPageProxy::isProcessingWheelEvents const): Return whether page has pending wheel events. 30 (WebKit::WebPageProxy::didReceiveEvent): Notify automation that pending wheel events have been processed. 31 * UIProcess/WebPageProxy.h: 32 * config.h: 33 1 34 2020-10-20 Peng Liu <peng.liu6@apple.com> 2 35 -
trunk/Source/WebKit/UIProcess/Automation/Automation.json
r268717 r268793 290 290 "Mouse", 291 291 "Keyboard", 292 "Touch" 292 "Touch", 293 "Wheel" 293 294 ] 294 295 }, … … 328 329 { "name": "pressedVirtualKeys", "type": "array", "items": { "$ref": "VirtualKey" }, "optional": true, "description": "For 'keyboard' input sources, specifies virtual keys that have a 'pressed' state. Unmentioned virtual keys are assumed to have a 'released' state." }, 329 330 { "name": "pressedButton", "$ref": "MouseButton", "optional": true, "description": "For 'mouse' input sources, specifies which mouse button has a 'pressed' state. Unmentioned mouse buttons are assumed to have a 'released' state. For 'touch' input sources, passing MouseButton::Left denotes a touch-down state." }, 330 { "name": "origin", "$ref": "MouseMoveOrigin", "optional": true, "description": "For 'mouse' input sources, specifies the origin type of a mouse move transition. Defaults to 'Viewport' if omitted."},331 { "name": "origin", "$ref": "MouseMoveOrigin", "optional": true, "description": "For 'mouse' or 'wheel' input sources, specifies the origin type of a mouse move transition. Defaults to 'Viewport' if omitted."}, 331 332 { "name": "nodeHandle", "$ref": "NodeHandle", "optional": true, "description": "The handle of the element to use as origin when origin type is 'Element'."}, 332 { "name": "location", "$ref": "Point", "optional": true, "description": "For 'mouse' or 'touch' input sources, specifies a location in view coordinates to which the input source should transition. Transitioning to this state may interpolate intemediate input source states to better simulate real user movements and gestures." }, 333 { "name": "location", "$ref": "Point", "optional": true, "description": "For 'mouse', 'wheel' or 'touch' input sources, specifies a location in view coordinates to which the input source should transition. Transitioning to this state may interpolate intemediate input source states to better simulate real user movements and gestures." }, 334 { "name": "delta", "$ref": "Size", "optional": true, "description": "For 'wheel' input sources, specifies a scroll delta."}, 333 335 { "name": "duration", "type": "integer", "optional": true, "description": "The minimum number of milliseconds that must elapse while the relevant input source transitions to this state." } 334 336 ] -
trunk/Source/WebKit/UIProcess/Automation/SimulatedInputDispatcher.cpp
r268717 r268793 44 44 case SimulatedInputSourceType::Keyboard: 45 45 break; 46 case SimulatedInputSourceType::Wheel: 47 result.scrollDelta = WebCore::IntSize(); 48 FALLTHROUGH; 46 49 case SimulatedInputSourceType::Mouse: 47 50 case SimulatedInputSourceType::Touch: … … 381 384 #endif // !ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 382 385 break; 386 case SimulatedInputSourceType::Wheel: 387 #if !ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 388 RELEASE_ASSERT_NOT_REACHED(); 389 #else 390 resolveLocation(a.location.valueOr(WebCore::IntPoint()), b.location, b.origin.valueOr(MouseMoveOrigin::Viewport), b.nodeHandle, [this, &a, &b, eventDispatchFinished = WTFMove(eventDispatchFinished)](Optional<WebCore::IntPoint> location, Optional<AutomationCommandError> error) mutable { 391 if (error) { 392 eventDispatchFinished(error); 393 return; 394 } 395 396 if (!location) { 397 eventDispatchFinished(AUTOMATION_COMMAND_ERROR_WITH_NAME(ElementNotInteractable)); 398 return; 399 } 400 401 b.location = location; 402 403 if (!a.scrollDelta->isZero()) 404 b.scrollDelta->contract(a.scrollDelta->width(), a.scrollDelta->height()); 405 406 if (!b.scrollDelta->isZero()) { 407 LOG(Automation, "SimulatedInputDispatcher[%p]: simulating Wheel from (%d, %d) to (%d, %d) for transition to %d.%d", this, a.scrollDelta->width(), a.scrollDelta->height(), b.scrollDelta->width(), b.scrollDelta->height(), m_keyframeIndex, m_inputSourceStateIndex); 408 // FIXME: This does not interpolate mouse scrolls per the "perform a scroll" algorithm (§15.4.4 Wheel actions). 409 m_client.simulateWheelInteraction(m_page, b.location.value(), b.scrollDelta.value(), WTFMove(eventDispatchFinished)); 410 } else 411 eventDispatchFinished(WTF::nullopt); 412 }); 413 #endif // !ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 414 break; 383 415 } 384 416 } -
trunk/Source/WebKit/UIProcess/Automation/SimulatedInputDispatcher.h
r268717 r268793 30 30 #include <WebCore/FrameIdentifier.h> 31 31 #include <WebCore/IntPoint.h> 32 #include <WebCore/IntSize.h> 32 33 #include <wtf/CompletionHandler.h> 33 34 #include <wtf/HashSet.h> … … 68 69 Mouse, 69 70 Touch, 71 Wheel, 70 72 }; 71 73 … … 83 85 Optional<String> nodeHandle; 84 86 Optional<WebCore::IntPoint> location; 87 Optional<WebCore::IntSize> scrollDelta; 85 88 Optional<Seconds> duration; 86 89 … … 134 137 #if ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 135 138 virtual void simulateKeyboardInteraction(WebPageProxy&, KeyboardInteraction, WTF::Variant<VirtualKey, CharKey>&&, AutomationCompletionHandler&&) = 0; 139 #endif 140 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 141 virtual void simulateWheelInteraction(WebPageProxy&, const WebCore::IntPoint& locationInView, const WebCore::IntSize& delta, AutomationCompletionHandler&&) = 0; 136 142 #endif 137 143 virtual void viewportInViewCenterPointOfElement(WebPageProxy&, Optional<WebCore::FrameIdentifier>, const String& nodeHandle, Function<void (Optional<WebCore::IntPoint>, Optional<AutomationCommandError>)>&&) = 0; -
trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp
r268717 r268793 93 93 m_inputSources.add(SimulatedInputSource::create(SimulatedInputSourceType::Keyboard)); 94 94 #endif 95 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 96 m_inputSources.add(SimulatedInputSource::create(SimulatedInputSourceType::Wheel)); 97 #endif 95 98 m_inputSources.add(SimulatedInputSource::create(SimulatedInputSourceType::Null)); 96 99 #endif // ENABLE(WEBDRIVER_ACTIONS_API) … … 165 168 } 166 169 #endif // ENABLE(WEBDRIVER_MOUSE_INTERACTIONS) 170 171 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 172 for (auto& identifier : copyToVector(m_pendingWheelEventsFlushedCallbacksPerPage.keys())) { 173 auto callback = m_pendingWheelEventsFlushedCallbacksPerPage.take(identifier); 174 callback(AUTOMATION_COMMAND_ERROR_WITH_NAME(InternalError)); 175 } 176 #endif // ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 167 177 168 178 #if ENABLE(REMOTE_INSPECTOR) … … 677 687 #endif // ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 678 688 }); 689 690 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 691 if (!m_pendingWheelEventsFlushedCallbacksPerPage.isEmpty()) { 692 for (auto key : copyToVector(m_pendingWheelEventsFlushedCallbacksPerPage.keys())) { 693 auto callback = m_pendingWheelEventsFlushedCallbacksPerPage.take(key); 694 callback(WTF::nullopt); 695 } 696 } 697 #endif // ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 679 698 } 680 699 … … 817 836 } 818 837 838 void WebAutomationSession::wheelEventsFlushedForPage(const WebPageProxy& page) 839 { 840 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 841 if (auto callback = m_pendingWheelEventsFlushedCallbacksPerPage.take(page.identifier())) 842 callback(WTF::nullopt); 843 #else 844 UNUSED_PARAM(page); 845 #endif 846 } 847 819 848 void WebAutomationSession::willClosePage(const WebPageProxy& page) 820 849 { … … 830 859 #if ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 831 860 if (auto callback = m_pendingKeyboardEventsFlushedCallbacksPerPage.take(page.identifier())) 861 callback(AUTOMATION_COMMAND_ERROR_WITH_NAME(WindowNotFound)); 862 #endif 863 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 864 if (auto callback = m_pendingWheelEventsFlushedCallbacksPerPage.take(page.identifier())) 832 865 callback(AUTOMATION_COMMAND_ERROR_WITH_NAME(WindowNotFound)); 833 866 #endif … … 1526 1559 return true; 1527 1560 #endif 1561 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 1562 if (!m_pendingWheelEventsFlushedCallbacksPerPage.isEmpty()) 1563 return true; 1564 #endif 1528 1565 #if ENABLE(WEBDRIVER_TOUCH_INTERACTIONS) 1529 1566 if (m_simulatingTouchInteraction) … … 1672 1709 } 1673 1710 #endif // ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 1711 1712 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 1713 void WebAutomationSession::simulateWheelInteraction(WebPageProxy& page, const WebCore::IntPoint& locationInViewport, const WebCore::IntSize& delta, AutomationCompletionHandler&& completionHandler) 1714 { 1715 page.getWindowFrameWithCallback([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler), page = makeRef(page), locationInViewport, delta](WebCore::FloatRect windowFrame) mutable { 1716 auto clippedX = std::min(std::max(0.0f, static_cast<float>(locationInViewport.x())), windowFrame.size().width()); 1717 auto clippedY = std::min(std::max(0.0f, static_cast<float>(locationInViewport.y())), windowFrame.size().height()); 1718 if (clippedX != locationInViewport.x() || clippedY != locationInViewport.y()) { 1719 completionHandler(AUTOMATION_COMMAND_ERROR_WITH_NAME(TargetOutOfBounds)); 1720 return; 1721 } 1722 1723 // Bridge the flushed callback to our command's completion handler. 1724 auto wheelEventsFlushedCallback = [completionHandler = WTFMove(completionHandler)](Optional<AutomationCommandError> error) mutable { 1725 completionHandler(error); 1726 }; 1727 1728 auto& callbackInMap = m_pendingWheelEventsFlushedCallbacksPerPage.add(page->identifier(), nullptr).iterator->value; 1729 if (callbackInMap) 1730 callbackInMap(AUTOMATION_COMMAND_ERROR_WITH_NAME(Timeout)); 1731 callbackInMap = WTFMove(wheelEventsFlushedCallback); 1732 1733 platformSimulateWheelInteraction(page, locationInViewport, delta); 1734 1735 // If the event does not hit test anything in the window, then it may not have been delivered. 1736 if (callbackInMap && !page->isProcessingWheelEvents()) { 1737 auto callbackToCancel = m_pendingWheelEventsFlushedCallbacksPerPage.take(page->identifier()); 1738 callbackToCancel(WTF::nullopt); 1739 } 1740 1741 // Otherwise, wait for wheelEventsFlushedCallback to run when all events are handled. 1742 }); 1743 } 1744 #endif 1674 1745 #endif // ENABLE(WEBDRIVER_ACTIONS_API) 1675 1746 … … 1855 1926 case Inspector::Protocol::Automation::InputSourceType::Touch: 1856 1927 return SimulatedInputSourceType::Touch; 1928 case Inspector::Protocol::Automation::InputSourceType::Wheel: 1929 return SimulatedInputSourceType::Wheel; 1857 1930 } 1858 1931 … … 1966 2039 ASYNC_FAIL_WITH_PREDEFINED_ERROR_AND_DETAILS(NotImplemented, "Keyboard input sources are not yet supported."); 1967 2040 #endif 2041 #if !ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 2042 if (inputSourceType == SimulatedInputSourceType::Wheel) 2043 ASYNC_FAIL_WITH_PREDEFINED_ERROR_AND_DETAILS(NotImplemented, "Wheel input sources are not yet supported."); 2044 #endif 1968 2045 if (typeToSourceIdMap.contains(inputSourceType)) 1969 2046 ASYNC_FAIL_WITH_PREDEFINED_ERROR_AND_DETAILS(InvalidParameter, "Two input sources with the same type were specified."); … … 2051 2128 if (x && y) 2052 2129 sourceState.location = WebCore::IntPoint(*x, *y); 2130 } 2131 2132 if (auto deltaObject = stateObject->getObject("delta"_s)) { 2133 auto deltaX = deltaObject->getInteger("width"_s); 2134 auto deltaY = deltaObject->getInteger("height"_s); 2135 if (deltaX && deltaY) 2136 sourceState.scrollDelta = WebCore::IntSize(*deltaX, *deltaY); 2053 2137 } 2054 2138 -
trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.h
r267918 r268793 126 126 void keyboardEventsFlushedForPage(const WebPageProxy&); 127 127 void mouseEventsFlushedForPage(const WebPageProxy&); 128 void wheelEventsFlushedForPage(const WebPageProxy&); 128 129 void willClosePage(const WebPageProxy&); 129 130 void handleRunOpenPanel(const WebPageProxy&, const WebFrameProxy&, const API::OpenPanelParameters&, WebOpenPanelResultListenerProxy&); … … 154 155 #if ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 155 156 void simulateKeyboardInteraction(WebPageProxy&, KeyboardInteraction, WTF::Variant<VirtualKey, CharKey>&&, AutomationCompletionHandler&&); 157 #endif 158 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 159 void simulateWheelInteraction(WebPageProxy&, const WebCore::IntPoint& locationInView, const WebCore::IntSize& delta, AutomationCompletionHandler&&); 156 160 #endif 157 161 void viewportInViewCenterPointOfElement(WebPageProxy&, Optional<WebCore::FrameIdentifier>, const Inspector::Protocol::Automation::NodeHandle&, Function<void(Optional<WebCore::IntPoint>, Optional<AutomationCommandError>)>&&); … … 264 268 void platformSimulateKeySequence(WebPageProxy&, const String&); 265 269 #endif // ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 270 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 271 void platformSimulateWheelInteraction(WebPageProxy&, const WebCore::IntPoint& locationInViewport, const WebCore::IntSize& delta); 272 #endif // ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 266 273 267 274 // Get base64-encoded PNG data from a bitmap. … … 307 314 HashMap<WebPageProxyIdentifier, Function<void(Optional<AutomationCommandError>)>> m_pendingMouseEventsFlushedCallbacksPerPage; 308 315 #endif 316 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 317 HashMap<WebPageProxyIdentifier, Function<void(Optional<AutomationCommandError>)>> m_pendingWheelEventsFlushedCallbacksPerPage; 318 #endif 309 319 310 320 uint64_t m_nextEvaluateJavaScriptCallbackID { 1 }; -
trunk/Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp
r268717 r268793 32 32 #include <WebCore/GtkUtilities.h> 33 33 #include <WebCore/GtkVersioning.h> 34 #include <WebCore/Scrollbar.h> 34 35 35 36 namespace WebKit { … … 329 330 #endif // ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 330 331 332 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 333 void WebAutomationSession::platformSimulateWheelInteraction(WebPageProxy& page, const WebCore::IntPoint& locationInViewport, const WebCore::IntSize& delta) 334 { 335 auto* viewWidget = reinterpret_cast<WebKitWebViewBase*>(page.viewWidget()); 336 FloatSize scrollDelta(delta); 337 scrollDelta.scale(1 / static_cast<float>(Scrollbar::pixelsPerLineStep())); 338 webkitWebViewBaseSynthesizeWheelEvent(viewWidget, -scrollDelta.width(), -scrollDelta.height(), locationInViewport.x(), locationInViewport.y(), WheelEventPhase::NoPhase, WheelEventPhase::NoPhase); 339 } 340 #endif // ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 341 331 342 } // namespace WebKit -
trunk/Source/WebKit/UIProcess/Automation/wpe/WebAutomationSessionWPE.cpp
r268717 r268793 365 365 #endif // ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) 366 366 367 #if ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 368 void WebAutomationSession::platformSimulateWheelInteraction(WebPageProxy& page, const WebCore::IntPoint& locationInView, const WebCore::IntSize& delta) 369 { 370 #if WPE_CHECK_VERSION(1, 5, 0) 371 struct wpe_input_axis_2d_event event; 372 memset(&event, 0, sizeof(event)); 373 event.base.type = static_cast<wpe_input_axis_event_type>(wpe_input_axis_event_type_mask_2d | wpe_input_axis_event_type_motion_smooth); 374 event.base.x = locationInView.x(); 375 event.base.y = locationInView.y(); 376 event.x_axis = -delta.width(); 377 event.y_axis = -delta.height(); 378 wpe_view_backend_dispatch_axis_event(page.viewBackend(), &event.base); 379 #else 380 if (auto deltaX = delta.width()) { 381 struct wpe_input_axis_event event = { wpe_input_axis_event_type_motion, 0, locationInView.x(), locationInView.y(), 1, -deltaX, 0 }; 382 wpe_view_backend_dispatch_axis_event(page.viewBackend(), &event); 383 } 384 if (auto deltaY = delta.height()) { 385 struct wpe_input_axis_event event = { wpe_input_axis_event_type_motion, 0, locationInView.x(), locationInView.y(), 0, -deltaY, 0 }; 386 wpe_view_backend_dispatch_axis_event(page.viewBackend(), &event); 387 } 388 #endif 389 } 390 #endif // ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 391 367 392 } // namespace WebKit 368 393 -
trunk/Source/WebKit/UIProcess/WebPageProxy.cpp
r268497 r268793 6427 6427 } 6428 6428 6429 bool WebPageProxy::isProcessingWheelEvents() const 6430 { 6431 return m_wheelEventCoalescer && m_wheelEventCoalescer->hasEventsBeingProcessed(); 6432 } 6433 6429 6434 NativeWebMouseEvent* WebPageProxy::currentlyProcessedMouseDownEvent() 6430 6435 { … … 6943 6948 if (auto eventToSend = wheelEventCoalescer().nextEventToDispatch()) 6944 6949 sendWheelEvent(*eventToSend); 6950 else if (auto* automationSession = process().processPool().automationSession()) 6951 automationSession->wheelEventsFlushedForPage(*this); 6945 6952 break; 6946 6953 } -
trunk/Source/WebKit/UIProcess/WebPageProxy.h
r268635 r268793 944 944 void flushPendingMouseEventCallbacks(); 945 945 946 bool isProcessingWheelEvents() const; 946 947 void handleWheelEvent(const NativeWebWheelEvent&); 947 948 -
trunk/Source/WebKit/config.h
r257619 r268793 61 61 #endif 62 62 63 // ENABLE_WEBDRIVER_ACTIONS_API represents whether mouse, keyboard or touchinteractions are defined64 #if ENABLE(WEBDRIVER_MOUSE_INTERACTIONS) || ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) || ENABLE(WEBDRIVER_TOUCH_INTERACTIONS) 63 // ENABLE_WEBDRIVER_ACTIONS_API represents whether mouse, keyboard, touch or wheel interactions are defined 64 #if ENABLE(WEBDRIVER_MOUSE_INTERACTIONS) || ENABLE(WEBDRIVER_KEYBOARD_INTERACTIONS) || ENABLE(WEBDRIVER_TOUCH_INTERACTIONS) || ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) 65 65 #define ENABLE_WEBDRIVER_ACTIONS_API 1 66 66 #endif -
trunk/Source/cmake/OptionsGTK.cmake
r268751 r268793 272 272 SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_MOUSE_INTERACTIONS ON) 273 273 SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_TOUCH_INTERACTIONS OFF) 274 SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_WHEEL_INTERACTIONS ON) 274 275 endif () 275 276 -
trunk/Source/cmake/OptionsWPE.cmake
r268453 r268793 166 166 SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_MOUSE_INTERACTIONS ON) 167 167 SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_TOUCH_INTERACTIONS OFF) 168 SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_WHEEL_INTERACTIONS ON) 168 169 endif () 169 170 -
trunk/Source/cmake/WebKitFeatures.cmake
r268599 r268793 220 220 WEBKIT_OPTION_DEFINE(ENABLE_WEBDRIVER_MOUSE_INTERACTIONS "Toggle WebDriver mouse interactions" PRIVATE OFF) 221 221 WEBKIT_OPTION_DEFINE(ENABLE_WEBDRIVER_TOUCH_INTERACTIONS "Toggle WebDriver touch interactions" PRIVATE OFF) 222 WEBKIT_OPTION_DEFINE(ENABLE_WEBDRIVER_WHEEL_INTERACTIONS "Toggle WebDriver wheel interactions" PRIVATE OFF) 222 223 WEBKIT_OPTION_DEFINE(ENABLE_WEBGL "Toggle WebGL support" PRIVATE ON) 223 224 WEBKIT_OPTION_DEFINE(ENABLE_WEBGL2 "Toggle WebGL2 support" PRIVATE OFF) -
trunk/Tools/ChangeLog
r268787 r268793 1 2020-10-21 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 WebDriver: add support for wheel actions 4 https://bugs.webkit.org/show_bug.cgi?id=217174 5 6 Reviewed by Brian Burg. 7 8 Add webdriver-wheel-interactions option. 9 10 * Scripts/webkitperl/FeatureList.pm: 11 1 12 2020-10-21 Lauro Moura <lmoura@igalia.com> 2 13 -
trunk/Tools/Scripts/webkitperl/FeatureList.pm
r268453 r268793 183 183 $webdriverSupport, 184 184 $webdriverTouchInteractionsSupport, 185 $webdriverWheelInteractionsSupport, 185 186 $webgl2Support, 186 187 $webglSupport, … … 554 555 define => "ENABLE_WEBDRIVER_TOUCH_INTERACTIONS", value => \$webdriverTouchInteractionsSupport }, 555 556 557 { option => "webdriver-wheel-interactions", desc => "Toggle WebDriver wheel interactions", 558 define => "ENABLE_WEBDRIVER_WHEEL_INTERACTIONS", value => \$webdriverWheelInteractionsSupport }, 559 556 560 { option => "webgl", desc => "Toggle WebGL support", 557 561 define => "ENABLE_WEBGL", value => \$webglSupport }, -
trunk/WebDriverTests/ChangeLog
r268784 r268793 1 2020-10-21 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 WebDriver: add support for wheel actions 4 https://bugs.webkit.org/show_bug.cgi?id=217174 5 6 Reviewed by Brian Burg. 7 8 Remove expectations for wheel actions test. 9 10 * TestExpectations.json: 11 1 12 2020-10-20 Lauro Moura <lmoura@igalia.com> 2 13 -
trunk/WebDriverTests/TestExpectations.json
r268784 r268793 471 471 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184967"}} 472 472 }, 473 "imported/w3c/webdriver/tests/perform_actions/wheel.py": {474 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/217174"}}475 },476 473 477 474 "imported/w3c/webdriver/tests/close_window/close.py": {
Note:
See TracChangeset
for help on using the changeset viewer.