~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit2/UIProcess/mac/WebContextMenuProxyMac.mm

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Apple Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
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.
 
12
 *
 
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.
 
24
 */
 
25
 
 
26
#import "config.h"
 
27
#import "WebContextMenuProxyMac.h"
 
28
 
 
29
#import "PageClientImpl.h"
 
30
#import "StringUtilities.h"
 
31
#import "WebContextMenuItemData.h"
 
32
#import "WKView.h"
 
33
 
 
34
#import <WebCore/IntRect.h>
 
35
#import <WebKitSystemInterface.h>
 
36
 
 
37
using namespace WebCore;
 
38
 
 
39
@interface WKUserDataWrapper : NSObject {
 
40
    RefPtr<WebKit::APIObject> _webUserData;
 
41
}
 
42
- (id)initWithUserData:(WebKit::APIObject*)userData;
 
43
- (WebKit::APIObject*)userData;
 
44
@end
 
45
 
 
46
@implementation WKUserDataWrapper
 
47
 
 
48
- (id)initWithUserData:(WebKit::APIObject*)userData
 
49
{
 
50
    self = [super init];
 
51
    if (!self)
 
52
        return nil;
 
53
    
 
54
    _webUserData = userData;
 
55
    return self;
 
56
}
 
57
 
 
58
- (WebKit::APIObject*)userData
 
59
{
 
60
    return _webUserData.get();
 
61
}
 
62
 
 
63
@end
 
64
 
 
65
@interface WKMenuTarget : NSObject {
 
66
    WebKit::WebContextMenuProxyMac* _menuProxy;
 
67
}
 
68
+ (WKMenuTarget*)sharedMenuTarget;
 
69
- (WebKit::WebContextMenuProxyMac*)menuProxy;
 
70
- (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy;
 
71
- (void)forwardContextMenuAction:(id)sender;
 
72
@end
 
73
 
 
74
@implementation WKMenuTarget
 
75
 
 
76
+ (WKMenuTarget*)sharedMenuTarget
 
77
{
 
78
    static WKMenuTarget* target = [[WKMenuTarget alloc] init];
 
79
    return target;
 
80
}
 
81
 
 
82
- (WebKit::WebContextMenuProxyMac*)menuProxy
 
83
{
 
84
    return _menuProxy;
 
85
}
 
86
 
 
87
- (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy
 
88
{
 
89
    _menuProxy = menuProxy;
 
90
}
 
91
 
 
92
- (void)forwardContextMenuAction:(id)sender
 
93
{
 
94
    WebKit::WebContextMenuItemData item(ActionType, static_cast<ContextMenuAction>([sender tag]), [sender title], [sender isEnabled], [sender state] == NSOnState);
 
95
    
 
96
    if (id representedObject = [sender representedObject]) {
 
97
        ASSERT([representedObject isKindOfClass:[WKUserDataWrapper class]]);
 
98
        item.setUserData([static_cast<WKUserDataWrapper *>(representedObject) userData]);
 
99
    }
 
100
            
 
101
    _menuProxy->contextMenuItemSelected(item);
 
102
}
 
103
 
 
104
@end
 
105
 
 
106
namespace WebKit {
 
107
 
 
108
WebContextMenuProxyMac::WebContextMenuProxyMac(WKView* webView, WebPageProxy* page)
 
109
    : m_webView(webView)
 
110
    , m_page(page)
 
111
{
 
112
}
 
113
 
 
114
WebContextMenuProxyMac::~WebContextMenuProxyMac()
 
115
{
 
116
    if (m_popup)
 
117
        [m_popup.get() setControlView:nil];
 
118
}
 
119
 
 
120
void WebContextMenuProxyMac::contextMenuItemSelected(const WebContextMenuItemData& item)
 
121
{
 
122
    m_page->contextMenuItemSelected(item);
 
123
}
 
124
 
 
125
static void populateNSMenu(NSMenu* menu, const Vector<RetainPtr<NSMenuItem> >& menuItemVector)
 
126
{
 
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];
 
131
    }
 
132
}
 
133
 
 
134
static Vector<RetainPtr<NSMenuItem> > nsMenuItemVector(const Vector<WebContextMenuItemData>& items)
 
135
{
 
136
    Vector<RetainPtr<NSMenuItem> > result;
 
137
 
 
138
    unsigned size = items.size();
 
139
    result.reserveCapacity(size);
 
140
    for (unsigned i = 0; i < size; i++) {
 
141
        switch (items[i].type()) {
 
142
        case ActionType:
 
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];
 
148
                        
 
149
            if (items[i].userData()) {
 
150
                WKUserDataWrapper *wrapper = [[WKUserDataWrapper alloc] initWithUserData:items[i].userData()];
 
151
                [menuItem setRepresentedObject:wrapper];
 
152
                [wrapper release];
 
153
            }
 
154
 
 
155
            result.append(RetainPtr<NSMenuItem>(AdoptNS, menuItem));
 
156
            break;
 
157
        }
 
158
        case SeparatorType:
 
159
            result.append([NSMenuItem separatorItem]);
 
160
            break;
 
161
        case SubmenuType: {
 
162
            NSMenu* menu = [[NSMenu alloc] initWithTitle:nsStringFromWebCoreString(items[i].title())];
 
163
            [menu setAutoenablesItems:NO];
 
164
            populateNSMenu(menu, nsMenuItemVector(items[i].submenu()));
 
165
                
 
166
            NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:nsStringFromWebCoreString(items[i].title()) action:@selector(forwardContextMenuAction:) keyEquivalent:@""];
 
167
            [menuItem setEnabled:items[i].enabled()];
 
168
            [menuItem setSubmenu:menu];
 
169
            [menu release];
 
170
 
 
171
            result.append(RetainPtr<NSMenuItem>(AdoptNS, menuItem));
 
172
            
 
173
            break;
 
174
        }
 
175
        default:
 
176
            ASSERT_NOT_REACHED();
 
177
        }
 
