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

Side by Side Diff: content/browser/renderer_host/render_widget_host_view_mac.mm

Issue 2164483006: [MacViews] Implemented text context menu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed tapted's comments and fixed tests Created 3 years, 11 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "content/browser/renderer_host/render_widget_host_view_mac.h" 5 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
6 6
7 #import <Carbon/Carbon.h> 7 #import <Carbon/Carbon.h>
8 #import <objc/runtime.h> 8 #import <objc/runtime.h>
9 #include <OpenGL/gl.h> 9 #include <OpenGL/gl.h>
10 #include <QuartzCore/QuartzCore.h> 10 #include <QuartzCore/QuartzCore.h>
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 #include "content/public/browser/web_contents.h" 66 #include "content/public/browser/web_contents.h"
67 #include "gpu/ipc/common/gpu_messages.h" 67 #include "gpu/ipc/common/gpu_messages.h"
68 #include "skia/ext/platform_canvas.h" 68 #include "skia/ext/platform_canvas.h"
69 #include "skia/ext/skia_utils_mac.h" 69 #include "skia/ext/skia_utils_mac.h"
70 #include "third_party/WebKit/public/platform/WebInputEvent.h" 70 #include "third_party/WebKit/public/platform/WebInputEvent.h"
71 #import "ui/base/clipboard/clipboard_util_mac.h" 71 #import "ui/base/clipboard/clipboard_util_mac.h"
72 #include "ui/base/cocoa/animation_utils.h" 72 #include "ui/base/cocoa/animation_utils.h"
73 #import "ui/base/cocoa/appkit_utils.h" 73 #import "ui/base/cocoa/appkit_utils.h"
74 #include "ui/base/cocoa/cocoa_base_utils.h" 74 #include "ui/base/cocoa/cocoa_base_utils.h"
75 #import "ui/base/cocoa/fullscreen_window_manager.h" 75 #import "ui/base/cocoa/fullscreen_window_manager.h"
76 #include "ui/base/cocoa/text_services_context_menu.h"
76 #import "ui/base/cocoa/underlay_opengl_hosting_window.h" 77 #import "ui/base/cocoa/underlay_opengl_hosting_window.h"
77 #include "ui/base/layout.h" 78 #include "ui/base/layout.h"
78 #include "ui/compositor/compositor.h" 79 #include "ui/compositor/compositor.h"
79 #include "ui/compositor/layer.h" 80 #include "ui/compositor/layer.h"
80 #include "ui/display/display.h" 81 #include "ui/display/display.h"
81 #include "ui/display/screen.h" 82 #include "ui/display/screen.h"
82 #include "ui/events/event_utils.h" 83 #include "ui/events/event_utils.h"
83 #include "ui/events/keycodes/keyboard_codes.h" 84 #include "ui/events/keycodes/keyboard_codes.h"
84 #include "ui/gfx/geometry/dip_util.h" 85 #include "ui/gfx/geometry/dip_util.h"
85 #include "ui/gfx/geometry/point.h" 86 #include "ui/gfx/geometry/point.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 return render_widget_host_view; 131 return render_widget_host_view;
131 content::WebContents* guest = 132 content::WebContents* guest =
132 guest_manager->GetFullPageGuest(web_contents); 133 guest_manager->GetFullPageGuest(web_contents);
133 if (!guest) 134 if (!guest)
134 return render_widget_host_view; 135 return render_widget_host_view;
135 return guest->GetRenderWidgetHostView(); 136 return guest->GetRenderWidgetHostView();
136 } 137 }
137 138
138 } // namespace 139 } // namespace
139 140
140 // These are not documented, so use only after checking -respondsToSelector:.
141 @interface NSApplication (UndocumentedSpeechMethods)
142 - (void)speakString:(NSString*)string;
143 - (void)stopSpeaking:(id)sender;
144 - (BOOL)isSpeaking;
145 @end
146
147 // Private methods: 141 // Private methods:
148 @interface RenderWidgetHostViewCocoa () 142 @interface RenderWidgetHostViewCocoa ()
149 @property(nonatomic, assign) NSRange selectedRange; 143 @property(nonatomic, assign) NSRange selectedRange;
150 @property(nonatomic, assign) NSRange markedRange; 144 @property(nonatomic, assign) NSRange markedRange;
151 145
152 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event; 146 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event;
153 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r; 147 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
154 - (void)processedWheelEvent:(const blink::WebMouseWheelEvent&)event 148 - (void)processedWheelEvent:(const blink::WebMouseWheelEvent&)event
155 consumed:(BOOL)consumed; 149 consumed:(BOOL)consumed;
156 - (void)processedGestureScrollEvent:(const blink::WebGestureEvent&)event 150 - (void)processedGestureScrollEvent:(const blink::WebGestureEvent&)event
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 697
704 if (!display_link_->GetVSyncParameters(&vsync_timebase_, &vsync_interval_)) { 698 if (!display_link_->GetVSyncParameters(&vsync_timebase_, &vsync_interval_)) {
705 vsync_timebase_ = base::TimeTicks(); 699 vsync_timebase_ = base::TimeTicks();
706 vsync_interval_ = base::TimeDelta(); 700 vsync_interval_ = base::TimeDelta();
707 return; 701 return;
708 } 702 }
709 703
710 browser_compositor_->UpdateVSyncParameters(vsync_timebase_, vsync_interval_); 704 browser_compositor_->UpdateVSyncParameters(vsync_timebase_, vsync_interval_);
711 } 705 }
712 706
713 void RenderWidgetHostViewMac::SpeakText(const std::string& text) {
714 [NSApp speakString:base::SysUTF8ToNSString(text)];
715 }
716
717 RenderWidgetHostViewBase* 707 RenderWidgetHostViewBase*
718 RenderWidgetHostViewMac::GetFocusedViewForTextSelection() { 708 RenderWidgetHostViewMac::GetFocusedViewForTextSelection() {
719 // We obtain the TextSelection from focused RWH which is obtained from the 709 // We obtain the TextSelection from focused RWH which is obtained from the
720 // frame tree. BrowserPlugin-based guests' RWH is not part of the frame tree 710 // frame tree. BrowserPlugin-based guests' RWH is not part of the frame tree
721 // and the focused RWH will be that of the embedder which is incorrect. In 711 // and the focused RWH will be that of the embedder which is incorrect. In
722 // this case we should use TextSelection for |this| since RWHV for guest 712 // this case we should use TextSelection for |this| since RWHV for guest
723 // forwards text selection information to its platform view. 713 // forwards text selection information to its platform view.
724 return is_guest_view_hack_ ? this : GetFocusedWidget() 714 return is_guest_view_hack_ ? this : GetFocusedWidget()
725 ? GetFocusedWidget()->GetView() 715 ? GetFocusedWidget()->GetView()
726 : nullptr; 716 : nullptr;
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 RenderWidgetHostViewBase* focused_view = GetFocusedViewForTextSelection(); 996 RenderWidgetHostViewBase* focused_view = GetFocusedViewForTextSelection();
1007 if (!focused_view) 997 if (!focused_view)
1008 return; 998 return;
1009 999
1010 const TextInputManager::TextSelection* selection = 1000 const TextInputManager::TextSelection* selection =
1011 GetTextInputManager()->GetTextSelection(focused_view); 1001 GetTextInputManager()->GetTextSelection(focused_view);
1012 1002
1013 base::string16 text; 1003 base::string16 text;
1014 if (!selection->GetSelectedText(&text)) 1004 if (!selection->GetSelectedText(&text))
1015 return; 1005 return;
1016 selected_text_ = base::UTF16ToUTF8(text); 1006 selected_text_ = text;
1017 1007
1018 [cocoa_view_ setSelectedRange:selection->range.ToNSRange()]; 1008 [cocoa_view_ setSelectedRange:selection->range.ToNSRange()];
1019 // Updates markedRange when there is no marked text so that retrieving 1009 // Updates markedRange when there is no marked text so that retrieving
1020 // markedRange immediately after calling setMarkdText: returns the current 1010 // markedRange immediately after calling setMarkdText: returns the current
1021 // caret position. 1011 // caret position.
1022 if (![cocoa_view_ hasMarkedText]) { 1012 if (![cocoa_view_ hasMarkedText]) {
1023 [cocoa_view_ setMarkedRange:selection->range.ToNSRange()]; 1013 [cocoa_view_ setMarkedRange:selection->range.ToNSRange()];
1024 } 1014 }
1025 1015
1026 // TODO(ekaramad): The following values are tracked by TextInputManager and 1016 // TODO(ekaramad): The following values are tracked by TextInputManager and
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 // set it again every single time the mouse moves. 1084 // set it again every single time the mouse moves.
1095 base::string16 display_text = tooltip_text_; 1085 base::string16 display_text = tooltip_text_;
1096 if (tooltip_text_.length() > kMaxTooltipLength) 1086 if (tooltip_text_.length() > kMaxTooltipLength)
1097 display_text = tooltip_text_.substr(0, kMaxTooltipLength); 1087 display_text = tooltip_text_.substr(0, kMaxTooltipLength);
1098 1088
1099 NSString* tooltip_nsstring = base::SysUTF16ToNSString(display_text); 1089 NSString* tooltip_nsstring = base::SysUTF16ToNSString(display_text);
1100 [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring]; 1090 [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring];
1101 } 1091 }
1102 } 1092 }
1103 1093
1104 bool RenderWidgetHostViewMac::SupportsSpeech() const {
1105 return [NSApp respondsToSelector:@selector(speakString:)] &&
1106 [NSApp respondsToSelector:@selector(stopSpeaking:)];
1107 }
1108
1109 void RenderWidgetHostViewMac::SpeakSelection() { 1094 void RenderWidgetHostViewMac::SpeakSelection() {
1110 if (![NSApp respondsToSelector:@selector(speakString:)]) 1095 if (![NSApp respondsToSelector:@selector(speakString:)])
tapted 2017/01/13 21:37:33 ooh - I think this is no longer needed, since we'r
spqchan 2017/01/26 18:27:00 Done.
1111 return; 1096 return;
1112 1097
1113 if (selected_text_.empty() && render_widget_host_) { 1098 if (selected_text_.empty() && render_widget_host_) {
1114 // If there's no selection, speak all text. Send an asynchronous IPC 1099 // If there's no selection, speak all text. Send an asynchronous IPC
1115 // request for fetching all the text for a webcontent. 1100 // request for fetching all the text for a webcontent.
1116 // ViewMsg_GetRenderedTextCompleted is sent back to IPC Message receiver. 1101 // ViewMsg_GetRenderedTextCompleted is sent back to IPC Message receiver.
1117 render_widget_host_->Send(new ViewMsg_GetRenderedText( 1102 render_widget_host_->Send(new ViewMsg_GetRenderedText(
1118 render_widget_host_->GetRoutingID())); 1103 render_widget_host_->GetRoutingID()));
1119 return; 1104 return;
1120 } 1105 }
1121 1106
1122 SpeakText(selected_text_); 1107 ui::TextServicesContextMenu::SpeakText(selected_text_);
1123 }
1124
1125 bool RenderWidgetHostViewMac::IsSpeaking() const {
1126 return [NSApp respondsToSelector:@selector(isSpeaking)] &&
1127 [NSApp isSpeaking];
1128 }
1129
1130 void RenderWidgetHostViewMac::StopSpeaking() {
1131 if ([NSApp respondsToSelector:@selector(stopSpeaking:)])
1132 [NSApp stopSpeaking:cocoa_view_];
1133 } 1108 }
1134 1109
1135 // 1110 //
1136 // RenderWidgetHostViewCocoa uses the stored selection text, 1111 // RenderWidgetHostViewCocoa uses the stored selection text,
1137 // which implements NSServicesRequests protocol. 1112 // which implements NSServicesRequests protocol.
1138 // 1113 //
1139 1114
1140 void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) { 1115 void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) {
1141 RenderWidgetHostViewBase::SetShowingContextMenu(showing); 1116 RenderWidgetHostViewBase::SetShowingContextMenu(showing);
1142 1117
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 else 1656 else
1682 DisablePasswordInput(); 1657 DisablePasswordInput();
1683 } else { 1658 } else {
1684 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_PASSWORD) 1659 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_PASSWORD)
1685 DisablePasswordInput(); 1660 DisablePasswordInput();
1686 } 1661 }
1687 } 1662 }
1688 1663
1689 void RenderWidgetHostViewMac::OnGetRenderedTextCompleted( 1664 void RenderWidgetHostViewMac::OnGetRenderedTextCompleted(
1690 const std::string& text) { 1665 const std::string& text) {
1691 SpeakText(text); 1666 ui::TextServicesContextMenu::SpeakText(base::UTF8ToUTF16(text));
1692 } 1667 }
1693 1668
1694 void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() { 1669 void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
1695 if (!render_widget_host_ || render_widget_host_->is_hidden()) 1670 if (!render_widget_host_ || render_widget_host_->is_hidden())
1696 return; 1671 return;
1697 1672
1698 // Pausing for one view prevents others from receiving frames. 1673 // Pausing for one view prevents others from receiving frames.
1699 // This may lead to large delays, causing overlaps. See crbug.com/352020. 1674 // This may lead to large delays, causing overlaps. See crbug.com/352020.
1700 if (!allow_pause_for_resize_or_repaint_) 1675 if (!allow_pause_for_resize_or_repaint_)
1701 return; 1676 return;
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
2356 } 2331 }
2357 2332
2358 - (void)showLookUpDictionaryOverlayInternal:(NSAttributedString*) string 2333 - (void)showLookUpDictionaryOverlayInternal:(NSAttributedString*) string
2359 baselinePoint:(NSPoint) baselinePoint 2334 baselinePoint:(NSPoint) baselinePoint
2360 targetView:(NSView*) view { 2335 targetView:(NSView*) view {
2361 if ([string length] == 0) { 2336 if ([string length] == 0) {
2362 // The PDF plugin does not support getting the attributed string at point. 2337 // The PDF plugin does not support getting the attributed string at point.
2363 // Until it does, use NSPerformService(), which opens Dictionary.app. 2338 // Until it does, use NSPerformService(), which opens Dictionary.app.
2364 // TODO(shuchen): Support GetStringAtPoint() & GetStringFromRange() for PDF. 2339 // TODO(shuchen): Support GetStringAtPoint() & GetStringFromRange() for PDF.
2365 // See crbug.com/152438. 2340 // See crbug.com/152438.
2366 NSString* text = base::SysUTF8ToNSString( 2341 NSString* text =
2367 renderWidgetHostView_->selected_text()); 2342 base::SysUTF16ToNSString(renderWidgetHostView_->selected_text());
2368 if ([text length] == 0) 2343 if ([text length] == 0)
2369 return; 2344 return;
2370 scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard; 2345 scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard;
2371 NSArray* types = [NSArray arrayWithObject:NSStringPboardType]; 2346 NSArray* types = [NSArray arrayWithObject:NSStringPboardType];
2372 [pasteboard->get() declareTypes:types owner:nil]; 2347 [pasteboard->get() declareTypes:types owner:nil];
2373 if ([pasteboard->get() setString:text forType:NSStringPboardType]) 2348 if ([pasteboard->get() setString:text forType:NSStringPboardType])
2374 NSPerformService(@"Look Up in Dictionary", pasteboard->get()); 2349 NSPerformService(@"Look Up in Dictionary", pasteboard->get());
2375 return; 2350 return;
2376 } 2351 }
2377 dispatch_async(dispatch_get_main_queue(), ^{ 2352 dispatch_async(dispatch_get_main_queue(), ^{
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2748 if (known) 2723 if (known)
2749 return valid; 2724 return valid;
2750 } 2725 }
2751 2726
2752 SEL action = [item action]; 2727 SEL action = [item action];
2753 BOOL is_render_view = 2728 BOOL is_render_view =
2754 RenderViewHost::From(renderWidgetHostView_->render_widget_host_) != 2729 RenderViewHost::From(renderWidgetHostView_->render_widget_host_) !=
2755 nullptr; 2730 nullptr;
2756 2731
2757 if (action == @selector(stopSpeaking:)) 2732 if (action == @selector(stopSpeaking:))
2758 return is_render_view && renderWidgetHostView_->IsSpeaking(); 2733 return is_render_view && ui::TextServicesContextMenu::IsSpeaking();
2759 2734
2760 if (action == @selector(startSpeaking:)) 2735 if (action == @selector(startSpeaking:))
2761 return is_render_view && renderWidgetHostView_->SupportsSpeech(); 2736 return is_render_view;
2762 2737
2763 // For now, these actions are always enabled for render view, 2738 // For now, these actions are always enabled for render view,
2764 // this is sub-optimal. 2739 // this is sub-optimal.
2765 // TODO(suzhe): Plumb the "can*" methods up from WebCore. 2740 // TODO(suzhe): Plumb the "can*" methods up from WebCore.
2766 if (action == @selector(undo:) || 2741 if (action == @selector(undo:) ||
2767 action == @selector(redo:) || 2742 action == @selector(redo:) ||
2768 action == @selector(cut:) || 2743 action == @selector(cut:) ||
2769 action == @selector(copy:) || 2744 action == @selector(copy:) ||
2770 action == @selector(copyToFindPboard:) || 2745 action == @selector(copyToFindPboard:) ||
2771 action == @selector(paste:) || 2746 action == @selector(paste:) ||
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
3344 renderWidgetHostView_->render_widget_host_->delegate(); 3319 renderWidgetHostView_->render_widget_host_->delegate();
3345 if (render_widget_host_delegate) 3320 if (render_widget_host_delegate)
3346 render_widget_host_delegate->SelectAll(); 3321 render_widget_host_delegate->SelectAll();
3347 } 3322 }
3348 3323
3349 - (void)startSpeaking:(id)sender { 3324 - (void)startSpeaking:(id)sender {
3350 GetRenderWidgetHostViewToUse(renderWidgetHostView_.get())->SpeakSelection(); 3325 GetRenderWidgetHostViewToUse(renderWidgetHostView_.get())->SpeakSelection();
3351 } 3326 }
3352 3327
3353 - (void)stopSpeaking:(id)sender { 3328 - (void)stopSpeaking:(id)sender {
3354 GetRenderWidgetHostViewToUse(renderWidgetHostView_.get())->StopSpeaking(); 3329 ui::TextServicesContextMenu::StopSpeaking();
3355 } 3330 }
3356 3331
3357 - (void)cancelComposition { 3332 - (void)cancelComposition {
3358 if (!hasMarkedText_) 3333 if (!hasMarkedText_)
3359 return; 3334 return;
3360 3335
3361 NSTextInputContext* inputContext = [self inputContext]; 3336 NSTextInputContext* inputContext = [self inputContext];
3362 [inputContext discardMarkedText]; 3337 [inputContext discardMarkedText];
3363 3338
3364 hasMarkedText_ = NO; 3339 hasMarkedText_ = NO;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3415 3390
3416 @end 3391 @end
3417 3392
3418 // 3393 //
3419 // Supporting application services 3394 // Supporting application services
3420 // 3395 //
3421 @implementation RenderWidgetHostViewCocoa(NSServicesRequests) 3396 @implementation RenderWidgetHostViewCocoa(NSServicesRequests)
3422 3397
3423 - (BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard 3398 - (BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard
3424 types:(NSArray*)types { 3399 types:(NSArray*)types {
3425 const std::string& str = renderWidgetHostView_->selected_text(); 3400 const base::string16& str = renderWidgetHostView_->selected_text();
3426 if (![types containsObject:NSStringPboardType] || str.empty()) return NO; 3401 if (![types containsObject:NSStringPboardType] || str.empty()) return NO;
3427 3402
3428 base::scoped_nsobject<NSString> text(
3429 [[NSString alloc] initWithUTF8String:str.c_str()]);
3430 NSArray* toDeclare = [NSArray arrayWithObject:NSStringPboardType]; 3403 NSArray* toDeclare = [NSArray arrayWithObject:NSStringPboardType];
3431 [pboard declareTypes:toDeclare owner:nil]; 3404 [pboard declareTypes:toDeclare owner:nil];
3432 return [pboard setString:text forType:NSStringPboardType]; 3405 return [pboard setString:SysUTF16ToNSString(str) forType:NSStringPboardType];
3433 } 3406 }
3434 3407
3435 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard { 3408 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard {
3436 NSString *string = [pboard stringForType:NSStringPboardType]; 3409 NSString *string = [pboard stringForType:NSStringPboardType];
3437 if (!string) return NO; 3410 if (!string) return NO;
3438 3411
3439 // If the user is currently using an IME, confirm the IME input, 3412 // If the user is currently using an IME, confirm the IME input,
3440 // and then insert the text from the service, the same as TextEdit and Safari. 3413 // and then insert the text from the service, the same as TextEdit and Safari.
3441 [self finishComposingText]; 3414 [self finishComposingText];
3442 [self insertText:string]; 3415 [self insertText:string];
3443 return YES; 3416 return YES;
3444 } 3417 }
3445 3418
3446 - (BOOL)isOpaque { 3419 - (BOOL)isOpaque {
3447 return opaque_; 3420 return opaque_;
3448 } 3421 }
3449 3422
3450 // "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding 3423 // "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding
3451 // regions that are not draggable. (See ControlRegionView in 3424 // regions that are not draggable. (See ControlRegionView in
3452 // native_app_window_cocoa.mm). This requires the render host view to be 3425 // native_app_window_cocoa.mm). This requires the render host view to be
3453 // draggable by default. 3426 // draggable by default.
3454 - (BOOL)mouseDownCanMoveWindow { 3427 - (BOOL)mouseDownCanMoveWindow {
3455 return YES; 3428 return YES;
3456 } 3429 }
3457 3430
3458 @end 3431 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698