Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm

Issue 178193005: Move render_view_context_menu.* related files out of tab_contents. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: context_menu->renderer_context_menu for disambiguation Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/ui/cocoa/tab_contents/render_view_context_menu_mac.h"
6
7 #include "base/compiler_specific.h"
8 #import "base/mac/scoped_sending_event.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/render_widget_host_view.h"
14 #include "grit/generated_resources.h"
15 #import "ui/base/cocoa/menu_controller.h"
16 #include "ui/base/l10n/l10n_util.h"
17
18 using content::WebContents;
19
20 namespace {
21
22 // Retrieves an NSMenuItem which has the specified command_id. This function
23 // traverses the given |model| in the depth-first order. When this function
24 // finds an item whose command_id is the same as the given |command_id|, it
25 // returns the NSMenuItem associated with the item. This function emulates
26 // views::MenuItemViews::GetMenuItemByID() for Mac.
27 NSMenuItem* GetMenuItemByID(ui::MenuModel* model,
28 NSMenu* menu,
29 int command_id) {
30 for (int i = 0; i < model->GetItemCount(); ++i) {
31 NSMenuItem* item = [menu itemAtIndex:i];
32 if (model->GetCommandIdAt(i) == command_id)
33 return item;
34
35 ui::MenuModel* submenu = model->GetSubmenuModelAt(i);
36 if (submenu && [item hasSubmenu]) {
37 NSMenuItem* subitem = GetMenuItemByID(submenu,
38 [item submenu],
39 command_id);
40 if (subitem)
41 return subitem;
42 }
43 }
44 return nil;
45 }
46
47 } // namespace
48
49 // Obj-C bridge class that is the target of all items in the context menu.
50 // Relies on the tag being set to the command id.
51
52 RenderViewContextMenuMac::RenderViewContextMenuMac(
53 content::RenderFrameHost* render_frame_host,
54 const content::ContextMenuParams& params,
55 NSView* parent_view)
56 : RenderViewContextMenu(render_frame_host, params),
57 speech_submenu_model_(this),
58 bidi_submenu_model_(this),
59 parent_view_(parent_view) {
60 }
61
62 RenderViewContextMenuMac::~RenderViewContextMenuMac() {
63 }
64
65 void RenderViewContextMenuMac::PlatformInit() {
66 InitPlatformMenu();
67 menu_controller_.reset(
68 [[MenuController alloc] initWithModel:&menu_model_
69 useWithPopUpButtonCell:NO]);
70
71 // Synthesize an event for the click, as there is no certainty that
72 // [NSApp currentEvent] will return a valid event.
73 NSEvent* currentEvent = [NSApp currentEvent];
74 NSWindow* window = [parent_view_ window];
75 NSPoint position = [window mouseLocationOutsideOfEventStream];
76 NSTimeInterval eventTime = [currentEvent timestamp];
77 NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown
78 location:position
79 modifierFlags:NSRightMouseDownMask
80 timestamp:eventTime
81 windowNumber:[window windowNumber]
82 context:nil
83 eventNumber:0
84 clickCount:1
85 pressure:1.0];
86
87 {
88 // Make sure events can be pumped while the menu is up.
89 base::MessageLoop::ScopedNestableTaskAllower allow(
90 base::MessageLoop::current());
91
92 // One of the events that could be pumped is |window.close()|.
93 // User-initiated event-tracking loops protect against this by
94 // setting flags in -[CrApplication sendEvent:], but since
95 // web-content menus are initiated by IPC message the setup has to
96 // be done manually.
97 base::mac::ScopedSendingEvent sendingEventScoper;
98
99 // Show the menu.
100 [NSMenu popUpContextMenu:[menu_controller_ menu]
101 withEvent:clickEvent
102 forView:parent_view_];
103 }
104 }
105
106 void RenderViewContextMenuMac::PlatformCancel() {
107 [menu_controller_ cancel];
108 }
109
110 void RenderViewContextMenuMac::ExecuteCommand(int command_id, int event_flags) {
111 switch (command_id) {
112 case IDC_CONTENT_CONTEXT_LOOK_UP_IN_DICTIONARY:
113 LookUpInDictionary();
114 break;
115
116 case IDC_CONTENT_CONTEXT_SPEECH_START_SPEAKING:
117 StartSpeaking();
118 break;
119
120 case IDC_CONTENT_CONTEXT_SPEECH_STOP_SPEAKING:
121 StopSpeaking();
122 break;
123
124 case IDC_WRITING_DIRECTION_DEFAULT:
125 // WebKit's current behavior is for this menu item to always be disabled.
126 NOTREACHED();
127 break;
128
129 case IDC_WRITING_DIRECTION_RTL:
130 case IDC_WRITING_DIRECTION_LTR: {
131 content::RenderViewHost* view_host = GetRenderViewHost();
132 blink::WebTextDirection dir = blink::WebTextDirectionLeftToRight;
133 if (command_id == IDC_WRITING_DIRECTION_RTL)
134 dir = blink::WebTextDirectionRightToLeft;
135 view_host->UpdateTextDirection(dir);
136 view_host->NotifyTextDirection();
137 break;
138 }
139
140 default:
141 RenderViewContextMenu::ExecuteCommand(command_id, event_flags);
142 break;
143 }
144 }
145
146 bool RenderViewContextMenuMac::IsCommandIdChecked(int command_id) const {
147 switch (command_id) {
148 case IDC_WRITING_DIRECTION_DEFAULT:
149 return params_.writing_direction_default &
150 blink::WebContextMenuData::CheckableMenuItemChecked;
151 case IDC_WRITING_DIRECTION_RTL:
152 return params_.writing_direction_right_to_left &
153 blink::WebContextMenuData::CheckableMenuItemChecked;
154 case IDC_WRITING_DIRECTION_LTR:
155 return params_.writing_direction_left_to_right &
156 blink::WebContextMenuData::CheckableMenuItemChecked;
157
158 default:
159 return RenderViewContextMenu::IsCommandIdChecked(command_id);
160 }
161 }
162
163 bool RenderViewContextMenuMac::IsCommandIdEnabled(int command_id) const {
164 switch (command_id) {
165 case IDC_CONTENT_CONTEXT_LOOK_UP_IN_DICTIONARY:
166 // This is OK because the menu is not shown when it isn't
167 // appropriate.
168 return true;
169
170 case IDC_CONTENT_CONTEXT_SPEECH_START_SPEAKING:
171 // This is OK because the menu is not shown when it isn't
172 // appropriate.
173 return true;
174
175 case IDC_CONTENT_CONTEXT_SPEECH_STOP_SPEAKING: {
176 content::RenderWidgetHostView* view = GetRenderViewHost()->GetView();
177 return view && view->IsSpeaking();
178 }
179
180 case IDC_WRITING_DIRECTION_DEFAULT: // Provided to match OS defaults.
181 return params_.writing_direction_default &
182 blink::WebContextMenuData::CheckableMenuItemEnabled;
183 case IDC_WRITING_DIRECTION_RTL:
184 return params_.writing_direction_right_to_left &
185 blink::WebContextMenuData::CheckableMenuItemEnabled;
186 case IDC_WRITING_DIRECTION_LTR:
187 return params_.writing_direction_left_to_right &
188 blink::WebContextMenuData::CheckableMenuItemEnabled;
189
190 default:
191 return RenderViewContextMenu::IsCommandIdEnabled(command_id);
192 }
193 }
194
195 bool RenderViewContextMenuMac::GetAcceleratorForCommandId(
196 int command_id,
197 ui::Accelerator* accelerator) {
198 return false;
199 }
200
201 void RenderViewContextMenuMac::AppendPlatformEditableItems() {
202 // OS X provides a contextual menu to set writing direction for BiDi
203 // languages.
204 // This functionality is exposed as a keyboard shortcut on Windows & Linux.
205 AppendBidiSubMenu();
206 }
207
208 void RenderViewContextMenuMac::InitPlatformMenu() {
209 bool has_selection = !params_.selection_text.empty();
210
211 if (has_selection) {
212 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
213 menu_model_.AddItemWithStringId(
214 IDC_CONTENT_CONTEXT_LOOK_UP_IN_DICTIONARY,
215 IDS_CONTENT_CONTEXT_LOOK_UP_IN_DICTIONARY);
216
217 content::RenderWidgetHostView* view = GetRenderViewHost()->GetView();
218 if (view && view->SupportsSpeech()) {
219 speech_submenu_model_.AddItemWithStringId(
220 IDC_CONTENT_CONTEXT_SPEECH_START_SPEAKING,
221 IDS_SPEECH_START_SPEAKING_MAC);
222 speech_submenu_model_.AddItemWithStringId(
223 IDC_CONTENT_CONTEXT_SPEECH_STOP_SPEAKING,
224 IDS_SPEECH_STOP_SPEAKING_MAC);
225 menu_model_.AddSubMenu(
226 IDC_CONTENT_CONTEXT_SPEECH_MENU,
227 l10n_util::GetStringUTF16(IDS_SPEECH_MAC),
228 &speech_submenu_model_);
229 }
230 }
231 }
232
233 void RenderViewContextMenuMac::AppendBidiSubMenu() {
234 bidi_submenu_model_.AddCheckItem(IDC_WRITING_DIRECTION_DEFAULT,
235 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT));
236 bidi_submenu_model_.AddCheckItem(IDC_WRITING_DIRECTION_LTR,
237 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR));
238 bidi_submenu_model_.AddCheckItem(IDC_WRITING_DIRECTION_RTL,
239 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL));
240
241 menu_model_.AddSubMenu(
242 IDC_WRITING_DIRECTION_MENU,
243 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU),
244 &bidi_submenu_model_);
245 }
246
247 void RenderViewContextMenuMac::LookUpInDictionary() {
248 content::RenderWidgetHostView* view = GetRenderViewHost()->GetView();
249 if (view)
250 view->ShowDefinitionForSelection();
251 }
252
253 void RenderViewContextMenuMac::StartSpeaking() {
254 content::RenderWidgetHostView* view = GetRenderViewHost()->GetView();
255 if (view)
256 view->SpeakSelection();
257 }
258
259 void RenderViewContextMenuMac::StopSpeaking() {
260 content::RenderWidgetHostView* view = GetRenderViewHost()->GetView();
261 if (view)
262 view->StopSpeaking();
263 }
264
265 void RenderViewContextMenuMac::UpdateMenuItem(int command_id,
266 bool enabled,
267 bool hidden,
268 const base::string16& title) {
269 NSMenuItem* item = GetMenuItemByID(&menu_model_, [menu_controller_ menu],
270 command_id);
271 if (!item)
272 return;
273
274 // Update the returned NSMenuItem directly so we can update it immediately.
275 [item setEnabled:enabled];
276 [item setTitle:SysUTF16ToNSString(title)];
277 [item setHidden:hidden];
278 [[item menu] itemChanged:item];
279 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698