178
    }
 
179
 
 
180
    WKMenuTarget* target = [WKMenuTarget sharedMenuTarget];
 
181
    for (unsigned i = 0; i < size; ++i)
 
182
        [result[i].get() setTarget:target];
 
183
    
 
184
    return result;
 
185
}
 
186
 
 
187
void WebContextMenuProxyMac::populate(const Vector<WebContextMenuItemData>& items)
 
188
{
 
189
    if (m_popup)
 
190
        [m_popup.get() removeAllItems];
 
191
    else {
 
192
        m_popup.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
 
193
        [m_popup.get() setUsesItemFromMenu:NO];
 
194
        [m_popup.get() setAutoenablesItems:NO];
 
195
    }
 
196
 
 
197
    NSMenu* menu = [m_popup.get() menu];
 
198
    populateNSMenu(menu, nsMenuItemVector(items));
 
199
}
 
200
 
 
201
void WebContextMenuProxyMac::showContextMenu(const IntPoint& menuLocation, const Vector<WebContextMenuItemData>& items)
 
202
{
 
203
    if (items.isEmpty())
 
204
        return;
 
205
    
 
206
    populate(items);
 
207
    [[WKMenuTarget sharedMenuTarget] setMenuProxy:this];
 
208
    
 
209
    NSRect menuRect = NSMakeRect(menuLocation.x(), menuLocation.y(), 0, 0);
 
210
    
 
211
    [m_popup.get() attachPopUpWithFrame:menuRect inView:m_webView];
 
212
 
 
213
    NSMenu* menu = [m_popup.get() menu];
 
214
 
 
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);
 
221
 
 
222
    location = [m_webView convertPoint:location toView:nil];
 
223
    location = [m_webView.window convertBaseToScreen:location];
 
224
 
 
225
    WKPopupContextMenu(menu, location);
 
226
 
 
227
    [m_popup.get() dismissPopUp];
 
228
}
 
229
 
 
230
void WebContextMenuProxyMac::hideContextMenu()
 
231
{
 
232
    [m_popup.get() dismissPopUp];
 
233
}
 
234
 
 
235
} // namespace WebKit