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

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

Issue 2164483006: [MacViews] Implemented text context menu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix for tapted Created 4 years 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu _mac.h" 5 #include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu _mac.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/mac/mac_util.h" 10 #include "base/mac/mac_util.h"
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 }; 176 };
177 177
178 // Obj-C bridge class that is the target of all items in the context menu. 178 // Obj-C bridge class that is the target of all items in the context menu.
179 // Relies on the tag being set to the command id. 179 // Relies on the tag being set to the command id.
180 180
181 RenderViewContextMenuMac::RenderViewContextMenuMac( 181 RenderViewContextMenuMac::RenderViewContextMenuMac(
182 content::RenderFrameHost* render_frame_host, 182 content::RenderFrameHost* render_frame_host,
183 const content::ContextMenuParams& params, 183 const content::ContextMenuParams& params,
184 NSView* parent_view) 184 NSView* parent_view)
185 : RenderViewContextMenu(render_frame_host, params), 185 : RenderViewContextMenu(render_frame_host, params),
186 speech_submenu_model_(this), 186 parent_view_(parent_view),
187 bidi_submenu_model_(this), 187 text_services_context_menu_(this) {
188 parent_view_(parent_view) {
189 std::unique_ptr<ToolkitDelegate> delegate(new ToolkitDelegateMac(this)); 188 std::unique_ptr<ToolkitDelegate> delegate(new ToolkitDelegateMac(this));
190 set_toolkit_delegate(std::move(delegate)); 189 set_toolkit_delegate(std::move(delegate));
191 } 190 }
192 191
193 RenderViewContextMenuMac::~RenderViewContextMenuMac() { 192 RenderViewContextMenuMac::~RenderViewContextMenuMac() {
194 } 193 }
195 194
196 void RenderViewContextMenuMac::Show() { 195 void RenderViewContextMenuMac::Show() {
197 menu_controller_.reset( 196 menu_controller_.reset(
198 [[MenuController alloc] initWithModel:&menu_model_ 197 [[MenuController alloc] initWithModel:&menu_model_
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 stopwatch.Start(); 237 stopwatch.Start();
239 // Show the menu. 238 // Show the menu.
240 [NSMenu popUpContextMenu:[menu_controller_ menu] 239 [NSMenu popUpContextMenu:[menu_controller_ menu]
241 withEvent:clickEvent 240 withEvent:clickEvent
242 forView:parent_view_]; 241 forView:parent_view_];
243 stopwatch.Stop(); 242 stopwatch.Stop();
244 } 243 }
245 } 244 }
246 245
247 void RenderViewContextMenuMac::ExecuteCommand(int command_id, int event_flags) { 246 void RenderViewContextMenuMac::ExecuteCommand(int command_id, int event_flags) {
248 switch (command_id) { 247 if (text_services_context_menu_.IsTextServicesCommandId(command_id))
249 case IDC_CONTENT_CONTEXT_LOOK_UP: 248 return text_services_context_menu_.ExecuteCommand(command_id, event_flags);
250 LookUpInDictionary();
251 break;
252 249
253 case IDC_CONTENT_CONTEXT_SPEECH_START_SPEAKING: 250 RenderViewContextMenu::ExecuteCommand(command_id, event_flags);
254 StartSpeaking();
255 break;
256
257 case IDC_CONTENT_CONTEXT_SPEECH_STOP_SPEAKING:
258 StopSpeaking();
259 break;
260
261 case IDC_WRITING_DIRECTION_DEFAULT:
262 // WebKit's current behavior is for this menu item to always be disabled.
263 NOTREACHED();
264 break;
265
266 case IDC_WRITING_DIRECTION_RTL:
267 case IDC_WRITING_DIRECTION_LTR: {
268 content::RenderViewHost* view_host = GetRenderViewHost();
269 blink::WebTextDirection dir = blink::WebTextDirectionLeftToRight;
270 if (command_id == IDC_WRITING_DIRECTION_RTL)
271 dir = blink::WebTextDirectionRightToLeft;
272 view_host->GetWidget()->UpdateTextDirection(dir);
273 view_host->GetWidget()->NotifyTextDirection();
274 RenderViewContextMenu::RecordUsedItem(command_id);
275 break;
276 }
277
278 default:
279 RenderViewContextMenu::ExecuteCommand(command_id, event_flags);
280 break;
281 }
282 } 251 }
283 252
284 bool RenderViewContextMenuMac::IsCommandIdChecked(int command_id) const { 253 bool RenderViewContextMenuMac::IsCommandIdChecked(int command_id) const {
285 switch (command_id) { 254 if (text_services_context_menu_.IsTextServicesCommandId(command_id))
286 case IDC_WRITING_DIRECTION_DEFAULT: 255 return text_services_context_menu_.IsCommandIdChecked(command_id);
287 return params_.writing_direction_default &
288 blink::WebContextMenuData::CheckableMenuItemChecked;
289 case IDC_WRITING_DIRECTION_RTL:
290 return params_.writing_direction_right_to_left &
291 blink::WebContextMenuData::CheckableMenuItemChecked;
292 case IDC_WRITING_DIRECTION_LTR:
293 return params_.writing_direction_left_to_right &
294 blink::WebContextMenuData::CheckableMenuItemChecked;
295 256
296 default: 257 return RenderViewContextMenu::IsCommandIdChecked(command_id);
297 return RenderViewContextMenu::IsCommandIdChecked(command_id);
298 }
299 } 258 }
300 259
301 bool RenderViewContextMenuMac::IsCommandIdEnabled(int command_id) const { 260 bool RenderViewContextMenuMac::IsCommandIdEnabled(int command_id) const {
302 switch (command_id) { 261 if (text_services_context_menu_.IsTextServicesCommandId(command_id))
303 case IDC_CONTENT_CONTEXT_LOOK_UP: 262 return text_services_context_menu_.IsCommandIdEnabled(command_id);
304 // This is OK because the menu is not shown when it isn't
305 // appropriate.
306 return true;
307 263
308 case IDC_CONTENT_CONTEXT_SPEECH_START_SPEAKING: 264 return RenderViewContextMenu::IsCommandIdEnabled(command_id);
309 // This is OK because the menu is not shown when it isn't
310 // appropriate.
311 return true;
312
313 case IDC_CONTENT_CONTEXT_SPEECH_STOP_SPEAKING: {
314 content::RenderWidgetHostView* view =
315 GetRenderViewHost()->GetWidget()->GetView();
316 return view && view->IsSpeaking();
317 }
318
319 case IDC_WRITING_DIRECTION_DEFAULT: // Provided to match OS defaults.
320 return params_.writing_direction_default &
321 blink::WebContextMenuData::CheckableMenuItemEnabled;
322 case IDC_WRITING_DIRECTION_RTL:
323 return params_.writing_direction_right_to_left &
324 blink::WebContextMenuData::CheckableMenuItemEnabled;
325 case IDC_WRITING_DIRECTION_LTR:
326 return params_.writing_direction_left_to_right &
327 blink::WebContextMenuData::CheckableMenuItemEnabled;
328
329 default:
330 return RenderViewContextMenu::IsCommandIdEnabled(command_id);
331 }
332 }
333
334 void RenderViewContextMenuMac::AppendPlatformEditableItems() {
tapted 2016/12/16 07:01:19 There might be a regression here. RenderViewContex
spqchan 2016/12/17 00:34:21 Augh, can't believe I missed this. Thanks for catc
335 // OS X provides a contextual menu to set writing direction for BiDi
336 // languages.
337 // This functionality is exposed as a keyboard shortcut on Windows & Linux.
338 AppendBidiSubMenu();
339 } 265 }
340 266
341 void RenderViewContextMenuMac::InitToolkitMenu() { 267 void RenderViewContextMenuMac::InitToolkitMenu() {
342 if (params_.selection_text.empty()) 268 if (params_.selection_text.empty())
343 return; 269 return;
344 270
345 if (params_.link_url.is_empty()) { 271 if (params_.link_url.is_empty()) {
346 // In case the user has selected a word that triggers spelling suggestions, 272 // In case the user has selected a word that triggers spelling suggestions,
347 // show the dictionary lookup under the group that contains the command to 273 // show the dictionary lookup under the group that contains the command to
348 // “Add to Dictionary.” 274 // “Add to Dictionary.”
349 int index = menu_model_.GetIndexOfCommandId( 275 int index = menu_model_.GetIndexOfCommandId(
350 IDC_SPELLCHECK_ADD_TO_DICTIONARY); 276 IDC_SPELLCHECK_ADD_TO_DICTIONARY);
351 if (index < 0) { 277 if (index < 0) {
352 index = 0; 278 index = 0;
353 } else { 279 } else {
354 while (menu_model_.GetTypeAt(index) != ui::MenuModel::TYPE_SEPARATOR) { 280 while (menu_model_.GetTypeAt(index) != ui::MenuModel::TYPE_SEPARATOR) {
355 index++; 281 index++;
356 } 282 }
357 index += 1; // Place it below the separator. 283 index += 1; // Place it below the separator.
tapted 2016/12/16 07:01:19 per comment on prior patchset (and with the separa
spqchan 2016/12/17 00:34:21 Doh, I see what you mean. Fixed it, thanks :)
358 } 284 }
359
360 base::string16 printable_selection_text = PrintableSelectionText();
361 EscapeAmpersands(&printable_selection_text);
362 menu_model_.InsertItemAt(
363 index++,
364 IDC_CONTENT_CONTEXT_LOOK_UP,
365 l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_LOOK_UP,
366 printable_selection_text));
367 menu_model_.InsertSeparatorAt(index++, ui::NORMAL_SEPARATOR);
368 } 285 }
369 286
370 content::RenderWidgetHostView* view = 287 text_services_context_menu_.AppendToContextMenu(&menu_model_);
371 GetRenderViewHost()->GetWidget()->GetView();
372 if (view && view->SupportsSpeech()) {
373 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
374 speech_submenu_model_.AddItemWithStringId(
375 IDC_CONTENT_CONTEXT_SPEECH_START_SPEAKING,
376 IDS_SPEECH_START_SPEAKING_MAC);
377 speech_submenu_model_.AddItemWithStringId(
378 IDC_CONTENT_CONTEXT_SPEECH_STOP_SPEAKING,
379 IDS_SPEECH_STOP_SPEAKING_MAC);
380 menu_model_.AddSubMenu(
381 IDC_CONTENT_CONTEXT_SPEECH_MENU,
382 l10n_util::GetStringUTF16(IDS_SPEECH_MAC),
383 &speech_submenu_model_);
384 }
385 } 288 }
386 289
387 void RenderViewContextMenuMac::CancelToolkitMenu() { 290 void RenderViewContextMenuMac::CancelToolkitMenu() {
388 [menu_controller_ cancel]; 291 [menu_controller_ cancel];
389 } 292 }
390 293
391 void RenderViewContextMenuMac::UpdateToolkitMenuItem( 294 void RenderViewContextMenuMac::UpdateToolkitMenuItem(
392 int command_id, 295 int command_id,
393 bool enabled, 296 bool enabled,
394 bool hidden, 297 bool hidden,
395 const base::string16& title) { 298 const base::string16& title) {
396 NSMenuItem* item = GetMenuItemByID(&menu_model_, [menu_controller_ menu], 299 NSMenuItem* item = GetMenuItemByID(&menu_model_, [menu_controller_ menu],
397 command_id); 300 command_id);
398 if (!item) 301 if (!item)
399 return; 302 return;
400 303
401 // Update the returned NSMenuItem directly so we can update it immediately. 304 // Update the returned NSMenuItem directly so we can update it immediately.
402 [item setEnabled:enabled]; 305 [item setEnabled:enabled];
403 [item setTitle:base::SysUTF16ToNSString(title)]; 306 [item setTitle:base::SysUTF16ToNSString(title)];
404 [item setHidden:hidden]; 307 [item setHidden:hidden];
405 [[item menu] itemChanged:item]; 308 [[item menu] itemChanged:item];
406 } 309 }
407 310
408 void RenderViewContextMenuMac::AppendBidiSubMenu() { 311 base::string16 RenderViewContextMenuMac::GetSelectedText() const {
409 bidi_submenu_model_.AddCheckItem(IDC_WRITING_DIRECTION_DEFAULT, 312 return params_.selection_text;
410 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT)); 313 }
411 bidi_submenu_model_.AddCheckItem(IDC_WRITING_DIRECTION_LTR,
412 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR));
413 bidi_submenu_model_.AddCheckItem(IDC_WRITING_DIRECTION_RTL,
414 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL));
415 314
416 menu_model_.AddSubMenu( 315 void RenderViewContextMenuMac::OnSpeakRequested() {
417 IDC_WRITING_DIRECTION_MENU, 316 content::RenderWidgetHostView* view =
418 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU), 317 GetRenderViewHost()->GetWidget()->GetView();
419 &bidi_submenu_model_); 318 if (view)
319 view->SpeakSelection();
320 }
321
322 bool RenderViewContextMenuMac::IsLookUpAvailable() const {
323 return params_.link_url.is_empty();
420 } 324 }
421 325
422 void RenderViewContextMenuMac::LookUpInDictionary() { 326 void RenderViewContextMenuMac::LookUpInDictionary() {
423 content::RenderWidgetHostView* view = 327 content::RenderWidgetHostView* view =
424 GetRenderViewHost()->GetWidget()->GetView(); 328 GetRenderViewHost()->GetWidget()->GetView();
425 if (view) 329 if (view)
426 view->ShowDefinitionForSelection(); 330 view->ShowDefinitionForSelection();
427 } 331 }
428 332
429 void RenderViewContextMenuMac::StartSpeaking() { 333 bool RenderViewContextMenuMac::IsTextDirectionEnabled(
430 content::RenderWidgetHostView* view = 334 base::i18n::TextDirection direction) const {
431 GetRenderViewHost()->GetWidget()->GetView(); 335 switch (direction) {
432 if (view) 336 case base::i18n::TextDirection::UNKNOWN_DIRECTION:
433 view->SpeakSelection(); 337 return params_.writing_direction_default &
338 blink::WebContextMenuData::CheckableMenuItemEnabled;
339 case base::i18n::TextDirection::RIGHT_TO_LEFT:
340 return params_.writing_direction_right_to_left &
341 blink::WebContextMenuData::CheckableMenuItemEnabled;
342 case base::i18n::TextDirection::LEFT_TO_RIGHT:
343 return params_.writing_direction_left_to_right &
344 blink::WebContextMenuData::CheckableMenuItemEnabled;
345 default:
tapted 2016/12/16 07:01:19 nit: I think the convention is to do case TEXT_
spqchan 2016/12/17 00:34:21 Done. Note, I put NOTREACHED(); return false; unde
346 NOTREACHED();
347 return false;
348 }
434 } 349 }
435 350
436 void RenderViewContextMenuMac::StopSpeaking() { 351 bool RenderViewContextMenuMac::IsTextDirectionChecked(
437 content::RenderWidgetHostView* view = 352 base::i18n::TextDirection direction) const {
438 GetRenderViewHost()->GetWidget()->GetView(); 353 switch (direction) {
439 if (view) 354 case base::i18n::TextDirection::UNKNOWN_DIRECTION:
440 view->StopSpeaking(); 355 return params_.writing_direction_default &
356 blink::WebContextMenuData::CheckableMenuItemChecked;
357 case base::i18n::TextDirection::RIGHT_TO_LEFT:
358 return params_.writing_direction_right_to_left &
359 blink::WebContextMenuData::CheckableMenuItemChecked;
360 case base::i18n::TextDirection::LEFT_TO_RIGHT:
361 return params_.writing_direction_left_to_right &
362 blink::WebContextMenuData::CheckableMenuItemChecked;
363 default:
364 NOTREACHED();
365 return false;
366 }
441 } 367 }
368
369 void RenderViewContextMenuMac::UpdateTextDirection(
370 base::i18n::TextDirection direction) {
371 DCHECK_NE(direction, base::i18n::TextDirection::UNKNOWN_DIRECTION);
372
373 content::RenderViewHost* view_host = GetRenderViewHost();
374 blink::WebTextDirection dir = blink::WebTextDirectionLeftToRight;
375 int command_id = IDC_WRITING_DIRECTION_LTR;
376 if (direction == base::i18n::TextDirection::RIGHT_TO_LEFT) {
377 dir = blink::WebTextDirectionRightToLeft;
378 command_id = IDC_WRITING_DIRECTION_RTL;
379 }
380
381 view_host->GetWidget()->UpdateTextDirection(dir);
382 view_host->GetWidget()->NotifyTextDirection();
383
384 RenderViewContextMenu::RecordUsedItem(command_id);
385 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698