Make image controls menu work in WK2
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Mar 2014 23:54:30 +0000 (23:54 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Mar 2014 23:54:30 +0000 (23:54 +0000)
<rdar://problem/16294412> and https://bugs.webkit.org/show_bug.cgi?id=130424

Reviewed by Tim Horton.

* Platform/SharedMemory.h:
* Platform/mac/SharedMemoryMac.cpp:
(WebKit::SharedMemory::Handle::~Handle):
(WebKit::SharedMemory::Handle::clear):

* Platform/unix/SharedMemoryUnix.cpp:
(WebKit::SharedMemory::Handle::~Handle):
(WebKit::SharedMemory::Handle::clear):

* Shared/ContextMenuContextData.cpp:
(WebKit::ContextMenuContextData::ContextMenuContextData):
(WebKit::ContextMenuContextData::operator=):
(WebKit::ContextMenuContextData::encode):
(WebKit::ContextMenuContextData::decode):
* Shared/ContextMenuContextData.h:
(WebKit::ContextMenuContextData::controlledImageHandle):

* Shared/ShareableBitmap.cpp:
(WebKit::ShareableBitmap::Handle::clear):
* Shared/ShareableBitmap.h:
* UIProcess/WebContextMenuProxy.h:

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::internalShowContextMenu):
(WebKit::WebPageProxy::replaceControlledImage):
* UIProcess/WebPageProxy.h:

* UIProcess/efl/WebContextMenuProxyEfl.cpp:
(WebKit::WebContextMenuProxyEfl::showContextMenu):
* UIProcess/efl/WebContextMenuProxyEfl.h:

* UIProcess/gtk/WebContextMenuProxyGtk.cpp:
(WebKit::WebContextMenuProxyGtk::showContextMenu):
* UIProcess/gtk/WebContextMenuProxyGtk.h:

Add a sharing service context menu that lives side-by-side with the normal one:
* UIProcess/mac/WebContextMenuProxyMac.h:
* UIProcess/mac/WebContextMenuProxyMac.mm:
(+[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate]):
(-[WKSharingServicePickerDelegate setMenuProxy:WebKit::]):
(-[WKSharingServicePickerDelegate setPicker:]):
(-[WKSharingServicePickerDelegate sharingServicePicker:delegateForSharingService:]):
(-[WKSharingServicePickerDelegate sharingService:willShareItems:]):
(-[WKSharingServicePickerDelegate sharingService:didShareItems:]):
(-[WKSharingServicePickerDelegate sharingService:sourceFrameOnScreenForShareItem:]):
(-[WKSharingServicePickerDelegate sharingService:transitionImageForShareItem:contentRect:]):
(-[WKSharingServicePickerDelegate sharingService:sourceWindowForShareItems:sharingContentScope:]):
(WebKit::WebContextMenuProxyMac::contextMenuItemSelected):
(WebKit::WebContextMenuProxyMac::setupImageServicesMenu):
(WebKit::WebContextMenuProxyMac::clearImageServicesMenu):
(WebKit::WebContextMenuProxyMac::populate):
(WebKit::WebContextMenuProxyMac::showContextMenu):
(WebKit::WebContextMenuProxyMac::window):
(WebKit::WebContextMenuProxyMac::replaceControlledImage):

* WebProcess/WebPage/WebContextMenu.cpp:
(WebKit::WebContextMenu::show):
(WebKit::WebContextMenu::replaceControlledImage):
* WebProcess/WebPage/WebContextMenu.h:

Teach the WebProcess how to accept the replaced image.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::replaceControlledImage):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

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

22 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/Platform/SharedMemory.h
Source/WebKit2/Platform/mac/SharedMemoryMac.cpp
Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp
Source/WebKit2/Shared/ContextMenuContextData.cpp
Source/WebKit2/Shared/ContextMenuContextData.h
Source/WebKit2/Shared/ShareableBitmap.cpp
Source/WebKit2/Shared/ShareableBitmap.h
Source/WebKit2/UIProcess/WebContextMenuProxy.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/efl/WebContextMenuProxyEfl.cpp
Source/WebKit2/UIProcess/efl/WebContextMenuProxyEfl.h
Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.cpp
Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.h
Source/WebKit2/UIProcess/mac/WebContextMenuProxyMac.h
Source/WebKit2/UIProcess/mac/WebContextMenuProxyMac.mm
Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp
Source/WebKit2/WebProcess/WebPage/WebContextMenu.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in

