1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/tab_contents/render_view_context_menu_mac.h" 6 7 #include "base/compiler_specific.h" 8 #include "base/memory/scoped_nsobject.h" 9 #include "base/message_loop.h" 10 #include "base/sys_string_conversions.h" 11 #include "chrome/app/chrome_command_ids.h" 12 #import "chrome/browser/ui/cocoa/browser_window_controller.h" 13 #import "chrome/browser/ui/cocoa/menu_controller.h" 14 #include "grit/generated_resources.h" 15 16 // Obj-C bridge class that is the target of all items in the context menu. 17 // Relies on the tag being set to the command id. 18 19 RenderViewContextMenuMac::RenderViewContextMenuMac( 20 TabContents* web_contents, 21 const ContextMenuParams& params, 22 NSView* parent_view) 23 : RenderViewContextMenu(web_contents, params), 24 parent_view_(parent_view) { 25 } 26 27 RenderViewContextMenuMac::~RenderViewContextMenuMac() { 28 } 29 30 void RenderViewContextMenuMac::PlatformInit() { 31 InitPlatformMenu(); 32 menuController_.reset( 33 [[MenuController alloc] initWithModel:&menu_model_ 34 useWithPopUpButtonCell:NO]); 35 36 // Synthesize an event for the click, as there is no certainty that 37 // [NSApp currentEvent] will return a valid event. 38 NSEvent* currentEvent = [NSApp currentEvent]; 39 NSWindow* window = [parent_view_ window]; 40 NSPoint position = [window mouseLocationOutsideOfEventStream]; 41 NSTimeInterval eventTime = [currentEvent timestamp]; 42 NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown 43 location:position 44 modifierFlags:NSRightMouseDownMask 45 timestamp:eventTime 46 windowNumber:[window windowNumber] 47 context:nil 48 eventNumber:0 49 clickCount:1 50 pressure:1.0]; 51 52 { 53 // Make sure events can be pumped while the menu is up. 54 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); 55 56 // Show the menu. 57 [NSMenu popUpContextMenu:[menuController_ menu] 58 withEvent:clickEvent 59 forView:parent_view_]; 60 } 61 } 62 63 void RenderViewContextMenuMac::ExecuteCommand(int id) { 64 [[[parent_view_ window] windowController] commitInstant]; 65 RenderViewContextMenu::ExecuteCommand(id); 66 } 67 68 bool RenderViewContextMenuMac::GetAcceleratorForCommandId( 69 int command_id, 70 ui::Accelerator* accelerator) { 71 return false; 72 } 73 74 void RenderViewContextMenuMac::InitPlatformMenu() { 75 bool has_selection = !params_.selection_text.empty(); 76 77 if (has_selection) { 78 menu_model_.AddSeparator(); 79 menu_model_.AddItemWithStringId( 80 IDC_CONTENT_CONTEXT_LOOK_UP_IN_DICTIONARY, 81 IDS_CONTENT_CONTEXT_LOOK_UP_IN_DICTIONARY); 82 } 83 84 } 85 86 void RenderViewContextMenuMac::LookUpInDictionary() { 87 // TODO(morrita): On Safari, A dictionary panel could be shown 88 // based on a preference setting of Dictionary.app. We currently 89 // don't support it: http://crbug.com/17951 90 NSString* text = base::SysUTF16ToNSString(params_.selection_text); 91 NSPasteboard* pboard = [NSPasteboard pasteboardWithUniqueName]; 92 // 10.5 and earlier require declareTypes before setData. 93 // See the documentation on [NSPasteboard declareTypes]. 94 NSArray* toDeclare = [NSArray arrayWithObject:NSStringPboardType]; 95 [pboard declareTypes:toDeclare owner:nil]; 96 BOOL ok = [pboard setString:text forType:NSStringPboardType]; 97 if (ok) 98 NSPerformService(@"Look Up in Dictionary", pboard); 99 } 100