2
* Copyright (C) 2010 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
* THE POSSIBILITY OF SUCH DAMAGE.
27
#import "WebContextMenuProxyMac.h"
29
#import "PageClientImpl.h"
30
#import "StringUtilities.h"
31
#import "WebContextMenuItemData.h"
34
#import <WebCore/IntRect.h>
35
#import <WebKitSystemInterface.h>
37
using namespace WebCore;
39
@interface WKUserDataWrapper : NSObject {
40
RefPtr<WebKit::APIObject> _webUserData;
42
- (id)initWithUserData:(WebKit::APIObject*)userData;
43
- (WebKit::APIObject*)userData;
46
@implementation WKUserDataWrapper
48
- (id)initWithUserData:(WebKit::APIObject*)userData
54
_webUserData = userData;
58
- (WebKit::APIObject*)userData
60
return _webUserData.get();
65
@interface WKMenuTarget : NSObject {
66
WebKit::WebContextMenuProxyMac* _menuProxy;
68
+ (WKMenuTarget*)sharedMenuTarget;
69
- (WebKit::WebContextMenuProxyMac*)menuProxy;
70
- (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy;
71
- (void)forwardContextMenuAction:(id)sender;
74
@implementation WKMenuTarget
76
+ (WKMenuTarget*)sharedMenuTarget
78
static WKMenuTarget* target = [[WKMenuTarget alloc] init];
82
- (WebKit::WebContextMenuProxyMac*)menuProxy
87
- (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy
89
_menuProxy = menuProxy;
92
- (void)forwardContextMenuAction:(id)sender
94
WebKit::WebContextMenuItemData item(ActionType, static_cast<ContextMenuAction>([sender tag]), [sender title], [sender isEnabled], [sender state] == NSOnState);
96
if (id representedObject = [sender representedObject]) {
97
ASSERT([representedObject isKindOfClass:[WKUserDataWrapper class]]);
98
item.setUserData([static_cast<WKUserDataWrapper *>(representedObject) userData]);
101
_menuProxy->contextMenuItemSelected(item);
108
WebContextMenuProxyMac::WebContextMenuProxyMac(WKView* webView, WebPageProxy* page)
114
WebContextMenuProxyMac::~WebContextMenuProxyMac()
117
[m_popup.get() setControlView:nil];
120
void WebContextMenuProxyMac::contextMenuItemSelected(const WebContextMenuItemData& item)
122
m_page->contextMenuItemSelected(item);
125
static void populateNSMenu(NSMenu* menu, const Vector<RetainPtr<NSMenuItem> >& menuItemVector)
127
for (unsigned i = 0; i < menuItemVector.size(); ++i) {
128
NSInteger oldState = [menuItemVector[i].get() state];
129
[menu addItem:menuItemVector[i].get()];
130
[menuItemVector[i].get() setState:oldState];
134
static Vector<RetainPtr<NSMenuItem> > nsMenuItemVector(const Vector<WebContextMenuItemData>& items)
136
Vector<RetainPtr<NSMenuItem> > result;
138
unsigned size = items.size();
139
result.reserveCapacity(size);
140
for (unsigned i = 0; i < size; i++) {
141
switch (items[i].type()) {
143
case CheckableActionType: {
144
NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:nsStringFromWebCoreString(items[i].title()) action:@selector(forwardContextMenuAction:) keyEquivalent:@""];
145
[menuItem setTag:items[i].action()];
146
[menuItem setEnabled:items[i].enabled()];
147
[menuItem setState:items[i].checked() ? NSOnState : NSOffState];
149
if (items[i].userData()) {
150
WKUserDataWrapper *wrapper = [[WKUserDataWrapper alloc] initWithUserData:items[i].userData()];
151
[menuItem setRepresentedObject:wrapper];
155
result.append(RetainPtr<NSMenuItem>(AdoptNS, menuItem));
159
result.append([NSMenuItem separatorItem]);
162
NSMenu* menu = [[NSMenu alloc] initWithTitle:nsStringFromWebCoreString(items[i].title())];
163
[menu setAutoenablesItems:NO];
164
populateNSMenu(menu, nsMenuItemVector(items[i].submenu()));
166
NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:nsStringFromWebCoreString(items[i].title()) action:@selector(forwardContextMenuAction:) keyEquivalent:@""];
167
[menuItem setEnabled:items[i].enabled()];
168
[menuItem setSubmenu:menu];
171
result.append(RetainPtr<NSMenuItem>(AdoptNS, menuItem));
176
ASSERT_NOT_REACHED();
180
WKMenuTarget* target = [WKMenuTarget sharedMenuTarget];
181
for (unsigned i = 0; i < size; ++i)
182
[result[i].get() setTarget:target];
187
void WebContextMenuProxyMac::populate(const Vector<WebContextMenuItemData>& items)
190
[m_popup.get() removeAllItems];
192
m_popup.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
193
[m_popup.get() setUsesItemFromMenu:NO];
194
[m_popup.get() setAutoenablesItems:NO];
197
NSMenu* menu = [m_popup.get() menu];
198
populateNSMenu(menu, nsMenuItemVector(items));
201
void WebContextMenuProxyMac::showContextMenu(const IntPoint& menuLocation, const Vector<WebContextMenuItemData>& items)
207
[[WKMenuTarget sharedMenuTarget] setMenuProxy:this];
209
NSRect menuRect = NSMakeRect(menuLocation.x(), menuLocation.y(), 0, 0);
211
[m_popup.get() attachPopUpWithFrame:menuRect inView:m_webView];
213
NSMenu* menu = [m_popup.get() menu];
215
// These values were borrowed from AppKit to match their placement of the menu.
216
NSRect titleFrame = [m_popup.get() titleRectForBounds:menuRect];
217
if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0)
218
titleFrame = menuRect;
219
float vertOffset = roundf((NSMaxY(menuRect) - NSMaxY(titleFrame)) + NSHeight(titleFrame));
220
NSPoint location = NSMakePoint(NSMinX(menuRect), NSMaxY(menuRect) - vertOffset);
222
location = [m_webView convertPoint:location toView:nil];
223
location = [m_webView.window convertBaseToScreen:location];
225
WKPopupContextMenu(menu, location);
227
[m_popup.get() dismissPopUp];
230
void WebContextMenuProxyMac::hideContextMenu()
232
[m_popup.get() dismissPopUp];
235
} // namespace WebKit