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

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

Issue 6259013: Update Mac plugin IME handling to match updated spec (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to trunk Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; 56 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey;
57 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; 57 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey;
58 return modifiers; 58 return modifiers;
59 } 59 }
60 60
61 @interface RenderWidgetHostViewCocoa (Private) 61 @interface RenderWidgetHostViewCocoa (Private)
62 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event; 62 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event;
63 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r; 63 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
64 - (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv; 64 - (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv;
65 - (void)cancelChildPopups; 65 - (void)cancelChildPopups;
66 - (void)checkForPluginImeCancellation;
66 @end 67 @end
67 68
68 // This API was published since 10.6. Provide the declaration so it can be 69 // This API was published since 10.6. Provide the declaration so it can be
69 // // called below when building with the 10.5 SDK. 70 // // called below when building with the 10.5 SDK.
70 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 71 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
71 @class NSTextInputContext; 72 @class NSTextInputContext;
72 @interface NSResponder (AppKitDetails) 73 @interface NSResponder (AppKitDetails)
73 - (NSTextInputContext *)inputContext; 74 - (NSTextInputContext *)inputContext;
74 @end 75 @end
75 #endif 76 #endif
76 77
77 namespace { 78 namespace {
78 79
79 // Maximum number of characters we allow in a tooltip. 80 // Maximum number of characters we allow in a tooltip.
80 const size_t kMaxTooltipLength = 1024; 81 const size_t kMaxTooltipLength = 1024;
81 82
82 // TODO(suzhe): Upstream this function. 83 // TODO(suzhe): Upstream this function.
83 WebKit::WebColor WebColorFromNSColor(NSColor *color) { 84 WebKit::WebColor WebColorFromNSColor(NSColor *color) {
84 CGFloat r, g, b, a; 85 CGFloat r, g, b, a;
85 [color getRed:&r green:&g blue:&b alpha:&a]; 86 [color getRed:&r green:&g blue:&b alpha:&a];
86 87
87 return 88 return
88 std::max(0, std::min(static_cast<int>(lroundf(255.0f * a)), 255)) << 24 | 89 std::max(0, std::min(static_cast<int>(lroundf(255.0f * a)), 255)) << 24 |
89 std::max(0, std::min(static_cast<int>(lroundf(255.0f * r)), 255)) << 16 | 90 std::max(0, std::min(static_cast<int>(lroundf(255.0f * r)), 255)) << 16 |
90 std::max(0, std::min(static_cast<int>(lroundf(255.0f * g)), 255)) << 8 | 91 std::max(0, std::min(static_cast<int>(lroundf(255.0f * g)), 255)) << 8 |
91 std::max(0, std::min(static_cast<int>(lroundf(255.0f * b)), 255)); 92 std::max(0, std::min(static_cast<int>(lroundf(255.0f * b)), 255));
92 } 93 }
93 94
94 // Extract underline information from an attributed string. 95 // Extract underline information from an attributed string. Mostly copied from
95 // Mostly copied from third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.m m 96 // third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm
96 void ExtractUnderlines( 97 void ExtractUnderlines(
97 NSAttributedString* string, 98 NSAttributedString* string,
98 std::vector<WebKit::WebCompositionUnderline>* underlines) { 99 std::vector<WebKit::WebCompositionUnderline>* underlines) {
99 int length = [[string string] length]; 100 int length = [[string string] length];
100 int i = 0; 101 int i = 0;
101 while (i < length) { 102 while (i < length) {
102 NSRange range; 103 NSRange range;
103 NSDictionary* attrs = [string attributesAtIndex:i 104 NSDictionary* attrs = [string attributesAtIndex:i
104 longestEffectiveRange:&range 105 longestEffectiveRange:&range
105 inRange:NSMakeRange(i, length - i)]; 106 inRange:NSMakeRange(i, length - i)];
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 875
875 void RenderWidgetHostViewMac::KillSelf() { 876 void RenderWidgetHostViewMac::KillSelf() {
876 if (shutdown_factory_.empty()) { 877 if (shutdown_factory_.empty()) {
877 [cocoa_view_ setHidden:YES]; 878 [cocoa_view_ setHidden:YES];
878 MessageLoop::current()->PostTask(FROM_HERE, 879 MessageLoop::current()->PostTask(FROM_HERE,
879 shutdown_factory_.NewRunnableMethod( 880 shutdown_factory_.NewRunnableMethod(
880 &RenderWidgetHostViewMac::ShutdownHost)); 881 &RenderWidgetHostViewMac::ShutdownHost));
881 } 882 }
882 } 883 }
883 884
884 void RenderWidgetHostViewMac::SetPluginImeEnabled(bool enabled, int plugin_id) { 885 void RenderWidgetHostViewMac::PluginFocusChanged(bool focused, int plugin_id) {
885 [cocoa_view_ setPluginImeEnabled:(enabled ? YES : NO) forPlugin:plugin_id]; 886 [cocoa_view_ pluginFocusChanged:(focused ? YES : NO) forPlugin:plugin_id];
887 }
888
889 void RenderWidgetHostViewMac::StartPluginIme() {
890 [cocoa_view_ setPluginImeActive:YES];
886 } 891 }
887 892
888 bool RenderWidgetHostViewMac::PostProcessEventForPluginIme( 893 bool RenderWidgetHostViewMac::PostProcessEventForPluginIme(
889 const NativeWebKeyboardEvent& event) { 894 const NativeWebKeyboardEvent& event) {
890 // Check WebInputEvent type since multiple types of events can be sent into 895 // Check WebInputEvent type since multiple types of events can be sent into
891 // WebKit for the same OS event (e.g., RawKeyDown and Char), so filtering is 896 // WebKit for the same OS event (e.g., RawKeyDown and Char), so filtering is
892 // necessary to avoid double processing. 897 // necessary to avoid double processing.
893 // Also check the native type, since NSFlagsChanged is considered a key event 898 // Also check the native type, since NSFlagsChanged is considered a key event
894 // for WebKit purposes, but isn't considered a key event by the OS. 899 // for WebKit purposes, but isn't considered a key event by the OS.
895 if (event.type == WebInputEvent::RawKeyDown && 900 if (event.type == WebInputEvent::RawKeyDown &&
896 [event.os_event type] == NSKeyDown) 901 [event.os_event type] == NSKeyDown)
897 return [cocoa_view_ postProcessEventForPluginIme:event.os_event]; 902 return [cocoa_view_ postProcessEventForPluginIme:event.os_event];
898 return false; 903 return false;
899 } 904 }
900 905
901 void RenderWidgetHostViewMac::PluginImeCompositionConfirmed( 906 void RenderWidgetHostViewMac::PluginImeCompositionCompleted(
902 const string16& text, int plugin_id) { 907 const string16& text, int plugin_id) {
903 if (render_widget_host_) { 908 if (render_widget_host_) {
904 render_widget_host_->Send(new ViewMsg_PluginImeCompositionConfirmed( 909 render_widget_host_->Send(new ViewMsg_PluginImeCompositionCompleted(
905 render_widget_host_->routing_id(), text, plugin_id)); 910 render_widget_host_->routing_id(), text, plugin_id));
906 } 911 }
907 } 912 }
908 913
909 gfx::PluginWindowHandle 914 gfx::PluginWindowHandle
910 RenderWidgetHostViewMac::AllocateFakePluginWindowHandle(bool opaque, 915 RenderWidgetHostViewMac::AllocateFakePluginWindowHandle(bool opaque,
911 bool root) { 916 bool root) {
912 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 917 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
913 918
914 // |render_widget_host_| is set to NULL when |RWHVMac::Destroy()| has 919 // |render_widget_host_| is set to NULL when |RWHVMac::Destroy()| has
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 1256
1252 NSRect bounds = [enclosing_window frame]; 1257 NSRect bounds = [enclosing_window frame];
1253 return FlipNSRectToRectScreen(bounds); 1258 return FlipNSRectToRectScreen(bounds);
1254 } 1259 }
1255 1260
1256 void RenderWidgetHostViewMac::SetActive(bool active) { 1261 void RenderWidgetHostViewMac::SetActive(bool active) {
1257 if (render_widget_host_) 1262 if (render_widget_host_)
1258 render_widget_host_->SetActive(active); 1263 render_widget_host_->SetActive(active);
1259 if (HasFocus()) 1264 if (HasFocus())
1260 SetTextInputActive(active); 1265 SetTextInputActive(active);
1266 if (!active)
1267 [cocoa_view_ setPluginImeActive:NO];
1261 } 1268 }
1262 1269
1263 void RenderWidgetHostViewMac::SetWindowVisibility(bool visible) { 1270 void RenderWidgetHostViewMac::SetWindowVisibility(bool visible) {
1264 if (render_widget_host_) { 1271 if (render_widget_host_) {
1265 render_widget_host_->Send(new ViewMsg_SetWindowVisibility( 1272 render_widget_host_->Send(new ViewMsg_SetWindowVisibility(
1266 render_widget_host_->routing_id(), visible)); 1273 render_widget_host_->routing_id(), visible));
1267 } 1274 }
1268 } 1275 }
1269 1276
1270 void RenderWidgetHostViewMac::WindowFrameChanged() { 1277 void RenderWidgetHostViewMac::WindowFrameChanged() {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { 1331 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r {
1325 self = [super initWithFrame:NSZeroRect]; 1332 self = [super initWithFrame:NSZeroRect];
1326 if (self) { 1333 if (self) {
1327 editCommand_helper_.reset(new RWHVMEditCommandHelper); 1334 editCommand_helper_.reset(new RWHVMEditCommandHelper);
1328 editCommand_helper_->AddEditingSelectorsToClass([self class]); 1335 editCommand_helper_->AddEditingSelectorsToClass([self class]);
1329 1336
1330 renderWidgetHostView_.reset(r); 1337 renderWidgetHostView_.reset(r);
1331 canBeKeyView_ = YES; 1338 canBeKeyView_ = YES;
1332 takesFocusOnlyOnMouseDown_ = NO; 1339 takesFocusOnlyOnMouseDown_ = NO;
1333 closeOnDeactivate_ = NO; 1340 closeOnDeactivate_ = NO;
1334 pluginImeIdentifier_ = -1; 1341 focusedPluginIdentifier_ = -1;
1335 } 1342 }
1336 return self; 1343 return self;
1337 } 1344 }
1338 1345
1339 - (void)setCanBeKeyView:(BOOL)can { 1346 - (void)setCanBeKeyView:(BOOL)can {
1340 canBeKeyView_ = can; 1347 canBeKeyView_ = can;
1341 } 1348 }
1342 1349
1343 - (void)setTakesFocusOnlyOnMouseDown:(BOOL)b { 1350 - (void)setTakesFocusOnlyOnMouseDown:(BOOL)b {
1344 takesFocusOnlyOnMouseDown_ = b; 1351 takesFocusOnlyOnMouseDown_ = b;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1480 1487
1481 // These variables might be set when handling the keyboard event. 1488 // These variables might be set when handling the keyboard event.
1482 // Clear them here so that we can know whether they have changed afterwards. 1489 // Clear them here so that we can know whether they have changed afterwards.
1483 textToBeInserted_.clear(); 1490 textToBeInserted_.clear();
1484 markedText_.clear(); 1491 markedText_.clear();
1485 underlines_.clear(); 1492 underlines_.clear();
1486 unmarkTextCalled_ = NO; 1493 unmarkTextCalled_ = NO;
1487 hasEditCommands_ = NO; 1494 hasEditCommands_ = NO;
1488 editCommands_.clear(); 1495 editCommands_.clear();
1489 1496
1497 // Before doing anything with a key down, check to see if plugin IME has been
1498 // cancelled, since the plugin host needs to be informed of that before
1499 // receiving the keydown.
1500 if ([theEvent type] == NSKeyDown)
1501 [self checkForPluginImeCancellation];
1502
1490 // Sends key down events to input method first, then we can decide what should 1503 // Sends key down events to input method first, then we can decide what should
1491 // be done according to input method's feedback. 1504 // be done according to input method's feedback.
1492 // If a plugin is active, bypass this step since events are forwarded directly 1505 // If a plugin is active, bypass this step since events are forwarded directly
1493 // to the plugin IME. 1506 // to the plugin IME.
1494 if (pluginImeIdentifier_ == -1) 1507 if (focusedPluginIdentifier_ == -1)
1495 [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; 1508 [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
1496 1509
1497 handlingKeyDown_ = NO; 1510 handlingKeyDown_ = NO;
1498 1511
1499 // Indicates if we should send the key event and corresponding editor commands 1512 // Indicates if we should send the key event and corresponding editor commands
1500 // after processing the input method result. 1513 // after processing the input method result.
1501 BOOL delayEventUntilAfterImeCompostion = NO; 1514 BOOL delayEventUntilAfterImeCompostion = NO;
1502 1515
1503 // To emulate Windows, over-write |event.windowsKeyCode| to VK_PROCESSKEY 1516 // To emulate Windows, over-write |event.windowsKeyCode| to VK_PROCESSKEY
1504 // while an input method is composing or inserting a text. 1517 // while an input method is composing or inserting a text.
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after
2392 } 2405 }
2393 2406
2394 - (NSInteger)conversationIdentifier { 2407 - (NSInteger)conversationIdentifier {
2395 return reinterpret_cast<NSInteger>(self); 2408 return reinterpret_cast<NSInteger>(self);
2396 } 2409 }
2397 2410
2398 // Each RenderWidgetHostViewCocoa has its own input context, but we return 2411 // 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 2412 // nil when the caret is in non-editable content or password box to avoid
2400 // making input methods do their work. 2413 // making input methods do their work.
2401 - (NSTextInputContext *)inputContext { 2414 - (NSTextInputContext *)inputContext {
2402 if (pluginImeIdentifier_ != -1) 2415 if (focusedPluginIdentifier_ != -1)
2403 return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext]; 2416 return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext];
2404 2417
2405 switch(renderWidgetHostView_->text_input_type_) { 2418 switch(renderWidgetHostView_->text_input_type_) {
2406 case WebKit::WebTextInputTypeNone: 2419 case WebKit::WebTextInputTypeNone:
2407 case WebKit::WebTextInputTypePassword: 2420 case WebKit::WebTextInputTypePassword:
2408 return nil; 2421 return nil;
2409 default: 2422 default:
2410 return [super inputContext]; 2423 return [super inputContext];
2411 } 2424 }
2412 } 2425 }
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
2625 - (void)confirmComposition { 2638 - (void)confirmComposition {
2626 if (!hasMarkedText_) 2639 if (!hasMarkedText_)
2627 return; 2640 return;
2628 2641
2629 if (renderWidgetHostView_->render_widget_host_) 2642 if (renderWidgetHostView_->render_widget_host_)
2630 renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(); 2643 renderWidgetHostView_->render_widget_host_->ImeConfirmComposition();
2631 2644
2632 [self cancelComposition]; 2645 [self cancelComposition];
2633 } 2646 }
2634 2647
2635 - (void)setPluginImeEnabled:(BOOL)enabled forPlugin:(int)pluginId { 2648 - (void)setPluginImeActive:(BOOL)active {
2636 if ((enabled && pluginId == pluginImeIdentifier_) || 2649 if (active == pluginImeActive_)
2637 (!enabled && pluginId != pluginImeIdentifier_))
2638 return; 2650 return;
2639 2651
2640 // If IME was already active then either it is being cancelled, or the plugin 2652 pluginImeActive_ = active;
2641 // changed; either way the current input needs to be cleared. 2653 if (!active) {
2642 if (pluginImeIdentifier_ != -1) 2654 [[ComplexTextInputPanel sharedComplexTextInputPanel] cancelComposition];
2643 [[ComplexTextInputPanel sharedComplexTextInputPanel] cancelInput]; 2655 renderWidgetHostView_->PluginImeCompositionCompleted(
2656 string16(), focusedPluginIdentifier_);
2657 }
2658 }
2644 2659
2645 pluginImeIdentifier_ = enabled ? pluginId : -1; 2660 - (void)pluginFocusChanged:(BOOL)focused forPlugin:(int)pluginId {
2661 if (focused)
2662 focusedPluginIdentifier_ = pluginId;
2663 else if (focusedPluginIdentifier_ == pluginId)
2664 focusedPluginIdentifier_ = -1;
2665
2666 // Whenever plugin focus changes, plugin IME resets.
2667 [self setPluginImeActive:NO];
2646 } 2668 }
2647 2669
2648 - (BOOL)postProcessEventForPluginIme:(NSEvent*)event { 2670 - (BOOL)postProcessEventForPluginIme:(NSEvent*)event {
2649 if (pluginImeIdentifier_ == -1) 2671 if (!pluginImeActive_)
2650 return false;
2651
2652 // ComplexTextInputPanel only works on 10.6+.
2653 static BOOL sImeSupported = NO;
2654 static BOOL sHaveCheckedSupport = NO;
2655 if (!sHaveCheckedSupport) {
2656 int32 major, minor, bugfix;
2657 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
2658 sImeSupported = major > 10 || (major == 10 && minor > 5);
2659 sHaveCheckedSupport = YES;
2660 }
2661 if (!sImeSupported)
2662 return false; 2672 return false;
2663 2673
2664 ComplexTextInputPanel* inputPanel = 2674 ComplexTextInputPanel* inputPanel =
2665 [ComplexTextInputPanel sharedComplexTextInputPanel]; 2675 [ComplexTextInputPanel sharedComplexTextInputPanel];
2666 NSString* composited_string = nil; 2676 NSString* composited_string = nil;
2667 BOOL handled = [inputPanel interpretKeyEvent:event 2677 BOOL handled = [inputPanel interpretKeyEvent:event
2668 string:&composited_string]; 2678 string:&composited_string];
2669 if (composited_string) { 2679 if (composited_string) {
2670 renderWidgetHostView_->PluginImeCompositionConfirmed( 2680 renderWidgetHostView_->PluginImeCompositionCompleted(
2671 base::SysNSStringToUTF16(composited_string), pluginImeIdentifier_); 2681 base::SysNSStringToUTF16(composited_string), focusedPluginIdentifier_);
2682 pluginImeActive_ = NO;
2672 } 2683 }
2673 return handled; 2684 return handled;
2674 } 2685 }
2675 2686
2687 - (void)checkForPluginImeCancellation {
2688 if (pluginImeActive_ &&
2689 ![[ComplexTextInputPanel sharedComplexTextInputPanel] inComposition]) {
2690 renderWidgetHostView_->PluginImeCompositionCompleted(
2691 string16(), focusedPluginIdentifier_);
2692 pluginImeActive_ = NO;
2693 }
2694 }
2695
2676 - (ViewID)viewID { 2696 - (ViewID)viewID {
2677 return VIEW_ID_TAB_CONTAINER_FOCUS_VIEW; 2697 return VIEW_ID_TAB_CONTAINER_FOCUS_VIEW;
2678 } 2698 }
2679 2699
2680 // Overriding a NSResponder method to support application services. 2700 // Overriding a NSResponder method to support application services.
2681 2701
2682 - (id)validRequestorForSendType:(NSString*)sendType 2702 - (id)validRequestorForSendType:(NSString*)sendType
2683 returnType:(NSString*)returnType { 2703 returnType:(NSString*)returnType {
2684 id requestor = nil; 2704 id requestor = nil;
2685 BOOL sendTypeIsString = [sendType isEqual:NSStringPboardType]; 2705 BOOL sendTypeIsString = [sendType isEqual:NSStringPboardType];
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2725 if (!string) return NO; 2745 if (!string) return NO;
2726 2746
2727 // If the user is currently using an IME, confirm the IME input, 2747 // 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. 2748 // and then insert the text from the service, the same as TextEdit and Safari.
2729 [self confirmComposition]; 2749 [self confirmComposition];
2730 [self insertText:string]; 2750 [self insertText:string];
2731 return YES; 2751 return YES;
2732 } 2752 }
2733 2753
2734 @end 2754 @end
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_mac.h ('k') | chrome/browser/renderer_host/test/test_render_view_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698