index 782d059..2d56c59 100644 (file)
@@ -1,3 +1,76 @@
+2014-03-18  Brady Eidson  <beidson@apple.com>
+
+        Make image controls menu work in WK2
+        <rdar://problem/16294412> and https://bugs.webkit.org/show_bug.cgi?id=130424
+
+        Reviewed by Tim Horton.
+
+        * Platform/SharedMemory.h:
+        * Platform/mac/SharedMemoryMac.cpp:
+        (WebKit::SharedMemory::Handle::~Handle):
+        (WebKit::SharedMemory::Handle::clear):
+
+        * Platform/unix/SharedMemoryUnix.cpp:
+        (WebKit::SharedMemory::Handle::~Handle):
+        (WebKit::SharedMemory::Handle::clear):
+
+        * Shared/ContextMenuContextData.cpp:
+        (WebKit::ContextMenuContextData::ContextMenuContextData):
+        (WebKit::ContextMenuContextData::operator=):
+        (WebKit::ContextMenuContextData::encode):
+        (WebKit::ContextMenuContextData::decode):
+        * Shared/ContextMenuContextData.h:
+        (WebKit::ContextMenuContextData::controlledImageHandle):
+
+        * Shared/ShareableBitmap.cpp:
+        (WebKit::ShareableBitmap::Handle::clear):
+        * Shared/ShareableBitmap.h:
+        * UIProcess/WebContextMenuProxy.h:
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::internalShowContextMenu):
+        (WebKit::WebPageProxy::replaceControlledImage):
+        * UIProcess/WebPageProxy.h:
+
+        * UIProcess/efl/WebContextMenuProxyEfl.cpp:
+        (WebKit::WebContextMenuProxyEfl::showContextMenu):
+        * UIProcess/efl/WebContextMenuProxyEfl.h:
+
+        * UIProcess/gtk/WebContextMenuProxyGtk.cpp:
+        (WebKit::WebContextMenuProxyGtk::showContextMenu):
+        * UIProcess/gtk/WebContextMenuProxyGtk.h:
+
+        Add a sharing service context menu that lives side-by-side with the normal one:
+        * UIProcess/mac/WebContextMenuProxyMac.h:
+        * UIProcess/mac/WebContextMenuProxyMac.mm:
+        (+[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate]):
+        (-[WKSharingServicePickerDelegate setMenuProxy:WebKit::]):
+        (-[WKSharingServicePickerDelegate setPicker:]):
+        (-[WKSharingServicePickerDelegate sharingServicePicker:delegateForSharingService:]):
+        (-[WKSharingServicePickerDelegate sharingService:willShareItems:]):
+        (-[WKSharingServicePickerDelegate sharingService:didShareItems:]):
+        (-[WKSharingServicePickerDelegate sharingService:sourceFrameOnScreenForShareItem:]):
+        (-[WKSharingServicePickerDelegate sharingService:transitionImageForShareItem:contentRect:]):
+        (-[WKSharingServicePickerDelegate sharingService:sourceWindowForShareItems:sharingContentScope:]):
+        (WebKit::WebContextMenuProxyMac::contextMenuItemSelected):
+        (WebKit::WebContextMenuProxyMac::setupImageServicesMenu):
+        (WebKit::WebContextMenuProxyMac::clearImageServicesMenu):
+        (WebKit::WebContextMenuProxyMac::populate):
+        (WebKit::WebContextMenuProxyMac::showContextMenu):
+        (WebKit::WebContextMenuProxyMac::window):
+        (WebKit::WebContextMenuProxyMac::replaceControlledImage):
+
+        * WebProcess/WebPage/WebContextMenu.cpp:
+        (WebKit::WebContextMenu::show):
+        (WebKit::WebContextMenu::replaceControlledImage):
+        * WebProcess/WebPage/WebContextMenu.h:
+
+        Teach the WebProcess how to accept the replaced image.
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::replaceControlledImage):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2014-03-18  Anders Carlsson  <andersca@apple.com>
 
         Begin cleaning up KeyedDecoder and KeyedEncoder
