summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--webkit/glue/webmenurunner_mac.h71
-rw-r--r--webkit/glue/webmenurunner_mac.mm130
-rwxr-xr-xwebkit/tools/test_shell/mac/test_webview_delegate.mm131
-rw-r--r--webkit/webkit.gyp2
4 files changed, 217 insertions, 117 deletions
diff --git a/webkit/glue/webmenurunner_mac.h b/webkit/glue/webmenurunner_mac.h
new file mode 100644
index 0000000..eceaa3f
--- /dev/null
+++ b/webkit/glue/webmenurunner_mac.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_WEBMENURUNNER_MAC_H_
+#define WEBKIT_GLUE_WEBMENURUNNER_MAC_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include <vector>
+
+#include "webkit/glue/webwidget_delegate.h"
+
+
+// WebMenuRunner ---------------------------------------------------------------
+// A class for determining whether an item was selected from an HTML select
+// control, or if the menu was dismissed without making a selection. If a menu
+// item is selected, MenuDelegate is informed and sets a flag which can be
+// queried after the menu has finished running.
+
+@interface WebMenuRunner : NSObject {
+ @private
+ // The actual menu object, which we own.
+ NSMenu* menu_;
+
+ // A flag set to YES if a menu item was chosen, or NO if the menu was
+ // dismissed without selecting an item.
+ BOOL menuItemWasChosen_;
+
+ // The index of the selected menu item.
+ int index_;
+}
+
+// Initializes the MenuDelegate with a list of items sent from WebKit.
+- (id)initWithItems:(const std::vector<WebMenuItem>&)items;
+- (void)dealloc;
+
+// Worker function used during initialization.
+- (void)addItem:(const WebMenuItem&)item;
+
+// Returns YES if an item was selected from the menu, NO if the menu was
+// dismissed.
+- (BOOL)menuItemWasChosen;
+
+// A callback for the menu controller object to call when an item is selected
+// from the menu. This is not called if the menu is dismissed without a
+// selection.
+- (void)menuItemSelected:(id)sender;
+
+// Displays and runs a native popup menu.
+- (void)runMenuInView:(NSView*)view
+ withBounds:(NSRect)bounds
+ initialIndex:(int)index;
+
+// Returns the index of selected menu item, or its initial value (-1) if no item
+// was selected.
+- (int)indexOfSelectedItem;
+
+@end // @interface WebMenuRunner
+
+// Helper function for manufacturing input events to send to WebKit. If
+// |item_chosen| is YES, we manufacture a mouse click event that corresponds to
+// the menu item that was selected, |selected_index|, based on the position of
+// the mouse click. Of |item_chosen| is NO, we create a keyboard event that
+// simulates an ESC (menu dismissal) action. The event is designed to be sent to
+// WebKit for processing by the PopupMenu class.
+NSEvent* CreateEventForMenuAction(BOOL item_chosen, int window_num,
+ int item_height, int selected_index,
+ NSRect menu_bounds, NSRect view_bounds);
+
+#endif // WEBKIT_GLUE_WEBMENURUNNER_MAC_H_
diff --git a/webkit/glue/webmenurunner_mac.mm b/webkit/glue/webmenurunner_mac.mm
new file mode 100644
index 0000000..32bedf3
--- /dev/null
+++ b/webkit/glue/webmenurunner_mac.mm
@@ -0,0 +1,130 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/webmenurunner_mac.h"
+
+#include "base/sys_string_conversions.h"
+
+@implementation WebMenuRunner
+
+- (id)initWithItems:(const std::vector<WebMenuItem>&)items {
+ if ((self = [super init])) {
+ menu_ = [[NSMenu alloc] initWithTitle:@""];
+ [menu_ setAutoenablesItems:NO];
+ menuItemWasChosen_ = NO;
+ index_ = -1;
+ for (int i = 0; i < static_cast<int>(items.size()); ++i)
+ [self addItem:items[i]];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [menu_ release];
+ [super dealloc];
+}
+
+- (void)addItem:(const WebMenuItem&)item {
+ if (item.type == WebMenuItem::SEPARATOR) {
+ [menu_ addItem:[NSMenuItem separatorItem]];
+ return;
+ }
+
+ NSString* title = base::SysUTF16ToNSString(item.label);
+ NSMenuItem* menu_item = [menu_ addItemWithTitle:title
+ action:@selector(menuItemSelected:)
+ keyEquivalent:@""];
+ [menu_item setEnabled:(item.enabled && item.type != WebMenuItem::GROUP)];
+ [menu_item setTarget:self];
+}
+
+// Reflects the result of the user's interaction with the popup menu. If NO, the
+// menu was dismissed without the user choosing an item, which can happen if the
+// user clicked outside the menu region or hit the escape key. If YES, the user
+// selected an item from the menu.
+- (BOOL)menuItemWasChosen {
+ return menuItemWasChosen_;
+}
+
+- (void)menuItemSelected:(id)sender {
+ menuItemWasChosen_ = YES;
+}
+
+- (void)runMenuInView:(NSView*)view
+ withBounds:(NSRect)bounds
+ initialIndex:(int)index {
+ // Set up the button cell, converting to NSView coordinates. The menu is
+ // positioned such that the currently selected menu item appears over the
+ // popup button, which is the expected Mac popup menu behavior.
+ NSPopUpButtonCell* button = [[NSPopUpButtonCell alloc] initTextCell:@""
+ pullsDown:NO];
+ [button autorelease];
+ [button setMenu:menu_];
+ [button selectItemAtIndex:index];
+
+ // Display the menu, and set a flag if a menu item was chosen.
+ [button performClickWithFrame:bounds inView:view];
+
+ if ([self menuItemWasChosen])
+ index_ = [button indexOfSelectedItem];
+}
+
+- (int)indexOfSelectedItem {
+ return index_;
+}
+
+@end // WebMenuRunner
+
+// Helper function for manufacturing input events to send to WebKit.
+NSEvent* CreateEventForMenuAction(BOOL item_chosen, int window_num,
+ int item_height, int selected_index,
+ NSRect menu_bounds, NSRect view_bounds) {
+ NSEvent* event = nil;
+ double event_time = (double)(AbsoluteToDuration(UpTime())) / 1000.0;
+
+ if (item_chosen) {
+ // Construct a mouse up event to simulate the selection of an appropriate
+ // menu item.
+ NSPoint click_pos;
+ click_pos.x = menu_bounds.size.width / 2;
+
+ // This is going to be hard to calculate since the button is painted by
+ // WebKit, the menu by Cocoa, and we have to translate the selected_item
+ // index to a coordinate that WebKit's PopupMenu expects which uses a
+ // different font *and* expects to draw the menu below the button like we do
+ // on Windows.
+ // The WebKit popup menu thinks it will draw just below the button, so
+ // create the click at the offset based on the selected item's index and
+ // account for the different coordinate system used by NSView.
+ int item_offset = selected_index * item_height + item_height / 2;
+ click_pos.y = view_bounds.size.height - item_offset;
+ event = [NSEvent mouseEventWithType:NSLeftMouseUp
+ location:click_pos
+ modifierFlags:0
+ timestamp:event_time
+ windowNumber:window_num
+ context:nil
+ eventNumber:0
+ clickCount:1
+ pressure:1.0];
+ } else {
+ // Fake an ESC key event (keyCode = 0x1B, from webinputevent_mac.mm) and
+ // forward that to WebKit.
+ NSPoint key_pos;
+ key_pos.x = 0;
+ key_pos.y = 0;
+ event = [NSEvent keyEventWithType:NSKeyUp
+ location:key_pos
+ modifierFlags:0
+ timestamp:event_time
+ windowNumber:window_num
+ context:nil
+ characters:@""
+ charactersIgnoringModifiers:@""
+ isARepeat:NO
+ keyCode:0x1B];
+ }
+
+ return event;
+}
diff --git a/webkit/tools/test_shell/mac/test_webview_delegate.mm b/webkit/tools/test_shell/mac/test_webview_delegate.mm
index 8df8d40..a1d1815 100755
--- a/webkit/tools/test_shell/mac/test_webview_delegate.mm
+++ b/webkit/tools/test_shell/mac/test_webview_delegate.mm
@@ -12,70 +12,11 @@
#include "webkit/glue/webview.h"
#include "webkit/glue/plugins/plugin_list.h"
#include "webkit/glue/plugins/webplugin_delegate_impl.h"
+#include "webkit/glue/webmenurunner_mac.h"
#include "webkit/tools/test_shell/test_shell.h"
using WebKit::WebRect;
-// MenuDelegate ----------------------------------------------------------------
-// A class for determining whether an item was selected from an HTML select
-// control, or if the menu was dismissed without making a selection. If a menu
-// item is selected, MenuDelegate is informed and sets a flag which can be
-// queried after the menu has finished running.
-
-@interface MenuDelegate : NSObject {
- @private
- NSMenu* menu_; // Non-owning
- BOOL menuItemWasChosen_;
-}
-- (id)initWithItems:(const std::vector<WebMenuItem>&)items
- forMenu:(NSMenu*)menu;
-- (void)addItem:(const WebMenuItem&)item;
-- (BOOL)menuItemWasChosen;
-- (void)menuItemSelected:(id)sender;
-@end
-
-@implementation MenuDelegate
-
-- (id)initWithItems:(const std::vector<WebMenuItem>&)items
- forMenu:(NSMenu*)menu {
- if ((self = [super init])) {
- menu_ = menu;
- menuItemWasChosen_ = NO;
- for (int i = 0; i < static_cast<int>(items.size()); ++i)
- [self addItem:items[i]];
- }
- return self;
-}
-
-- (void)addItem:(const WebMenuItem&)item {
- if (item.type == WebMenuItem::SEPARATOR) {
- [menu_ addItem:[NSMenuItem separatorItem]];
- return;
- }
-
- NSString* title = base::SysUTF16ToNSString(item.label);
- NSMenuItem* menu_item = [menu_ addItemWithTitle:title
- action:@selector(menuItemSelected:)
- keyEquivalent:@""];
- [menu_item setEnabled:(item.enabled && item.type != WebMenuItem::GROUP)];
- [menu_item setTarget:self];
-}
-
-// Reflects the result of the user's interaction with the popup menu. If NO, the
-// menu was dismissed without the user choosing an item, which can happen if the
-// user clicked outside the menu region or hit the escape key. If YES, the user
-// selected an item from the menu.
-- (BOOL)menuItemWasChosen {
- return menuItemWasChosen_;
-}
-
-- (void)menuItemSelected:(id)sender {
- menuItemWasChosen_ = YES;
-}
-
-@end // MenuDelegate
-
-
// WebViewDelegate -----------------------------------------------------------
TestWebViewDelegate::~TestWebViewDelegate() {
@@ -130,82 +71,38 @@ void TestWebViewDelegate::ShowAsPopupWithItems(
int item_height,
int selected_index,
const std::vector<WebMenuItem>& items) {
- // Populate the menu.
- NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
- [menu setAutoenablesItems:NO];
- MenuDelegate* menu_delegate =
- [[[MenuDelegate alloc] initWithItems:items forMenu:menu] autorelease];
-
- // Set up the button cell, converting to NSView coordinates. The menu is
- // positioned such that the currently selected menu item appears over the
- // popup button, which is the expected Mac popup menu behavior.
- NSPopUpButtonCell* button = [[NSPopUpButtonCell alloc] initTextCell:@""
- pullsDown:NO];
- [button autorelease];
- [button setMenu:menu];
- [button selectItemAtIndex:selected_index];
+ // Set up the menu position.
NSView* web_view = shell_->webViewWnd();
NSRect view_rect = [web_view bounds];
int y_offset = bounds.y + bounds.height;
NSRect position = NSMakeRect(bounds.x, view_rect.size.height - y_offset,
bounds.width, bounds.height);
- // Display the menu, and set a flag to determine if something was chosen. If
- // nothing was chosen (i.e., the user dismissed the popup by the "ESC" key or
- // clicking outside popup's region), send a dismiss message to WebKit.
- [button performClickWithFrame:position inView:shell_->webViewWnd()];
+ // Display the menu.
+ WebMenuRunner* menu_runner =
+ [[[WebMenuRunner alloc] initWithItems:items] autorelease];
+
+ [menu_runner runMenuInView:shell_->webViewWnd()
+ withBounds:position
+ initialIndex:selected_index];
// Get the selected item and forward to WebKit. WebKit expects an input event
// (mouse down, keyboard activity) for this, so we calculate the proper
// position based on the selected index and provided bounds.
WebWidgetHost* popup = shell_->popupHost();
- NSEvent* event = nil;
- double event_time = (double)(AbsoluteToDuration(UpTime())) / 1000.0;
int window_num = [shell_->mainWnd() windowNumber];
- if ([menu_delegate menuItemWasChosen]) {
+ NSEvent* event = CreateEventForMenuAction([menu_runner menuItemWasChosen],
+ window_num, item_height,
+ [menu_runner indexOfSelectedItem],
+ position, view_rect);
+ if ([menu_runner menuItemWasChosen]) {
// Construct a mouse up event to simulate the selection of an appropriate
// menu item.
- NSPoint click_pos;
- click_pos.x = position.size.width / 2;
-
- // This is going to be hard to calculate since the button is painted by
- // WebKit, the menu by Cocoa, and we have to translate the selected_item
- // index to a coordinate that WebKit's PopupMenu expects which uses a
- // different font *and* expects to draw the menu below the button like we do
- // on Windows.
- // The WebKit popup menu thinks it will draw just below the button, so
- // create the click at the offset based on the selected item's index and
- // account for the different coordinate system used by NSView.
- int item_offset = [button indexOfSelectedItem] * item_height +
- item_height / 2;
- click_pos.y = view_rect.size.height - item_offset;
- event = [NSEvent mouseEventWithType:NSLeftMouseUp
- location:click_pos
- modifierFlags:0
- timestamp:event_time
- windowNumber:window_num
- context:nil
- eventNumber:0
- clickCount:1
- pressure:1.0];
popup->MouseEvent(event);
} else {
// Fake an ESC key event (keyCode = 0x1B, from webinputevent_mac.mm) and
// forward that to WebKit.
- NSPoint key_pos;
- key_pos.x = 0;
- key_pos.y = 0;
- event = [NSEvent keyEventWithType:NSKeyUp
- location:key_pos
- modifierFlags:0
- timestamp:event_time
- windowNumber:window_num
- context:nil
- characters:@""
- charactersIgnoringModifiers:@""
- isARepeat:NO
- keyCode:0x1B];
popup->KeyEvent(event);
}
}
diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp
index 954fe6a..22d6ab7 100644
--- a/webkit/webkit.gyp
+++ b/webkit/webkit.gyp
@@ -4474,6 +4474,8 @@
'glue/webmediaplayer_delegate.h',
'glue/webmediaplayer_impl.cc',
'glue/webmediaplayer_impl.h',
+ 'glue/webmenurunner_mac.h',
+ 'glue/webmenurunner_mac.mm',
'glue/webplugin.h',
'glue/webplugin_delegate.cc',
'glue/webplugin_delegate.h',