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

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

Issue 3808001: Implement IME for Mac plugins using the Cocoa event model on 10.6 (Closed)
Patch Set: Windows and unit test compile fixes Created 10 years, 2 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) 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"
11 #import "base/chrome_application_mac.h" 11 #import "base/chrome_application_mac.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #import "base/scoped_nsautorelease_pool.h" 15 #import "base/scoped_nsautorelease_pool.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_string_conversions.h" 19 #include "base/sys_string_conversions.h"
19 #include "chrome/browser/browser_thread.h" 20 #include "chrome/browser/browser_thread.h"
20 #include "chrome/browser/browser_trial.h" 21 #include "chrome/browser/browser_trial.h"
21 #import "chrome/browser/cocoa/rwhvm_editcommand_helper.h" 22 #import "chrome/browser/cocoa/rwhvm_editcommand_helper.h"
22 #import "chrome/browser/cocoa/view_id_util.h" 23 #import "chrome/browser/cocoa/view_id_util.h"
23 #include "chrome/browser/plugin_process_host.h" 24 #include "chrome/browser/plugin_process_host.h"
24 #include "chrome/browser/renderer_host/backing_store_mac.h" 25 #include "chrome/browser/renderer_host/backing_store_mac.h"
25 #include "chrome/browser/renderer_host/render_process_host.h" 26 #include "chrome/browser/renderer_host/render_process_host.h"
26 #include "chrome/browser/renderer_host/render_view_host.h" 27 #include "chrome/browser/renderer_host/render_view_host.h"
27 #include "chrome/browser/renderer_host/render_widget_host.h" 28 #include "chrome/browser/renderer_host/render_widget_host.h"
28 #include "chrome/browser/spellchecker_platform_engine.h" 29 #include "chrome/browser/spellchecker_platform_engine.h"
29 #include "chrome/common/chrome_switches.h" 30 #include "chrome/common/chrome_switches.h"
30 #include "chrome/common/native_web_keyboard_event.h" 31 #include "chrome/common/native_web_keyboard_event.h"
31 #include "chrome/common/edit_command.h" 32 #include "chrome/common/edit_command.h"
32 #include "chrome/common/plugin_messages.h" 33 #include "chrome/common/plugin_messages.h"
33 #include "chrome/common/render_messages.h" 34 #include "chrome/common/render_messages.h"
34 #include "skia/ext/platform_canvas.h" 35 #include "skia/ext/platform_canvas.h"
35 #include "third_party/skia/include/core/SkColor.h" 36 #include "third_party/skia/include/core/SkColor.h"
36 #include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h" 37 #include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h"
37 #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" 38 #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
38 #include "webkit/glue/plugins/webplugin.h" 39 #include "webkit/glue/plugins/webplugin.h"
39 #include "webkit/glue/webaccessibility.h" 40 #include "webkit/glue/webaccessibility.h"
40 #include "webkit/glue/webmenurunner_mac.h" 41 #include "webkit/glue/webmenurunner_mac.h"
42 #import "third_party/mozilla/ComplexTextInputPanel.h"
41 43
42 using WebKit::WebInputEvent; 44 using WebKit::WebInputEvent;
43 using WebKit::WebInputEventFactory; 45 using WebKit::WebInputEventFactory;
44 using WebKit::WebMouseEvent; 46 using WebKit::WebMouseEvent;
45 using WebKit::WebMouseWheelEvent; 47 using WebKit::WebMouseWheelEvent;
46 48
47 static inline int ToWebKitModifiers(NSUInteger flags) { 49 static inline int ToWebKitModifiers(NSUInteger flags) {
48 int modifiers = 0; 50 int modifiers = 0;
49 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; 51 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey;
50 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey; 52 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey;
51 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; 53 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey;
52 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; 54 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey;
53 return modifiers; 55 return modifiers;
54 } 56 }
55 57
56 @interface RenderWidgetHostViewCocoa (Private) 58 @interface RenderWidgetHostViewCocoa (Private)
57 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event; 59 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event;
58 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r; 60 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
59 - (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv; 61 - (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv;
60 - (void)cancelChildPopups; 62 - (void)cancelChildPopups;
61 - (void)attachPluginLayer;
62 @end 63 @end
63 64
64 // This API was published since 10.6. Provide the declaration so it can be 65 // This API was published since 10.6. Provide the declaration so it can be
65 // // called below when building with the 10.5 SDK. 66 // // called below when building with the 10.5 SDK.
66 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 67 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
67 @class NSTextInputContext; 68 @class NSTextInputContext;
68 @interface NSResponder (AppKitDetails) 69 @interface NSResponder (AppKitDetails)
69 - (NSTextInputContext *)inputContext; 70 - (NSTextInputContext *)inputContext;
70 @end 71 @end
71 #endif 72 #endif
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 884
884 void RenderWidgetHostViewMac::KillSelf() { 885 void RenderWidgetHostViewMac::KillSelf() {
885 if (shutdown_factory_.empty()) { 886 if (shutdown_factory_.empty()) {
886 [cocoa_view_ setHidden:YES]; 887 [cocoa_view_ setHidden:YES];
887 MessageLoop::current()->PostTask(FROM_HERE, 888 MessageLoop::current()->PostTask(FROM_HERE,
888 shutdown_factory_.NewRunnableMethod( 889 shutdown_factory_.NewRunnableMethod(
889 &RenderWidgetHostViewMac::ShutdownHost)); 890 &RenderWidgetHostViewMac::ShutdownHost));
890 } 891 }
891 } 892 }
892 893
894 void RenderWidgetHostViewMac::SetPluginImeEnabled(bool enabled, int plugin_id) {
895 [cocoa_view_ setPluginImeEnabled:(enabled ? YES : NO) forPlugin:plugin_id];
896 }
897
898 bool RenderWidgetHostViewMac::PostProcessEventForPluginIme(
899 const NativeWebKeyboardEvent& event) {
900 // Check WebInputEvent type since multiple types of events can be sent into
901 // WebKit for the same OS event (e.g., RawKeyDown and Char), so filtering is
902 // necessary to avoid double processing.
903 // Also check the native type, since NSFlagsChanged is considered a key event
904 // for WebKit purposes, but isn't considered a key event by the OS.
905 if (event.type == WebInputEvent::RawKeyDown &&
906 [event.os_event type] == NSKeyDown)
907 return [cocoa_view_ postProcessEventForPluginIme:event.os_event];
908 return false;
909 }
910
911 void RenderWidgetHostViewMac::PluginImeCompositionConfirmed(
912 const string16& text, int plugin_id) {
913 if (render_widget_host_) {
914 render_widget_host_->Send(new ViewMsg_PluginImeCompositionConfirmed(
915 render_widget_host_->routing_id(), text, plugin_id));
916 }
917 }
918
893 gfx::PluginWindowHandle 919 gfx::PluginWindowHandle
894 RenderWidgetHostViewMac::AllocateFakePluginWindowHandle(bool opaque, 920 RenderWidgetHostViewMac::AllocateFakePluginWindowHandle(bool opaque,
895 bool root) { 921 bool root) {
896 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 922 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
897 // Create an NSView to host the plugin's/compositor's pixels. 923 // Create an NSView to host the plugin's/compositor's pixels.
898 gfx::PluginWindowHandle handle = 924 gfx::PluginWindowHandle handle =
899 plugin_container_manager_.AllocateFakePluginWindowHandle(opaque, root); 925 plugin_container_manager_.AllocateFakePluginWindowHandle(opaque, root);
900 926
901 scoped_nsobject<AcceleratedPluginView> plugin_view( 927 scoped_nsobject<AcceleratedPluginView> plugin_view(
902 [[AcceleratedPluginView alloc] initWithRenderWidgetHostViewMac:this 928 [[AcceleratedPluginView alloc] initWithRenderWidgetHostViewMac:this
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1187 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { 1213 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r {
1188 self = [super initWithFrame:NSZeroRect]; 1214 self = [super initWithFrame:NSZeroRect];
1189 if (self) { 1215 if (self) {
1190 editCommand_helper_.reset(new RWHVMEditCommandHelper); 1216 editCommand_helper_.reset(new RWHVMEditCommandHelper);
1191 editCommand_helper_->AddEditingSelectorsToClass([self class]); 1217 editCommand_helper_->AddEditingSelectorsToClass([self class]);
1192 1218
1193 renderWidgetHostView_.reset(r); 1219 renderWidgetHostView_.reset(r);
1194 canBeKeyView_ = YES; 1220 canBeKeyView_ = YES;
1195 takesFocusOnlyOnMouseDown_ = NO; 1221 takesFocusOnlyOnMouseDown_ = NO;
1196 closeOnDeactivate_ = NO; 1222 closeOnDeactivate_ = NO;
1223 pluginImeIdentifier_ = -1;
1197 } 1224 }
1198 return self; 1225 return self;
1199 } 1226 }
1200 1227
1201 - (void)setCanBeKeyView:(BOOL)can { 1228 - (void)setCanBeKeyView:(BOOL)can {
1202 canBeKeyView_ = can; 1229 canBeKeyView_ = can;
1203 } 1230 }
1204 1231
1205 - (void)setTakesFocusOnlyOnMouseDown:(BOOL)b { 1232 - (void)setTakesFocusOnlyOnMouseDown:(BOOL)b {
1206 takesFocusOnlyOnMouseDown_ = b; 1233 takesFocusOnlyOnMouseDown_ = b;
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
1344 // Clear them here so that we can know whether they have changed afterwards. 1371 // Clear them here so that we can know whether they have changed afterwards.
1345 textToBeInserted_.clear(); 1372 textToBeInserted_.clear();
1346 markedText_.clear(); 1373 markedText_.clear();
1347 underlines_.clear(); 1374 underlines_.clear();
1348 unmarkTextCalled_ = NO; 1375 unmarkTextCalled_ = NO;
1349 hasEditCommands_ = NO; 1376 hasEditCommands_ = NO;
1350 editCommands_.clear(); 1377 editCommands_.clear();
1351 1378
1352 // Sends key down events to input method first, then we can decide what should 1379 // Sends key down events to input method first, then we can decide what should
1353 // be done according to input method's feedback. 1380 // be done according to input method's feedback.
1354 [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; 1381 // If a plugin is active, bypass this step since events are forwarded directly
1382 // to the plugin IME.
1383 if (pluginImeIdentifier_ == -1)
1384 [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
1355 1385
1356 handlingKeyDown_ = NO; 1386 handlingKeyDown_ = NO;
1357 1387
1358 // Indicates if we should send the key event and corresponding editor commands 1388 // Indicates if we should send the key event and corresponding editor commands
1359 // after processing the input method result. 1389 // after processing the input method result.
1360 BOOL delayEventUntilAfterImeCompostion = NO; 1390 BOOL delayEventUntilAfterImeCompostion = NO;
1361 1391
1362 // To emulate Windows, over-write |event.windowsKeyCode| to VK_PROCESSKEY 1392 // To emulate Windows, over-write |event.windowsKeyCode| to VK_PROCESSKEY
1363 // while an input method is composing or inserting a text. 1393 // while an input method is composing or inserting a text.
1364 // Gmail checks this code in its onkeydown handler to stop auto-completing 1394 // Gmail checks this code in its onkeydown handler to stop auto-completing
(...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after
2232 } 2262 }
2233 2263
2234 - (NSInteger)conversationIdentifier { 2264 - (NSInteger)conversationIdentifier {
2235 return reinterpret_cast<NSInteger>(self); 2265 return reinterpret_cast<NSInteger>(self);
2236 } 2266 }
2237 2267
2238 // Each RenderWidgetHostViewCocoa has its own input context, but we return 2268 // Each RenderWidgetHostViewCocoa has its own input context, but we return
2239 // nil when the caret is in non-editable content or password box to avoid 2269 // nil when the caret is in non-editable content or password box to avoid
2240 // making input methods do their work. 2270 // making input methods do their work.
2241 - (NSTextInputContext *)inputContext { 2271 - (NSTextInputContext *)inputContext {
2272 if (pluginImeIdentifier_ != -1)
2273 return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext];
2274
2242 switch(renderWidgetHostView_->text_input_type_) { 2275 switch(renderWidgetHostView_->text_input_type_) {
2243 case WebKit::WebTextInputTypeNone: 2276 case WebKit::WebTextInputTypeNone:
2244 case WebKit::WebTextInputTypePassword: 2277 case WebKit::WebTextInputTypePassword:
2245 return nil; 2278 return nil;
2246 default: 2279 default:
2247 return [super inputContext]; 2280 return [super inputContext];
2248 } 2281 }
2249 } 2282 }
2250 2283
2251 - (BOOL)hasMarkedText { 2284 - (BOOL)hasMarkedText {
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
2462 - (void)confirmComposition { 2495 - (void)confirmComposition {
2463 if (!hasMarkedText_) 2496 if (!hasMarkedText_)
2464 return; 2497 return;
2465 2498
2466 if (renderWidgetHostView_->render_widget_host_) 2499 if (renderWidgetHostView_->render_widget_host_)
2467 renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(); 2500 renderWidgetHostView_->render_widget_host_->ImeConfirmComposition();
2468 2501
2469 [self cancelComposition]; 2502 [self cancelComposition];
2470 } 2503 }
2471 2504
2505 - (void)setPluginImeEnabled:(BOOL)enabled forPlugin:(int)pluginId {
2506 if ((enabled && pluginId == pluginImeIdentifier_) ||
2507 (!enabled && pluginId != pluginImeIdentifier_))
2508 return;
2509
2510 // If IME was already active then either it is being cancelled, or the plugin
2511 // changed; either way the current input needs to be cleared.
2512 if (pluginImeIdentifier_ != -1)
2513 [[ComplexTextInputPanel sharedComplexTextInputPanel] cancelInput];
2514
2515 pluginImeIdentifier_ = enabled ? pluginId : -1;
2516 }
2517
2518 - (BOOL)postProcessEventForPluginIme:(NSEvent*)event {
2519 if (pluginImeIdentifier_ == -1)
2520 return false;
2521
2522 // ComplexTextInputPanel only works on 10.6+.
2523 static BOOL sImeSupported = NO;
2524 static BOOL sHaveCheckedSupport = NO;
2525 if (!sHaveCheckedSupport) {
2526 int32 major, minor, bugfix;
2527 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
2528 sImeSupported = major > 10 || (major == 10 && minor > 5);
2529 }
2530 if (!sImeSupported)
2531 return false;
2532
2533 ComplexTextInputPanel* inputPanel =
2534 [ComplexTextInputPanel sharedComplexTextInputPanel];
2535 NSString* composited_string = nil;
2536 BOOL handled = [inputPanel interpretKeyEvent:event
2537 string:&composited_string];
2538 if (composited_string) {
2539 renderWidgetHostView_->PluginImeCompositionConfirmed(
2540 base::SysNSStringToUTF16(composited_string), pluginImeIdentifier_);
2541 }
2542 return handled;
2543 }
2544
2472 - (ViewID)viewID { 2545 - (ViewID)viewID {
2473 return VIEW_ID_TAB_CONTAINER_FOCUS_VIEW; 2546 return VIEW_ID_TAB_CONTAINER_FOCUS_VIEW;
2474 } 2547 }
2475 2548
2476 // Overriding a NSResponder method to support application services. 2549 // Overriding a NSResponder method to support application services.
2477 2550
2478 - (id)validRequestorForSendType:(NSString*)sendType 2551 - (id)validRequestorForSendType:(NSString*)sendType
2479 returnType:(NSString*)returnType { 2552 returnType:(NSString*)returnType {
2480 id requestor = nil; 2553 id requestor = nil;
2481 BOOL sendTypeIsString = [sendType isEqual:NSStringPboardType]; 2554 BOOL sendTypeIsString = [sendType isEqual:NSStringPboardType];
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2521 if (!string) return NO; 2594 if (!string) return NO;
2522 2595
2523 // If the user is currently using an IME, confirm the IME input, 2596 // If the user is currently using an IME, confirm the IME input,
2524 // and then insert the text from the service, the same as TextEdit and Safari. 2597 // and then insert the text from the service, the same as TextEdit and Safari.
2525 [self confirmComposition]; 2598 [self confirmComposition];
2526 [self insertText:string]; 2599 [self insertText:string];
2527 return YES; 2600 return YES;
2528 } 2601 }
2529 2602
2530 @end 2603 @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