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 19RenderViewContextMenuMac::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 27RenderViewContextMenuMac::~RenderViewContextMenuMac() { 28} 29 30void 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 63void RenderViewContextMenuMac::ExecuteCommand(int id) { 64 [[[parent_view_ window] windowController] commitInstant]; 65 RenderViewContextMenu::ExecuteCommand(id); 66} 67 68bool RenderViewContextMenuMac::GetAcceleratorForCommandId( 69 int command_id, 70 ui::Accelerator* accelerator) { 71 return false; 72} 73 74void 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 86void 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