index efa5f00..9e25d08 100644 (file)
@@ -57,6 +57,8 @@ public:
 
         bool isNull() const;
 
+        void clear();
+
         void encode(IPC::ArgumentEncoder&) const;
         static bool decode(IPC::ArgumentDecoder&, Handle&);
 
index 46a43f3..c774a27 100644 (file)
@@ -46,8 +46,7 @@ SharedMemory::Handle::Handle()
 
 SharedMemory::Handle::~Handle()
 {
-    if (m_port)
-        mach_port_deallocate(mach_task_self(), m_port);
+    clear();
 }
 
 bool SharedMemory::Handle::isNull() const
@@ -55,6 +54,15 @@ bool SharedMemory::Handle::isNull() const
     return !m_port;
 }
 
+void SharedMemory::Handle::clear()
+{
+    if (m_port)
+        mach_port_deallocate(mach_task_self(), m_port);
+
+    m_port = MACH_PORT_NULL;
+    m_size = 0;
+}
+
 void SharedMemory::Handle::encode(IPC::ArgumentEncoder& encoder) const
 {
     encoder << static_cast<uint64_t>(m_size);
index f1392cd..7781806 100644 (file)
@@ -54,6 +54,11 @@ SharedMemory::Handle::Handle()
 
 SharedMemory::Handle::~Handle()
 {
+    clear();
+}
+
+void SharedMemory::Handle::clear()
+{
     if (!isNull())
         closeWithRetry(m_fileDescriptor);
 }
index d6faad6..dcf73eb 100644 (file)
 
 #include "WebCoreArgumentCoders.h"
 #include <WebCore/ContextMenuContext.h>
+#include <WebCore/GraphicsContext.h>
 
 using namespace WebCore;
 
 namespace WebKit {
 
 ContextMenuContextData::ContextMenuContextData()
-#if ENABLE(IMAGE_CONTROLS)
-    : m_isImageControl(false)
-#endif
 {
 }
 
 ContextMenuContextData::ContextMenuContextData(const ContextMenuContext& context)
     : m_webHitTestResultData(WebHitTestResult::Data(context.hitTestResult()))
+{
 #if ENABLE(IMAGE_CONTROLS)
-    , m_isImageControl(context.controlledImage())
+    Image* image = context.controlledImage();
+    if (!image)
+        return;
+
+    RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(image->size(), ShareableBitmap::SupportsAlpha);
+    bitmap->createGraphicsContext()->drawImage(image, ColorSpaceDeviceRGB, IntPoint());
+    bitmap->createHandle(m_controlledImageHandle);
 #endif
+}
+
+ContextMenuContextData::ContextMenuContextData(const ContextMenuContextData& other)
 {
+    *this = other;
+}
+
+ContextMenuContextData& ContextMenuContextData::operator=(const ContextMenuContextData& other)
+{
+    m_webHitTestResultData = other.m_webHitTestResultData;
+#if ENABLE(IMAGE_CONTROLS)
+    m_controlledImageHandle.clear();
+
+    if (!other.m_controlledImageHandle.isNull()) {
+        RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(other.m_controlledImageHandle);
+        bitmap->createHandle(m_controlledImageHandle);
+    }
+#endif
+
+    return *this;
 }
 
 void ContextMenuContextData::encode(IPC::ArgumentEncoder& encoder) const
 {
     encoder << m_webHitTestResultData;
 #if ENABLE(IMAGE_CONTROLS)
-    encoder << m_isImageControl;
+    encoder << m_controlledImageHandle;
 #endif
 }
 
@@ -65,7 +89,7 @@ bool ContextMenuContextData::decode(IPC::ArgumentDecoder& decoder, ContextMenuCo
         return false;
         
 #if ENABLE(IMAGE_CONTROLS)
-    if (!decoder.decode(contextMenuContextData.m_isImageControl))
+    if (!decoder.decode(contextMenuContextData.m_controlledImageHandle))
         return false;
 #endif
 
index 8949339..6c6ae89 100644 (file)
@@ -29,6 +29,7 @@
 
 #if ENABLE(CONTEXT_MENUS)
 
+#include "ShareableBitmap.h"
 #include "WebHitTestResult.h"
 
 namespace IPC {
@@ -46,11 +47,14 @@ class ContextMenuContextData {
 public:
     ContextMenuContextData();
     ContextMenuContextData(const WebCore::ContextMenuContext&);
+
+    ContextMenuContextData(const ContextMenuContextData&);
+    ContextMenuContextData& operator=(const ContextMenuContextData&);
     
     const WebHitTestResult::Data& webHitTestResultData() const { return m_webHitTestResultData; }
 
 #if ENABLE(IMAGE_CONTROLS)
-    bool isImageControl() const { return m_isImageControl; }
+    const ShareableBitmap::Handle& controlledImageHandle() const { return m_controlledImageHandle; }
 #endif
 
     void encode(IPC::ArgumentEncoder&) const;
@@ -61,7 +65,7 @@ private:
     WebHitTestResult::Data m_webHitTestResultData;
 
 #if ENABLE(IMAGE_CONTROLS)
-    bool m_isImageControl;
+    ShareableBitmap::Handle m_controlledImageHandle;
 #endif
 };
 
index 9eb4759..2a28ca5 100644 (file)
@@ -57,6 +57,13 @@ bool ShareableBitmap::Handle::decode(IPC::ArgumentDecoder& decoder, Handle& hand
     return true;
 }
 
+void ShareableBitmap::Handle::clear()
+{
+    m_handle.clear();
+    m_size = IntSize();
+    m_flags = Flag::NoFlags;
+}
+
 PassRefPtr<ShareableBitmap> ShareableBitmap::create(const IntSize& size, Flags flags)
 {
     size_t numBytes = numBytesForSize(size);
index 47161f0..a196db6 100644 (file)
@@ -63,6 +63,8 @@ public:
 
         bool isNull() const { return m_handle.isNull(); }
 
+        void clear();
+
         void encode(IPC::ArgumentEncoder&) const;
         static bool decode(IPC::ArgumentDecoder&, Handle&);
 
index 098552d..5546e5a 100644 (file)
@@ -36,13 +36,14 @@ namespace WebCore {
 
 namespace WebKit {
 
+class ContextMenuContextData;
 class WebContextMenuItemData;
 
 class WebContextMenuProxy : public RefCounted<WebContextMenuProxy> {
 public:
     virtual ~WebContextMenuProxy();
 
-    virtual void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>& items) = 0;
+    virtual void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&, const ContextMenuContextData&) = 0;
     virtual void hideContextMenu() = 0;
 
 protected:
index 0560ae3..da6bfd7 100644 (file)
@@ -3309,22 +3309,32 @@ void WebPageProxy::internalShowContextMenu(const IntPoint& menuLocation, const C
     // Unless this is an image control, give the PageContextMenuClient one last swipe at changing the menu.
     Vector<WebContextMenuItemData> items;
     bool useProposedItems = true;
-
+    bool askClientToChangeMenu = true;
 #if ENABLE(IMAGE_CONTROLS)
-    if (!contextMenuContextData.isImageControl() && m_contextMenuClient.getContextMenuFromProposedMenu(this, proposedItems, items, contextMenuContextData.webHitTestResultData(), userData.get())) {
-#else
-    if (m_contextMenuClient.getContextMenuFromProposedMenu(this, proposedItems, items, contextMenuContextData.webHitTestResultData(), userData.get())) {
+    if (!contextMenuContextData.controlledImageHandle().isNull())
+        askClientToChangeMenu = false;
 #endif
+
+    if (askClientToChangeMenu && m_contextMenuClient.getContextMenuFromProposedMenu(this, proposedItems, items, contextMenuContextData.webHitTestResultData(), userData.get()))
         useProposedItems = false;
-    }
     
     const Vector<WebContextMenuItemData>& itemsToShow = useProposedItems ? proposedItems : items;
     if (!m_contextMenuClient.showContextMenu(this, menuLocation, itemsToShow))
-        m_activeContextMenu->showContextMenu(menuLocation, itemsToShow);
-    
+        m_activeContextMenu->showContextMenu(menuLocation, itemsToShow, contextMenuContextData);
+
     m_contextMenuClient.contextMenuDismissed(this);
 }
 
+#if ENABLE(IMAGE_CONTROLS)
+void WebPageProxy::replaceControlledImage(PassRefPtr<ShareableBitmap> newBitmap)
+{
+    RefPtr<ShareableBitmap> bitmap = newBitmap;
+    ShareableBitmap::Handle bitmapHandle;
+    bitmap->createHandle(bitmapHandle);
+    m_process->send(Messages::WebPage::ReplaceControlledImage(bitmapHandle), m_pageID);
+}
+#endif
+
 void WebPageProxy::contextMenuItemSelected(const WebContextMenuItemData& item)
 {
     // Application custom items don't need to round-trip through to WebCore in the WebProcess.
index 350f51c..9830e79 100644 (file)
@@ -925,6 +925,10 @@ public:
 
     void takeThumbnailSnapshot(ImageCallback::CallbackFunction);
 
+#if ENABLE(IMAGE_CONTROLS)
+    void replaceControlledImage(PassRefPtr<ShareableBitmap>);
+#endif
+
 private:
     WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, const WebPageConfiguration&);
     void platformInitialize();
index 830d919..2de883f 100644 (file)
@@ -47,7 +47,7 @@ WebContextMenuProxyEfl::~WebContextMenuProxyEfl()
 {
 }
 
-void WebContextMenuProxyEfl::showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&)
+void WebContextMenuProxyEfl::showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&, const ContextMenuContextData&)
 {
     notImplemented();
 }
index b74a54f..29182bf 100644 (file)
@@ -48,7 +48,7 @@ public:
 
     ~WebContextMenuProxyEfl();
 
-    void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&);
+    void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&, const ContextMenuContextData&);
     void hideContextMenu();
 
 private:
index 19a6977..0adc766 100644 (file)
@@ -138,7 +138,7 @@ void WebContextMenuProxyGtk::populate(const Vector<WebContextMenuItemData>& item
     }
 }
 
-void WebContextMenuProxyGtk::showContextMenu(const WebCore::IntPoint& position, const Vector<WebContextMenuItemData>& items)
+void WebContextMenuProxyGtk::showContextMenu(const WebCore::IntPoint& position, const Vector<WebContextMenuItemData>& items, const ContextMenuContextData&)
 {
     if (!items.isEmpty())
         populate(items);
index ded4b7a..4de398d 100644 (file)
@@ -46,7 +46,7 @@ public:
     }
     ~WebContextMenuProxyGtk();
 
-    virtual void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&);
+    virtual void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&, const ContextMenuContextData&);
     virtual void hideContextMenu();
 
     void populate(Vector<WebCore::ContextMenuItem>&);
