WebKit Bugzilla
Attachment 361637 Details for
Bug 191446
: [iOS] Mouse/Touch/Pointer events are missing modifier keys
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch and layout tests
bug-191446-20190210123610.patch (text/plain), 105.72 KB, created by
Daniel Bates
on 2019-02-10 12:36:11 PST
(
hide
)
Description:
Patch and layout tests
Filename:
MIME Type:
Creator:
Daniel Bates
Created:
2019-02-10 12:36:11 PST
Size:
105.72 KB
patch
obsolete
>Subversion Revision: 241028 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 3a2d0355d110760d7a4621f1a8499152698cd79e..5daab396379ca38494537cdf4fe9101ccf1acf76 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,22 @@ >+2019-02-08 Daniel Bates <dabates@apple.com> >+ >+ [iOS] Mouse/Touch/Pointer events are missing modifier keys >+ https://bugs.webkit.org/show_bug.cgi?id=191446 >+ <rdar://problem/45929460> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Extract the modifier flags from the WebEvent. This code is only used by Legacy WebKit >+ on iOS and we will need to fix <rdar://problem/47929759> in order for modifier flags >+ to be passed to WebKit. >+ >+ Tests: fast/events/touch/ios/mouse-events-with-modifiers.html >+ fast/events/touch/ios/pointer-events-with-modifiers.html >+ fast/events/touch/ios/touch-events-with-modifiers.html >+ >+ * platform/ios/PlatformEventFactoryIOS.mm: >+ (WebCore::PlatformMouseEventBuilder::PlatformMouseEventBuilder): >+ > 2019-02-06 Daniel Bates <dabates@apple.com> > > Standardize on ControlKey instead of CtrlKey >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 9993ba9c078d548137086505697b35c3672dd21d..7951e4a506ae2142bdd68514f13e5401e1e0cc69 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,65 @@ >+2019-02-08 Daniel Bates <dabates@apple.com> >+ >+ [iOS] Mouse/Touch/Pointer events are missing modifier keys >+ https://bugs.webkit.org/show_bug.cgi?id=191446 >+ <rdar://problem/45929460> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Make use of UIKit SPI to retreive the modifier flags when dispatching mouse and touch events. >+ Add new WebKit SPI for iOS, -[WKNavigationAction modifierFlags], to retrieve the the modifier >+ flags held when a navigation action was initiated. >+ >+ * Platform/spi/ios/UIKitSPI.h: Expose SPI. >+ * Shared/NativeWebTouchEvent.h: Re-arrange macro guards so that we can expose the helper function >+ WebKit::webEventModifierFlags(). This is a bit more involved that usual since this header is included >+ from both C++ and Objective-C source files. It only makes sense to expose this function when >+ compiling as part of an Objective-C source file. >+ * Shared/ios/NativeWebTouchEventIOS.mm: >+ (WebKit::NativeWebTouchEvent::NativeWebTouchEvent): Modified to take the modifier flags held down >+ when the platform touch event was received and pass them through to the base constructor. >+ (WebKit::webEventModifierFlags): Added. Converts from the platform-speciifc UIKeyModifierFlags to >+ OptionSet<WebKit::WebEvent::Modifier>. >+ * Shared/ios/WebIOSEventFactory.h: >+ * Shared/ios/WebIOSEventFactory.mm: >+ (WebIOSEventFactory::toUIKeyModifierFlags): Added. Converts from OptionSet<WebKit::WebEvent::Modifier> >+ to the platform-specific UIKeyModifierFlags. >+ * UIProcess/API/Cocoa/WKNavigationAction.mm: >+ (-[WKNavigationAction modifierFlags]): Added. >+ * UIProcess/API/Cocoa/WKNavigationActionPrivate.h: >+ * UIProcess/WebPageProxy.h: >+ * UIProcess/ios/WKContentViewInteraction.h: >+ * UIProcess/ios/WKContentViewInteraction.mm: >+ (-[WKContentView _webTouchEventsRecognized:]): >+ (-[WKContentView _highlightLongPressRecognized:]): >+ (-[WKContentView _twoFingerSingleTapGestureRecognized:]): >+ (-[WKContentView _singleTapCommited:]): >+ (-[WKContentView _attemptClickAtLocation:modifierFlags:]): >+ Pass modifier flags through. >+ >+ (-[WKContentView actionSheetAssistant:openElementAtLocation:]): This is invoked when a person opens a link >+ via the action sheet. We don't have access to the modifier flags to pass. It also seems like an implementation >+ detail that this action is implemented via mouse click and we should re-evaluate this decision in light of >+ the fact tht the action sheet is browser UI and we tend to be very reserved on what UI actions are visible >+ to the page. On Mac, opening a link via the context menu is not visible to the page, at least from a mouse >+ event perspective. >+ (-[WKContentView _attemptClickAtLocation:]): Pass modifier flags through. >+ >+ * UIProcess/ios/WebPageProxyIOS.mm: >+ (WebKit::WebPageProxy::handleTwoFingerTapAtPoint): >+ (WebKit::WebPageProxy::commitPotentialTap): >+ (WebKit::WebPageProxy::handleTap): >+ * WebProcess/WebPage/WebPage.h: >+ * WebProcess/WebPage/WebPage.messages.in: >+ * WebProcess/WebPage/ios/WebPageIOS.mm: >+ (WebKit::WebPage::handleSyntheticClick): >+ (WebKit::WebPage::completePendingSyntheticClickForContentChangeObserver): >+ (WebKit::WebPage::completeSyntheticClick): >+ (WebKit::WebPage::handleTap): >+ (WebKit::WebPage::handleTwoFingerTapAtPoint): >+ (WebKit::WebPage::commitPotentialTap): >+ Pass modifier flags through. >+ > 2019-02-06 Daniel Bates <dabates@apple.com> > > Standardize on ControlKey instead of CtrlKey >diff --git a/Source/WebCore/platform/ios/PlatformEventFactoryIOS.mm b/Source/WebCore/platform/ios/PlatformEventFactoryIOS.mm >index be23f54c059324603a139d96b53db3d7448b285a..a171b9db1fd4f503454d46b4e87fc1f2fb046029 100644 >--- a/Source/WebCore/platform/ios/PlatformEventFactoryIOS.mm >+++ b/Source/WebCore/platform/ios/PlatformEventFactoryIOS.mm >@@ -95,6 +95,7 @@ public: > m_globalPosition = globalPointForEvent(event); > m_button = LeftButton; // This has always been the LeftButton on iOS. > m_clickCount = 1; // This has always been 1 on iOS. >+ m_modifiers = modifiersForEvent(event); > } > }; > >diff --git a/Source/WebKit/Platform/spi/ios/UIKitSPI.h b/Source/WebKit/Platform/spi/ios/UIKitSPI.h >index 1190812e718eaaf4d2aebdbf589a3320dbc89814..d9fef25345829e464fb74341d2615797787ef060 100644 >--- a/Source/WebKit/Platform/spi/ios/UIKitSPI.h >+++ b/Source/WebKit/Platform/spi/ios/UIKitSPI.h >@@ -358,6 +358,10 @@ typedef NS_ENUM(NSInteger, UIScrollViewIndicatorInsetAdjustmentBehavior) { > - (CGSize)_legacy_sizeWithFont:(UIFont *)font minFontSize:(CGFloat)minFontSize actualFontSize:(CGFloat *)actualFontSize forWidth:(CGFloat)width lineBreakMode:(NSLineBreakMode)lineBreakMode; > @end > >+@interface UIGestureRecognizer () >+@property (nonatomic, readonly, getter=_modifierFlags) UIKeyModifierFlags modifierFlags; >+@end >+ > @interface UITapGestureRecognizer () > @property (nonatomic, getter=_allowableSeparation, setter=_setAllowableSeparation:) CGFloat allowableSeparation; > @property (nonatomic, readonly) CGPoint location; >diff --git a/Source/WebKit/Shared/NativeWebTouchEvent.h b/Source/WebKit/Shared/NativeWebTouchEvent.h >index 3b7cedb15f6d6946375e8dd1c57cf71c698899a6..3910a48c757c578760371cb5b875a4bc0686078b 100644 >--- a/Source/WebKit/Shared/NativeWebTouchEvent.h >+++ b/Source/WebKit/Shared/NativeWebTouchEvent.h >@@ -23,27 +23,35 @@ > * THE POSSIBILITY OF SUCH DAMAGE. > */ > >-#ifndef NativeWebTouchEvent_h >-#define NativeWebTouchEvent_h >- >-#if ENABLE(TOUCH_EVENTS) >+#pragma once > > #include "WebEvent.h" > >+#if ENABLE(TOUCH_EVENTS) >+ > #if PLATFORM(IOS_FAMILY) >+#if defined(__OBJC__) >+#include <UIKit/UIKit.h> > struct _UIWebTouchEvent; >+#endif > #elif PLATFORM(GTK) > #include <WebCore/GUniquePtrGtk.h> > #elif USE(LIBWPE) > #include <wpe/wpe.h> > #endif > >+#endif // ENABLE(TOUCH_EVENTS) >+ > namespace WebKit { > >+#if ENABLE(TOUCH_EVENTS) >+ > class NativeWebTouchEvent : public WebTouchEvent { > public: > #if PLATFORM(IOS_FAMILY) >- explicit NativeWebTouchEvent(const _UIWebTouchEvent*); >+#if defined(__OBJC__) >+ explicit NativeWebTouchEvent(const _UIWebTouchEvent*, UIKeyModifierFlags); >+#endif > #elif PLATFORM(GTK) > NativeWebTouchEvent(GdkEvent*, Vector<WebPlatformTouchPoint>&&); > NativeWebTouchEvent(const NativeWebTouchEvent&); >@@ -56,7 +64,7 @@ public: > #endif > > private: >-#if PLATFORM(IOS_FAMILY) >+#if PLATFORM(IOS_FAMILY) && defined(__OBJC__) > Vector<WebPlatformTouchPoint> extractWebTouchPoint(const _UIWebTouchEvent*); > #endif > >@@ -67,8 +75,10 @@ private: > #endif > }; > >-} // namespace WebKit >- > #endif // ENABLE(TOUCH_EVENTS) > >-#endif // NativeWebTouchEvent_h >+#if PLATFORM(IOS_FAMILY) && defined(__OBJC__) >+OptionSet<WebEvent::Modifier> webEventModifierFlags(UIKeyModifierFlags); >+#endif >+ >+} // namespace WebKit >diff --git a/Source/WebKit/Shared/ios/NativeWebTouchEventIOS.mm b/Source/WebKit/Shared/ios/NativeWebTouchEventIOS.mm >index 995f640cf7365fa26ac9c3e517cf3be8f24c2681..323c9ec03255acc9ec6bdaa3f055c6d20227da21 100644 >--- a/Source/WebKit/Shared/ios/NativeWebTouchEventIOS.mm >+++ b/Source/WebKit/Shared/ios/NativeWebTouchEventIOS.mm >@@ -26,16 +26,17 @@ > #import "config.h" > #import "NativeWebTouchEvent.h" > >-#if PLATFORM(IOS_FAMILY) && ENABLE(TOUCH_EVENTS) >+#if PLATFORM(IOS_FAMILY) > > #import "UIKitSPI.h" >-#import "WebEvent.h" > #import <UIKit/UITouch.h> > #import <WebCore/IntPoint.h> > #import <WebCore/WAKAppKitStubs.h> > > namespace WebKit { > >+#if ENABLE(TOUCH_EVENTS) >+ > static inline WebEvent::Type webEventTypeForUIWebTouchEventType(UIWebTouchEventType type) > { > switch (type) { >@@ -117,10 +118,10 @@ Vector<WebPlatformTouchPoint> NativeWebTouchEvent::extractWebTouchPoint(const _U > return touchPointList; > } > >-NativeWebTouchEvent::NativeWebTouchEvent(const _UIWebTouchEvent* event) >+NativeWebTouchEvent::NativeWebTouchEvent(const _UIWebTouchEvent* event, UIKeyModifierFlags flags) > : WebTouchEvent( > webEventTypeForUIWebTouchEventType(event->type), >- OptionSet<Modifier> { }, >+ webEventModifierFlags(flags), > WallTime::fromRawSeconds(event->timestamp), > extractWebTouchPoint(event), > positionForCGPoint(event->locationInDocumentCoordinates), >@@ -135,6 +136,24 @@ NativeWebTouchEvent::NativeWebTouchEvent(const _UIWebTouchEvent* event) > { > } > >+#endif // ENABLE(TOUCH_EVENTS) >+ >+OptionSet<WebEvent::Modifier> webEventModifierFlags(UIKeyModifierFlags flags) >+{ >+ OptionSet<WebEvent::Modifier> modifiers; >+ if (flags & UIKeyModifierShift) >+ modifiers.add(WebEvent::Modifier::ShiftKey); >+ if (flags & UIKeyModifierControl) >+ modifiers.add(WebEvent::Modifier::ControlKey); >+ if (flags & UIKeyModifierAlternate) >+ modifiers.add(WebEvent::Modifier::AltKey); >+ if (flags & UIKeyModifierCommand) >+ modifiers.add(WebEvent::Modifier::MetaKey); >+ if (flags & UIKeyModifierAlphaShift) >+ modifiers.add(WebEvent::Modifier::CapsLockKey); >+ return modifiers; >+} >+ > } // namespace WebKit > >-#endif // PLATFORM(IOS_FAMILY) && ENABLE(TOUCH_EVENTS) >+#endif // PLATFORM(IOS_FAMILY) >diff --git a/Source/WebKit/Shared/ios/WebIOSEventFactory.h b/Source/WebKit/Shared/ios/WebIOSEventFactory.h >index ab98d8fc0d8e1b2d84a3ebd71baf7dab0ee21d9a..8579c334fac22707079af2fa3fd94413532396a3 100644 >--- a/Source/WebKit/Shared/ios/WebIOSEventFactory.h >+++ b/Source/WebKit/Shared/ios/WebIOSEventFactory.h >@@ -23,20 +23,20 @@ > * THE POSSIBILITY OF SUCH DAMAGE. > */ > >-#ifndef WebIOSEventFactory_h >-#define WebIOSEventFactory_h >+#pragma once > > #if PLATFORM(IOS_FAMILY) > > #import "WebEvent.h" >+#import <UIKit/UIKit.h> > #import <WebCore/WebEvent.h> > > class WebIOSEventFactory { > public: > static WebKit::WebKeyboardEvent createWebKeyboardEvent(::WebEvent *); > static WebKit::WebMouseEvent createWebMouseEvent(::WebEvent *); >+ >+ static UIKeyModifierFlags toUIKeyModifierFlags(OptionSet<WebKit::WebEvent::Modifier>); > }; > > #endif // PLATFORM(IOS_FAMILY) >- >-#endif // WebIOSEventFactory_h >diff --git a/Source/WebKit/Shared/ios/WebIOSEventFactory.mm b/Source/WebKit/Shared/ios/WebIOSEventFactory.mm >index 84a7a5a4dbf012e222bd386eae01c6f6d24d15ad..25c16ec2252d450694cc823749571ed20fbd0a47 100644 >--- a/Source/WebKit/Shared/ios/WebIOSEventFactory.mm >+++ b/Source/WebKit/Shared/ios/WebIOSEventFactory.mm >@@ -31,6 +31,22 @@ > #import <WebCore/KeyEventCodesIOS.h> > #import <WebCore/PlatformEventFactoryIOS.h> > >+UIKeyModifierFlags WebIOSEventFactory::toUIKeyModifierFlags(OptionSet<WebKit::WebEvent::Modifier> modifiers) >+{ >+ UIKeyModifierFlags modifierFlags = 0; >+ if (modifiers.contains(WebKit::WebEvent::Modifier::ShiftKey)) >+ modifierFlags |= UIKeyModifierShift; >+ if (modifiers.contains(WebKit::WebEvent::Modifier::ControlKey)) >+ modifierFlags |= UIKeyModifierControl; >+ if (modifiers.contains(WebKit::WebEvent::Modifier::AltKey)) >+ modifierFlags |= UIKeyModifierAlternate; >+ if (modifiers.contains(WebKit::WebEvent::Modifier::MetaKey)) >+ modifierFlags |= UIKeyModifierCommand; >+ if (modifiers.contains(WebKit::WebEvent::Modifier::CapsLockKey)) >+ modifierFlags |= UIKeyModifierAlphaShift; >+ return modifierFlags; >+} >+ > static OptionSet<WebKit::WebEvent::Modifier> modifiersForEvent(::WebEvent *event) > { > OptionSet<WebKit::WebEvent::Modifier> modifiers; >diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKNavigationAction.mm b/Source/WebKit/UIProcess/API/Cocoa/WKNavigationAction.mm >index 44c8bb6092edaa12ca3ecc9c47de510d6cfb6d73..8ebba1f5bc53c697498b514bbb4e6d6a8d838570 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/WKNavigationAction.mm >+++ b/Source/WebKit/UIProcess/API/Cocoa/WKNavigationAction.mm >@@ -36,6 +36,10 @@ > #import <WebCore/FloatPoint.h> > #import <wtf/RetainPtr.h> > >+#if PLATFORM(IOS_FAMILY) >+#import "WebIOSEventFactory.h" >+#endif >+ > @implementation WKNavigationAction > > static WKNavigationType toWKNavigationType(WebCore::NavigationType navigationType) >@@ -127,6 +131,7 @@ - (CGPoint)_clickLocationInRootViewCoordinates > #endif > > #if PLATFORM(MAC) >+ > - (NSEventModifierFlags)modifierFlags > { > return WebKit::WebEventFactory::toNSEventModifierFlags(_navigationAction->modifiers()); >@@ -136,6 +141,14 @@ - (NSInteger)buttonNumber > { > return WebKit::WebEventFactory::toNSButtonNumber(_navigationAction->mouseButton()); > } >+ >+#else >+ >+- (UIKeyModifierFlags)modifierFlags >+{ >+ return WebIOSEventFactory::toUIKeyModifierFlags(_navigationAction->modifiers()); >+} >+ > #endif > > #pragma mark WKObject protocol implementation >diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKNavigationActionPrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKNavigationActionPrivate.h >index 5df7ae0d509155870fbb8e1066f3ffcd22a197ba..ad7422f2b75715a4cdec89c826efd6707b6e75ee 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/WKNavigationActionPrivate.h >+++ b/Source/WebKit/UIProcess/API/Cocoa/WKNavigationActionPrivate.h >@@ -31,6 +31,8 @@ > @class _WKUserInitiatedAction; > > #if TARGET_OS_IPHONE >+#include <UIKit/UIKit.h> >+ > typedef NS_ENUM(NSInteger, WKSyntheticClickType) { > WKSyntheticClickTypeNoTap, > WKSyntheticClickTypeOneFingerTap, >@@ -53,6 +55,8 @@ typedef NS_ENUM(NSInteger, WKSyntheticClickType) { > #if TARGET_OS_IPHONE > @property (nonatomic, readonly) WKSyntheticClickType _syntheticClickType WK_API_AVAILABLE(ios(10.0)); > @property (nonatomic, readonly) CGPoint _clickLocationInRootViewCoordinates WK_API_AVAILABLE(ios(11.0)); >+ >+@property (nonatomic, readonly) UIKeyModifierFlags modifierFlags WK_API_AVAILABLE(ios(WK_IOS_TBA)); > #endif > > @property (nonatomic, readonly) BOOL _isRedirect WK_API_AVAILABLE(macosx(10.13), ios(11.0)); >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index 7be91943890b75d0e28ca3701f5b467ec08747a2..6cf3469c3b3ce492abaaa3b3697f573d025d3091 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -80,6 +80,7 @@ > #include <WebCore/LayoutSize.h> > #include <WebCore/MediaPlaybackTargetContext.h> > #include <WebCore/MediaProducer.h> >+#include <WebCore/PlatformEvent.h> > #include <WebCore/PlatformScreen.h> > #include <WebCore/PointerID.h> > #include <WebCore/ScrollTypes.h> >@@ -666,7 +667,7 @@ public: > void disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID); > void contentSizeCategoryDidChange(const String& contentSizeCategory); > void getSelectionContext(WTF::Function<void(const String&, const String&, const String&, CallbackBase::Error)>&&); >- void handleTwoFingerTapAtPoint(const WebCore::IntPoint&, uint64_t requestID); >+ void handleTwoFingerTapAtPoint(const WebCore::IntPoint&, OptionSet<WebKit::WebEvent::Modifier>, uint64_t requestID); > void handleStylusSingleTapAtPoint(const WebCore::IntPoint&, uint64_t requestID); > void setForceAlwaysUserScalable(bool); > bool forceAlwaysUserScalable() const { return m_forceAlwaysUserScalable; } >@@ -1165,10 +1166,10 @@ public: > void willStartUserTriggeredZooming(); > > void potentialTapAtPosition(const WebCore::FloatPoint&, uint64_t& requestID); >- void commitPotentialTap(uint64_t layerTreeTransactionIdAtLastTouchStart); >+ void commitPotentialTap(OptionSet<WebKit::WebEvent::Modifier>, uint64_t layerTreeTransactionIdAtLastTouchStart); > void cancelPotentialTap(); > void tapHighlightAtPosition(const WebCore::FloatPoint&, uint64_t& requestID); >- void handleTap(const WebCore::FloatPoint&, uint64_t layerTreeTransactionIdAtLastTouchStart); >+ void handleTap(const WebCore::FloatPoint&, OptionSet<WebKit::WebEvent::Modifier>, uint64_t layerTreeTransactionIdAtLastTouchStart); > > void inspectorNodeSearchMovedToPosition(const WebCore::FloatPoint&); > void inspectorNodeSearchEndedAtPosition(const WebCore::FloatPoint&); >diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >index 38be0d0e2acfc46a2f969ceddbf021b016ed9a6c..e6ce727156ae9daf31af8e5bdd4a47dbdba262c6 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >@@ -408,7 +408,7 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW) > - (void)_updateChangedSelection; > - (BOOL)_interpretKeyEvent:(::WebEvent *)theEvent isCharEvent:(BOOL)isCharEvent; > - (void)_positionInformationDidChange:(const WebKit::InteractionInformationAtPosition&)info; >-- (void)_attemptClickAtLocation:(CGPoint)location; >+- (void)_attemptClickAtLocation:(CGPoint)location modifierFlags:(UIKeyModifierFlags)modifierFlags; > - (void)_willStartScrollingOrZooming; > - (void)_didScroll; > - (void)_didEndScrollingOrZooming; >diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >index 4d8e3604a8ea88f516f6743c3af8d47474185689..0cb2c76d5ab3fc672b1c1ec06fdeb4648b9d8d46 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >@@ -1171,7 +1171,7 @@ - (void)_webTouchEventsRecognized:(UIWebTouchEventsGestureRecognizer *)gestureRe > _layerTreeTransactionIdAtLastTouchStart = downcast<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page->drawingArea()).lastCommittedLayerTreeTransactionID(); > > #if ENABLE(TOUCH_EVENTS) >- WebKit::NativeWebTouchEvent nativeWebTouchEvent(lastTouchEvent); >+ WebKit::NativeWebTouchEvent nativeWebTouchEvent { lastTouchEvent, gestureRecognizer.modifierFlags }; > nativeWebTouchEvent.setCanPreventNativeGestures(!_canSendTouchEventsAsynchronously || [gestureRecognizer isDefaultPrevented]); > > #if ENABLE(POINTER_EVENTS) >@@ -2051,7 +2051,7 @@ - (void)_highlightLongPressRecognized:(UILongPressGestureRecognizer *)gestureRec > break; > case UIGestureRecognizerStateEnded: > if (_highlightLongPressCanClick && _positionInformation.isElement) { >- [self _attemptClickAtLocation:[gestureRecognizer startPoint]]; >+ [self _attemptClickAtLocation:gestureRecognizer.startPoint modifierFlags:gestureRecognizer.modifierFlags]; > [self _finishInteraction]; > } else > [self _cancelInteraction]; >@@ -2070,7 +2070,7 @@ - (void)_twoFingerSingleTapGestureRecognized:(UITapGestureRecognizer *)gestureRe > { > _isTapHighlightIDValid = YES; > _isExpectingFastSingleTapCommit = YES; >- _page->handleTwoFingerTapAtPoint(WebCore::roundedIntPoint(gestureRecognizer.centroid), ++_latestTapID); >+ _page->handleTwoFingerTapAtPoint(WebCore::roundedIntPoint(gestureRecognizer.centroid), WebKit::webEventModifierFlags(gestureRecognizer.modifierFlags), ++_latestTapID); > } > > - (void)_stylusSingleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer >@@ -2194,7 +2194,7 @@ - (void)_singleTapCommited:(UITapGestureRecognizer *)gestureRecognizer > } > > [_inputPeripheral endEditing]; >- _page->commitPotentialTap(_layerTreeTransactionIdAtLastTouchStart); >+ _page->commitPotentialTap(WebKit::webEventModifierFlags(gestureRecognizer.modifierFlags), _layerTreeTransactionIdAtLastTouchStart); > > if (!_isExpectingFastSingleTapCommit) > [self _finishInteraction]; >@@ -2227,7 +2227,7 @@ - (void)_twoFingerDoubleTapRecognized:(UITapGestureRecognizer *)gestureRecognize > _smartMagnificationController->handleResetMagnificationGesture(gestureRecognizer.location); > } > >-- (void)_attemptClickAtLocation:(CGPoint)location >+- (void)_attemptClickAtLocation:(CGPoint)location modifierFlags:(UIKeyModifierFlags)modifierFlags > { > if (![self isFirstResponder]) { > if (!_inputViewUpdateDeferrer) >@@ -2236,7 +2236,7 @@ - (void)_attemptClickAtLocation:(CGPoint)location > } > > [_inputPeripheral endEditing]; >- _page->handleTap(location, _layerTreeTransactionIdAtLastTouchStart); >+ _page->handleTap(location, WebKit::webEventModifierFlags(modifierFlags), _layerTreeTransactionIdAtLastTouchStart); > } > > - (void)setUpTextSelectionAssistant >@@ -5424,7 +5424,7 @@ - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant performAction:( > > - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant openElementAtLocation:(CGPoint)location > { >- [self _attemptClickAtLocation:location]; >+ [self _attemptClickAtLocation:location modifierFlags:0]; > } > > - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant shareElementWithURL:(NSURL *)url rect:(CGRect)boundingRect >diff --git a/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm b/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm >index 4726894a93a787190746fd53c67d92820eab7ddf..4c1a087eef006126f1bcb51286dfc4f45db79faf 100644 >--- a/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm >+++ b/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm >@@ -593,9 +593,9 @@ void WebPageProxy::getSelectionContext(WTF::Function<void(const String&, const S > m_process->send(Messages::WebPage::GetSelectionContext(callbackID), m_pageID); > } > >-void WebPageProxy::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID) >+void WebPageProxy::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, OptionSet<WebEvent::Modifier> modifiers, uint64_t requestID) > { >- process().send(Messages::WebPage::HandleTwoFingerTapAtPoint(point, requestID), m_pageID); >+ process().send(Messages::WebPage::HandleTwoFingerTapAtPoint(point, modifiers, requestID), m_pageID); > } > > void WebPageProxy::handleStylusSingleTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID) >@@ -824,9 +824,9 @@ void WebPageProxy::potentialTapAtPosition(const WebCore::FloatPoint& position, u > process().send(Messages::WebPage::PotentialTapAtPosition(requestID, position), m_pageID); > } > >-void WebPageProxy::commitPotentialTap(uint64_t layerTreeTransactionIdAtLastTouchStart) >+void WebPageProxy::commitPotentialTap(OptionSet<WebEvent::Modifier> modifiers, uint64_t layerTreeTransactionIdAtLastTouchStart) > { >- process().send(Messages::WebPage::CommitPotentialTap(layerTreeTransactionIdAtLastTouchStart), m_pageID); >+ process().send(Messages::WebPage::CommitPotentialTap(modifiers, layerTreeTransactionIdAtLastTouchStart), m_pageID); > } > > void WebPageProxy::cancelPotentialTap() >@@ -839,9 +839,9 @@ void WebPageProxy::tapHighlightAtPosition(const WebCore::FloatPoint& position, u > process().send(Messages::WebPage::TapHighlightAtPosition(requestID, position), m_pageID); > } > >-void WebPageProxy::handleTap(const FloatPoint& location, uint64_t layerTreeTransactionIdAtLastTouchStart) >+void WebPageProxy::handleTap(const FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers, uint64_t layerTreeTransactionIdAtLastTouchStart) > { >- process().send(Messages::WebPage::HandleTap(roundedIntPoint(location), layerTreeTransactionIdAtLastTouchStart), m_pageID); >+ process().send(Messages::WebPage::HandleTap(roundedIntPoint(location), modifiers, layerTreeTransactionIdAtLastTouchStart), m_pageID); > } > > void WebPageProxy::inspectorNodeSearchMovedToPosition(const WebCore::FloatPoint& position) >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h >index a1a0294aa5a6d5af92380413dddc4e33a2ff3ff8..0659a0758d3f03a7018317babda7d8c8933b258a 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.h >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h >@@ -613,9 +613,9 @@ public: > bool allowsUserScaling() const; > bool hasStablePageScaleFactor() const { return m_hasStablePageScaleFactor; } > >- void handleTap(const WebCore::IntPoint&, uint64_t lastLayerTreeTransactionId); >+ void handleTap(const WebCore::IntPoint&, OptionSet<WebKit::WebEvent::Modifier>, uint64_t lastLayerTreeTransactionId); > void potentialTapAtPosition(uint64_t requestID, const WebCore::FloatPoint&); >- void commitPotentialTap(uint64_t lastLayerTreeTransactionId); >+ void commitPotentialTap(OptionSet<WebKit::WebEvent::Modifier>, uint64_t lastLayerTreeTransactionId); > void commitPotentialTapFailed(); > void cancelPotentialTap(); > void cancelPotentialTapInFrame(WebFrame&); >@@ -661,7 +661,7 @@ public: > WebCore::IntRect rectForElementAtInteractionLocation(); > void updateSelectionAppearance(); > void getSelectionContext(CallbackID); >- void handleTwoFingerTapAtPoint(const WebCore::IntPoint&, uint64_t requestID); >+ void handleTwoFingerTapAtPoint(const WebCore::IntPoint&, OptionSet<WebKit::WebEvent::Modifier>, uint64_t requestID); > void handleStylusSingleTapAtPoint(const WebCore::IntPoint&, uint64_t requestID); > void getRectsForGranularityWithSelectionOffset(uint32_t, int32_t, CallbackID); > void getRectsAtSelectionOffsetWithText(int32_t, const String&, CallbackID); >@@ -1180,8 +1180,8 @@ private: > RefPtr<WebCore::Range> rangeForWebSelectionAtPosition(const WebCore::IntPoint&, const WebCore::VisiblePosition&, SelectionFlags&); > void getFocusedElementInformation(FocusedElementInformation&); > void platformInitializeAccessibility(); >- void handleSyntheticClick(WebCore::Node* nodeRespondingToClick, const WebCore::FloatPoint& location); >- void completeSyntheticClick(WebCore::Node* nodeRespondingToClick, const WebCore::FloatPoint& location, WebCore::SyntheticClickType); >+ void handleSyntheticClick(WebCore::Node* nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>); >+ void completeSyntheticClick(WebCore::Node* nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>, WebCore::SyntheticClickType); > void sendTapHighlightForNodeIfNecessary(uint64_t requestID, WebCore::Node*); > void resetTextAutosizing(); > WebCore::VisiblePosition visiblePositionInFocusedNodeForPoint(const WebCore::Frame&, const WebCore::IntPoint&, bool isInteractingWithFocusedElement); >@@ -1757,6 +1757,7 @@ private: > RefPtr<WebCore::Node> m_pendingSyntheticClickNode; > WebCore::FloatPoint m_pendingSyntheticClickLocation; > WebCore::FloatRect m_previousExposedContentRect; >+ OptionSet<WebKit::WebEvent::Modifier> m_pendingSyntheticClickModifiers; > FocusedElementIdentifier m_currentFocusedElementIdentifier { 0 }; > Optional<DynamicViewportSizeUpdateID> m_pendingDynamicViewportSizeUpdateID; > double m_lastTransactionPageScaleFactor { 0 }; >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >index 776ed755639356dc50e04f3acabbbc89aabb566d..608a6c2aa279fb203198e7fa470ebcff7a9380e7 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >@@ -51,9 +51,9 @@ messages -> WebPage LegacyReceiver { > SetOverrideViewportArguments(Optional<WebCore::ViewportArguments> arguments) > DynamicViewportSizeUpdate(WebCore::FloatSize viewLayoutSize, WebCore::FloatSize maximumUnobscuredSize, WebCore::FloatRect targetExposedContentRect, WebCore::FloatRect targetUnobscuredRect, WebCore::FloatRect targetUnobscuredRectInScrollViewCoordinates, WebCore::RectEdges<float> targetUnobscuredSafeAreaInsets, double scale, int32_t deviceOrientation, uint64_t dynamicViewportSizeUpdateID) > >- HandleTap(WebCore::IntPoint point, uint64_t lastLayerTreeTransactionId) >+ HandleTap(WebCore::IntPoint point, OptionSet<WebKit::WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId) > PotentialTapAtPosition(uint64_t requestID, WebCore::FloatPoint point) >- CommitPotentialTap(uint64_t lastLayerTreeTransactionId) >+ CommitPotentialTap(OptionSet<WebKit::WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId) > CancelPotentialTap() > TapHighlightAtPosition(uint64_t requestID, WebCore::FloatPoint point) > InspectorNodeSearchMovedToPosition(WebCore::FloatPoint point) >@@ -98,7 +98,7 @@ messages -> WebPage LegacyReceiver { > ContentSizeCategoryDidChange(String contentSizeCategory) > GetSelectionContext(WebKit::CallbackID callbackID) > SetAllowsMediaDocumentInlinePlayback(bool allows) >- HandleTwoFingerTapAtPoint(WebCore::IntPoint point, uint64_t requestID) >+ HandleTwoFingerTapAtPoint(WebCore::IntPoint point, OptionSet<WebKit::WebEvent::Modifier> modifiers, uint64_t requestID) > HandleStylusSingleTapAtPoint(WebCore::IntPoint point, uint64_t requestID) > SetForceAlwaysUserScalable(bool userScalable) > GetRectsForGranularityWithSelectionOffset(uint32_t granularity, int32_t offset, WebKit::CallbackID callbackID) >diff --git a/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm b/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm >index 5d1b1dd90697cf80c4819a2a3e6964041b8eb825..8e473030c21a433d2d8068c59bb388494c29da2b 100644 >--- a/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm >+++ b/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm >@@ -533,7 +533,7 @@ void WebPage::updateSelectionAppearance() > didChangeSelection(); > } > >-void WebPage::handleSyntheticClick(Node* nodeRespondingToClick, const WebCore::FloatPoint& location) >+void WebPage::handleSyntheticClick(Node* nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers) > { > IntPoint roundedAdjustedPoint = roundedIntPoint(location); > Frame& mainframe = m_page->mainFrame(); >@@ -542,7 +542,12 @@ void WebPage::handleSyntheticClick(Node* nodeRespondingToClick, const WebCore::F > WKStartObservingContentChanges(); > WKStartObservingDOMTimerScheduling(); > >- mainframe.eventHandler().mouseMoved(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, NoButton, PlatformEvent::MouseMoved, 0, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, WebCore::NoTap)); >+ // FIXME: Pass caps lock state. >+ bool shiftKey = modifiers.contains(WebEvent::Modifier::ShiftKey); >+ bool ctrlKey = modifiers.contains(WebEvent::Modifier::ControlKey); >+ bool altKey = modifiers.contains(WebEvent::Modifier::AltKey); >+ bool metaKey = modifiers.contains(WebEvent::Modifier::MetaKey); >+ mainframe.eventHandler().mouseMoved(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, WebCore::NoTap)); > mainframe.document()->updateStyleIfNeeded(); > > WKStopObservingDOMTimerScheduling(); >@@ -550,6 +555,7 @@ void WebPage::handleSyntheticClick(Node* nodeRespondingToClick, const WebCore::F > > m_pendingSyntheticClickNode = nullptr; > m_pendingSyntheticClickLocation = FloatPoint(); >+ m_pendingSyntheticClickModifiers = { }; > > if (m_isClosed) > return; >@@ -559,15 +565,16 @@ void WebPage::handleSyntheticClick(Node* nodeRespondingToClick, const WebCore::F > // The move event caused new contents to appear. Don't send the click event. > LOG(ContentObservation, "handleSyntheticClick: Observed meaningful visible change -> hover."); > return; >- case WKContentIndeterminateChange: >+ case WKContentIndeterminateChange: { > // Wait for callback to completePendingSyntheticClickForContentChangeObserver() to decide whether to send the click event. > m_pendingSyntheticClickNode = nodeRespondingToClick; > m_pendingSyntheticClickLocation = location; >+ m_pendingSyntheticClickModifiers = modifiers; > LOG(ContentObservation, "handleSyntheticClick: Observed some change, but can't decide it yet -> wait."); > return; >- case WKContentNoChange: >+ } case WKContentNoChange: > LOG(ContentObservation, "handleSyntheticClick: No change was observed -> click."); >- completeSyntheticClick(nodeRespondingToClick, location, WebCore::OneFingerTap); >+ completeSyntheticClick(nodeRespondingToClick, location, modifiers, WebCore::OneFingerTap); > return; > } > ASSERT_NOT_REACHED(); >@@ -581,15 +588,16 @@ void WebPage::completePendingSyntheticClickForContentChangeObserver() > // Only dispatch the click if the document didn't get changed by any timers started by the move event. > if (WKObservedContentChange() == WKContentNoChange) { > LOG(ContentObservation, "No chage was observed -> click."); >- completeSyntheticClick(m_pendingSyntheticClickNode.get(), m_pendingSyntheticClickLocation, WebCore::OneFingerTap); >+ completeSyntheticClick(m_pendingSyntheticClickNode.get(), m_pendingSyntheticClickLocation, m_pendingSyntheticClickModifiers, WebCore::OneFingerTap); > } else > LOG(ContentObservation, "Observed meaningful visible change -> hover."); > > m_pendingSyntheticClickNode = nullptr; > m_pendingSyntheticClickLocation = FloatPoint(); >+ m_pendingSyntheticClickModifiers = { }; > } > >-void WebPage::completeSyntheticClick(Node* nodeRespondingToClick, const WebCore::FloatPoint& location, SyntheticClickType syntheticClickType) >+void WebPage::completeSyntheticClick(Node* nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers, SyntheticClickType syntheticClickType) > { > IntPoint roundedAdjustedPoint = roundedIntPoint(location); > Frame& mainframe = m_page->mainFrame(); >@@ -602,11 +610,17 @@ void WebPage::completeSyntheticClick(Node* nodeRespondingToClick, const WebCore: > bool tapWasHandled = false; > m_lastInteractionLocation = roundedAdjustedPoint; > >- tapWasHandled |= mainframe.eventHandler().handleMousePressEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MousePressed, 1, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, syntheticClickType)); >+ // FIXME: Pass caps lock state. >+ bool shiftKey = modifiers.contains(WebEvent::Modifier::ShiftKey); >+ bool ctrlKey = modifiers.contains(WebEvent::Modifier::ControlKey); >+ bool altKey = modifiers.contains(WebEvent::Modifier::AltKey); >+ bool metaKey = modifiers.contains(WebEvent::Modifier::MetaKey); >+ >+ tapWasHandled |= mainframe.eventHandler().handleMousePressEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MousePressed, 1, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, syntheticClickType)); > if (m_isClosed) > return; > >- tapWasHandled |= mainframe.eventHandler().handleMouseReleaseEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MouseReleased, 1, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, syntheticClickType)); >+ tapWasHandled |= mainframe.eventHandler().handleMouseReleaseEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MouseReleased, 1, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, syntheticClickType)); > if (m_isClosed) > return; > >@@ -626,7 +640,7 @@ void WebPage::completeSyntheticClick(Node* nodeRespondingToClick, const WebCore: > send(Messages::WebPageProxy::DidCompleteSyntheticClick()); > } > >-void WebPage::handleTap(const IntPoint& point, uint64_t lastLayerTreeTransactionId) >+void WebPage::handleTap(const IntPoint& point, OptionSet<WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId) > { > FloatPoint adjustedPoint; > Node* nodeRespondingToClick = m_page->mainFrame().nodeRespondingToClickEvents(point, adjustedPoint); >@@ -643,7 +657,7 @@ void WebPage::handleTap(const IntPoint& point, uint64_t lastLayerTreeTransaction > } > #endif > else >- handleSyntheticClick(nodeRespondingToClick, adjustedPoint); >+ handleSyntheticClick(nodeRespondingToClick, adjustedPoint, modifiers); > } > > void WebPage::requestFocusedElementInformation(WebKit::CallbackID callbackID) >@@ -738,7 +752,7 @@ void WebPage::sendTapHighlightForNodeIfNecessary(uint64_t requestID, Node* node) > #endif > } > >-void WebPage::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID) >+void WebPage::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, OptionSet<WebKit::WebEvent::Modifier> modifiers, uint64_t requestID) > { > FloatPoint adjustedPoint; > Node* nodeRespondingToClick = m_page->mainFrame().nodeRespondingToClickEvents(point, adjustedPoint); >@@ -754,7 +768,7 @@ void WebPage::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, uint64_t > send(Messages::WebPageProxy::DidNotHandleTapAsClick(roundedIntPoint(adjustedPoint))); > } else > #endif >- completeSyntheticClick(nodeRespondingToClick, adjustedPoint, WebCore::TwoFingerTap); >+ completeSyntheticClick(nodeRespondingToClick, adjustedPoint, modifiers, WebCore::TwoFingerTap); > } > > void WebPage::handleStylusSingleTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID) >@@ -799,7 +813,7 @@ void WebPage::potentialTapAtPosition(uint64_t requestID, const WebCore::FloatPoi > #endif > } > >-void WebPage::commitPotentialTap(uint64_t lastLayerTreeTransactionId) >+void WebPage::commitPotentialTap(OptionSet<WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId) > { > if (!m_potentialTapNode || (!m_potentialTapNode->renderer() && !is<HTMLAreaElement>(m_potentialTapNode.get()))) { > commitPotentialTapFailed(); >@@ -823,7 +837,7 @@ void WebPage::commitPotentialTap(uint64_t lastLayerTreeTransactionId) > commitPotentialTapFailed(); > } else > #endif >- handleSyntheticClick(nodeRespondingToClick, adjustedPoint); >+ handleSyntheticClick(nodeRespondingToClick, adjustedPoint, modifiers); > } else > commitPotentialTapFailed(); > >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 92f03030799a17a6b6153177268f4099fd87b01c..e6ec3a79830f6e189b1854d8820b6c173458a288 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,29 @@ >+2019-02-08 Daniel Bates <dabates@apple.com> >+ >+ [iOS] Mouse/Touch/Pointer events are missing modifier keys >+ https://bugs.webkit.org/show_bug.cgi?id=191446 >+ <rdar://problem/45929460> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add support infrastructure for testing touch and stylus taps when holding modifier keys. >+ >+ * DumpRenderTree/ios/UIScriptControllerIOS.mm: >+ (WTR::UIScriptController::singleTapAtPointWithModifiers): Added. >+ (WTR::UIScriptController::stylusTapAtPointWithModifiers): Added. >+ * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl: >+ * TestRunnerShared/UIScriptContext/UIScriptController.cpp: >+ (WTR::UIScriptController::singleTapAtPointWithModifiers): Added. >+ (WTR::UIScriptController::stylusTapAtPointWithModifiers): Added. >+ * TestRunnerShared/UIScriptContext/UIScriptController.h: >+ * WebKitTestRunner/ios/UIScriptControllerIOS.mm: >+ (WTR::arrayLength): >+ (WTR::parseModifierArray): >+ (WTR::UIScriptController::singleTapAtPoint): Implemented in terms of singleTapAtPointWithModifiers(). >+ (WTR::UIScriptController::singleTapAtPointWithModifiers): Added. >+ (WTR::UIScriptController::stylusTapAtPoint): Implemented in terms of stylusTapAtPointWithModifiers(). >+ (WTR::UIScriptController::stylusTapAtPointWithModifiers): Added. >+ > 2019-02-06 Michael Catanzaro <mcatanzaro@igalia.com> > > Unreviewed, fix a typo >diff --git a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >index db11ad641562d1d3a3164294b65446df8f53a39c..7a9b084964e4ad9d6b16e4b78f4ab1d3198f1309 100644 >--- a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >+++ b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >@@ -115,6 +115,10 @@ void UIScriptController::singleTapAtPoint(long x, long y, JSValueRef callback) > { > } > >+void UIScriptController::singleTapAtPointWithModifiers(long x, long y, JSValueRef modifierArray, JSValueRef callback) >+{ >+} >+ > void UIScriptController::doubleTapAtPoint(long x, long y, JSValueRef callback) > { > } >@@ -143,6 +147,10 @@ void UIScriptController::stylusTapAtPoint(long x, long y, float azimuthAngle, fl > { > } > >+void UIScriptController::stylusTapAtPointWithModifiers(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef modifierArray, JSValueRef callback) >+{ >+} >+ > void UIScriptController::sendEventStream(JSStringRef eventsJSON, JSValueRef callback) > { > } >diff --git a/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl b/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >index e54467ff448a0a7c37070e9b7d0f18825c943143..5a8d07ab7be807a3ccd715796f6fc1f9c57df661 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >+++ b/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >@@ -56,6 +56,7 @@ interface UIScriptController { > void touchDownAtPoint(long x, long y, long touchCount, object callback); > void liftUpAtPoint(long x, long y, long touchCount, object callback); > void singleTapAtPoint(long x, long y, object callback); >+ void singleTapAtPointWithModifiers(long x, long y, object modifierArray, object callback); > void doubleTapAtPoint(long x, long y, object callback); > void dragFromPointToPoint(long startX, long startY, long endX, long endY, double durationSeconds, object callback); > >@@ -65,6 +66,7 @@ interface UIScriptController { > void stylusMoveToPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, object callback); > void stylusUpAtPoint(long x, long y, object callback); > void stylusTapAtPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, object callback); >+ void stylusTapAtPointWithModifiers(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, object modifierArray, object callback); > > void enterText(DOMString text); > void typeCharacterUsingHardwareKeyboard(DOMString character, object callback); >diff --git a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >index 4b45d56fdc2cb2ca4dae0f66dd1f527eefe7c39e..0cdc70010d55cd762e88a9b1c7da75b099072954 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >+++ b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >@@ -265,6 +265,10 @@ void UIScriptController::singleTapAtPoint(long x, long y, JSValueRef) > { > } > >+void UIScriptController::singleTapAtPointWithModifiers(long x, long y, JSValueRef modifierArray, JSValueRef callback) >+{ >+} >+ > void UIScriptController::doubleTapAtPoint(long x, long y, JSValueRef) > { > } >@@ -293,6 +297,10 @@ void UIScriptController::stylusTapAtPoint(long x, long y, float azimuthAngle, fl > { > } > >+void UIScriptController::stylusTapAtPointWithModifiers(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef modifierArray, JSValueRef callback) >+{ >+} >+ > void UIScriptController::sendEventStream(JSStringRef eventsJSON, JSValueRef callback) > { > } >diff --git a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >index 956c345c32f61351cfede1143f4a61c00e66c740..11a1cb2330c6bd83623d07d89d7938fbf8bda2ae 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >+++ b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >@@ -78,6 +78,7 @@ public: > void touchDownAtPoint(long x, long y, long touchCount, JSValueRef callback); > void liftUpAtPoint(long x, long y, long touchCount, JSValueRef callback); > void singleTapAtPoint(long x, long y, JSValueRef callback); >+ void singleTapAtPointWithModifiers(long x, long y, JSValueRef modifierArray, JSValueRef callback); > void doubleTapAtPoint(long x, long y, JSValueRef callback); > void dragFromPointToPoint(long startX, long startY, long endX, long endY, double durationSeconds, JSValueRef callback); > >@@ -85,6 +86,7 @@ public: > void stylusMoveToPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef callback); > void stylusUpAtPoint(long x, long y, JSValueRef callback); > void stylusTapAtPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef callback); >+ void stylusTapAtPointWithModifiers(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef modifierArray, JSValueRef callback); > > void longPressAtPoint(long x, long y, JSValueRef callback); > >diff --git a/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm b/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >index 4952765a0acfd3de3f182be28e2fe8e19395683b..fbcc25b6b33878dacc80474a246bbf7d29a84e5e 100644 >--- a/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >+++ b/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >@@ -63,7 +63,45 @@ static NSDictionary *toNSDictionary(CGRect rect) > @"height": @(rect.size.height) > }; > } >- >+ >+static unsigned arrayLength(JSContextRef context, JSObjectRef array) >+{ >+ auto lengthString = adopt(JSStringCreateWithUTF8CString("length")); >+ if (auto lengthValue = JSObjectGetProperty(context, array, lengthString.get(), nullptr)) >+ return static_cast<unsigned>(JSValueToNumber(context, lengthValue, nullptr)); >+ return 0; >+} >+ >+static Vector<String> parseModifierArray(JSContextRef context, JSValueRef arrayValue) >+{ >+ if (!arrayValue) >+ return { }; >+ >+ // The value may either be a string with a single modifier or an array of modifiers. >+ if (JSValueIsString(context, arrayValue)) { >+ auto string = toWTFString(toWK(adopt(JSValueToStringCopy(context, arrayValue, nullptr)))); >+ return { string }; >+ } >+ >+ if (!JSValueIsObject(context, arrayValue)) >+ return { }; >+ JSObjectRef array = const_cast<JSObjectRef>(arrayValue); >+ unsigned length = arrayLength(context, array); >+ Vector<String> modifiers; >+ modifiers.reserveInitialCapacity(length); >+ for (unsigned i = 0; i < length; ++i) { >+ JSValueRef exception = nullptr; >+ JSValueRef value = JSObjectGetPropertyAtIndex(context, array, i, &exception); >+ if (exception) >+ continue; >+ auto string = adopt(JSValueToStringCopy(context, value, &exception)); >+ if (exception) >+ continue; >+ modifiers.append(toWTFString(toWK(string.get()))); >+ } >+ return modifiers; >+} >+ > void UIScriptController::checkForOutstandingCallbacks() > { > if (![[HIDEventGenerator sharedHIDEventGenerator] checkForOutstandingCallbacks]) >@@ -192,13 +230,30 @@ void UIScriptController::liftUpAtPoint(long x, long y, long touchCount, JSValueR > } > > void UIScriptController::singleTapAtPoint(long x, long y, JSValueRef callback) >+{ >+ singleTapAtPointWithModifiers(x, y, nullptr, callback); >+} >+ >+void UIScriptController::singleTapAtPointWithModifiers(long x, long y, JSValueRef modifierArray, JSValueRef callback) > { > unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent); > >+ auto modifierFlags = parseModifierArray(m_context->jsContext(), modifierArray); >+ for (auto& modifierFlag : modifierFlags) >+ [[HIDEventGenerator sharedHIDEventGenerator] keyDown:modifierFlag]; >+ > [[HIDEventGenerator sharedHIDEventGenerator] tap:globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), x, y) completionBlock:^{ > if (!m_context) > return; >- m_context->asyncTaskComplete(callbackID); >+ for (size_t i = modifierFlags.size(); i; ) { >+ --i; >+ [[HIDEventGenerator sharedHIDEventGenerator] keyUp:modifierFlags[i]]; >+ } >+ [[HIDEventGenerator sharedHIDEventGenerator] sendMarkerHIDEventWithCompletionBlock:^{ >+ if (!m_context) >+ return; >+ m_context->asyncTaskComplete(callbackID); >+ }]; > }]; > } > >@@ -250,17 +305,34 @@ void UIScriptController::stylusUpAtPoint(long x, long y, JSValueRef callback) > } > > void UIScriptController::stylusTapAtPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef callback) >+{ >+ stylusTapAtPointWithModifiers(x, y, azimuthAngle, altitudeAngle, pressure, nullptr, callback); >+} >+ >+void UIScriptController::stylusTapAtPointWithModifiers(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef modifierArray, JSValueRef callback) > { > unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent); > >+ auto modifierFlags = parseModifierArray(m_context->jsContext(), modifierArray); >+ for (auto& modifierFlag : modifierFlags) >+ [[HIDEventGenerator sharedHIDEventGenerator] keyDown:modifierFlag]; >+ > auto location = globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), x, y); > [[HIDEventGenerator sharedHIDEventGenerator] stylusTapAtPoint:location azimuthAngle:azimuthAngle altitudeAngle:altitudeAngle pressure:pressure completionBlock:^{ > if (!m_context) > return; >- m_context->asyncTaskComplete(callbackID); >+ for (size_t i = modifierFlags.size(); i; ) { >+ --i; >+ [[HIDEventGenerator sharedHIDEventGenerator] keyUp:modifierFlags[i]]; >+ } >+ [[HIDEventGenerator sharedHIDEventGenerator] sendMarkerHIDEventWithCompletionBlock:^{ >+ if (!m_context) >+ return; >+ m_context->asyncTaskComplete(callbackID); >+ }]; > }]; > } >- >+ > void convertCoordinates(NSMutableDictionary *event) > { > if (event[HIDEventTouchesKey]) { >@@ -349,44 +421,6 @@ void UIScriptController::typeCharacterUsingHardwareKeyboard(JSStringRef characte > }]; > } > >-static unsigned arrayLength(JSContextRef context, JSObjectRef array) >-{ >- auto lengthString = adopt(JSStringCreateWithUTF8CString("length")); >- if (auto lengthValue = JSObjectGetProperty(context, array, lengthString.get(), nullptr)) >- return static_cast<unsigned>(JSValueToNumber(context, lengthValue, nullptr)); >- return 0; >-} >- >-static Vector<String> parseModifierArray(JSContextRef context, JSValueRef arrayValue) >-{ >- if (!arrayValue) >- return { }; >- >- // The value may either be a string with a single modifier or an array of modifiers. >- if (JSValueIsString(context, arrayValue)) { >- auto string = toWTFString(toWK(adopt(JSValueToStringCopy(context, arrayValue, nullptr)))); >- return { string }; >- } >- >- if (!JSValueIsObject(context, arrayValue)) >- return { }; >- JSObjectRef array = const_cast<JSObjectRef>(arrayValue); >- unsigned length = arrayLength(context, array); >- Vector<String> modifiers; >- modifiers.reserveInitialCapacity(length); >- for (unsigned i = 0; i < length; ++i) { >- JSValueRef exception = nullptr; >- JSValueRef value = JSObjectGetPropertyAtIndex(context, array, i, &exception); >- if (exception) >- continue; >- auto string = adopt(JSValueToStringCopy(context, value, &exception)); >- if (exception) >- continue; >- modifiers.append(toWTFString(toWK(string.get()))); >- } >- return modifiers; >-} >- > static UIPhysicalKeyboardEvent *createUIPhysicalKeyboardEvent(NSString *hidInputString, NSString *uiEventInputString, UIKeyModifierFlags modifierFlags, UIKeyboardInputFlags inputFlags, bool isKeyDown) > { > auto* keyboardEvent = [getUIPhysicalKeyboardEventClass() _eventWithInput:uiEventInputString inputFlags:inputFlags]; >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 67d1203113c64add6fa5cdc5ce18543fca842c4b..8907383ef5341644312174205bc8afce24c5440b 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,35 @@ >+2019-02-08 Daniel Bates <dabates@apple.com> >+ >+ [iOS] Mouse/Touch/Pointer events are missing modifier keys >+ https://bugs.webkit.org/show_bug.cgi?id=191446 >+ <rdar://problem/45929460> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Refactor existing iOS key events tests to share code. Add new tests to ensure touch and mouse events >+ have accurate modifier key details. >+ >+ * fast/events/ios/key-events-meta-alt-combinations.html: >+ * fast/events/ios/resources/key-tester.js: >+ (computeSubsets.compareByModifierOrder): Deleted. >+ * fast/events/resources/compute-subsets.js: Added. >+ (computeSubsets.compareByOriginalArrayOrder): >+ (computeSubsets): >+ * fast/events/touch/ios/mouse-events-with-modifiers-expected.txt: Added. >+ * fast/events/touch/ios/mouse-events-with-modifiers.html: Added. >+ * fast/events/touch/ios/pointer-events-with-modifiers-expected.txt: Added. >+ * fast/events/touch/ios/pointer-events-with-modifiers.html: Added. >+ * fast/events/touch/ios/touch-events-with-modifiers-expected.txt: Added. >+ * fast/events/touch/ios/touch-events-with-modifiers.html: Added. >+ * http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt: Update expected result >+ due to changes to ui-helper.js. >+ * platform/ios/TestExpectations: >+ * resources/ui-helper.js: >+ (window.UIHelper.tapAt.return.new.Promise): >+ (window.UIHelper.tapAt): >+ (window.UIHelper.stylusTapAt.return.new.Promise): >+ (window.UIHelper.stylusTapAt): >+ > 2019-02-06 Jonathan Bedard <jbedard@apple.com> > > [iPad] Initial test gardening (Part 2) >diff --git a/LayoutTests/fast/events/ios/key-events-meta-alt-combinations.html b/LayoutTests/fast/events/ios/key-events-meta-alt-combinations.html >index fe88d341ebdba1d87410f0979c83f364f616c260..4f0e5af797c1d555c1b57d5f961a05cff438710f 100644 >--- a/LayoutTests/fast/events/ios/key-events-meta-alt-combinations.html >+++ b/LayoutTests/fast/events/ios/key-events-meta-alt-combinations.html >@@ -2,11 +2,12 @@ > <html> > <head> > <script src="../../../resources/ui-helper.js"></script> >+<script src="../resources/compute-subsets.js"></script> > <script src="resources/key-tester.js"></script> > <script> > const modiferKeySubsetsToTest = computeSubsets(["metaKey", "altKey"]); > for (const k of keysExcludingDeadAndSkippedKeys) { >- for (const modifiers of modiferKeySubsetsToTest) >+ for (const modifiers of computeSubsets(modifierKeys)) > tests.push(new KeyCommand(k, modifiers)); > } > </script> >diff --git a/LayoutTests/fast/events/ios/resources/key-tester.js b/LayoutTests/fast/events/ios/resources/key-tester.js >index 5748070b3b8fa3b6fb80be7ebb844537c6cdba40..60dbe9ece7dd6e3cace83fd5649a44ec3ed2b35c 100644 >--- a/LayoutTests/fast/events/ios/resources/key-tester.js >+++ b/LayoutTests/fast/events/ios/resources/key-tester.js >@@ -53,43 +53,6 @@ function keyCommandsHasCommand(keyCommands, command) > return !!keyCommands.find((k) => areKeyCommandsEqual(k, command)); > } > >-// This algorithm runs in O(2^N). >-function computeSubsets(anArray) >-{ >- function compareByModifierOrder(a, b) { >- if (a.length < b.length) >- return -1; >- if (a.length > b.length) >- return 1; >- for (let i = 0; i < a.length; ++i) { >- let rankA = anArray.indexOf(a[i]); >- let rankB = anArray.indexOf(b[i]); >- if (rankA < rankB) >- return -1; >- if (rankA > rankB) >- return 1; >- } >- return 0; >- } >- let result = []; >- const numberOfNonEmptyPermutations = (1 << anArray.length) - 1; >- // For each ordinal 1, 2, ... numberOfNonEmptyPermutations we look at its binary representation >- // and generate a permutation that consists of the entries in anArray at the indices where there >- // is a one bit in the binary representation. For example, suppose anArray = ["metaKey", "altKey", "ctrlKey"]. >- // To generate the 5th permutation we look at the binary representation of i = 5 => 0b101. And >- // compute the permutation to be [ anArray[0], anArray[2] ] = [ "metaKey", "ctrlKey" ] because >- // the 0th and 2nd bits are ones in the binary representation. >- for (let i = 1; i <= numberOfNonEmptyPermutations; ++i) { >- let temp = []; >- for (let bitmask = i, j = 0; bitmask; bitmask = Math.floor(bitmask / 2), ++j) { >- if (bitmask % 2) >- temp.push(anArray[j]); >- } >- result.push(temp); >- } >- return result.sort(compareByModifierOrder); >-} >- > const keys = new Set("abcdefghijklmnopqrstuvwxyz0123456789-=[]\\;',./".split("")); > const deadKeys = new Set("`euin".split("")); > const keysExcludingDeadKeys = computeDifference(keys, deadKeys); >@@ -117,7 +80,6 @@ for (let i = 1; i <= 9; ++i) > disallowedKeyCommands.push(new KeyCommand(i, ["metaKey"])); > > const modifierKeys = ["metaKey", "altKey", "ctrlKey", "shiftKey"]; >-const modiferKeySubsets = computeSubsets(modifierKeys); > > let tests = []; > >diff --git a/LayoutTests/fast/events/resources/compute-subsets.js b/LayoutTests/fast/events/resources/compute-subsets.js >new file mode 100644 >index 0000000000000000000000000000000000000000..a0f92876ea604b648de787d3e7723f1a2cc12a6b >--- /dev/null >+++ b/LayoutTests/fast/events/resources/compute-subsets.js >@@ -0,0 +1,36 @@ >+// This algorithm runs in O(2^N). >+function computeSubsets(anArray) >+{ >+ function compareByOriginalArrayOrder(a, b) { >+ if (a.length < b.length) >+ return -1; >+ if (a.length > b.length) >+ return 1; >+ for (let i = 0; i < a.length; ++i) { >+ let rankA = anArray.indexOf(a[i]); >+ let rankB = anArray.indexOf(b[i]); >+ if (rankA < rankB) >+ return -1; >+ if (rankA > rankB) >+ return 1; >+ } >+ return 0; >+ } >+ let result = []; >+ const numberOfNonEmptyPermutations = (1 << anArray.length) - 1; >+ // For each ordinal 1, 2, ... numberOfNonEmptyPermutations we look at its binary representation >+ // and generate a permutation that consists of the entries in anArray at the indices where there >+ // is a one bit in the binary representation. For example, suppose anArray = ["metaKey", "altKey", "ctrlKey"]. >+ // To generate the 5th permutation we look at the binary representation of i = 5 => 0b101. And >+ // compute the permutation to be [ anArray[0], anArray[2] ] = [ "metaKey", "ctrlKey" ] because >+ // the 0th and 2nd bits are ones in the binary representation. >+ for (let i = 1; i <= numberOfNonEmptyPermutations; ++i) { >+ let temp = []; >+ for (let bitmask = i, j = 0; bitmask; bitmask = Math.floor(bitmask / 2), ++j) { >+ if (bitmask % 2) >+ temp.push(anArray[j]); >+ } >+ result.push(temp); >+ } >+ return result.sort(compareByOriginalArrayOrder); >+} >diff --git a/LayoutTests/fast/events/touch/ios/mouse-events-with-modifiers-expected.txt b/LayoutTests/fast/events/touch/ios/mouse-events-with-modifiers-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..8051383674d9e3ca2bec1ac703eb9cddd12a8124 >--- /dev/null >+++ b/LayoutTests/fast/events/touch/ios/mouse-events-with-modifiers-expected.txt >@@ -0,0 +1,78 @@ >+This logs DOM mousedown, mousemove, and mouseup events that are dispatched when single tapping an element while holding modifier keys. Must be run in WebKitTestRunner. >+ >+ >+Test Command + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+ >+Test Option + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+ >+Test Control + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+ >+Test Shift + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+ >+Test Command + Option + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+ >+Test Command + Control + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+ >+Test Command + Shift + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+ >+Test Option + Control + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+ >+Test Option + Shift + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+ >+Test Control + Shift + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+ >+Test Command + Option + Control + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+ >+Test Command + Option + Shift + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+ >+Test Command + Control + Shift + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+ >+Test Option + Control + Shift + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+ >+Test Command + Option + Control + Shift + Single Tap: >+type: mousemove, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+type: mousedown, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+type: mouseup, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+ >diff --git a/LayoutTests/fast/events/touch/ios/mouse-events-with-modifiers.html b/LayoutTests/fast/events/touch/ios/mouse-events-with-modifiers.html >new file mode 100644 >index 0000000000000000000000000000000000000000..48afac7f52c620e3be4ba2a753538f85d7950c3d >--- /dev/null >+++ b/LayoutTests/fast/events/touch/ios/mouse-events-with-modifiers.html >@@ -0,0 +1,141 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="../../../../resources/ui-helper.js"></script> >+<script src="../../resources/compute-subsets.js"></script> >+<script> >+if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+} >+ >+class TouchTest { >+ constructor(elementToTouch, modifiers = []) >+ { >+ this.elementToTouch = elementToTouch; >+ this.modifiers = modifiers; >+ } >+ >+ toString() >+ { >+ return `{ ${this.elementToTouch}, [${this.modifiers}] }`; >+ } >+ >+ run() >+ { >+ let centerX = this.elementToTouch.offsetLeft + this.elementToTouch.offsetWidth / 2; >+ let centerY = this.elementToTouch.offsetTop + this.elementToTouch.offsetHeight / 2; >+ return UIHelper.tapAt(centerX, centerY, this.modifiers); >+ } >+} >+ >+const modifierKeys = ["metaKey", "altKey", "ctrlKey", "shiftKey"]; >+ >+let currentTest; >+let tests = []; >+ >+function handleMouseDown(event) >+{ >+ logMouseEvent(event); >+} >+ >+function handleMouseMove(event) >+{ >+ logMouseEvent(event); >+} >+ >+function handleMouseUp(event) >+{ >+ logMouseEvent(event); >+ nextTouchPress(); >+} >+ >+function log(message) >+{ >+ document.getElementById("console").appendChild(document.createTextNode(message + "\n")); >+} >+ >+function logMouseEvent(event) >+{ >+ let pieces = []; >+ for (let propertyName of ["type", "x", "y", "offsetX", "offsetY", "button", "buttons", "screenX", "screenY", "clientX", "clientY", "altKey", "ctrlKey", "metaKey", "shiftKey"]) >+ pieces.push(`${propertyName}: ${event[propertyName]}`); >+ log(pieces.join(", ")); >+} >+ >+const modifierDisplayNameMap = { >+ "altKey": "Option", >+ "ctrlKey": "Control", >+ "metaKey": "Command", >+ "shiftKey": "Shift", >+ "capsLockKey": "Caps Lock", >+} >+ >+function displayNameForTest(test) >+{ >+ let displayNamesOfModifiers = []; >+ for (const modifier of test.modifiers) >+ displayNamesOfModifiers.push(modifierDisplayNameMap[modifier]); >+ let result = ""; >+ if (displayNamesOfModifiers.length) >+ result += displayNamesOfModifiers.join(" + ") + " + "; >+ result += "Single Tap"; >+ return result; >+} >+ >+async function nextTouchPress() >+{ >+ if (!tests.length) { >+ document.body.removeChild(document.getElementById("square")); >+ if (window.testRunner) >+ testRunner.notifyDone(); >+ return; >+ } >+ currentTest = tests.shift(); >+ log(`\nTest ${displayNameForTest(currentTest)}:`); >+ if (window.testRunner) >+ await currentTest.run(); >+} >+ >+function runTest() >+{ >+ if (!window.testRunner) >+ return; >+ nextTouchPress(); >+} >+ >+function setUp() >+{ >+ let square = document.getElementById("square"); >+ square.addEventListener("mousedown", handleMouseDown, true); >+ square.addEventListener("mousemove", handleMouseMove, true); >+ square.addEventListener("mouseup", handleMouseUp, true); >+ >+ for (const modifiers of computeSubsets(modifierKeys)) >+ tests.push(new TouchTest(square, modifiers)); >+ >+ runTest(); >+} >+ >+window.addEventListener("load", setUp, true); >+</script> >+<style> >+#square { >+ background-color: blue; >+ color: white; >+ height: 128px; >+ width: 128px; >+ display: flex; >+ align-items: center; >+ justify-content: center; >+ user-select: none; >+ -webkit-user-select: none; >+} >+</style> >+</head> >+<body> >+<p>This logs DOM mousedown, mousemove, and mouseup events that are dispatched when single tapping an element while holding modifier keys. Must be run in WebKitTestRunner.</p> >+<div id="square">Touch Me</div> >+<pre id="console"></pre> >+</body> >+</html> >diff --git a/LayoutTests/fast/events/touch/ios/pointer-events-with-modifiers-expected.txt b/LayoutTests/fast/events/touch/ios/pointer-events-with-modifiers-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..09be81f0c739cd4bf57902535cc2116471aa597c >--- /dev/null >+++ b/LayoutTests/fast/events/touch/ios/pointer-events-with-modifiers-expected.txt >@@ -0,0 +1,63 @@ >+This logs DOM pointerdown and pointerup events that are dispatched when single tapping an element while holding modifier keys. Must be run in WebKitTestRunner. >+ >+ >+Test Command + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+ >+Test Option + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+ >+Test Control + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+ >+Test Shift + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+ >+Test Command + Option + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+ >+Test Command + Control + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+ >+Test Command + Shift + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+ >+Test Option + Control + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+ >+Test Option + Shift + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+ >+Test Control + Shift + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+ >+Test Command + Option + Control + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+ >+Test Command + Option + Shift + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+ >+Test Command + Control + Shift + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+ >+Test Option + Control + Shift + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+ >+Test Command + Option + Control + Shift + Single Tap: >+type: pointerdown, pointerType: touch, isPrimary: true, width: 40, height: 40, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+type: pointerup, pointerType: touch, isPrimary: false, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 90, tiltY: 0, twist: 0, x: 72, y: 136, offsetX: 64, offsetY: 64, button: 0, buttons: 0, screenX: 72, screenY: 136, clientX: 72, clientY: 136, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+ >diff --git a/LayoutTests/fast/events/touch/ios/pointer-events-with-modifiers.html b/LayoutTests/fast/events/touch/ios/pointer-events-with-modifiers.html >new file mode 100644 >index 0000000000000000000000000000000000000000..d475303bea92d3cae3b923e1418ef9f03ad74837 >--- /dev/null >+++ b/LayoutTests/fast/events/touch/ios/pointer-events-with-modifiers.html >@@ -0,0 +1,135 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="../../../../resources/ui-helper.js"></script> >+<script src="../../resources/compute-subsets.js"></script> >+<script> >+if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+} >+ >+class TouchTest { >+ constructor(elementToTouch, modifiers = []) >+ { >+ this.elementToTouch = elementToTouch; >+ this.modifiers = modifiers; >+ } >+ >+ toString() >+ { >+ return `{ ${this.elementToTouch}, [${this.modifiers}] }`; >+ } >+ >+ run() >+ { >+ let centerX = this.elementToTouch.offsetLeft + this.elementToTouch.offsetWidth / 2; >+ let centerY = this.elementToTouch.offsetTop + this.elementToTouch.offsetHeight / 2; >+ return UIHelper.tapAt(centerX, centerY, this.modifiers); >+ } >+} >+ >+const modifierKeys = ["metaKey", "altKey", "ctrlKey", "shiftKey"]; >+ >+let currentTest; >+let tests = []; >+ >+function handlePointerDown(event) >+{ >+ logPointerEvent(event); >+} >+ >+function handlePointerUp(event) >+{ >+ logPointerEvent(event); >+ nextTouchPress(); >+} >+ >+function log(message) >+{ >+ document.getElementById("console").appendChild(document.createTextNode(message + "\n")); >+} >+ >+function logPointerEvent(event) >+{ >+ let pieces = []; >+ for (let propertyName of ["type", "pointerType", "isPrimary", "width", "height", "pressure", "tangentialPressure", "tiltX", "tiltY", "twist", "x", "y", "offsetX", "offsetY", "button", "buttons", "screenX", "screenY", "clientX", "clientY", "altKey", "ctrlKey", "metaKey", "shiftKey"]) >+ pieces.push(`${propertyName}: ${event[propertyName]}`); >+ log(pieces.join(", ")); >+} >+ >+const modifierDisplayNameMap = { >+ "altKey": "Option", >+ "ctrlKey": "Control", >+ "metaKey": "Command", >+ "shiftKey": "Shift", >+ "capsLockKey": "Caps Lock", >+} >+ >+function displayNameForTest(test) >+{ >+ let displayNamesOfModifiers = []; >+ for (const modifier of test.modifiers) >+ displayNamesOfModifiers.push(modifierDisplayNameMap[modifier]); >+ let result = ""; >+ if (displayNamesOfModifiers.length) >+ result += displayNamesOfModifiers.join(" + ") + " + "; >+ result += "Single Tap"; >+ return result; >+} >+ >+async function nextTouchPress() >+{ >+ if (!tests.length) { >+ document.body.removeChild(document.getElementById("square")); >+ if (window.testRunner) >+ testRunner.notifyDone(); >+ return; >+ } >+ currentTest = tests.shift(); >+ log(`\nTest ${displayNameForTest(currentTest)}:`); >+ if (window.testRunner) >+ await currentTest.run(); >+} >+ >+function runTest() >+{ >+ if (!window.testRunner) >+ return; >+ nextTouchPress(); >+} >+ >+function setUp() >+{ >+ let square = document.getElementById("square"); >+ square.addEventListener("pointerdown", handlePointerDown, true); >+ square.addEventListener("pointerup", handlePointerUp, true); >+ >+ for (const modifiers of computeSubsets(modifierKeys)) >+ tests.push(new TouchTest(square, modifiers)); >+ >+ runTest(); >+} >+ >+window.addEventListener("load", setUp, true); >+</script> >+<style> >+#square { >+ background-color: blue; >+ color: white; >+ height: 128px; >+ width: 128px; >+ display: flex; >+ align-items: center; >+ justify-content: center; >+ user-select: none; >+ -webkit-user-select: none; >+} >+</style> >+</head> >+<body> >+<p>This logs DOM pointerdown and pointerup events that are dispatched when single tapping an element while holding modifier keys. Must be run in WebKitTestRunner.</p> >+<div id="square">Touch Me</div> >+<pre id="console"></pre> >+</body> >+</html> >diff --git a/LayoutTests/fast/events/touch/ios/touch-events-with-modifiers-expected.txt b/LayoutTests/fast/events/touch/ios/touch-events-with-modifiers-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..4e5550c9d0e647d403be98c757f0da7354aa10bd >--- /dev/null >+++ b/LayoutTests/fast/events/touch/ios/touch-events-with-modifiers-expected.txt >@@ -0,0 +1,123 @@ >+This logs DOM touchdown and touchup events that are dispatched when single tapping an element while holding modifier keys with and without a stylus. Must be run in WebKitTestRunner. >+ >+ >+Test Command + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+ >+Test Option + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+ >+Test Control + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+ >+Test Shift + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+ >+Test Command + Option + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+ >+Test Command + Control + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+ >+Test Command + Shift + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+ >+Test Option + Control + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+ >+Test Option + Shift + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+ >+Test Control + Shift + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+ >+Test Command + Option + Control + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+ >+Test Command + Option + Shift + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+ >+Test Command + Control + Shift + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+ >+Test Option + Control + Shift + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+ >+Test Command + Option + Control + Shift + Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+ >+Test Command + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: true, shiftKey: false >+ >+Test Option + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false >+ >+Test Control + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: false, shiftKey: false >+ >+Test Shift + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: false, shiftKey: true >+ >+Test Command + Option + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: true, shiftKey: false >+ >+Test Command + Control + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: true, shiftKey: false >+ >+Test Command + Shift + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: false, metaKey: true, shiftKey: true >+ >+Test Option + Control + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: false, shiftKey: false >+ >+Test Option + Shift + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true >+ >+Test Control + Shift + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: false, shiftKey: true >+ >+Test Command + Option + Control + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: true, shiftKey: false >+ >+Test Command + Option + Shift + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: false, metaKey: true, shiftKey: true >+ >+Test Command + Control + Shift + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: false, ctrlKey: true, metaKey: true, shiftKey: true >+ >+Test Option + Control + Shift + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true >+ >+Test Command + Option + Control + Shift + Stylus Single Tap: >+type: touchstart, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+type: touchend, pageX: 72, pageX: 72, scale: 1, rotation: 0, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true >+ >diff --git a/LayoutTests/fast/events/touch/ios/touch-events-with-modifiers.html b/LayoutTests/fast/events/touch/ios/touch-events-with-modifiers.html >new file mode 100644 >index 0000000000000000000000000000000000000000..a52f5096839a91de403c77ba6c15c87dde9861cd >--- /dev/null >+++ b/LayoutTests/fast/events/touch/ios/touch-events-with-modifiers.html >@@ -0,0 +1,150 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="../../../../resources/ui-helper.js"></script> >+<script src="../../resources/compute-subsets.js"></script> >+<script> >+if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+} >+ >+// FIXME: Add support for testing force touch. >+const TouchType = { >+ "SingleTap": "SingleTap", >+ "StylusSingleTap": "StylusSingleTap", >+}; >+const TouchTypeDisplayName = { >+ "SingleTap": "Single Tap", >+ "StylusSingleTap": "Stylus Single Tap", >+}; >+ >+class TouchTest { >+ constructor(elementToTouch, touchType, modifiers = []) >+ { >+ this.elementToTouch = elementToTouch; >+ this.touchType = touchType; >+ this.modifiers = modifiers; >+ } >+ >+ toString() >+ { >+ return `{ ${this.touchType}, ${this.elementToTouch}, [${this.modifiers}] }`; >+ } >+ >+ run() >+ { >+ let centerX = this.elementToTouch.offsetLeft + this.elementToTouch.offsetWidth / 2; >+ let centerY = this.elementToTouch.offsetTop + this.elementToTouch.offsetHeight / 2; >+ if (this.touchType === TouchType.SingleTap) >+ return UIHelper.tapAt(centerX, centerY, this.modifiers); >+ return UIHelper.stylusTapAt(centerX, centerY, this.modifiers); >+ } >+} >+ >+const modifierKeys = ["metaKey", "altKey", "ctrlKey", "shiftKey"]; >+ >+let currentTest; >+let tests = []; >+ >+function handleTouchDown(event) >+{ >+ logTouchEvent(event); >+} >+ >+function handleTouchUp(event) >+{ >+ logTouchEvent(event); >+ nextTouchPress(); >+} >+ >+function log(message) >+{ >+ document.getElementById("console").appendChild(document.createTextNode(message + "\n")); >+} >+ >+function logTouchEvent(event) >+{ >+ let pieces = []; >+ for (let propertyName of ["type", "pageX", "pageX", "scale", "rotation", "altKey", "ctrlKey", "metaKey", "shiftKey"]) >+ pieces.push(`${propertyName}: ${event[propertyName]}`); >+ log(pieces.join(", ")); >+} >+ >+const modifierDisplayNameMap = { >+ "altKey": "Option", >+ "ctrlKey": "Control", >+ "metaKey": "Command", >+ "shiftKey": "Shift", >+ "capsLockKey": "Caps Lock", >+} >+ >+function displayNameForTest(test) >+{ >+ let displayNamesOfModifiers = []; >+ for (const modifier of test.modifiers) >+ displayNamesOfModifiers.push(modifierDisplayNameMap[modifier]); >+ let result = ""; >+ if (displayNamesOfModifiers.length) >+ result += displayNamesOfModifiers.join(" + ") + " + "; >+ result += TouchTypeDisplayName[test.touchType]; >+ return result; >+} >+ >+async function nextTouchPress() >+{ >+ if (!tests.length) { >+ document.body.removeChild(document.getElementById("square")); >+ if (window.testRunner) >+ testRunner.notifyDone(); >+ return; >+ } >+ currentTest = tests.shift(); >+ log(`\nTest ${displayNameForTest(currentTest)}:`); >+ if (window.testRunner) >+ await currentTest.run(); >+} >+ >+function runTest() >+{ >+ if (!window.testRunner) >+ return; >+ nextTouchPress(); >+} >+ >+function setUp() >+{ >+ let square = document.getElementById("square"); >+ square.addEventListener("touchstart", handleTouchDown, true); >+ square.addEventListener("touchend", handleTouchUp, true); >+ >+ for (const touchType in TouchType) { >+ for (const modifiers of computeSubsets(modifierKeys)) >+ tests.push(new TouchTest(square, touchType, modifiers)); >+ } >+ >+ runTest(); >+} >+ >+window.addEventListener("load", setUp, true); >+</script> >+<style> >+#square { >+ background-color: blue; >+ color: white; >+ height: 128px; >+ width: 128px; >+ display: flex; >+ align-items: center; >+ justify-content: center; >+ user-select: none; >+ -webkit-user-select: none; >+} >+</style> >+</head> >+<body> >+<p>This logs DOM touchdown and touchup events that are dispatched when single tapping an element while holding modifier keys with and without a stylus. Must be run in WebKitTestRunner.</p> >+<div id="square">Touch Me</div> >+<pre id="console"></pre> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt b/LayoutTests/http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt >index 311084e6d34ff2348d5dd98a7a4ec29e833e2921..4de18cc3794b843aa8542c480707d484065aa689 100644 >--- a/LayoutTests/http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt >+++ b/LayoutTests/http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt >@@ -1,13 +1,13 @@ >-CONSOLE MESSAGE: line 107: adcampaignid must have a non-negative value less than 64 for Ad Click Attribution. >-CONSOLE MESSAGE: line 107: adcampaignid must have a non-negative value less than 64 for Ad Click Attribution. >-CONSOLE MESSAGE: line 107: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution. >-CONSOLE MESSAGE: line 107: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution. >-CONSOLE MESSAGE: line 107: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution. >-CONSOLE MESSAGE: line 107: adddestination could not be converted to a valid HTTP-family URL. >-CONSOLE MESSAGE: line 107: adddestination could not be converted to a valid HTTP-family URL. >-CONSOLE MESSAGE: line 107: adddestination could not be converted to a valid HTTP-family URL. >-CONSOLE MESSAGE: line 107: Both adcampaignid and addestination need to be set for Ad Click Attribution to work. >-CONSOLE MESSAGE: line 107: Both adcampaignid and addestination need to be set for Ad Click Attribution to work. >+CONSOLE MESSAGE: line 108: adcampaignid must have a non-negative value less than 64 for Ad Click Attribution. >+CONSOLE MESSAGE: line 108: adcampaignid must have a non-negative value less than 64 for Ad Click Attribution. >+CONSOLE MESSAGE: line 108: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution. >+CONSOLE MESSAGE: line 108: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution. >+CONSOLE MESSAGE: line 108: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution. >+CONSOLE MESSAGE: line 108: adddestination could not be converted to a valid HTTP-family URL. >+CONSOLE MESSAGE: line 108: adddestination could not be converted to a valid HTTP-family URL. >+CONSOLE MESSAGE: line 108: adddestination could not be converted to a valid HTTP-family URL. >+CONSOLE MESSAGE: line 108: Both adcampaignid and addestination need to be set for Ad Click Attribution to work. >+CONSOLE MESSAGE: line 108: Both adcampaignid and addestination need to be set for Ad Click Attribution to work. > Test for validity of ad click attribution attributes on anchor tags. > > On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >diff --git a/LayoutTests/platform/ios/TestExpectations b/LayoutTests/platform/ios/TestExpectations >index f40161cca2c98c73d76e5260531e817037b32c5f..5a7435d1a4da81eb385038f5bb5723537cbe57ae 100644 >--- a/LayoutTests/platform/ios/TestExpectations >+++ b/LayoutTests/platform/ios/TestExpectations >@@ -3210,3 +3210,8 @@ webkit.org/b/193955 compositing/iframes/remove-reinsert-webview-with-iframe.html > webkit.org/b/153337 pageoverlay/overlay-installation.html [ Pass Failure ] > webkit.org/b/153337 pageoverlay/overlay-large-document-scrolled.html [ Pass Failure ] > webkit.org/b/153337 pageoverlay/overlay-large-document.html [ Pass Failure ] >+ >+# FIXME: Unskip the following test once we have the fix for <rdar://problem/45970040>. >+fast/events/touch/ios/touch-events-with-modifiers.html [ Skip ] >+fast/events/touch/ios/mouse-events-with-modifiers.html [ Skip ] >+fast/events/touch/ios/pointer-events-with-modifiers.html [ Skip ] >diff --git a/LayoutTests/resources/ui-helper.js b/LayoutTests/resources/ui-helper.js >index fe546a8c865013de4ed045ecc6acd0e23bbbeac3..5aeff043f700ee45012bc29bba5c46b904f60bb0 100644 >--- a/LayoutTests/resources/ui-helper.js >+++ b/LayoutTests/resources/ui-helper.js >@@ -29,11 +29,12 @@ window.UIHelper = class UIHelper { > eventSender.mouseUp(); > } > >- static tapAt(x, y) >+ static tapAt(x, y, modifiers=[]) > { > console.assert(this.isIOS()); > > if (!this.isWebKit2()) { >+ console.assert(!modifiers || !modifiers.length); > eventSender.addTouchPoint(x, y); > eventSender.touchStart(); > eventSender.releaseTouchPoint(0); >@@ -43,7 +44,7 @@ window.UIHelper = class UIHelper { > > return new Promise((resolve) => { > testRunner.runUIScript(` >- uiController.singleTapAtPoint(${x}, ${y}, function() { >+ uiController.singleTapAtPointWithModifiers(${x}, ${y}, ${JSON.stringify(modifiers)}, function() { > uiController.uiScriptComplete(); > });`, resolve); > }); >@@ -534,14 +535,14 @@ window.UIHelper = class UIHelper { > return new Promise(resolve => testRunner.runUIScript(`uiController.drawSquareInEditableImage()`, resolve)); > } > >- static stylusTapAt(x, y) >+ static stylusTapAt(x, y, modifiers=[]) > { > if (!this.isWebKit2()) > return Promise.resolve(); > > return new Promise((resolve) => { > testRunner.runUIScript(` >- uiController.stylusTapAtPoint(${x}, ${y}, 2, 1, 0.5, function() { >+ uiController.stylusTapAtPointWithModifiers(${x}, ${y}, 2, 1, 0.5, ${JSON.stringify(modifiers)}, function() { > uiController.uiScriptComplete(); > });`, resolve); > });
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 191446
:
361342
|
361421
|
361427
|
361435
|
361447
|
361455
|
361456
|
361458
|
361538
|
361551
|
361553
|
361556
|
361575
|
361637
|
361639
|
361641
|
361642
|
361646
|
361696