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

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: Fix for tapted 2 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 (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 541 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 692
699 if (!display_link_->GetVSyncParameters(&vsync_timebase_, &vsync_interval_)) { 693 if (!display_link_->GetVSyncParameters(&vsync_timebase_, &vsync_interval_)) {
700 vsync_timebase_ = base::TimeTicks(); 694 vsync_timebase_ = base::TimeTicks();
701 vsync_interval_ = base::TimeDelta(); 695 vsync_interval_ = base::TimeDelta();
702 return; 696 return;
703 } 697 }
704 698
705 browser_compositor_->UpdateVSyncParameters(vsync_timebase_, vsync_interval_); 699 browser_compositor_->UpdateVSyncParameters(vsync_timebase_, vsync_interval_);
706 } 700 }
707 701
708 void RenderWidgetHostViewMac::SpeakText(const std::string& text) {
709 [NSApp speakString:base::SysUTF8ToNSString(text)];
710 }
711
712 RenderWidgetHostViewBase* 702 RenderWidgetHostViewBase*
713 RenderWidgetHostViewMac::GetFocusedViewForTextSelection() { 703 RenderWidgetHostViewMac::GetFocusedViewForTextSelection() {
714 // We obtain the TextSelection from focused RWH which is obtained from the 704 // We obtain the TextSelection from focused RWH which is obtained from the
715 // frame tree. BrowserPlugin-based guests' RWH is not part of the frame tree 705 // frame tree. BrowserPlugin-based guests' RWH is not part of the frame tree
716 // and the focused RWH will be that of the embedder which is incorrect. In 706 // and the focused RWH will be that of the embedder which is incorrect. In
717 // this case we should use TextSelection for |this| since RWHV for guest 707 // this case we should use TextSelection for |this| since RWHV for guest
718 // forwards text selection information to its platform view. 708 // forwards text selection information to its platform view.
719 return is_guest_view_hack_ ? this : GetFocusedWidget() 709 return is_guest_view_hack_ ? this : GetFocusedWidget()
720 ? GetFocusedWidget()->GetView() 710 ? GetFocusedWidget()->GetView()
721 : nullptr; 711 : nullptr;
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 990
1001 RenderWidgetHostViewBase* focused_view = GetFocusedViewForTextSelection(); 991 RenderWidgetHostViewBase* focused_view = GetFocusedViewForTextSelection();
1002 if (!focused_view) 992 if (!focused_view)
1003 return; 993 return;
1004 994
1005 const TextInputManager::TextSelection* selection = 995 const TextInputManager::TextSelection* selection =
1006 GetTextInputManager()->GetTextSelection(focused_view); 996 GetTextInputManager()->GetTextSelection(focused_view);
1007 997
1008 base::string16 text; 998 base::string16 text;
1009 if (selection->GetSelectedText(&text)) 999 if (selection->GetSelectedText(&text))
1010 selected_text_ = base::UTF16ToUTF8(text); 1000 selected_text_ = text;
1011 1001
1012 [cocoa_view_ setSelectedRange:selection->range.ToNSRange()]; 1002 [cocoa_view_ setSelectedRange:selection->range.ToNSRange()];
1013 // Updates markedRange when there is no marked text so that retrieving 1003 // Updates markedRange when there is no marked text so that retrieving
1014 // markedRange immediately after calling setMarkdText: returns the current 1004 // markedRange immediately after calling setMarkdText: returns the current
1015 // caret position. 1005 // caret position.
1016 if (![cocoa_view_ hasMarkedText]) { 1006 if (![cocoa_view_ hasMarkedText]) {
1017 [cocoa_view_ setMarkedRange:selection->range.ToNSRange()]; 1007 [cocoa_view_ setMarkedRange:selection->range.ToNSRange()];
1018 } 1008 }
1019 1009
1020 // TODO(ekaramad): The following values are tracked by TextInputManager and 1010 // TODO(ekaramad): The following values are tracked by TextInputManager and
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 // set it again every single time the mouse moves. 1078 // set it again every single time the mouse moves.
1089 base::string16 display_text = tooltip_text_; 1079 base::string16 display_text = tooltip_text_;
1090 if (tooltip_text_.length() > kMaxTooltipLength) 1080 if (tooltip_text_.length() > kMaxTooltipLength)
1091 display_text = tooltip_text_.substr(0, kMaxTooltipLength); 1081 display_text = tooltip_text_.substr(0, kMaxTooltipLength);
1092 1082
1093 NSString* tooltip_nsstring = base::SysUTF16ToNSString(display_text); 1083 NSString* tooltip_nsstring = base::SysUTF16ToNSString(display_text);
1094 [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring]; 1084 [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring];
1095 } 1085 }
1096 } 1086 }
1097 1087
1098 bool RenderWidgetHostViewMac::SupportsSpeech() const {
1099 return [NSApp respondsToSelector:@selector(speakString:)] &&
1100 [NSApp respondsToSelector:@selector(stopSpeaking:)];
1101 }
1102
1103 void RenderWidgetHostViewMac::SpeakSelection() { 1088 void RenderWidgetHostViewMac::SpeakSelection() {
1104 if (![NSApp respondsToSelector:@selector(speakString:)]) 1089 if (![NSApp respondsToSelector:@selector(speakString:)])
1105 return; 1090 return;
1106 1091
1107 if (selected_text_.empty() && render_widget_host_) { 1092 if (selected_text_.empty() && render_widget_host_) {
1108 // If there's no selection, speak all text. Send an asynchronous IPC 1093 // If there's no selection, speak all text. Send an asynchronous IPC
1109 // request for fetching all the text for a webcontent. 1094 // request for fetching all the text for a webcontent.
1110 // ViewMsg_GetRenderedTextCompleted is sent back to IPC Message receiver. 1095 // ViewMsg_GetRenderedTextCompleted is sent back to IPC Message receiver.
1111 render_widget_host_->Send(new ViewMsg_GetRenderedText( 1096 render_widget_host_->Send(new ViewMsg_GetRenderedText(
1112 render_widget_host_->GetRoutingID())); 1097 render_widget_host_->GetRoutingID()));
1113 return; 1098 return;
1114 } 1099 }
1115 1100
1116 SpeakText(selected_text_); 1101 ui::TextServicesContextMenu::SpeakText(selected_text_);
1117 }
1118
1119 bool RenderWidgetHostViewMac::IsSpeaking() const {
1120 return [NSApp respondsToSelector:@selector(isSpeaking)] &&
1121 [NSApp isSpeaking];
1122 }
1123
1124 void RenderWidgetHostViewMac::StopSpeaking() {
1125 if ([NSApp respondsToSelector:@selector(stopSpeaking:)])
1126 [NSApp stopSpeaking:cocoa_view_];
1127 } 1102 }
1128 1103
1129 // 1104 //
1130 // RenderWidgetHostViewCocoa uses the stored selection text, 1105 // RenderWidgetHostViewCocoa uses the stored selection text,
1131 // which implements NSServicesRequests protocol. 1106 // which implements NSServicesRequests protocol.
1132 // 1107 //
1133 1108
1134 void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) { 1109 void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) {
1135 RenderWidgetHostViewBase::SetShowingContextMenu(showing); 1110 RenderWidgetHostViewBase::SetShowingContextMenu(showing);
1136 1111
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
1670 else 1645 else
1671 DisablePasswordInput(); 1646 DisablePasswordInput();
1672 } else { 1647 } else {
1673 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_PASSWORD) 1648 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_PASSWORD)
1674 DisablePasswordInput(); 1649 DisablePasswordInput();
1675 } 1650 }
1676 } 1651 }
1677 1652
1678 void RenderWidgetHostViewMac::OnGetRenderedTextCompleted( 1653 void RenderWidgetHostViewMac::OnGetRenderedTextCompleted(
1679 const std::string& text) { 1654 const std::string& text) {
1680 SpeakText(text); 1655 ui::TextServicesContextMenu::SpeakText(base::UTF8ToUTF16(text));
1681 } 1656 }
1682 1657
1683 void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() { 1658 void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
1684 if (!render_widget_host_ || render_widget_host_->is_hidden()) 1659 if (!render_widget_host_ || render_widget_host_->is_hidden())
1685 return; 1660 return;
1686 1661
1687 // Pausing for one view prevents others from receiving frames. 1662 // Pausing for one view prevents others from receiving frames.
1688 // This may lead to large delays, causing overlaps. See crbug.com/352020. 1663 // This may lead to large delays, causing overlaps. See crbug.com/352020.
1689 if (!allow_pause_for_resize_or_repaint_) 1664 if (!allow_pause_for_resize_or_repaint_)
1690 return; 1665 return;
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
2345 } 2320 }
2346 2321
2347 - (void)showLookUpDictionaryOverlayInternal:(NSAttributedString*) string 2322 - (void)showLookUpDictionaryOverlayInternal:(NSAttributedString*) string
2348 baselinePoint:(NSPoint) baselinePoint 2323 baselinePoint:(NSPoint) baselinePoint
2349 targetView:(NSView*) view { 2324 targetView:(NSView*) view {
2350 if ([string length] == 0) { 2325 if ([string length] == 0) {
2351 // The PDF plugin does not support getting the attributed string at point. 2326 // The PDF plugin does not support getting the attributed string at point.
2352 // Until it does, use NSPerformService(), which opens Dictionary.app. 2327 // Until it does, use NSPerformService(), which opens Dictionary.app.
2353 // TODO(shuchen): Support GetStringAtPoint() & GetStringFromRange() for PDF. 2328 // TODO(shuchen): Support GetStringAtPoint() & GetStringFromRange() for PDF.
2354 // See crbug.com/152438. 2329 // See crbug.com/152438.
2355 NSString* text = base::SysUTF8ToNSString( 2330 NSString* text =
2356 renderWidgetHostView_->selected_text()); 2331 base::SysUTF16ToNSString(renderWidgetHostView_->selected_text());
2357 if ([text length] == 0) 2332 if ([text length] == 0)
2358 return; 2333 return;
2359 scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard; 2334 scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard;
2360 NSArray* types = [NSArray arrayWithObject:NSStringPboardType]; 2335 NSArray* types = [NSArray arrayWithObject:NSStringPboardType];
2361 [pasteboard->get() declareTypes:types owner:nil]; 2336 [pasteboard->get() declareTypes:types owner:nil];
2362 if ([pasteboard->get() setString:text forType:NSStringPboardType]) 2337 if ([pasteboard->get() setString:text forType:NSStringPboardType])
2363 NSPerformService(@"Look Up in Dictionary", pasteboard->get()); 2338 NSPerformService(@"Look Up in Dictionary", pasteboard->get());
2364 return; 2339 return;
2365 } 2340 }
2366 dispatch_async(dispatch_get_main_queue(), ^{ 2341 dispatch_async(dispatch_get_main_queue(), ^{
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2737 if (known) 2712 if (known)
2738 return valid; 2713 return valid;
2739 } 2714 }
2740 2715
2741 SEL action = [item action]; 2716 SEL action = [item action];
2742 BOOL is_render_view = 2717 BOOL is_render_view =
2743 RenderViewHost::From(renderWidgetHostView_->render_widget_host_) != 2718 RenderViewHost::From(renderWidgetHostView_->render_widget_host_) !=
2744 nullptr; 2719 nullptr;
2745 2720
2746 if (action == @selector(stopSpeaking:)) 2721 if (action == @selector(stopSpeaking:))
2747 return is_render_view && renderWidgetHostView_->IsSpeaking(); 2722 return is_render_view && ui::TextServicesContextMenu::IsSpeaking();
2748 2723
2749 if (action == @selector(startSpeaking:)) 2724 if (action == @selector(startSpeaking:))
2750 return is_render_view && renderWidgetHostView_->SupportsSpeech(); 2725 return is_render_view;
2751 2726
2752 // For now, these actions are always enabled for render view, 2727 // For now, these actions are always enabled for render view,
2753 // this is sub-optimal. 2728 // this is sub-optimal.
2754 // TODO(suzhe): Plumb the "can*" methods up from WebCore. 2729 // TODO(suzhe): Plumb the "can*" methods up from WebCore.
2755 if (action == @selector(undo:) || 2730 if (action == @selector(undo:) ||
2756 action == @selector(redo:) || 2731 action == @selector(redo:) ||
2757 action == @selector(cut:) || 2732 action == @selector(cut:) ||
2758 action == @selector(copy:) || 2733 action == @selector(copy:) ||
2759 action == @selector(copyToFindPboard:) || 2734 action == @selector(copyToFindPboard:) ||
2760 action == @selector(paste:) || 2735 action == @selector(paste:) ||
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
3333 renderWidgetHostView_->render_widget_host_->delegate(); 3308 renderWidgetHostView_->render_widget_host_->delegate();
3334 if (render_widget_host_delegate) 3309 if (render_widget_host_delegate)
3335 render_widget_host_delegate->SelectAll(); 3310 render_widget_host_delegate->SelectAll();
3336 } 3311 }
3337 3312
3338 - (void)startSpeaking:(id)sender { 3313 - (void)startSpeaking:(id)sender {
3339 GetRenderWidgetHostViewToUse(renderWidgetHostView_.get())->SpeakSelection(); 3314 GetRenderWidgetHostViewToUse(renderWidgetHostView_.get())->SpeakSelection();
3340 } 3315 }
3341 3316
3342 - (void)stopSpeaking:(id)sender { 3317 - (void)stopSpeaking:(id)sender {
3343 GetRenderWidgetHostViewToUse(renderWidgetHostView_.get())->StopSpeaking(); 3318 ui::TextServicesContextMenu::StopSpeaking();
3344 } 3319 }
3345 3320
3346 - (void)cancelComposition { 3321 - (void)cancelComposition {
3347 if (!hasMarkedText_) 3322 if (!hasMarkedText_)
3348 return; 3323 return;
3349 3324
3350 NSTextInputContext* inputContext = [self inputContext]; 3325 NSTextInputContext* inputContext = [self inputContext];
3351 [inputContext discardMarkedText]; 3326 [inputContext discardMarkedText];
3352 3327
3353 hasMarkedText_ = NO; 3328 hasMarkedText_ = NO;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3404 3379
3405 @end 3380 @end
3406 3381
3407 // 3382 //
3408 // Supporting application services 3383 // Supporting application services
3409 // 3384 //
3410 @implementation RenderWidgetHostViewCocoa(NSServicesRequests) 3385 @implementation RenderWidgetHostViewCocoa(NSServicesRequests)
3411 3386
3412 - (BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard 3387 - (BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard
3413 types:(NSArray*)types { 3388 types:(NSArray*)types {
3414 const std::string& str = renderWidgetHostView_->selected_text(); 3389 const base::string16& str = renderWidgetHostView_->selected_text();
3415 if (![types containsObject:NSStringPboardType] || str.empty()) return NO; 3390 if (![types containsObject:NSStringPboardType] || str.empty()) return NO;
3416 3391
3417 base::scoped_nsobject<NSString> text( 3392 base::scoped_nsobject<NSString> text(SysUTF16ToNSString(str));
tapted 2016/12/19 07:41:21 This might be a refcounting bug (nsobject expects
spqchan 2016/12/21 01:03:02 Done.
3418 [[NSString alloc] initWithUTF8String:str.c_str()]);
3419 NSArray* toDeclare = [NSArray arrayWithObject:NSStringPboardType]; 3393 NSArray* toDeclare = [NSArray arrayWithObject:NSStringPboardType];
3420 [pboard declareTypes:toDeclare owner:nil]; 3394 [pboard declareTypes:toDeclare owner:nil];
3421 return [pboard setString:text forType:NSStringPboardType]; 3395 return [pboard setString:text forType:NSStringPboardType];
3422 } 3396 }
3423 3397
3424 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard { 3398 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard {
3425 NSString *string = [pboard stringForType:NSStringPboardType]; 3399 NSString *string = [pboard stringForType:NSStringPboardType];
3426 if (!string) return NO; 3400 if (!string) return NO;
3427 3401
3428 // If the user is currently using an IME, confirm the IME input, 3402 // If the user is currently using an IME, confirm the IME input,
3429 // and then insert the text from the service, the same as TextEdit and Safari. 3403 // and then insert the text from the service, the same as TextEdit and Safari.
3430 [self finishComposingText]; 3404 [self finishComposingText];
3431 [self insertText:string]; 3405 [self insertText:string];
3432 return YES; 3406 return YES;
3433 } 3407 }
3434 3408
3435 - (BOOL)isOpaque { 3409 - (BOOL)isOpaque {
3436 return opaque_; 3410 return opaque_;
3437 } 3411 }
3438 3412
3439 // "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding 3413 // "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding
3440 // regions that are not draggable. (See ControlRegionView in 3414 // regions that are not draggable. (See ControlRegionView in
3441 // native_app_window_cocoa.mm). This requires the render host view to be 3415 // native_app_window_cocoa.mm). This requires the render host view to be
3442 // draggable by default. 3416 // draggable by default.
3443 - (BOOL)mouseDownCanMoveWindow { 3417 - (BOOL)mouseDownCanMoveWindow {
3444 return YES; 3418 return YES;
3445 } 3419 }
3446 3420
3447 @end 3421 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698