index 4faa3ed..5ba9bb4 100644 (file)
 #include <wtf/RetainPtr.h>
 
 OBJC_CLASS NSPopUpButtonCell;
+OBJC_CLASS NSWindow;
 OBJC_CLASS WKView;
 
 namespace WebKit {
 
+class ShareableBitmap;
 class WebPageProxy;
 
 class WebContextMenuProxyMac : public WebContextMenuProxy {
@@ -46,17 +48,31 @@ public:
     }
     ~WebContextMenuProxyMac();
 
-    virtual void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&);
-    virtual void hideContextMenu();
+    virtual void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&, const ContextMenuContextData&) override;
+    virtual void hideContextMenu() override;
     
     void contextMenuItemSelected(const WebContextMenuItemData&);
 
+#if ENABLE(IMAGE_CONTROLS)
+    void clearImageServicesMenu();
+    void replaceControlledImage(CGImageRef newImage);
+#endif
+
+    NSWindow *window() const;
+
 private:
     WebContextMenuProxyMac(WKView*, WebPageProxy*);
 
-    void populate(const Vector<WebContextMenuItemData>&);
+    void populate(const Vector<WebContextMenuItemData>&, const ContextMenuContextData&);
+
+#if ENABLE(IMAGE_CONTROLS)
+    void setupImageServicesMenu(ShareableBitmap&);
+#endif
 
     RetainPtr<NSPopUpButtonCell> m_popup;
