Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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 <QuartzCore/QuartzCore.h> | 5 #include <QuartzCore/QuartzCore.h> |
| 6 | 6 |
| 7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" | 7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" |
| 8 | 8 |
| 9 #include "app/app_switches.h" | 9 #include "app/app_switches.h" |
| 10 #include "app/surface/io_surface_support_mac.h" | 10 #include "app/surface/io_surface_support_mac.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/mac/scoped_cftyperef.h" | 13 #include "base/mac/scoped_cftyperef.h" |
| 14 #import "base/mac/scoped_nsautorelease_pool.h" | 14 #import "base/mac/scoped_nsautorelease_pool.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #import "base/scoped_nsobject.h" | 16 #import "base/scoped_nsobject.h" |
| 17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
| 18 #include "base/sys_info.h" | 18 #include "base/sys_info.h" |
| 19 #include "base/sys_string_conversions.h" | 19 #include "base/sys_string_conversions.h" |
| 20 #import "chrome/browser/accessibility/browser_accessibility_cocoa.h" | 20 #import "chrome/browser/accessibility/browser_accessibility_cocoa.h" |
| 21 #include "chrome/browser/accessibility/browser_accessibility_state.h" | 21 #include "chrome/browser/accessibility/browser_accessibility_state.h" |
| 22 #include "chrome/browser/browser_thread.h" | 22 #include "chrome/browser/browser_thread.h" |
| 23 #include "chrome/browser/browser_trial.h" | 23 #include "chrome/browser/browser_trial.h" |
| 24 #include "chrome/browser/gpu_process_host.h" | 24 #include "chrome/browser/gpu_process_host.h" |
| 25 #include "chrome/browser/plugin_process_host.h" | 25 #include "chrome/browser/plugin_process_host.h" |
| 26 #include "chrome/browser/renderer_host/backing_store_mac.h" | 26 #include "chrome/browser/renderer_host/backing_store_mac.h" |
| 27 #include "chrome/browser/renderer_host/render_process_host.h" | 27 #include "chrome/browser/renderer_host/render_process_host.h" |
| 28 #include "chrome/browser/renderer_host/render_view_host.h" | 28 #include "chrome/browser/renderer_host/render_view_host.h" |
| 29 #include "chrome/browser/renderer_host/render_widget_host.h" | 29 #include "chrome/browser/renderer_host/render_widget_host.h" |
| 30 #import "chrome/browser/renderer_host/text_input_client_mac.h" | |
| 30 #include "chrome/browser/spellchecker_platform_engine.h" | 31 #include "chrome/browser/spellchecker_platform_engine.h" |
| 31 #import "chrome/browser/ui/cocoa/rwhvm_editcommand_helper.h" | 32 #import "chrome/browser/ui/cocoa/rwhvm_editcommand_helper.h" |
| 32 #import "chrome/browser/ui/cocoa/view_id_util.h" | 33 #import "chrome/browser/ui/cocoa/view_id_util.h" |
| 33 #include "chrome/common/chrome_switches.h" | 34 #include "chrome/common/chrome_switches.h" |
| 34 #include "chrome/common/native_web_keyboard_event.h" | 35 #include "chrome/common/native_web_keyboard_event.h" |
| 35 #include "chrome/common/edit_command.h" | 36 #include "chrome/common/edit_command.h" |
| 36 #include "chrome/common/gpu_messages.h" | 37 #include "chrome/common/gpu_messages.h" |
| 37 #include "chrome/common/plugin_messages.h" | 38 #include "chrome/common/plugin_messages.h" |
| 38 #include "chrome/common/render_messages.h" | 39 #include "chrome/common/render_messages.h" |
| 40 #include "gfx/point.h" | |
| 39 #include "skia/ext/platform_canvas.h" | 41 #include "skia/ext/platform_canvas.h" |
| 40 #include "third_party/skia/include/core/SkColor.h" | 42 #include "third_party/skia/include/core/SkColor.h" |
| 41 #include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebInputEventFact ory.h" | 43 #include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebInputEventFact ory.h" |
| 42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | 44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
| 43 #include "webkit/glue/webaccessibility.h" | 45 #include "webkit/glue/webaccessibility.h" |
| 44 #include "webkit/plugins/npapi/webplugin.h" | 46 #include "webkit/plugins/npapi/webplugin.h" |
| 45 #import "third_party/mozilla/ComplexTextInputPanel.h" | 47 #import "third_party/mozilla/ComplexTextInputPanel.h" |
| 46 | 48 |
| 47 using WebKit::WebInputEvent; | 49 using WebKit::WebInputEvent; |
| 48 using WebKit::WebInputEventFactory; | 50 using WebKit::WebInputEventFactory; |
| 49 using WebKit::WebMouseEvent; | 51 using WebKit::WebMouseEvent; |
| 50 using WebKit::WebMouseWheelEvent; | 52 using WebKit::WebMouseWheelEvent; |
| 51 | 53 |
| 52 static inline int ToWebKitModifiers(NSUInteger flags) { | 54 static inline int ToWebKitModifiers(NSUInteger flags) { |
| 53 int modifiers = 0; | 55 int modifiers = 0; |
| 54 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; | 56 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; |
| 55 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey; | 57 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey; |
| 56 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; | 58 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; |
| 57 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; | 59 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; |
| 58 return modifiers; | 60 return modifiers; |
| 59 } | 61 } |
| 60 | 62 |
| 61 @interface RenderWidgetHostViewCocoa (Private) | 63 @interface RenderWidgetHostViewCocoa (Private) |
| 62 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event; | 64 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event; |
| 63 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r; | 65 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r; |
| 64 - (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv; | 66 - (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv; |
| 65 - (void)cancelChildPopups; | 67 - (void)cancelChildPopups; |
| 68 - (void)setSelectedRange:(NSRange)range; | |
| 66 @end | 69 @end |
| 67 | 70 |
| 68 // This API was published since 10.6. Provide the declaration so it can be | 71 // This API was published since 10.6. Provide the declaration so it can be |
| 69 // // called below when building with the 10.5 SDK. | 72 // // called below when building with the 10.5 SDK. |
| 70 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 | 73 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 |
| 71 @class NSTextInputContext; | 74 @class NSTextInputContext; |
| 72 @interface NSResponder (AppKitDetails) | 75 @interface NSResponder (AppKitDetails) |
| 73 - (NSTextInputContext *)inputContext; | 76 - (NSTextInputContext *)inputContext; |
| 74 @end | 77 @end |
| 75 #endif | 78 #endif |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 721 } | 724 } |
| 722 | 725 |
| 723 void RenderWidgetHostViewMac::ImeUpdateTextInputState( | 726 void RenderWidgetHostViewMac::ImeUpdateTextInputState( |
| 724 WebKit::WebTextInputType type, | 727 WebKit::WebTextInputType type, |
| 725 const gfx::Rect& caret_rect) { | 728 const gfx::Rect& caret_rect) { |
| 726 if (text_input_type_ != type) { | 729 if (text_input_type_ != type) { |
| 727 text_input_type_ = type; | 730 text_input_type_ = type; |
| 728 if (HasFocus()) | 731 if (HasFocus()) |
| 729 SetTextInputActive(true); | 732 SetTextInputActive(true); |
| 730 } | 733 } |
| 731 | |
| 732 // We need to convert the coordinate of the cursor rectangle sent from the | |
| 733 // renderer and save it. Our input method backend uses a coordinate system | |
| 734 // whose origin is the upper-left corner of this view. On the other hand, | |
| 735 // Cocoa uses a coordinate system whose origin is the lower-left corner of | |
| 736 // this view. So, we convert the cursor rectangle and save it. | |
| 737 [cocoa_view_ setCaretRect:[cocoa_view_ flipRectToNSRect:caret_rect]]; | |
| 738 } | 734 } |
| 739 | 735 |
| 740 void RenderWidgetHostViewMac::ImeCancelComposition() { | 736 void RenderWidgetHostViewMac::ImeCancelComposition() { |
| 741 [cocoa_view_ cancelComposition]; | 737 [cocoa_view_ cancelComposition]; |
| 742 } | 738 } |
| 743 | 739 |
| 744 void RenderWidgetHostViewMac::DidUpdateBackingStore( | 740 void RenderWidgetHostViewMac::DidUpdateBackingStore( |
| 745 const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, | 741 const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, |
| 746 const std::vector<gfx::Rect>& copy_rects) { | 742 const std::vector<gfx::Rect>& copy_rects) { |
| 747 if (!is_hidden_) { | 743 if (!is_hidden_) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 851 | 847 |
| 852 NSString* tooltip_nsstring = base::SysWideToNSString(display_text); | 848 NSString* tooltip_nsstring = base::SysWideToNSString(display_text); |
| 853 [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring]; | 849 [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring]; |
| 854 } | 850 } |
| 855 } | 851 } |
| 856 | 852 |
| 857 // | 853 // |
| 858 // RenderWidgetHostViewCocoa uses the stored selection text, | 854 // RenderWidgetHostViewCocoa uses the stored selection text, |
| 859 // which implements NSServicesRequests protocol. | 855 // which implements NSServicesRequests protocol. |
| 860 // | 856 // |
| 861 void RenderWidgetHostViewMac::SelectionChanged(const std::string& text) { | 857 void RenderWidgetHostViewMac::SelectionChanged(const std::string& text, |
| 858 int range_start, | |
| 859 int range_end) { | |
| 862 selected_text_ = text; | 860 selected_text_ = text; |
| 861 NSRange range = NSMakeRange(range_start, range_end - range_start); | |
| 862 [cocoa_view_ setSelectedRange:range]; | |
| 863 } | 863 } |
| 864 | 864 |
| 865 BackingStore* RenderWidgetHostViewMac::AllocBackingStore( | 865 BackingStore* RenderWidgetHostViewMac::AllocBackingStore( |
| 866 const gfx::Size& size) { | 866 const gfx::Size& size) { |
| 867 return new BackingStoreMac(render_widget_host_, size); | 867 return new BackingStoreMac(render_widget_host_, size); |
| 868 } | 868 } |
| 869 | 869 |
| 870 // Sets whether or not to accept first responder status. | 870 // Sets whether or not to accept first responder status. |
| 871 void RenderWidgetHostViewMac::SetTakesFocusOnlyOnMouseDown(bool flag) { | 871 void RenderWidgetHostViewMac::SetTakesFocusOnlyOnMouseDown(bool flag) { |
| 872 [cocoa_view_ setTakesFocusOnlyOnMouseDown:flag]; | 872 [cocoa_view_ setTakesFocusOnlyOnMouseDown:flag]; |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1312 } else { | 1312 } else { |
| 1313 if (text_input_type_ == WebKit::WebTextInputTypePassword) | 1313 if (text_input_type_ == WebKit::WebTextInputTypePassword) |
| 1314 DisablePasswordInput(); | 1314 DisablePasswordInput(); |
| 1315 } | 1315 } |
| 1316 } | 1316 } |
| 1317 | 1317 |
| 1318 // RenderWidgetHostViewCocoa --------------------------------------------------- | 1318 // RenderWidgetHostViewCocoa --------------------------------------------------- |
| 1319 | 1319 |
| 1320 @implementation RenderWidgetHostViewCocoa | 1320 @implementation RenderWidgetHostViewCocoa |
| 1321 | 1321 |
| 1322 @synthesize caretRect = caretRect_; | |
| 1323 | |
| 1324 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { | 1322 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { |
| 1325 self = [super initWithFrame:NSZeroRect]; | 1323 self = [super initWithFrame:NSZeroRect]; |
| 1326 if (self) { | 1324 if (self) { |
| 1327 editCommand_helper_.reset(new RWHVMEditCommandHelper); | 1325 editCommand_helper_.reset(new RWHVMEditCommandHelper); |
| 1328 editCommand_helper_->AddEditingSelectorsToClass([self class]); | 1326 editCommand_helper_->AddEditingSelectorsToClass([self class]); |
| 1329 | 1327 |
| 1330 renderWidgetHostView_.reset(r); | 1328 renderWidgetHostView_.reset(r); |
| 1331 canBeKeyView_ = YES; | 1329 canBeKeyView_ = YES; |
| 1332 takesFocusOnlyOnMouseDown_ = NO; | 1330 takesFocusOnlyOnMouseDown_ = NO; |
| 1333 closeOnDeactivate_ = NO; | 1331 closeOnDeactivate_ = NO; |
| (...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2339 NSUnderlineStyleAttributeName, | 2337 NSUnderlineStyleAttributeName, |
| 2340 NSUnderlineColorAttributeName, | 2338 NSUnderlineColorAttributeName, |
| 2341 NSMarkedClauseSegmentAttributeName, | 2339 NSMarkedClauseSegmentAttributeName, |
| 2342 NSTextInputReplacementRangeAttributeName, | 2340 NSTextInputReplacementRangeAttributeName, |
| 2343 nil]); | 2341 nil]); |
| 2344 } | 2342 } |
| 2345 return validAttributesForMarkedText_.get(); | 2343 return validAttributesForMarkedText_.get(); |
| 2346 } | 2344 } |
| 2347 | 2345 |
| 2348 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint { | 2346 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint { |
| 2349 NOTIMPLEMENTED(); | 2347 DCHECK([self window]); |
| 2350 return NSNotFound; | 2348 // |thePoint| is in screen coordinates, but needs to be converted to WebKit |
| 2349 // coordinates (upper left origin). Scroll offsets will be taken care of in | |
| 2350 // the renderer. | |
| 2351 thePoint = [[self window] convertScreenToBase:thePoint]; | |
| 2352 thePoint = [self convertPoint:thePoint fromView:nil]; | |
| 2353 thePoint.y = NSHeight([self frame]) - thePoint.y; | |
| 2354 | |
| 2355 TextInputClientMac* service = TextInputClientMac::GetInstance(); | |
| 2356 service->BeforeRequest(); | |
| 2357 renderWidgetHostView_->render_widget_host_->Send( | |
| 2358 new ViewMsg_CharacterIndexForPoint( | |
| 2359 renderWidgetHostView_->render_widget_host_->routing_id(), | |
| 2360 gfx::Point(thePoint.x, thePoint.y))); | |
| 2361 NSUInteger index = service->WaitForCharacterIndex(); | |
| 2362 service->AfterRequest(); | |
| 2363 return index; | |
| 2351 } | 2364 } |
| 2352 | 2365 |
| 2353 - (NSRect)firstRectForCharacterRange:(NSRange)theRange { | 2366 - (NSRect)firstRectForCharacterRange:(NSRange)theRange { |
| 2354 // An input method requests a cursor rectangle to display its candidate | 2367 TextInputClientMac* service = TextInputClientMac::GetInstance(); |
| 2355 // window. | 2368 service->BeforeRequest(); |
| 2356 // Calculate the screen coordinate of the cursor rectangle saved in | 2369 renderWidgetHostView_->render_widget_host_->Send( |
| 2357 // RenderWidgetHostViewMac::ImeUpdateTextInputState() and send it to the | 2370 new ViewMsg_FirstRectForCharacterRange( |
| 2358 // input method. | 2371 renderWidgetHostView_->render_widget_host_->routing_id(), |
| 2359 // Since this window may be moved since we receive the cursor rectangle last | 2372 theRange.location, |
| 2360 // time we sent the cursor rectangle to the input method, so we should map | 2373 theRange.length)); |
| 2361 // from the view coordinate to the screen coordinate every time when an input | 2374 NSRect rect = service->WaitForFirstRect(); |
| 2362 // method need it. | 2375 service->AfterRequest(); |
| 2363 NSRect resultRect = [self convertRect:caretRect_ toView:nil]; | 2376 // The returned rectangle is in WebKit coordinates (upper left origin), so |
| 2364 NSWindow* window = [self window]; | 2377 // flip the coordinate system and then convert it into screen coordinates for |
| 2365 if (window) | 2378 // return. |
| 2366 resultRect.origin = [window convertBaseToScreen:resultRect.origin]; | 2379 NSRect viewFrame = [self frame]; |
| 2380 rect.origin.y = NSHeight(viewFrame) - rect.origin.y; | |
| 2381 rect.origin.y -= rect.size.height; | |
| 2382 rect = [self convertRectToBase:rect]; | |
| 2383 rect.origin = [[self window] convertBaseToScreen:rect.origin]; | |
| 2384 return rect; | |
|
James Su
2011/01/20 23:46:06
We probably can do an optimization here:
Usually w
| |
| 2385 } | |
| 2367 | 2386 |
| 2368 return resultRect; | 2387 // Called from RWHVM::OnSelectionChanged. |
| 2388 - (void)setSelectedRange:(NSRange)range { | |
| 2389 selectedRange_ = range; | |
|
James Su
2011/01/20 23:46:06
How about to use @synthesize for this property?
Robert Sesek
2011/01/21 23:40:07
Done.
| |
| 2369 } | 2390 } |
| 2370 | 2391 |
| 2371 - (NSRange)selectedRange { | 2392 - (NSRange)selectedRange { |
| 2372 // Return the selected range saved in the setMarkedText method. | 2393 return selectedRange_; |
| 2373 return hasMarkedText_ ? selectedRange_ : NSMakeRange(NSNotFound, 0); | |
| 2374 } | 2394 } |
| 2375 | 2395 |
| 2376 - (NSRange)markedRange { | 2396 - (NSRange)markedRange { |
| 2377 // An input method calls this method to check if an application really has | 2397 // An input method calls this method to check if an application really has |
| 2378 // a text being composed when hasMarkedText call returns true. | 2398 // a text being composed when hasMarkedText call returns true. |
| 2379 // Returns the range saved in the setMarkedText method so the input method | 2399 // Returns the range saved in the setMarkedText method so the input method |
| 2380 // calls the setMarkedText method and we can update the composition node | 2400 // calls the setMarkedText method and we can update the composition node |
| 2381 // there. (When this method returns an empty range, the input method doesn't | 2401 // there. (When this method returns an empty range, the input method doesn't |
| 2382 // call the setMarkedText method.) | 2402 // call the setMarkedText method.) |
| 2383 return hasMarkedText_ ? markedRange_ : NSMakeRange(NSNotFound, 0); | 2403 return hasMarkedText_ ? markedRange_ : NSMakeRange(NSNotFound, 0); |
| 2384 } | 2404 } |
| 2385 | 2405 |
| 2386 - (NSAttributedString *)attributedSubstringFromRange:(NSRange)range { | 2406 - (NSAttributedString*)attributedSubstringFromRange:(NSRange)range { |
| 2387 // TODO(hbono): Even though many input method works without implementing | 2407 TextInputClientMac* service = TextInputClientMac::GetInstance(); |
| 2388 // this method, we need to save a copy of the string in the setMarkedText | 2408 service->BeforeRequest(); |
| 2389 // method and create a NSAttributedString with the given range. | 2409 renderWidgetHostView_->render_widget_host_->Send( |
| 2390 // http://crbug.com/37715 | 2410 new ViewMsg_StringForRange( |
| 2391 return nil; | 2411 renderWidgetHostView_->render_widget_host_->routing_id(), |
| 2412 range.location, | |
| 2413 range.length)); | |
| 2414 NSAttributedString* string = service->WaitForSubstring(); | |
| 2415 service->AfterRequest(); | |
| 2416 return string; | |
| 2392 } | 2417 } |
| 2393 | 2418 |
| 2394 - (NSInteger)conversationIdentifier { | 2419 - (NSInteger)conversationIdentifier { |
| 2395 return reinterpret_cast<NSInteger>(self); | 2420 return reinterpret_cast<NSInteger>(self); |
| 2396 } | 2421 } |
| 2397 | 2422 |
| 2398 // Each RenderWidgetHostViewCocoa has its own input context, but we return | 2423 // Each RenderWidgetHostViewCocoa has its own input context, but we return |
| 2399 // nil when the caret is in non-editable content or password box to avoid | 2424 // nil when the caret is in non-editable content or password box to avoid |
| 2400 // making input methods do their work. | 2425 // making input methods do their work. |
| 2401 - (NSTextInputContext *)inputContext { | 2426 - (NSTextInputContext *)inputContext { |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2725 if (!string) return NO; | 2750 if (!string) return NO; |
| 2726 | 2751 |
| 2727 // If the user is currently using an IME, confirm the IME input, | 2752 // If the user is currently using an IME, confirm the IME input, |
| 2728 // and then insert the text from the service, the same as TextEdit and Safari. | 2753 // and then insert the text from the service, the same as TextEdit and Safari. |
| 2729 [self confirmComposition]; | 2754 [self confirmComposition]; |
| 2730 [self insertText:string]; | 2755 [self insertText:string]; |
| 2731 return YES; | 2756 return YES; |
| 2732 } | 2757 } |
| 2733 | 2758 |
| 2734 @end | 2759 @end |
| OLD | NEW |