summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc11
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h1
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h11
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h15
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm77
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.cc9
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h3
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/common/plugin_messages_internal.h6
-rw-r--r--chrome/common/render_messages_internal.h12
-rw-r--r--chrome/plugin/webplugin_delegate_stub.cc7
-rw-r--r--chrome/plugin/webplugin_delegate_stub.h1
-rw-r--r--chrome/plugin/webplugin_proxy.cc8
-rw-r--r--chrome/plugin/webplugin_proxy.h2
-rw-r--r--chrome/renderer/render_view.cc22
-rw-r--r--chrome/renderer/render_view.h8
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc19
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.h3
-rw-r--r--third_party/mozilla/ComplexTextInputPanel.h49
-rw-r--r--third_party/mozilla/ComplexTextInputPanel.mm143
-rw-r--r--third_party/mozilla/README.chromium11
-rw-r--r--webkit/glue/plugins/webplugin.h3
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h17
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm39
24 files changed, 465 insertions, 14 deletions
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 7d4aa79f..a6efd58 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -168,6 +168,8 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_GetScreenInfo, OnMsgGetScreenInfo)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnMsgGetWindowRect)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowRect, OnMsgGetRootWindowRect)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SetPluginImeEnabled,
+ OnMsgSetPluginImeEnabled)
IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateFakePluginWindowHandle,
OnAllocateFakePluginWindowHandle)
IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyFakePluginWindowHandle,
@@ -1006,6 +1008,10 @@ void RenderWidgetHost::OnMsgGetRootWindowRect(gfx::NativeViewId window_id,
}
}
+void RenderWidgetHost::OnMsgSetPluginImeEnabled(bool enabled, int plugin_id) {
+ view_->SetPluginImeEnabled(enabled, plugin_id);
+}
+
void RenderWidgetHost::OnAllocateFakePluginWindowHandle(
bool opaque,
bool root,
@@ -1209,6 +1215,11 @@ void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) {
NativeWebKeyboardEvent front_item = key_queue_.front();
key_queue_.pop_front();
+#if defined(OS_MACOSX)
+ if (!is_hidden_ && view_->PostProcessEventForPluginIme(front_item))
+ return;
+#endif
+
// We only send unprocessed key event upwards if we are not hidden,
// because the user has moved away from us and no longer expect any effect
// of this key event.
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index f4e0b96..6c3fed7 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -499,6 +499,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
WebKit::WebScreenInfo* results);
void OnMsgGetWindowRect(gfx::NativeViewId window_id, gfx::Rect* results);
void OnMsgGetRootWindowRect(gfx::NativeViewId window_id, gfx::Rect* results);
+ void OnMsgSetPluginImeEnabled(bool enabled, int plugin_id);
void OnAllocateFakePluginWindowHandle(bool opaque,
bool root,
gfx::PluginWindowHandle* id);
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index 86c2abc..46d6bda 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -32,6 +32,7 @@ class RenderProcessHost;
class RenderWidgetHost;
class VideoLayer;
class WebCursor;
+struct NativeWebKeyboardEvent;
struct ViewHostMsg_AccessibilityNotification_Params;
struct WebMenuItem;
@@ -211,6 +212,16 @@ class RenderWidgetHostView {
// Informs the view that its containing window's frame changed.
virtual void WindowFrameChanged() = 0;
+ // Start or stop plugin IME for the given plugin.
+ virtual void SetPluginImeEnabled(bool enabled, int plugin_id) = 0;
+
+ // Does any event handling necessary for plugin IME; should be called after
+ // the plugin has already had a chance to process the event. If plugin IME is
+ // not enabled, this is a no-op, so it is always safe to call.
+ // Returns true if the event was handled by IME.
+ virtual bool PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event) = 0;
+
// Methods associated with GPU-accelerated plug-in instances.
virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(
bool opaque, bool root) = 0;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index f41ae8d..b9e41f9 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -124,6 +124,9 @@ class RWHVMEditCommandHelper;
// handling a key down event, not including inserting commands, eg. insertTab,
// etc.
EditCommands editCommands_;
+
+ // The plugin for which IME is currently enabled (-1 if not enabled).
+ int pluginImeIdentifier_;
}
@property(assign, nonatomic) NSRect caretRect;
@@ -145,6 +148,11 @@ class RWHVMEditCommandHelper;
- (void)setAccessibilityTreeRoot:(BrowserAccessibility*) treeRoot;
// Confirm ongoing composition.
- (void)confirmComposition;
+// Enables or disables plugin IME for the given plugin.
+- (void)setPluginImeEnabled:(BOOL)enabled forPlugin:(int)pluginId;
+// Evaluates the event in the context of plugin IME, if plugin IME is enabled.
+// Returns YES if the event was handled.
+- (BOOL)postProcessEventForPluginIme:(NSEvent*)event;
@end
@@ -224,6 +232,10 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
virtual void OnAccessibilityNotifications(
const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params);
+ virtual void SetPluginImeEnabled(bool enabled, int plugin_id);
+ virtual bool PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event);
+
// Methods associated with GPU-accelerated plug-in instances and the
// accelerated compositor.
virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(bool opaque,
@@ -263,6 +275,9 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
void SetTextInputActive(bool active);
+ // Sends confirmed plugin IME text back to the renderer.
+ void PluginImeCompositionConfirmed(const string16& text, int plugin_id);
+
const std::string& selected_text() const { return selected_text_; }
// These member variables should be private, but the associated ObjC class
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index ce0f8c0..a27fbcd 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -15,6 +15,7 @@
#import "base/scoped_nsautorelease_pool.h"
#import "base/scoped_nsobject.h"
#include "base/string_util.h"
+#include "base/sys_info.h"
#include "base/sys_string_conversions.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/browser_trial.h"
@@ -38,6 +39,7 @@
#include "webkit/glue/plugins/webplugin.h"
#include "webkit/glue/webaccessibility.h"
#include "webkit/glue/webmenurunner_mac.h"
+#import "third_party/mozilla/ComplexTextInputPanel.h"
using WebKit::WebInputEvent;
using WebKit::WebInputEventFactory;
@@ -58,7 +60,6 @@ static inline int ToWebKitModifiers(NSUInteger flags) {
- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
- (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv;
- (void)cancelChildPopups;
-- (void)attachPluginLayer;
@end
// This API was published since 10.6. Provide the declaration so it can be
@@ -890,6 +891,31 @@ void RenderWidgetHostViewMac::KillSelf() {
}
}
+void RenderWidgetHostViewMac::SetPluginImeEnabled(bool enabled, int plugin_id) {
+ [cocoa_view_ setPluginImeEnabled:(enabled ? YES : NO) forPlugin:plugin_id];
+}
+
+bool RenderWidgetHostViewMac::PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event) {
+ // Check WebInputEvent type since multiple types of events can be sent into
+ // WebKit for the same OS event (e.g., RawKeyDown and Char), so filtering is
+ // necessary to avoid double processing.
+ // Also check the native type, since NSFlagsChanged is considered a key event
+ // for WebKit purposes, but isn't considered a key event by the OS.
+ if (event.type == WebInputEvent::RawKeyDown &&
+ [event.os_event type] == NSKeyDown)
+ return [cocoa_view_ postProcessEventForPluginIme:event.os_event];
+ return false;
+}
+
+void RenderWidgetHostViewMac::PluginImeCompositionConfirmed(
+ const string16& text, int plugin_id) {
+ if (render_widget_host_) {
+ render_widget_host_->Send(new ViewMsg_PluginImeCompositionConfirmed(
+ render_widget_host_->routing_id(), text, plugin_id));
+ }
+}
+
gfx::PluginWindowHandle
RenderWidgetHostViewMac::AllocateFakePluginWindowHandle(bool opaque,
bool root) {
@@ -1194,6 +1220,7 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
canBeKeyView_ = YES;
takesFocusOnlyOnMouseDown_ = NO;
closeOnDeactivate_ = NO;
+ pluginImeIdentifier_ = -1;
}
return self;
}
@@ -1351,7 +1378,10 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
// Sends key down events to input method first, then we can decide what should
// be done according to input method's feedback.
- [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+ // If a plugin is active, bypass this step since events are forwarded directly
+ // to the plugin IME.
+ if (pluginImeIdentifier_ == -1)
+ [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
handlingKeyDown_ = NO;
@@ -2239,6 +2269,9 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// nil when the caret is in non-editable content or password box to avoid
// making input methods do their work.
- (NSTextInputContext *)inputContext {
+ if (pluginImeIdentifier_ != -1)
+ return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext];
+
switch(renderWidgetHostView_->text_input_type_) {
case WebKit::WebTextInputTypeNone:
case WebKit::WebTextInputTypePassword:
@@ -2469,6 +2502,46 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
[self cancelComposition];
}
+- (void)setPluginImeEnabled:(BOOL)enabled forPlugin:(int)pluginId {
+ if ((enabled && pluginId == pluginImeIdentifier_) ||
+ (!enabled && pluginId != pluginImeIdentifier_))
+ return;
+
+ // If IME was already active then either it is being cancelled, or the plugin
+ // changed; either way the current input needs to be cleared.
+ if (pluginImeIdentifier_ != -1)
+ [[ComplexTextInputPanel sharedComplexTextInputPanel] cancelInput];
+
+ pluginImeIdentifier_ = enabled ? pluginId : -1;
+}
+
+- (BOOL)postProcessEventForPluginIme:(NSEvent*)event {
+ if (pluginImeIdentifier_ == -1)
+ return false;
+
+ // ComplexTextInputPanel only works on 10.6+.
+ static BOOL sImeSupported = NO;
+ static BOOL sHaveCheckedSupport = NO;
+ if (!sHaveCheckedSupport) {
+ int32 major, minor, bugfix;
+ base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
+ sImeSupported = major > 10 || (major == 10 && minor > 5);
+ }
+ if (!sImeSupported)
+ return false;
+
+ ComplexTextInputPanel* inputPanel =
+ [ComplexTextInputPanel sharedComplexTextInputPanel];
+ NSString* composited_string = nil;
+ BOOL handled = [inputPanel interpretKeyEvent:event
+ string:&composited_string];
+ if (composited_string) {
+ renderWidgetHostView_->PluginImeCompositionConfirmed(
+ base::SysNSStringToUTF16(composited_string), pluginImeIdentifier_);
+ }
+ return handled;
+}
+
- (ViewID)viewID {
return VIEW_ID_TAB_CONTAINER_FOCUS_VIEW;
}
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.cc b/chrome/browser/renderer_host/test/test_render_view_host.cc
index 70d6a9c..ecc2426 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.cc
+++ b/chrome/browser/renderer_host/test/test_render_view_host.cc
@@ -143,6 +143,15 @@ void TestRenderWidgetHostView::SetActive(bool active) {
// <viettrungluu@gmail.com>: Do I need to do anything here?
}
+void TestRenderWidgetHostView::SetPluginImeEnabled(bool enabled,
+ int plugin_id) {
+}
+
+bool TestRenderWidgetHostView::PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event) {
+ return false;
+}
+
gfx::PluginWindowHandle
TestRenderWidgetHostView::AllocateFakePluginWindowHandle(
bool opaque,
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index 2312ba3..e3c9f39 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -101,6 +101,9 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
virtual void SetActive(bool active);
virtual void SetWindowVisibility(bool visible) {}
virtual void WindowFrameChanged() {}
+ virtual void SetPluginImeEnabled(bool enabled, int plugin_id);
+ virtual bool PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event);
virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(
bool opaque,
bool root);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index bcfca8ce..7d77275 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3496,6 +3496,8 @@
'../third_party/mozilla/NSURL+Utils.m',
'../third_party/mozilla/NSWorkspace+Utils.h',
'../third_party/mozilla/NSWorkspace+Utils.m',
+ '../third_party/mozilla/ComplexTextInputPanel.h',
+ '../third_party/mozilla/ComplexTextInputPanel.mm',
# Headers so that IB can find classes it needs to resolve classes
# in XIB files.
'../base/chrome_application_mac.h',
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
index 99e265a..a83b41a 100644
--- a/chrome/common/plugin_messages_internal.h
+++ b/chrome/common/plugin_messages_internal.h
@@ -238,6 +238,9 @@ IPC_BEGIN_MESSAGES(Plugin)
IPC_MESSAGE_ROUTED2(PluginMsg_WindowFrameChanged,
gfx::Rect /* window_frame */,
gfx::Rect /* view_frame */)
+
+ IPC_MESSAGE_ROUTED1(PluginMsg_ImeCompositionConfirmed,
+ string16 /* text */)
#endif
IPC_SYNC_MESSAGE_ROUTED2_0(PluginMsg_WillSendRequest,
@@ -402,6 +405,9 @@ IPC_BEGIN_MESSAGES(PluginHost)
IPC_MESSAGE_ROUTED1(PluginHostMsg_UpdateGeometry_ACK,
int /* ack_key */)
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_SetImeEnabled,
+ bool /* enabled */)
+
// This message, used in Mac OS X 10.5 and earlier, is sent from the plug-in
// process to the renderer process to indicate that the plug-in allocated a
// new TransportDIB that holds the GPU's rendered image. This information is
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 1307799..1cfa70b3 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -851,6 +851,11 @@ IPC_BEGIN_MESSAGES(View)
IPC_MESSAGE_ROUTED2(ViewMsg_WindowFrameChanged,
gfx::Rect /* window frame */,
gfx::Rect /* content view frame */)
+
+ // Tell the renderer that text has been retured from plugin IME.
+ IPC_MESSAGE_ROUTED2(ViewMsg_PluginImeCompositionConfirmed,
+ string16 /* text */,
+ int /* plugin_id */)
#endif
// Response message to ViewHostMsg_CreateShared/DedicatedWorker.
@@ -2148,8 +2153,13 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_CONTROL1(ViewHostMsg_FreeTransportDIB,
TransportDIB::Id /* DIB id */)
+ // Instructs the browser to start or stop plugin IME.
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_SetPluginImeEnabled,
+ bool, /* enabled */
+ int /* plugin_id */)
+
//---------------------------------------------------------------------------
- // Messages related to the GPU plugin on Mac OS X 10.6 and later
+ // Messages related to accelerated plugins
// This is sent from the renderer to the browser to allocate a fake
// PluginWindowHandle on the browser side which is used to identify
diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc
index 39282a1..cb6af0d 100644
--- a/chrome/plugin/webplugin_delegate_stub.cc
+++ b/chrome/plugin/webplugin_delegate_stub.cc
@@ -122,6 +122,8 @@ void WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(PluginMsg_ContainerHidden, OnContainerHidden)
IPC_MESSAGE_HANDLER(PluginMsg_ContainerShown, OnContainerShown)
IPC_MESSAGE_HANDLER(PluginMsg_WindowFrameChanged, OnWindowFrameChanged)
+ IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionConfirmed,
+ OnImeCompositionConfirmed)
#endif
IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveManualResponse,
OnDidReceiveManualResponse)
@@ -367,6 +369,11 @@ void WebPluginDelegateStub::OnWindowFrameChanged(const gfx::Rect& window_frame,
if (delegate_)
delegate_->WindowFrameChanged(window_frame, view_frame);
}
+
+void WebPluginDelegateStub::OnImeCompositionConfirmed(const string16& text) {
+ if (delegate_)
+ delegate_->ImeCompositionConfirmed(text);
+}
#endif // OS_MACOSX
void WebPluginDelegateStub::OnDidReceiveManualResponse(
diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h
index 0c1101e..5bc2887 100644
--- a/chrome/plugin/webplugin_delegate_stub.h
+++ b/chrome/plugin/webplugin_delegate_stub.h
@@ -85,6 +85,7 @@ class WebPluginDelegateStub : public IPC::Channel::Listener,
bool has_focus);
void OnWindowFrameChanged(const gfx::Rect& window_frame,
const gfx::Rect& view_frame);
+ void OnImeCompositionConfirmed(const string16& text);
#endif
void OnDidReceiveManualResponse(
diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc
index 5ec1b43..9741393 100644
--- a/chrome/plugin/webplugin_proxy.cc
+++ b/chrome/plugin/webplugin_proxy.cc
@@ -648,6 +648,14 @@ void WebPluginProxy::SetDeferResourceLoading(unsigned long resource_id,
}
#if defined(OS_MACOSX)
+void WebPluginProxy::SetImeEnabled(bool enabled) {
+ IPC::Message* msg = new PluginHostMsg_SetImeEnabled(route_id_, enabled);
+ // This message can be sent during event-handling, and needs to be delivered
+ // within that context.
+ msg->set_unblock(true);
+ Send(msg);
+}
+
void WebPluginProxy::BindFakePluginWindowHandle(bool opaque) {
Send(new PluginHostMsg_BindFakePluginWindowHandle(route_id_, opaque));
}
diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h
index 2134bf3..bf0b705 100644
--- a/chrome/plugin/webplugin_proxy.h
+++ b/chrome/plugin/webplugin_proxy.h
@@ -141,6 +141,8 @@ class WebPluginProxy : public webkit_glue::WebPlugin {
gfx::NativeViewId containing_window() { return containing_window_; }
#if defined(OS_MACOSX)
+ virtual void SetImeEnabled(bool enabled);
+
virtual void BindFakePluginWindowHandle(bool opaque);
virtual webkit_glue::WebPluginAcceleratedSurface* GetAcceleratedSurface();
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 0ca3650..125e4d5 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -789,6 +789,8 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility)
IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged)
+ IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionConfirmed,
+ OnPluginImeCompositionConfirmed)
#endif
IPC_MESSAGE_HANDLER(ViewMsg_SetEditCommandsForNextKeyEvent,
OnSetEditCommandsForNextKeyEvent)
@@ -4872,6 +4874,17 @@ void RenderView::OnWindowFrameChanged(const gfx::Rect& window_frame,
(*plugin_it)->WindowFrameChanged(window_frame, view_frame);
}
}
+
+void RenderView::OnPluginImeCompositionConfirmed(const string16& text,
+ int plugin_id) {
+ // WebPluginDelegateProxy is responsible for figuring out if this text
+ // applies to it or not, so inform all the delegates.
+ std::set<WebPluginDelegateProxy*>::iterator plugin_it;
+ for (plugin_it = plugin_delegates_.begin();
+ plugin_it != plugin_delegates_.end(); ++plugin_it) {
+ (*plugin_it)->ImeCompositionConfirmed(text, plugin_id);
+ }
+}
#endif // OS_MACOSX
void RenderView::SendExtensionRequest(
@@ -5794,6 +5807,15 @@ void RenderView::EnsureDocumentTag() {
}
#if defined(OS_MACOSX)
+void RenderView::SetPluginImeEnabled(bool enabled, int plugin_id) {
+ IPC::Message* msg = new ViewHostMsg_SetPluginImeEnabled(routing_id(),
+ enabled, plugin_id);
+ // This message can be sent during event-handling, and needs to be delivered
+ // within that context.
+ msg->set_unblock(true);
+ Send(msg);
+}
+
gfx::PluginWindowHandle RenderView::AllocateFakePluginWindowHandle(
bool opaque, bool root) {
gfx::PluginWindowHandle window = NULL;
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 95766c1..360b24d 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -304,7 +304,10 @@ class RenderView : public RenderWidget,
uint32 GetCPBrowsingContext();
#if defined(OS_MACOSX)
- // Helper routines for GPU plugin support. Used by the
+ // Enables/disabled plugin IME for the given plugin.
+ void SetPluginImeEnabled(bool enabled, int plugin_id);
+
+ // Helper routines for accelerated plugin support. Used by the
// WebPluginDelegateProxy, which has a pointer to the RenderView.
gfx::PluginWindowHandle AllocateFakePluginWindowHandle(bool opaque,
bool root);
@@ -824,6 +827,9 @@ class RenderView : public RenderWidget,
void OnFillPasswordForm(
const webkit_glue::PasswordFormFillData& form_data);
void OnPaste();
+#if defined(OS_MACOSX)
+ void OnPluginImeCompositionConfirmed(const string16& text, int plugin_id);
+#endif
void OnPrintingDone(int document_cookie, bool success);
void OnPrintPages();
void OnRedo();
diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc
index 708bbc9..f4229ff 100644
--- a/chrome/renderer/webplugin_delegate_proxy.cc
+++ b/chrome/renderer/webplugin_delegate_proxy.cc
@@ -462,6 +462,8 @@ void WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
OnDeferResourceLoading)
#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(PluginHostMsg_SetImeEnabled,
+ OnSetImeEnabled);
IPC_MESSAGE_HANDLER(PluginHostMsg_BindFakePluginWindowHandle,
OnBindFakePluginWindowHandle);
IPC_MESSAGE_HANDLER(PluginHostMsg_UpdateGeometry_ACK,
@@ -1015,6 +1017,18 @@ void WebPluginDelegateProxy::WindowFrameChanged(gfx::Rect window_frame,
msg->set_unblock(true);
Send(msg);
}
+void WebPluginDelegateProxy::ImeCompositionConfirmed(const string16& text,
+ int plugin_id) {
+ // If the text isn't intended for this plugin, there's nothing to do.
+ if (instance_id_ != plugin_id)
+ return;
+
+ IPC::Message* msg = new PluginMsg_ImeCompositionConfirmed(instance_id_,
+ text);
+ // Order relative to other key events is important.
+ msg->set_unblock(true);
+ Send(msg);
+}
#endif // OS_MACOSX
void WebPluginDelegateProxy::OnSetWindow(gfx::PluginWindowHandle window) {
@@ -1363,6 +1377,11 @@ WebPluginDelegateProxy::CreateSeekableResourceClient(
}
#if defined(OS_MACOSX)
+void WebPluginDelegateProxy::OnSetImeEnabled(bool enabled) {
+ if (render_view_)
+ render_view_->SetPluginImeEnabled(enabled, instance_id_);
+}
+
void WebPluginDelegateProxy::OnBindFakePluginWindowHandle(bool opaque) {
BindFakePluginWindowHandle(opaque);
}
diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h
index 0cabc1b..204cf4d 100644
--- a/chrome/renderer/webplugin_delegate_proxy.h
+++ b/chrome/renderer/webplugin_delegate_proxy.h
@@ -88,6 +88,8 @@ class WebPluginDelegateProxy
virtual void SetContainerVisibility(bool is_visible);
// Informs the plugin that its enclosing window's frame has changed.
virtual void WindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame);
+ // Informs the plugin that text is avaiable from plugin IME.
+ virtual void ImeCompositionConfirmed(const string16& text, int plugin_id);
#endif
// IPC::Channel::Listener implementation:
@@ -160,6 +162,7 @@ class WebPluginDelegateProxy
void OnDeferResourceLoading(unsigned long resource_id, bool defer);
#if defined(OS_MACOSX)
+ void OnSetImeEnabled(bool enabled);
void OnBindFakePluginWindowHandle(bool opaque);
void OnUpdateGeometry_ACK(int ack_key);
void OnAcceleratedSurfaceSetIOSurface(gfx::PluginWindowHandle window,
diff --git a/third_party/mozilla/ComplexTextInputPanel.h b/third_party/mozilla/ComplexTextInputPanel.h
new file mode 100644
index 0000000..598a2b8
--- /dev/null
+++ b/third_party/mozilla/ComplexTextInputPanel.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Modified by Josh Aas of Mozilla Corporation.
+ */
+
+#ifndef ComplexTextInputPanel_h_
+#define ComplexTextInputPanel_h_
+
+#import <Cocoa/Cocoa.h>
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
+@class NSTextInputContext;
+#endif
+
+@interface ComplexTextInputPanel : NSPanel {
+ NSTextView *mInputTextView;
+}
+
++ (ComplexTextInputPanel*)sharedComplexTextInputPanel;
+
+- (NSTextInputContext*)inputContext;
+- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
+- (void)cancelInput;
+
+@end
+
+#endif // ComplexTextInputPanel_h_
diff --git a/third_party/mozilla/ComplexTextInputPanel.mm b/third_party/mozilla/ComplexTextInputPanel.mm
new file mode 100644
index 0000000..638ed9d
--- /dev/null
+++ b/third_party/mozilla/ComplexTextInputPanel.mm
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Modified by Josh Aas of Mozilla Corporation.
+ */
+
+#import "ComplexTextInputPanel.h"
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
+@interface NSView (SnowLeopardMethods)
+- (NSTextInputContext *)inputContext;
+@end
+
+// This is actually an NSTextInputContext method, but we can't declare
+// that since the whole class is 10.6+.
+@interface NSObject (SnowLeopardMethods)
+- (BOOL)handleEvent:(NSEvent *)theEvent;
+@end
+
+static NSString* const NSTextInputContextKeyboardSelectionDidChangeNotification =
+ @"NSTextInputContextKeyboardSelectionDidChangeNotification";
+#endif
+
+#define kInputWindowHeight 20
+
+@implementation ComplexTextInputPanel
+
++ (ComplexTextInputPanel*)sharedComplexTextInputPanel
+{
+ static ComplexTextInputPanel *sComplexTextInputPanel;
+ if (!sComplexTextInputPanel)
+ sComplexTextInputPanel = [[ComplexTextInputPanel alloc] init];
+ return sComplexTextInputPanel;
+}
+
+- (id)init
+{
+ // In the original Apple code the style mask is given by a function which is not open source.
+ // What could possibly be worth hiding in that function, I do not know.
+ // Courtesy of gdb: stylemask: 011000011111, 0x61f
+ self = [super initWithContentRect:NSZeroRect styleMask:0x61f backing:NSBackingStoreBuffered defer:YES];
+ if (!self)
+ return nil;
+
+ // Set the frame size.
+ NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame];
+ NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, kInputWindowHeight);
+
+ [self setFrame:frame display:NO];
+
+ mInputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];
+ mInputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
+
+ NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
+ scrollView.documentView = mInputTextView;
+ self.contentView = scrollView;
+ [scrollView release];
+
+ [self setFloatingPanel:YES];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(keyboardInputSourceChanged:)
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ [mInputTextView release];
+
+ [super dealloc];
+}
+
+- (void)keyboardInputSourceChanged:(NSNotification *)notification
+{
+ [mInputTextView setString:@""];
+ [self orderOut:nil];
+}
+
+- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
+{
+ BOOL hadMarkedText = [mInputTextView hasMarkedText];
+
+ *string = nil;
+
+ if (![[mInputTextView inputContext] handleEvent:event])
+ return NO;
+
+ if ([mInputTextView hasMarkedText]) {
+ // Don't show the input method window for dead keys
+ if ([[event characters] length] > 0)
+ [self orderFront:nil];
+
+ return YES;
+ } else {
+ [self orderOut:nil];
+
+ NSString *text = [[mInputTextView textStorage] string];
+ if ([text length] > 0)
+ *string = [[text copy] autorelease];
+ }
+
+ [mInputTextView setString:@""];
+ return hadMarkedText;
+}
+
+- (void)cancelInput
+{
+ [self orderOut:nil];
+ [mInputTextView setString:@""];
+}
+
+- (NSTextInputContext*)inputContext
+{
+ return [mInputTextView inputContext];
+}
+
+@end
diff --git a/third_party/mozilla/README.chromium b/third_party/mozilla/README.chromium
index fe93bb8..8c66389 100644
--- a/third_party/mozilla/README.chromium
+++ b/third_party/mozilla/README.chromium
@@ -20,3 +20,14 @@ Local modifications:
-[NSPasteboard getURLs:andTitles:] to determine whether or not filenames in
the drag should be converted to file URLs.
-[NSPasteboard htmlFromRtf] added to do rtf->html conversion.
+
+-----------------------------------------------------------------
+
+Also includes IME panel from Gecko, which is based on WebKit's implementation.
+Although it comes from Mozilla (http://mxr.mozilla.org), it uses the original
+WebKit license.
+
+Local modifitations:
+- Added a cancelInput method.
+- Add #ifdef'd definifitions of a few symbols to support 10.5 SDK.
+
diff --git a/webkit/glue/plugins/webplugin.h b/webkit/glue/plugins/webplugin.h
index 1a14d545..36426fa 100644
--- a/webkit/glue/plugins/webplugin.h
+++ b/webkit/glue/plugins/webplugin.h
@@ -149,6 +149,9 @@ class WebPlugin {
bool defer) = 0;
#if defined(OS_MACOSX)
+ // Enables/disables plugin IME.
+ virtual void SetImeEnabled(bool enabled) {};
+
// Synthesize a fake window handle for the plug-in to identify the instance
// to the browser, allowing mapping to a surface for hardware accelleration
// of plug-in content. The browser generates the handle which is then set on
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index 55381f9..30a4a58 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -161,6 +161,8 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
// Frames are in screen coordinates.
void WindowFrameChanged(const gfx::Rect& window_frame,
const gfx::Rect& view_frame);
+ // Informs the plugin that IME composition has been confirmed.
+ void ImeCompositionConfirmed(const string16& text);
// Informs the delegate that the plugin set a Carbon ThemeCursor.
void SetThemeCursor(ThemeCursor cursor);
// Informs the delegate that the plugin set a Carbon Cursor.
@@ -385,20 +387,15 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
void SetContentAreaOrigin(const gfx::Point& origin);
// Updates everything that depends on the plugin's absolute screen location.
void PluginScreenLocationChanged();
+ // Updates anything that depends on plugin visibility.
+ void PluginVisibilityChanged();
- // Returns the apparent zoom ratio for the given event, as inferred from our
- // current knowledge about about where on screen the plugin is.
- // This is a temporary workaround for <http://crbug.com/9996>; once that is
- // fixed we should have correct event coordinates (or an explicit
- // notification of zoom level).
- float ApparentEventZoomLevel(const WebKit::WebMouseEvent& event);
+ // Enables/disables IME.
+ void SetImeEnabled(bool enabled);
// Informs the browser about the updated accelerated drawing surface.
void UpdateAcceleratedSurface();
- // Updates anything that depends on plugin visibility.
- void PluginVisibilityChanged();
-
// Uses a CARenderer to draw the plug-in's layer in our OpenGL surface.
void DrawLayerInSurface();
@@ -447,6 +444,8 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
gfx::Rect cached_clip_rect_;
+ bool ime_enabled_;
+
scoped_ptr<ExternalDragTracker> external_drag_tracker_;
#endif // OS_MACOSX
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
index b7e7702..cca8695 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
+++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
@@ -17,6 +17,7 @@
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
+#include "base/sys_string_conversions.h"
#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
#include "webkit/glue/plugins/plugin_instance.h"
#include "webkit/glue/plugins/plugin_lib.h"
@@ -263,6 +264,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
initial_window_focus_(false),
container_is_visible_(false),
have_called_set_window_(false),
+ ime_enabled_(false),
external_drag_tracker_(new ExternalDragTracker()),
handle_event_depth_(0),
first_set_window_call_(true),
@@ -573,7 +575,13 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent(
event_scope.reset(new NPAPI::ScopedCurrentPluginEvent(
instance(), static_cast<NPCocoaEvent*>(plugin_event)));
}
- bool handled = instance()->NPP_HandleEvent(plugin_event) != 0;
+ int16_t handle_response = instance()->NPP_HandleEvent(plugin_event);
+ bool handled = handle_response != kNPEventNotHandled;
+
+ if (handled && event.type == WebInputEvent::KeyDown) {
+ // Update IME state as requested by the plugin.
+ SetImeEnabled(handle_response == kNPEventStartIME);
+ }
// Plugins don't give accurate information about whether or not they handled
// events, so browsers on the Mac ignore the return value.
@@ -778,6 +786,9 @@ void WebPluginDelegateImpl::SetWindowHasFocus(bool has_focus) {
return;
containing_window_has_focus_ = has_focus;
+ if (!has_focus)
+ SetImeEnabled(false);
+
#ifndef NP_NO_QUICKDRAW
// Make sure controls repaint with the correct look.
if (quirks_ & PLUGIN_QUIRK_ALLOW_FASTER_QUICKDRAW_PATH)
@@ -814,6 +825,9 @@ bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) {
if (!have_called_set_window_)
return false;
+ if (!focused)
+ SetImeEnabled(false);
+
ScopedActiveDelegate active_delegate(this);
switch (instance()->event_model()) {
@@ -878,6 +892,20 @@ void WebPluginDelegateImpl::WindowFrameChanged(const gfx::Rect& window_frame,
SetContentAreaOrigin(gfx::Point(view_frame.x(), view_frame.y()));
}
+void WebPluginDelegateImpl::ImeCompositionConfirmed(const string16& text) {
+ if (instance()->event_model() != NPEventModelCocoa) {
+ DLOG(ERROR) << "IME text receieved in Carbon event model";
+ return;
+ }
+
+ NPCocoaEvent text_event;
+ memset(&text_event, 0, sizeof(NPCocoaEvent));
+ text_event.type = NPCocoaEventTextInput;
+ text_event.data.text.text =
+ reinterpret_cast<NPNSString*>(base::SysUTF16ToNSString(text));
+ instance()->NPP_HandleEvent(&text_event);
+}
+
void WebPluginDelegateImpl::SetThemeCursor(ThemeCursor cursor) {
current_windowless_cursor_.InitFromThemeCursor(cursor);
}
@@ -936,6 +964,15 @@ void WebPluginDelegateImpl::PluginVisibilityChanged() {
}
}
+void WebPluginDelegateImpl::SetImeEnabled(bool enabled) {
+ if (instance()->event_model() != NPEventModelCocoa)
+ return;
+ if (enabled == ime_enabled_)
+ return;
+ ime_enabled_ = enabled;
+ plugin_->SetImeEnabled(enabled);
+}
+
#pragma mark -
#pragma mark Core Animation Support