+#if ENABLE(IMAGE_CONTROLS)
+    RetainPtr<NSMenu> m_servicesMenu;
+#endif
     WKView* m_webView;
     WebPageProxy* m_page;
 };
index 9bb360c..86eb4c3 100644 (file)
 #if PLATFORM(MAC)
 
 #import "PageClientImpl.h"
+#import "ShareableBitmap.h"
 #import "StringUtilities.h"
 #import "WebContextMenuItemData.h"
 #import "WKView.h"
+#import <WebCore/GraphicsContext.h>
 #import <WebCore/IntRect.h>
+#import <WebCore/NotImplemented.h>
 #import <WebKitSystemInterface.h>
+#import <wtf/RetainPtr.h>
+
+#if ENABLE(IMAGE_CONTROLS)
+#import <AppKit/NSSharingService.h>
+
+#if __has_include(<AppKit/NSSharingService_Private.h>)
+#import <AppKit/NSSharingService_Private.h>
+#else
+typedef enum {
+    NSSharingServicePickerStyleMenu = 0,
+    NSSharingServicePickerStyleRollover = 1,
+    NSSharingServicePickerStyleTextSelection = 2
+} NSSharingServicePickerStyle;
+#endif
+
+@interface NSSharingServicePicker (Details)
+@property NSSharingServicePickerStyle style;
+- (NSMenu *)menu;
+@end
+#endif
 
 using namespace WebCore;
 
