[Mac] WebKit is not honoring OS preferences for secondary click behaviors
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Apr 2015 02:41:31 +0000 (02:41 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Apr 2015 02:41:31 +0000 (02:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=143452
<rdar://problem/20437483>

Reviewed by Tim Horton.

Source/WebCore:

We cannot rely on the event's button number to decide behavior. The OS settings might have
mapped middle button to context menu, etc. Instead, we should ask the OS (via NSMenu) what
the proper button press behavior is.

* platform/mac/PlatformEventFactoryMac.mm:
(WebCore::mouseButtonForEvent): Ask NSMenu what kind of button press we have received.

Source/WebKit/mac:

We were improperly intercepting contextual menu clicks and passing them through
the mouseDown handler, rather than processing via NSView's menu handling code.

* WebView/WebHTMLView.mm:
(-[WebHTMLView otherMouseDown:]): Treat context menu events the same as the action
menu case, and pass it to AppKit for normal menu processing.

Source/WebKit2:

We cannot rely on the event's button number to decide behavior. The OS settings might have
mapped middle button to context menu, etc. Instead, we should ask the OS (via NSMenu) what
the proper button press behavior is.

* Shared/mac/WebEventFactory.mm:
(WebKit::mouseButtonForEvent): Ask NSMenu what kind of button press we have received.

Tools:

Add a new API test to confirm that Cocoa mouse button press events are properly
tagged with the desired menu behavior (i.e., 'None', 'Context', or 'Action'.)

The WK2 test dispatches mouse down events to a PlatformWebView, and checks with
some registered event handlers that the expected button press and context menu
events are received.

The WK1 unit test creates an NSEvent with the desired button press state, and then
uses WebCore::PlatformEventFactory::createPlatformMouseEvent to create a WebCore event.
We check the resulting PlatformMouseEvent for proper state.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Add new test files.
* TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp: Added.
(TestWebKitAPI::buildAndPerformTest): Helper function to build/run an individual test.
* TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html: Added.
* TestWebKitAPI/Tests/mac/MenuTypesForMouseEvents.mm: Added.
(TestWebKitAPI::canCallMenuTypeForEvent): Helper function.
(TestWebKitAPI::buildAndPerformTest): Helper function to build/run an individual test.
* TestWebKitAPI/mac/PlatformWebViewMac.mm:
(TestWebKitAPI::PlatformWebView::simulateButtonClick): Added method to support firing
mouse down events.
* TestWebKitAPI/mac/PlatformWebViewMac.h:

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

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/PlatformMouseEvent.h
Source/WebCore/platform/mac/PlatformEventFactoryMac.mm
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebView/WebHTMLView.mm
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebEvent.h
Source/WebKit2/Shared/WebEventConversion.cpp
Source/WebKit2/Shared/WebMouseEvent.cpp
Source/WebKit2/Shared/mac/WebEventFactory.h
Source/WebKit2/Shared/mac/WebEventFactory.mm
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/PlatformWebView.h
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/mac/MenuTypesForMouseEvents.mm [new file with mode: 0644]
Tools/TestWebKitAPI/mac/PlatformWebViewMac.mm

index 0fb1c6d9e7266e82beeb8b35e63d80307c39c2e1..c5da5badf04eb27ddc40d9f34080a27cf20a00ea 100644 (file)
@@ -1,3 +1,18 @@
+2015-04-08  Brent Fulgham  <bfulgham@apple.com>
+
+        [Mac] WebKit is not honoring OS preferences for secondary click behaviors
+        https://bugs.webkit.org/show_bug.cgi?id=143452
+        <rdar://problem/20437483>
+
+        Reviewed by Tim Horton.
+
+        We cannot rely on the event's button number to decide behavior. The OS settings might have
+        mapped middle button to context menu, etc. Instead, we should ask the OS (via NSMenu) what
+        the proper button press behavior is.
+
+        * platform/mac/PlatformEventFactoryMac.mm:
+        (WebCore::mouseButtonForEvent): Ask NSMenu what kind of button press we have received.
+
 2015-04-08  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         Fix -Wformat in AnimationBase.cpp
index 4da63190fe0360a75f176027a1d18b8966d8382b..d417d3a77a8e173375512eece1fcd477b67f8c2f 100644 (file)
@@ -55,6 +55,7 @@ namespace WebCore {
             , m_modifierFlags(0)
 #if PLATFORM(MAC)
             , m_eventNumber(0)
+            , m_menuTypeForEvent(0)
 #elif PLATFORM(WIN)
             , m_didActivateWebView(false)
 #endif
@@ -71,6 +72,7 @@ namespace WebCore {
             , m_modifierFlags(0)
 #if PLATFORM(MAC)
             , m_eventNumber(0)
+            , m_menuTypeForEvent(0)
 #elif PLATFORM(WIN)
             , m_didActivateWebView(false)
 #endif
@@ -103,6 +105,7 @@ namespace WebCore {
 
 #if PLATFORM(MAC)
         int eventNumber() const { return m_eventNumber; }
+        int menuTypeForEvent() const { return m_menuTypeForEvent; }
 #endif
 
 #if PLATFORM(WIN)
@@ -123,6 +126,7 @@ namespace WebCore {
 
 #if PLATFORM(MAC)
         int m_eventNumber;
+        int m_menuTypeForEvent;
 #elif PLATFORM(WIN)
         bool m_didActivateWebView;
 #endif
index d5649af92da9459648c6c8337096b440e1cc4f93..314fb1d711f505d2a11f55d5682fb3b66df4b737 100644 (file)
@@ -28,6 +28,7 @@
 
 #import "KeyEventCocoa.h"
 #import "Logging.h"
+#import "NSMenuSPI.h"
 #import "PlatformScreen.h"
 #import "Scrollbar.h"
 #import "WebCoreSystemInterface.h"
@@ -394,7 +395,20 @@ static inline PlatformEvent::Modifiers modifiersForEvent(NSEvent *event)
     return (PlatformEvent::Modifiers)modifiers;
 }
 
+static int typeForEvent(NSEvent *event)
+{
+    if ([NSMenu respondsToSelector:@selector(menuTypeForEvent:)])
+        return static_cast<int>([NSMenu menuTypeForEvent:event]);
+
+    if (mouseButtonForEvent(event) == RightButton)
+        return static_cast<int>(NSMenuTypeContextMenu);
+
+    if (mouseButtonForEvent(event) == LeftButton && (modifiersForEvent(event) & NSControlKeyMask))
+        return static_cast<int>(NSMenuTypeContextMenu);
 
+    return static_cast<int>(NSMenuTypeNone);
+}
+    
 class PlatformMouseEventBuilder : public PlatformMouseEvent {
 public:
     PlatformMouseEventBuilder(NSEvent *event, NSView *windowView)
@@ -413,6 +427,7 @@ public:
         // Mac specific
         m_modifierFlags                     = [event modifierFlags];
         m_eventNumber                       = [event eventNumber];
+        m_menuTypeForEvent                  = typeForEvent(event);
     }
 };
 
index 9a219f2739ed9701eaeccc168b667cb5a1f85587..66cf7233e135d8f30805a27424fc58ead1ac12e2 100644 (file)
@@ -1,3 +1,18 @@
+2015-04-08  Brent Fulgham  <bfulgham@apple.com>
+
+        [Mac] WebKit is not honoring OS preferences for secondary click behaviors
+        https://bugs.webkit.org/show_bug.cgi?id=143452
+        <rdar://problem/20437483>
+
+        Reviewed by Tim Horton.
+
+        We were improperly intercepting contextual menu clicks and passing them through
+        the mouseDown handler, rather than processing via NSView's menu handling code.
+
+        * WebView/WebHTMLView.mm:
+        (-[WebHTMLView otherMouseDown:]): Treat context menu events the same as the action
+        menu case, and pass it to AppKit for normal menu processing. 
+
 2015-04-08  Brady Eidson  <beidson@apple.com>
 
         Expose the "Share" menu for links, images, and media.
index 73ba4e1d2cf14911a6ff1ea9171ce6151c98ba3d..6dd4c4c1237d21249eb0a96f8288cb7f09b54c48 100644 (file)
@@ -5392,7 +5392,8 @@ static BOOL writingDirectionKeyBindingsEnabled()
 #if !PLATFORM(IOS)
 - (void)otherMouseDown:(NSEvent *)event
 {
-    if ([event buttonNumber] != 2 || ([NSMenu respondsToSelector:@selector(menuTypeForEvent:)] && [NSMenu menuTypeForEvent:event] == NSMenuTypeActionMenu)) {
+    if ([event buttonNumber] != 2 || ([NSMenu respondsToSelector:@selector(menuTypeForEvent:)]
+        && ([NSMenu menuTypeForEvent:event] == NSMenuTypeActionMenu || [NSMenu menuTypeForEvent:event] == NSMenuTypeContextMenu))) {
         [super otherMouseDown:event];
         return;
     }
index 097140c71f41c7c12eedf078f01897eb40363cef..f460e52a97c3ff762d321bec13a413bbd665f7b1 100644 (file)
@@ -1,3 +1,18 @@
+2015-04-08  Brent Fulgham  <bfulgham@apple.com>
+
+        [Mac] WebKit is not honoring OS preferences for secondary click behaviors
+        https://bugs.webkit.org/show_bug.cgi?id=143452
+        <rdar://problem/20437483>
+
+        Reviewed by Tim Horton.
+
+        We cannot rely on the event's button number to decide behavior. The OS settings might have
+        mapped middle button to context menu, etc. Instead, we should ask the OS (via NSMenu) what
+        the proper button press behavior is.
+
+        * Shared/mac/WebEventFactory.mm:
+        (WebKit::mouseButtonForEvent): Ask NSMenu what kind of button press we have received.
+
 2015-04-08  Brady Eidson  <beidson@apple.com>
 
         Expose the "Share" menu for links, images, and media.
index 705ed5e04ecbfb332b89a831f8ee21104a392366..ada49a7b607aa6a89e32836046222f478c893018 100644 (file)
@@ -124,7 +124,7 @@ public:
     WebMouseEvent();
 
 #if PLATFORM(MAC)
-    WebMouseEvent(Type, Button, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, Modifiers, double timestamp, int eventNumber = -1);
+    WebMouseEvent(Type, Button, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, Modifiers, double timestamp, int eventNumber = -1, int menuType = 0);
 #else
     WebMouseEvent(Type, Button, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, Modifiers, double timestamp);
 #endif
@@ -138,6 +138,7 @@ public:
     int32_t clickCount() const { return m_clickCount; }
 #if PLATFORM(MAC)
     int32_t eventNumber() const { return m_eventNumber; }
+    int32_t menuTypeForEvent() const { return m_menuTypeForEvent; }
 #endif
 
     void encode(IPC::ArgumentEncoder&) const;
@@ -155,6 +156,7 @@ private:
     int32_t m_clickCount;
 #if PLATFORM(MAC)
     int32_t m_eventNumber;
+    int32_t m_menuTypeForEvent;
 #endif
 };
 
index 329287cb918984ad191ba5c3857f68bd47bcbf43..422e0c7391e2d9d42603b2e9dc9cc4e9fd0566a1 100644 (file)
@@ -84,6 +84,7 @@ public:
         m_clickCount = webEvent.clickCount();
 #if PLATFORM(MAC)
         m_eventNumber = webEvent.eventNumber();
+        m_menuTypeForEvent = webEvent.menuTypeForEvent();
 #endif
 
         m_modifierFlags = 0;
index b599fbce9be1c175fdc72bb3f9a9f95eab3b4b66..791f709dbc448ad549be778658be3ae0f01ca1f2 100644 (file)
@@ -42,12 +42,13 @@ WebMouseEvent::WebMouseEvent()
     , m_clickCount(0)
 #if PLATFORM(MAC)
     , m_eventNumber(-1)
+    , m_menuTypeForEvent(0)
 #endif
 {
 }
 
 #if PLATFORM(MAC)
-WebMouseEvent::WebMouseEvent(Type type, Button button, const IntPoint& position, const IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, Modifiers modifiers, double timestamp, int eventNumber)
+WebMouseEvent::WebMouseEvent(Type type, Button button, const IntPoint& position, const IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, Modifiers modifiers, double timestamp, int eventNumber, int menuType)
 #else
 WebMouseEvent::WebMouseEvent(Type type, Button button, const IntPoint& position, const IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, Modifiers modifiers, double timestamp)
 #endif
@@ -61,6 +62,7 @@ WebMouseEvent::WebMouseEvent(Type type, Button button, const IntPoint& position,
     , m_clickCount(clickCount)
 #if PLATFORM(MAC)
     , m_eventNumber(eventNumber)
+    , m_menuTypeForEvent(menuType)
 #endif
 {
     ASSERT(isMouseEventType(type));
@@ -79,6 +81,7 @@ void WebMouseEvent::encode(IPC::ArgumentEncoder& encoder) const
     encoder << m_clickCount;
 #if PLATFORM(MAC)
     encoder << m_eventNumber;
+    encoder << m_menuTypeForEvent;
 #endif
 }
 
@@ -104,6 +107,8 @@ bool WebMouseEvent::decode(IPC::ArgumentDecoder& decoder, WebMouseEvent& result)
 #if PLATFORM(MAC)
     if (!decoder.decode(result.m_eventNumber))
         return false;
+    if (!decoder.decode(result.m_menuTypeForEvent))
+        return false;
 #endif
 
     return true;
index df16fc65c10817e5d049c96535b38ec7199c75a9..71b93fc9f29c2b832e6c259c6cb095efe44eb47d 100644 (file)
 
 #import "WebEvent.h"
 
+#if USE(APPKIT)
+namespace WebCore {
+class PlatformMouseEvent;
+}
+#endif
+
 namespace WebKit {
 
 // FIXME: This is not needed in the WebProcess and should be moved to be a peer
@@ -39,6 +45,7 @@ public:
     static WebMouseEvent createWebMouseEvent(NSEvent *, NSView *windowView);
     static WebWheelEvent createWebWheelEvent(NSEvent *, NSView *windowView);
     static WebKeyboardEvent createWebKeyboardEvent(NSEvent *, bool handledByInputMethod, const Vector<WebCore::KeypressCommand>&);
+    static bool shouldBeHandledAsContextClick(const WebCore::PlatformMouseEvent&);
 #endif // USE(APPKIT)
 };
 
index 2b3c5a383cb1f53df8a421926287ee7f0d3dfee3..04fc472ae1ef275f4369b581f6832c62182b9283 100644 (file)
@@ -30,6 +30,7 @@
 
 #import "WebKitSystemInterface.h"
 #import <WebCore/KeyboardEvent.h>
+#import <WebCore/NSMenuSPI.h>
 #import <WebCore/PlatformEventFactoryMac.h>
 #import <WebCore/Scrollbar.h>
 #import <WebCore/WindowsKeyboardCodes.h>
@@ -338,6 +339,25 @@ static inline WebEvent::Modifiers modifiersForEvent(NSEvent *event)
     return (WebEvent::Modifiers)modifiers;
 }
 
+static int typeForEvent(NSEvent *event)
+{
+    if ([NSMenu respondsToSelector:@selector(menuTypeForEvent:)])
+        return static_cast<int>([NSMenu menuTypeForEvent:event]);
+    
+    if (mouseButtonForEvent(event) == WebMouseEvent::RightButton)
+        return static_cast<int>(NSMenuTypeContextMenu);
+    
+    if (mouseButtonForEvent(event) == WebMouseEvent::LeftButton && (modifiersForEvent(event) & NSControlKeyMask))
+        return static_cast<int>(NSMenuTypeContextMenu);
+    
+    return static_cast<int>(NSMenuTypeNone);
+}
+
+bool WebEventFactory::shouldBeHandledAsContextClick(const WebCore::PlatformMouseEvent& event)
+{
+    return (static_cast<NSMenuType>(event.menuTypeForEvent()) == NSMenuTypeContextMenu);
+}
+
 WebMouseEvent WebEventFactory::createWebMouseEvent(NSEvent *event, NSView *windowView)
 {
     NSPoint position = pointForEvent(event, windowView);
@@ -352,8 +372,9 @@ WebMouseEvent WebEventFactory::createWebMouseEvent(NSEvent *event, NSView *windo
     WebEvent::Modifiers modifiers           = modifiersForEvent(event);
     double timestamp                        = eventTimeStampSince1970(event);
     int eventNumber                         = [event eventNumber];
+    int menuTypeForEvent                    = typeForEvent(event);
 
-    return WebMouseEvent(type, button, IntPoint(position), IntPoint(globalPosition), deltaX, deltaY, deltaZ, clickCount, modifiers, timestamp, eventNumber);
+    return WebMouseEvent(type, button, IntPoint(position), IntPoint(globalPosition), deltaX, deltaY, deltaZ, clickCount, modifiers, timestamp, eventNumber, menuTypeForEvent);
 }
 
 WebWheelEvent WebEventFactory::createWebWheelEvent(NSEvent *event, NSView *windowView)
index 5bd73a79e642dc7bc7094ef953a046a24a5bee13..97162637ae4c9a674a306e5dbb84663b937a9f68 100644 (file)
@@ -71,6 +71,7 @@
 #include "WebEditorClient.h"
 #include "WebEvent.h"
 #include "WebEventConversion.h"
+#include "WebEventFactory.h"
 #include "WebFrame.h"
 #include "WebFrameLoaderClient.h"
 #include "WebFullScreenManager.h"
@@ -1822,16 +1823,11 @@ private:
 #if ENABLE(CONTEXT_MENUS)
 static bool isContextClick(const PlatformMouseEvent& event)
 {
-    if (event.button() == WebCore::RightButton)
-        return true;
-
 #if PLATFORM(COCOA)
-    // FIXME: this really should be about OSX-style UI, not about the Mac port
-    if (event.button() == WebCore::LeftButton && event.ctrlKey())
-        return true;
+    return WebEventFactory::shouldBeHandledAsContextClick(event);
+#else
+    return event.button() == WebCore::RightButton;
 #endif
-
-    return false;
 }
 
 static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, WebPage* page)
index 4ca9b4e5f286f89680e7de792d2f766d3dc2e5b0..86f25ec7a79058f33c9b61327c0553c06018b975 100644 (file)
@@ -1,3 +1,34 @@
+2015-04-08  Brent Fulgham  <bfulgham@apple.com>
+
+        [Mac] WebKit is not honoring OS preferences for secondary click behaviors
+        https://bugs.webkit.org/show_bug.cgi?id=143452
+        <rdar://problem/20437483>
+
+        Reviewed by Tim Horton.
+
+        Add a new API test to confirm that Cocoa mouse button press events are properly
+        tagged with the desired menu behavior (i.e., 'None', 'Context', or 'Action'.)
+
+        The WK2 test dispatches mouse down events to a PlatformWebView, and checks with
+        some registered event handlers that the expected button press and context menu
+        events are received.
+
+        The WK1 unit test creates an NSEvent with the desired button press state, and then
+        uses WebCore::PlatformEventFactory::createPlatformMouseEvent to create a WebCore event.
+        We check the resulting PlatformMouseEvent for proper state.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Add new test files.
+        * TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp: Added.
+        (TestWebKitAPI::buildAndPerformTest): Helper function to build/run an individual test.
+        * TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html: Added.
+        * TestWebKitAPI/Tests/mac/MenuTypesForMouseEvents.mm: Added.
+        (TestWebKitAPI::canCallMenuTypeForEvent): Helper function.
+        (TestWebKitAPI::buildAndPerformTest): Helper function to build/run an individual test.
+        * TestWebKitAPI/mac/PlatformWebViewMac.mm:
+        (TestWebKitAPI::PlatformWebView::simulateButtonClick): Added method to support firing
+        mouse down events.
+        * TestWebKitAPI/mac/PlatformWebViewMac.h:
+
 2015-04-08  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         [GTK] Add pango to jhbuild-optional.modules
index 1f658147eb140f22ccfe95899883c8dd21a0ac45..2e11cf7a601e57c9372a89c2f47e05e370e26bf1 100644 (file)
@@ -73,6 +73,9 @@ public:
     void simulateAltKeyPress();
     void simulateRightClick(unsigned x, unsigned y);
     void simulateMouseMove(unsigned x, unsigned y);
+#if PLATFORM(MAC)
+    void simulateButtonClick(WKEventMouseButton, unsigned x, unsigned y, WKEventModifiers);
+#endif
 
 private:
 #if PLATFORM(MAC)
index 0d67b2c6978df5d6834d927798dd237a8a352d09..b5039a2ae8be3a1367803313c41021d77d58bdb4 100644 (file)
@@ -57,6 +57,9 @@
                7673499D1930C5BB00E44DF9 /* StopLoadingDuringDidFailProvisionalLoad_bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7673499A1930182E00E44DF9 /* StopLoadingDuringDidFailProvisionalLoad_bundle.cpp */; };
                76E182DD1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76E182DC1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp */; };
                76E182DF154767E600F1FADD /* auto-submitting-form.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 76E182DE15475A8300F1FADD /* auto-submitting-form.html */; };
+               7A1458FC1AD5C07000E06772 /* mouse-button-listener.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */; };
+               7A5623111AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A5623101AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp */; };
+               7A99D9941AD4A29D00373141 /* MenuTypesForMouseEvents.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A99D9931AD4A29D00373141 /* MenuTypesForMouseEvents.mm */; };
                7AA021BB1AB09EA70052953F /* DateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AA021BA1AB09EA70052953F /* DateMath.cpp */; };
                7AA6A1521AAC0B31002B2ED3 /* WorkQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AA6A1511AAC0B31002B2ED3 /* WorkQueue.cpp */; };
                7C486BA11AA12567003F6F9B /* bundle-file.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7C486BA01AA1254B003F6F9B /* bundle-file.html */; };
                        dstPath = TestWebKitAPI.resources;
                        dstSubfolderSpec = 7;
                        files = (
+                               7A1458FC1AD5C07000E06772 /* mouse-button-listener.html in Copy Resources */,
                                7C486BA11AA12567003F6F9B /* bundle-file.html in Copy Resources */,
                                1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
                                379028B914FAC24C007E6B43 /* acceptsFirstMouse.html in Copy Resources */,
                76E182D91547550100F1FADD /* WillSendSubmitEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillSendSubmitEvent.cpp; sourceTree = "<group>"; };
                76E182DC1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillSendSubmitEvent_Bundle.cpp; sourceTree = "<group>"; };
                76E182DE15475A8300F1FADD /* auto-submitting-form.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "auto-submitting-form.html"; sourceTree = "<group>"; };
+               7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "mouse-button-listener.html"; sourceTree = "<group>"; };
+               7A5623101AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MenuTypesForMouseEvents.cpp; sourceTree = "<group>"; };
+               7A99D9931AD4A29D00373141 /* MenuTypesForMouseEvents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MenuTypesForMouseEvents.mm; sourceTree = "<group>"; };
                7AA021BA1AB09EA70052953F /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; };
                7AA6A1511AAC0B31002B2ED3 /* WorkQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkQueue.cpp; sourceTree = "<group>"; };
                7C486BA01AA1254B003F6F9B /* bundle-file.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "bundle-file.html"; sourceTree = "<group>"; };
                                7C54A4BC1AA11CCA00380F78 /* WKBundleFileHandle.cpp */,
                                7C54A4BF1AA11CE400380F78 /* WKBundleFileHandle_Bundle.cpp */,
                                A1FDFD2E19C288BB005148A4 /* WKImageCreateCGImageCrash.cpp */,
+                               7A5623101AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp */,
                                7C89D2AA1A69B80D003A5FDE /* WKPageConfiguration.cpp */,
                                51E93016156B13E1004C99DF /* WKPageGetScaleFactorNotZero.cpp */,
                                524BBC9C19DF377A002F1AF1 /* WKPageIsPlayingAudio.cpp */,
                BC90977B125571AE00083756 /* Resources */ = {
                        isa = PBXGroup;
                        children = (
+                               7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */,
                                C045F9461385C2F800C0F3CD /* 18-characters.html */,
                                2D950FBF1A230C1E00012434 /* action-menu-targets.html */,
                                93D3D19B17B1A7B000C7C415 /* all-content-in-one-iframe.html */,
                                4BB4160116815B2600824238 /* JSWrapperForNodeInWebFrame.mm */,
                                E1220D9F155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm */,
                                517E7DFB15110EA600D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.mm */,
+                               7A99D9931AD4A29D00373141 /* MenuTypesForMouseEvents.mm */,
                                A57A34EF16AF677200C2501F /* PageVisibilityStateWithWindowChanges.mm */,
                                00BC16851680FE810065F1E5 /* PublicSuffix.mm */,
                                37C784DE197C8F2E0010A496 /* RenderedImageFromDOMNode.mm */,
                                2E7765CD16C4D80A00BA2BB1 /* mainIOS.mm in Sources */,
                                7AA6A1521AAC0B31002B2ED3 /* WorkQueue.cpp in Sources */,
                                2E7765CF16C4D81100BA2BB1 /* mainMac.mm in Sources */,
+                               7A5623111AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp in Sources */,
+                               7A99D9941AD4A29D00373141 /* MenuTypesForMouseEvents.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp
new file mode 100644 (file)
index 0000000..f77a11a
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "JavaScriptTest.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+    didFinishLoad = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+    WKPageLoaderClientV0 loaderClient;
+    memset(&loaderClient, 0, sizeof(loaderClient));
+
+    loaderClient.base.version = 0;
+    loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+    WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+static void buildAndPerformTest(WKEventMouseButton button, WKEventModifiers modifiers, const char* expectedButton, const char* expectedMenuType)
+{
+    WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+    PlatformWebView webView(context.get());
+    setPageLoaderClient(webView.page());
+
+    WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("mouse-button-listener", "html"));
+    WKPageLoadURL(webView.page(), url.get());
+    Util::run(&didFinishLoad);
+
+    didFinishLoad = false;
+
+    webView.simulateButtonClick(button, 10, 10, modifiers);
+
+    EXPECT_JS_EQ(webView.page(), "pressedMouseButton()", expectedButton);
+    EXPECT_JS_EQ(webView.page(), "displayedMenu()", expectedMenuType);
+}
+
+TEST(WebKit2, MenuAndButtonForNormalLeftClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonLeftButton, 0, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForNormalRightClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonRightButton, 0, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForNormalMiddleClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonMiddleButton, 0, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForControlLeftClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersControlKey, "0", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForControlRightClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersControlKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForControlMiddleClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersControlKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftLeftClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersShiftKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftRightClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersShiftKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftMiddleClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersShiftKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandLeftClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersMetaKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandRightClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersMetaKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandMiddleClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersMetaKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForAltLeftClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersAltKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForAltRightClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersAltKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForAltMiddleClick)
+{
+    buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersAltKey, "1", "none");
+}
+    
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html
new file mode 100644 (file)
index 0000000..1fdbb1a
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<script>
+    var mouseButton = -1;
+    var menuType = "none";
+
+    function mouseDownHandler(event)
+    {
+        mouseButton = event.button;
+        event.preventDefault();
+    }
+    
+    function pressedMouseButton()
+    {
+        return mouseButton;
+    }
+    function contextMenuHandler(event)
+    {
+        menuType = "context";
+        event.preventDefault();
+    }
+  
+    function displayedMenu()
+    {
+        return menuType;
+    }
+
+    addEventListener("mousedown", mouseDownHandler);
+    addEventListener("contextmenu", contextMenuHandler);
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/mac/MenuTypesForMouseEvents.mm b/Tools/TestWebKitAPI/Tests/mac/MenuTypesForMouseEvents.mm
new file mode 100644 (file)
index 0000000..03f0f74
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "PlatformUtilities.h"
+#import <Carbon/Carbon.h> // For GetCurrentEventTime
+#import <WebCore/NSMenuSPI.h>
+#import <WebCore/PlatformEventFactoryMac.h>
+#import <wtf/AutodrainedPool.h>
+#import <wtf/RetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool canCallMenuTypeForEvent()
+{
+    return [NSMenu respondsToSelector:@selector(menuTypeForEvent:)];
+}
+
+static void buildAndPerformTest(NSEventType buttonEvent, NSEventModifierFlags modifierFlags, WebCore::MouseButton expectedButton, NSMenuType expectedMenu)
+{
+    AutodrainedPool pool;
+    RetainPtr<WebView> webView = adoptNS([[WebView alloc] init]);
+    NSEvent *event = [NSEvent mouseEventWithType:buttonEvent
+                                        location:NSMakePoint(100, 100)
+                                   modifierFlags:modifierFlags
+                                       timestamp:GetCurrentEventTime()
+                                    windowNumber:[[webView window] windowNumber]
+                                         context:[NSGraphicsContext currentContext]
+                                     eventNumber:0
+                                      clickCount:0
+                                        pressure:0];
+    
+    auto pme = WebCore::PlatformEventFactory::createPlatformMouseEvent(event, webView.get());
+    
+    EXPECT_EQ(expectedButton, pme.button());
+    EXPECT_TRUE(!modifierFlags || pme.modifierFlags() & modifierFlags);
+    EXPECT_EQ(expectedMenu, pme.menuTypeForEvent());
+    if (canCallMenuTypeForEvent())
+        EXPECT_EQ(expectedMenu, [NSMenu menuTypeForEvent:event]);
+}
+
+TEST(WebKit1, MenuAndButtonForNormalLeftClick)
+{
+    buildAndPerformTest(NSLeftMouseDown, 0, WebCore::LeftButton, NSMenuTypeNone);
+}
+
+TEST(WebKit1, MenuAndButtonForNormalRightClick)
+{
+    buildAndPerformTest(NSRightMouseDown, 0, WebCore::RightButton, NSMenuTypeContextMenu);
+}
+
+TEST(WebKit1, MenuAndButtonForNormalMiddleClick)
+{
+    buildAndPerformTest(NSOtherMouseDown, 0, WebCore::MiddleButton, NSMenuTypeNone);
+}
+
+TEST(WebKit1, MenuAndButtonForControlLeftClick)
+{
+    buildAndPerformTest(NSLeftMouseDown, NSControlKeyMask, WebCore::LeftButton, NSMenuTypeContextMenu);
+}
+
+TEST(WebKit1, MenuAndButtonForControlRightClick)
+{
+    buildAndPerformTest(NSRightMouseDown, NSControlKeyMask, WebCore::RightButton, NSMenuTypeContextMenu);
+}
+
+TEST(WebKit1, MenuAndButtonForControlMiddleClick)
+{
+    buildAndPerformTest(NSOtherMouseDown, NSControlKeyMask, WebCore::MiddleButton, NSMenuTypeNone);
+}
+    
+TEST(WebKit1, MenuAndButtonForShiftLeftClick)
+{
+    buildAndPerformTest(NSLeftMouseDown, NSShiftKeyMask, WebCore::LeftButton, NSMenuTypeNone);
+}
+
+TEST(WebKit1, MenuAndButtonForShiftRightClick)
+{
+    buildAndPerformTest(NSRightMouseDown, NSShiftKeyMask, WebCore::RightButton, NSMenuTypeContextMenu);
+}
+
+TEST(WebKit1, MenuAndButtonForShiftMiddleClick)
+{
+    buildAndPerformTest(NSOtherMouseDown, NSShiftKeyMask, WebCore::MiddleButton, NSMenuTypeNone);
+}
+
+TEST(WebKit1, MenuAndButtonForCommandLeftClick)
+{
+    buildAndPerformTest(NSLeftMouseDown, NSCommandKeyMask, WebCore::LeftButton, NSMenuTypeNone);
+}
+
+TEST(WebKit1, MenuAndButtonForCommandRightClick)
+{
+    buildAndPerformTest(NSRightMouseDown, NSCommandKeyMask, WebCore::RightButton, NSMenuTypeContextMenu);
+}
+
+TEST(WebKit1, MenuAndButtonForCommandMiddleClick)
+{
+    buildAndPerformTest(NSOtherMouseDown, NSCommandKeyMask, WebCore::MiddleButton, NSMenuTypeNone);
+}
+
+TEST(WebKit1, MenuAndButtonForAltLeftClick)
+{
+    buildAndPerformTest(NSLeftMouseDown, NSAlternateKeyMask, WebCore::LeftButton, NSMenuTypeNone);
+}
+
+TEST(WebKit1, MenuAndButtonForAltRightClick)
+{
+    buildAndPerformTest(NSRightMouseDown, NSAlternateKeyMask, WebCore::RightButton, NSMenuTypeContextMenu);
+}
+
+TEST(WebKit1, MenuAndButtonForAltMiddleClick)
+{
+    buildAndPerformTest(NSOtherMouseDown, NSAlternateKeyMask, WebCore::MiddleButton, NSMenuTypeNone);
+}
+
+
+} // namespace TestWebKitAPI
index 0bcbb14157d89afe0308fe65f3416e70315b9db9..3159cecb4a09c776ce32c3d7015a6b5ffb685ce6 100644 (file)
@@ -193,4 +193,50 @@ void PlatformWebView::simulateMouseMove(unsigned x, unsigned y)
     
 }
 
+static NSEventType eventTypeForButton(WKEventMouseButton button)
+{
+    switch (button) {
+    case kWKEventMouseButtonLeftButton:
+        return NSLeftMouseDown;
+    case kWKEventMouseButtonRightButton:
+        return NSRightMouseDown;
+    case kWKEventMouseButtonMiddleButton:
+        return NSOtherMouseDown;
+    case kWKEventMouseButtonNoButton:
+        return NSLeftMouseDown;
+    }
+
+    return NSLeftMouseDown;
+}
+
+static NSEventModifierFlags modifierFlagsForWKModifiers(WKEventModifiers modifiers)
+{
+    NSEventModifierFlags returnVal = 0;
+    if (modifiers & kWKEventModifiersShiftKey)
+        returnVal |= NSShiftKeyMask;
+    if (modifiers & kWKEventModifiersControlKey)
+        returnVal |= NSControlKeyMask;
+    if (modifiers & kWKEventModifiersAltKey)
+        returnVal |= NSAlternateKeyMask;
+    if (modifiers & kWKEventModifiersMetaKey)
+        returnVal |= NSCommandKeyMask;
+
+    return returnVal;
+}
+    
+void PlatformWebView::simulateButtonClick(WKEventMouseButton button, unsigned x, unsigned y, WKEventModifiers modifiers)
+{
+    NSEvent *event = [NSEvent mouseEventWithType:eventTypeForButton(button)
+                                        location:NSMakePoint(x, y)
+                                   modifierFlags:modifierFlagsForWKModifiers(modifiers)
+                                       timestamp:GetCurrentEventTime()
+                                    windowNumber:[m_window windowNumber]
+                                         context:[NSGraphicsContext currentContext]
+                                     eventNumber:0
+                                      clickCount:0
+                                        pressure:0];
+
+    [m_view mouseDown:event];
+}
+
 } // namespace TestWebKitAPI