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

« back to all changes in this revision

Viewing changes to Source/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.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, 2011 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 "WebPopupMenuProxyMac.h"
 
28
 
 
29
#if USE(APPKIT)
 
30
 
 
31
#import "NativeWebMouseEvent.h"
 
32
#import "PageClientImpl.h"
 
33
#import "PlatformPopupMenuData.h"
 
34
#import "StringUtilities.h"
 
35
#import "WKView.h"
 
36
#import "WebPopupItem.h"
 
37
#import <WebKitSystemInterface.h>
 
38
 
 
39
using namespace WebCore;
 
40
 
 
41
namespace WebKit {
 
42
 
 
43
WebPopupMenuProxyMac::WebPopupMenuProxyMac(WKView *webView, WebPopupMenuProxy::Client* client)
 
44
    : WebPopupMenuProxy(client)
 
45
    , m_webView(webView)
 
46
{
 
47
}
 
48
 
 
49
WebPopupMenuProxyMac::~WebPopupMenuProxyMac()
 
50
{
 
51
    if (m_popup)
 
52
        [m_popup.get() setControlView:nil];
 
53
}
 
54
 
 
55
void WebPopupMenuProxyMac::populate(const Vector<WebPopupItem>& items, NSFont *font, TextDirection menuTextDirection)
 
56
{
 
57
    if (m_popup)
 
58
        [m_popup.get() removeAllItems];
 
59
    else {
 
60
        m_popup.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
 
61
        [m_popup.get() setUsesItemFromMenu:NO];
 
62
        [m_popup.get() setAutoenablesItems:NO];
 
63
    }
 
64
 
 
65
    int size = items.size();
 
66
 
 
67
    for (int i = 0; i < size; i++) {
 
68
        if (items[i].m_type == WebPopupItem::Separator)
 
69
            [[m_popup.get() menu] addItem:[NSMenuItem separatorItem]];
 
70
        else {
 
71
            [m_popup.get() addItemWithTitle:@""];
 
72
            NSMenuItem *menuItem = [m_popup.get() lastItem];
 
73
 
 
74
            RetainPtr<NSMutableParagraphStyle> paragraphStyle(AdoptNS, [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
 
75
            NSWritingDirection writingDirection = items[i].m_textDirection == LTR ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft;
 
76
            [paragraphStyle.get() setBaseWritingDirection:writingDirection];
 
77
            [paragraphStyle.get() setAlignment:menuTextDirection == LTR ? NSLeftTextAlignment : NSRightTextAlignment];
 
78
            RetainPtr<NSMutableDictionary> attributes(AdoptNS, [[NSMutableDictionary alloc] initWithObjectsAndKeys:
 
79
                paragraphStyle.get(), NSParagraphStyleAttributeName,
 
80
                font, NSFontAttributeName,
 
81
            nil]);
 
82
            if (items[i].m_hasTextDirectionOverride) {
 
83
                RetainPtr<NSNumber> writingDirectionValue(AdoptNS, [[NSNumber alloc] initWithInteger:writingDirection + NSTextWritingDirectionOverride]);
 
84
                RetainPtr<NSArray> writingDirectionArray(AdoptNS, [[NSArray alloc] initWithObjects:writingDirectionValue.get(), nil]);
 
85
                [attributes.get() setObject:writingDirectionArray.get() forKey:NSWritingDirectionAttributeName];
 
86
            }
 
87
            RetainPtr<NSAttributedString> string(AdoptNS, [[NSAttributedString alloc] initWithString:nsStringFromWebCoreString(items[i].m_text) attributes:attributes.get()]);
 
88
 
 
89
            [menuItem setAttributedTitle:string.get()];
 
90
            // We set the title as well as the attributed title here. The attributed title will be displayed in the menu,
 
91
            // but typeahead will use the non-attributed string that doesn't contain any leading or trailing whitespace.
 
92
            [menuItem setTitle:[[string.get() string] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
 
93
            [menuItem setEnabled:items[i].m_isEnabled];
 
94
            [menuItem setToolTip:nsStringFromWebCoreString(items[i].m_toolTip)];
 
95
        }
 
96
    }
 
97
}
 
98
 
 
99
void WebPopupMenuProxyMac::showPopupMenu(const IntRect& rect, TextDirection textDirection, double pageScaleFactor, const Vector<WebPopupItem>& items, const PlatformPopupMenuData& data, int32_t selectedIndex)
 
100
{
 
101
    NSFont *font;
 
102
    if (data.fontInfo.fontAttributeDictionary) {
 
103
        NSFontDescriptor *fontDescriptor = [NSFontDescriptor fontDescriptorWithFontAttributes:(NSDictionary *)data.fontInfo.fontAttributeDictionary.get()];
 
104
        font = [NSFont fontWithDescriptor:fontDescriptor size:((pageScaleFactor != 1) ? [fontDescriptor pointSize] * pageScaleFactor : 0)];
 
105
    } else
 
106
        font = [NSFont menuFontOfSize:0];
 
107
 
 
108
    populate(items, font, textDirection);
 
109
 
 
110
    [m_popup.get() attachPopUpWithFrame:rect inView:m_webView];
 
111
    [m_popup.get() selectItemAtIndex:selectedIndex];
 
112
    [m_popup.get() setUserInterfaceLayoutDirection:textDirection == LTR ? NSUserInterfaceLayoutDirectionLeftToRight : NSUserInterfaceLayoutDirectionRightToLeft];
 
113
 
 
114
    NSMenu *menu = [m_popup.get() menu];
 
115
 
 
116
    // These values were borrowed from AppKit to match their placement of the menu.
 
117
    const int popOverHorizontalAdjust = -10;
 
118
    const int popUnderHorizontalAdjust = 6;
 
119
    const int popUnderVerticalAdjust = 6;
 
120
    
 
121
    // Menus that pop-over directly obscure the node that generated the popup menu.
 
122
    // Menus that pop-under are offset underneath it.
 
123
    NSPoint location;
 
124
    if (data.shouldPopOver) {
 
125
        NSRect titleFrame = [m_popup.get()  titleRectForBounds:rect];
 
126
        if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0)
 
127
            titleFrame = rect;
 
128
        float vertOffset = roundf((NSMaxY(rect) - NSMaxY(titleFrame)) + NSHeight(titleFrame));
 
129
        location = NSMakePoint(NSMinX(rect) + popOverHorizontalAdjust, NSMaxY(rect) - vertOffset);
 
130
    } else
 
131
        location = NSMakePoint(NSMinX(rect) + popUnderHorizontalAdjust, NSMaxY(rect) + popUnderVerticalAdjust);  
 
132
 
 
133
    RetainPtr<NSView> dummyView(AdoptNS, [[NSView alloc] initWithFrame:rect]);
 
134
    [m_webView addSubview:dummyView.get()];
 
135
    location = [dummyView.get() convertPoint:location fromView:m_webView];
 
136
 
 
137
    WKPopupMenu(menu, location, roundf(NSWidth(rect)), dummyView.get(), selectedIndex, font);
 
138
 
 
139
    [m_popup.get() dismissPopUp];
 
140
    [dummyView.get() removeFromSuperview];
 
141
    
 
142
    if (!m_client)
 
143
        return;
 
144
    
 
145
    m_client->valueChangedForPopupMenu(this, [m_popup.get() indexOfSelectedItem]);
 
146
    
 
147
    // <https://bugs.webkit.org/show_bug.cgi?id=57904> This code is adopted from EventHandler::sendFakeEventsAfterWidgetTracking().
 
148
    if (!m_client->currentlyProcessedMouseDownEvent())
 
149
        return;
 
150
    
 
151
    NSEvent* initiatingNSEvent = m_client->currentlyProcessedMouseDownEvent()->nativeEvent();
 
152
    if ([initiatingNSEvent type] != NSLeftMouseDown)
 
153
        return;
 
154
    
 
155
    NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSLeftMouseUp
 
156
                                            location:[initiatingNSEvent locationInWindow]
 
157
                                       modifierFlags:[initiatingNSEvent modifierFlags]
 
158
                                           timestamp:[initiatingNSEvent timestamp]
 
159
                                        windowNumber:[initiatingNSEvent windowNumber]
 
160
                                             context:[initiatingNSEvent context]
 
161
                                         eventNumber:[initiatingNSEvent eventNumber]
 
162
                                          clickCount:[initiatingNSEvent clickCount]
 
163
                                            pressure:[initiatingNSEvent pressure]];
 
164
    
 
165
    [NSApp postEvent:fakeEvent atStart:YES];
 
166
    fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved
 
167
                                   location:[[m_webView window] convertScreenToBase:[NSEvent mouseLocation]]
 
168
                              modifierFlags:[initiatingNSEvent modifierFlags]
 
169
                                  timestamp:[initiatingNSEvent timestamp]
 
170
                               windowNumber:[initiatingNSEvent windowNumber]
 
171
                                    context:[initiatingNSEvent context]
 
172
                                eventNumber:0
 
173
                                 clickCount:0
 
174
                                   pressure:0];
 
175
    [NSApp postEvent:fakeEvent atStart:YES];
 
176
}
 
177
 
 
178
void WebPopupMenuProxyMac::hidePopupMenu()
 
179
{
 
180
    [m_popup.get() dismissPopUp];
 
181
}
 
182
 
 
183
} // namespace WebKit
 
184
 
 
185
#endif // USE(APPKIT)