@@ -66,7 +89,7 @@ using namespace WebCore;
 @interface WKMenuTarget : NSObject {
     WebKit::WebContextMenuProxyMac* _menuProxy;
 }
-+ (WKMenuTarget*)sharedMenuTarget;
++ (WKMenuTarget *)sharedMenuTarget;
 - (WebKit::WebContextMenuProxyMac*)menuProxy;
 - (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy;
 - (void)forwardContextMenuAction:(id)sender;
@@ -104,6 +127,67 @@ using namespace WebCore;
 
 @end
 
+#if ENABLE(IMAGE_CONTROLS)
+@interface WKSharingServicePickerDelegate : NSObject <NSSharingServiceDelegate, NSSharingServicePickerDelegate> {
+    WebKit::WebContextMenuProxyMac* _menuProxy;
+    RetainPtr<NSSharingServicePicker> _picker;
+}
+
++ (WKSharingServicePickerDelegate *)sharedSharingServicePickerDelegate;
+- (WebKit::WebContextMenuProxyMac*)menuProxy;
+- (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy;
+- (void)setPicker:(NSSharingServicePicker *)picker;
+@end
+
+// FIXME: We probably need to hang on the picker itself until the context menu operation is done, and this object will probably do that.
+@implementation WKSharingServicePickerDelegate
++ (WKSharingServicePickerDelegate*)sharedSharingServicePickerDelegate
+{
+    static WKSharingServicePickerDelegate* delegate = [[WKSharingServicePickerDelegate alloc] init];
+    return delegate;
+}
+
+- (WebKit::WebContextMenuProxyMac*)menuProxy
+{
+    return _menuProxy;
+}
+
+- (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy
+{
+    _menuProxy = menuProxy;
+}
+
+- (void)setPicker:(NSSharingServicePicker *)picker
+{
+    _picker = picker;
+}
+
+- (id <NSSharingServiceDelegate>)sharingServicePicker:(NSSharingServicePicker *)sharingServicePicker delegateForSharingService:(NSSharingService *)sharingService
+{
+    return self;
+}
+
+- (void)sharingService:(NSSharingService *)sharingService willShareItems:(NSArray *)items
+{
+    _menuProxy->clearImageServicesMenu();
+}
+
+- (void)sharingService:(NSSharingService *)sharingService didShareItems:(NSArray *)items
+{
+    RetainPtr<CGImageSourceRef> source = adoptCF(CGImageSourceCreateWithData((CFDataRef)[items objectAtIndex:0], NULL));
+    RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(source.get(), 0, NULL));
+    _menuProxy->replaceControlledImage(image.get());
+}
+
+- (NSWindow *)sharingService:(NSSharingService *)sharingService sourceWindowForShareItems:(NSArray *)items sharingContentScope:(NSSharingContentScope *)sharingContentScope
+{
+    return _menuProxy->window();
+}
+
+@end
+
+#endif
+
 namespace WebKit {
 
 WebContextMenuProxyMac::WebContextMenuProxyMac(WKView* webView, WebPageProxy* page)
@@ -120,6 +204,10 @@ WebContextMenuProxyMac::~WebContextMenuProxyMac()
 
 void WebContextMenuProxyMac::contextMenuItemSelected(const WebContextMenuItemData& item)
 {
+#if ENABLE(IMAGE_CONTROLS)
+    clearImageServicesMenu();
+#endif
+
     m_page->contextMenuItemSelected(item);
 }
 
@@ -185,8 +273,36 @@ static Vector<RetainPtr<NSMenuItem>> nsMenuItemVector(const Vector<WebContextMen
     return result;
 }
 
-void WebContextMenuProxyMac::populate(const Vector<WebContextMenuItemData>& items)
+#if ENABLE(IMAGE_CONTROLS)
+void WebContextMenuProxyMac::setupImageServicesMenu(ShareableBitmap& image)
+{
+    RetainPtr<CGImageRef> cgImage = image.makeCGImage();
+    RetainPtr<NSImage> nsImage = adoptNS([[NSImage alloc] initWithCGImage:cgImage.get() size:image.size()]);
+
+    RetainPtr<NSSharingServicePicker> picker = adoptNS([[NSSharingServicePicker alloc] initWithItems:@[ nsImage.get() ]]);
+    [picker setStyle:NSSharingServicePickerStyleRollover];
+    [picker setDelegate:[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate]];
+    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setPicker:picker.get()];
+
+    m_servicesMenu = [picker menu];
+}
+
+void WebContextMenuProxyMac::clearImageServicesMenu()
 {
+    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setPicker:nullptr];
+    m_servicesMenu = nullptr;
+}
+#endif
+
+void WebContextMenuProxyMac::populate(const Vector<WebContextMenuItemData>& items, const ContextMenuContextData& context)
+{
+#if ENABLE(IMAGE_CONTROLS)
+    if (RefPtr<ShareableBitmap> image = ShareableBitmap::create(context.controlledImageHandle())) {
+        setupImageServicesMenu(*image);
+        return;
+    }
+#endif
+
     if (m_popup)
         [m_popup removeAllItems];
     else {
@@ -199,22 +315,38 @@ void WebContextMenuProxyMac::populate(const Vector<WebContextMenuItemData>& item
     populateNSMenu(menu, nsMenuItemVector(items));
 }
 
-void WebContextMenuProxyMac::showContextMenu(const IntPoint& menuLocation, const Vector<WebContextMenuItemData>& items)
+void WebContextMenuProxyMac::showContextMenu(const IntPoint& menuLocation, const Vector<WebContextMenuItemData>& items, const ContextMenuContextData& context)
 {
+#if ENABLE(IMAGE_CONTROLS)
+    if (items.isEmpty() && context.controlledImageHandle().isNull())
+        return;
+#else
     if (items.isEmpty())
         return;
-    
-    populate(items);
+#endif
+
+    populate(items, context);
+
     [[WKMenuTarget sharedMenuTarget] setMenuProxy:this];
-    
+
     NSRect menuRect = NSMakeRect(menuLocation.x(), menuLocation.y(), 0, 0);
-    
+
+#if ENABLE(IMAGE_CONTROLS)
+    if (!context.controlledImageHandle().isNull())
+        [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setMenuProxy:this];
+
+    if (!m_servicesMenu)
+        [m_popup attachPopUpWithFrame:menuRect inView:m_webView];
+
+    NSMenu *menu = m_servicesMenu ? m_servicesMenu.get() : [m_popup menu];
+#else
     [m_popup attachPopUpWithFrame:menuRect inView:m_webView];
 
-    NSMenu* menu = [m_popup menu];
+    NSMenu *menu = [m_popup menu];
+#endif
 
     // These values were borrowed from AppKit to match their placement of the menu.
-    NSRect titleFrame = [m_popup  titleRectForBounds:menuRect];
+    NSRect titleFrame = [m_popup titleRectForBounds:menuRect];
     if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0)
         titleFrame = menuRect;
     float vertOffset = roundf((NSMaxY(menuRect) - NSMaxY(titleFrame)) + NSHeight(titleFrame));
@@ -228,7 +360,7 @@ void WebContextMenuProxyMac::showContextMenu(const IntPoint& menuLocation, const
 
     WKPopupContextMenu(menu, location);
 
-    [m_popup dismissPopUp];
+    hideContextMenu();
 }
 
 void WebContextMenuProxyMac::hideContextMenu()
@@ -236,6 +368,22 @@ void WebContextMenuProxyMac::hideContextMenu()
     [m_popup dismissPopUp];
 }
 
+NSWindow *WebContextMenuProxyMac::window() const
+{
+    return [m_webView window];
+}
+
+#if ENABLE(IMAGE_CONTROLS)
+void WebContextMenuProxyMac::replaceControlledImage(CGImageRef newImage)
+{
+    FloatSize newImageSize(CGImageGetWidth(newImage), CGImageGetHeight(newImage));
+    RefPtr<ShareableBitmap> newBitmap = ShareableBitmap::createShareable(expandedIntSize(newImageSize), ShareableBitmap::SupportsAlpha);
+    newBitmap->createGraphicsContext()->drawNativeImage(newImage, newImageSize, ColorSpaceDeviceRGB, FloatRect(FloatPoint(), newImageSize), FloatRect(FloatPoint(), newImageSize));
+
+    m_page->replaceControlledImage(newBitmap.release());
+}
+#endif
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)
index b0030dc..48d1e3c 100644 (file)
@@ -54,9 +54,6 @@ WebContextMenu::~WebContextMenu()
 void WebContextMenu::show()
 {
     ContextMenuController& controller = m_page->corePage()->contextMenuController();
-    ContextMenu* menu = controller.contextMenu();
-    if (!menu)
-        return;
     Frame* frame = controller.hitTestResult().innerNodeFrame();
     if (!frame)
         return;
@@ -80,6 +77,13 @@ void WebContextMenu::itemSelected(const WebContextMenuItemData& item)
     m_page->corePage()->contextMenuController().contextMenuItemSelected(&coreItem);
 }
 
+#if ENABLE(IMAGE_CONTROLS)
+void WebContextMenu::replaceControlledImage(PassRefPtr<Image> newImage)
+{
+    m_page->corePage()->contextMenuController().replaceControlledImage(newImage);
+}
+#endif
+
 void WebContextMenu::menuItemsWithUserData(Vector<WebContextMenuItemData> &menuItems, RefPtr<API::Object>& userData) const
 {
     ContextMenuController& controller = m_page->corePage()->contextMenuController();
index 75ed7e6..d9b1883 100644 (file)
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
+namespace WebCore {
+class Image;
+}
+
 namespace WebKit {
 
+class ShareableBitmap;
 class WebPage;
 
 class WebContextMenu : public RefCounted<WebContextMenu> {
@@ -45,6 +50,10 @@ public:
     void itemSelected(const WebContextMenuItemData&);
     Vector<WebContextMenuItemData> items() const;
 
+#if ENABLE(IMAGE_CONTROLS)
+    void replaceControlledImage(PassRefPtr<WebCore::Image>);
+#endif
+
 private:
     WebContextMenu(WebPage*);
     void menuItemsWithUserData(Vector<WebContextMenuItemData>&, RefPtr<API::Object>&) const;
index d80ae35..122ce96 100644 (file)
@@ -3088,6 +3088,15 @@ void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& i
 }
 #endif
 
+#if ENABLE(IMAGE_CONTROLS)
+void WebPage::replaceControlledImage(const ShareableBitmap::Handle& bitmapHandle)
+{
+    RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(bitmapHandle);
+    if (bitmap)
+        m_contextMenu->replaceControlledImage(bitmap->createImage());
+}
+#endif
+
 void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
 {
     bool selectReplacement = true;
index 579da1f..aa8d184 100644 (file)
@@ -742,6 +742,10 @@ public:
 
     void getBytecodeProfile(uint64_t callbackID);
 
+#if ENABLE(IMAGE_CONTROLS)
+    void replaceControlledImage(const ShareableBitmap::Handle&);
+#endif
+
 private:
     WebPage(uint64_t pageID, const WebPageCreationParameters&);
 
index 30b07b2..42f1709 100644 (file)
@@ -343,4 +343,7 @@ messages -> WebPage LegacyReceiver {
     
     TakeThumbnailSnapshot(uint64_t callbackID)
 
+#if ENABLE(IMAGE_CONTROLS)
+    ReplaceControlledImage(WebKit::ShareableBitmap::Handle newBitmapHandle)
+#endif
 }