diff options
author | amanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-20 18:26:16 +0000 |
---|---|---|
committer | amanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-20 18:26:16 +0000 |
commit | 27f5a6c85610ac97a87bc64918ead7891f58fda5 (patch) | |
tree | 8454f2a3e2526b203628c0e434ebee62e563ad0b /chrome | |
parent | 8806b8a53168e161e8a2cbbf4051067c095832a9 (diff) | |
download | chromium_src-27f5a6c85610ac97a87bc64918ead7891f58fda5.zip chromium_src-27f5a6c85610ac97a87bc64918ead7891f58fda5.tar.gz chromium_src-27f5a6c85610ac97a87bc64918ead7891f58fda5.tar.bz2 |
Mac: Simulate the OS-level focus handling that windows and linux plugins
rely on to trigger NPAPI keyboard focus notifications.
BUG=26585
TEST=On pages with multiple Flash text entry fields, only one should have
a blinking caret at any time. Flash elements that use the ActionScript2
"Key.IsDown()" function should only detect keydowns when they are in a
visible tab and focused.
Review URL: http://codereview.chromium.org/399090
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32631 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/plugin_process_host.cc | 2 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.h | 1 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host_mac.cc | 15 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.mm | 30 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 14 | ||||
-rw-r--r-- | chrome/plugin/plugin_thread.cc | 19 | ||||
-rw-r--r-- | chrome/plugin/plugin_thread.h | 1 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.cc | 19 |
8 files changed, 101 insertions, 0 deletions
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index 4d5cd22..e09807b 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -512,6 +512,8 @@ void PluginProcessHost::OnMessageReceived(const IPC::Message& msg) { OnPluginHideWindow) IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginDisposeWindow, OnPluginDisposeWindow) + IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginReceivedFocus, + OnPluginReceivedFocus) #endif IPC_MESSAGE_UNHANDLED_ERROR() IPC_END_MESSAGE_MAP() diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h index 5d0c7e3..c2a240d 100644 --- a/chrome/browser/plugin_process_host.h +++ b/chrome/browser/plugin_process_host.h @@ -130,6 +130,7 @@ class PluginProcessHost : public ChildProcessHost, bool modal); void OnPluginHideWindow(uint32 window_id, gfx::Rect window_rect); void OnPluginDisposeWindow(uint32 window_id, gfx::Rect window_rect); + void OnPluginReceivedFocus(int process_id, int instance_id); #endif virtual bool CanShutdown() { return sent_requests_.empty(); } diff --git a/chrome/browser/plugin_process_host_mac.cc b/chrome/browser/plugin_process_host_mac.cc index bea1cbc..f1f0ff8 100644 --- a/chrome/browser/plugin_process_host_mac.cc +++ b/chrome/browser/plugin_process_host_mac.cc @@ -12,6 +12,8 @@ #include "base/mac_util.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/plugin_process_host.h" +#include "chrome/common/plugin_messages.h" + void PluginProcessHost::OnPluginSelectWindow(uint32 window_id, gfx::Rect window_rect, @@ -75,3 +77,16 @@ void PluginProcessHost::OnAppActivation() { NewRunnableFunction(mac_util::ActivateProcess, handle())); } } + +void PluginProcessHost::OnPluginReceivedFocus(int process_id, int instance_id) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + // A plugin has received keyboard focus, so tell all other plugin processes + // that they no longer have it (simulating the OS-level focus notifications + // that Gtk and Windows provide). + for (ChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); + !iter.Done(); ++iter) { + PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); + int instance = (plugin->handle() == process_id) ? instance_id : 0; + plugin->Send(new PluginProcessMsg_PluginFocusNotify(instance)); + } +} 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 d36e999..881a0b3 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -10,12 +10,14 @@ #include "base/sys_string_conversions.h" #include "chrome/browser/browser_trial.h" #import "chrome/browser/cocoa/rwhvm_editcommand_helper.h" +#include "chrome/browser/plugin_process_host.h" #include "chrome/browser/renderer_host/backing_store.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_widget_host.h" #include "chrome/browser/spellchecker_platform_engine.h" #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/edit_command.h" +#include "chrome/common/plugin_messages.h" #include "chrome/common/render_messages.h" #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h" @@ -48,6 +50,26 @@ namespace { // Maximum number of characters we allow in a tooltip. const size_t kMaxTooltipLength = 1024; +class NotifyPluginProcessHostTask : public Task { + public: + NotifyPluginProcessHostTask(uint32 process_id, uint32 instance_id) + : process_id_(process_id), instance_id_(instance_id) { } + + private: + void Run() { + for (ChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); + !iter.Done(); ++iter) { + PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); + uint32 plugin_pid = plugin->handle(); + uint32 instance = (plugin_pid == process_id_) ? instance_id_ : 0; + plugin->Send(new PluginProcessMsg_PluginFocusNotify(instance)); + } + } + + uint32 process_id_; + uint32 instance_id_; +}; + } // RenderWidgetHostView -------------------------------------------------------- @@ -134,6 +156,10 @@ void RenderWidgetHostViewMac::WasHidden() { // everything again when we become selected again. is_hidden_ = true; + // tell any plugins that thought they had the focus that they do not now. + ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, + new NotifyPluginProcessHostTask(0, 0)); + // If we have a renderer, then inform it that we are being hidden so it can // reduce its resource utilization. render_widget_host_->WasHidden(); @@ -453,6 +479,10 @@ gfx::Rect RenderWidgetHostViewMac::GetRootWindowRect() { void RenderWidgetHostViewMac::SetActive(bool active) { if (render_widget_host_) render_widget_host_->SetActive(active); + if (!active) + // tell any plugins that thought they had the focus that they do not now. + ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, + new NotifyPluginProcessHostTask(0, 0)); } void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) { diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h index 84f9cd3..0cfbc9f 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -47,6 +47,15 @@ IPC_BEGIN_MESSAGES(PluginProcess) bool /* on or off */) #endif +#if defined(OS_MACOSX) + // Notifies a plugin process that keyboard focus has changed. If another + // plugin instance has received focus, the process and instance IDs are + // passed as parameters; if focus has been taken away from a plugin, 0 is + // passed for both parameters. + IPC_MESSAGE_CONTROL1(PluginProcessMsg_PluginFocusNotify, + uint32 /* instance ID */) +#endif + IPC_END_MESSAGES(PluginProcess) @@ -151,6 +160,11 @@ IPC_BEGIN_MESSAGES(PluginProcessHost) IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginDisposeWindow, uint32 /* window ID */, gfx::Rect /* window rect */) + + // Notifies the browser that a plugin instance has received keyboard focus + IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginReceivedFocus, + uint32 /* process ID */, + uint32 /* instance ID */) #endif IPC_END_MESSAGES(PluginProcessHost) diff --git a/chrome/plugin/plugin_thread.cc b/chrome/plugin/plugin_thread.cc index 914a8ce..9ef6c45 100644 --- a/chrome/plugin/plugin_thread.cc +++ b/chrome/plugin/plugin_thread.cc @@ -21,6 +21,7 @@ #include "net/base/net_errors.h" #include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/webkit_glue.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" static base::LazyInstance<base::ThreadLocalPointer<PluginThread> > lazy_tls( base::LINKER_INITIALIZED); @@ -102,6 +103,10 @@ void PluginThread::OnControlMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(PluginThread, msg) IPC_MESSAGE_HANDLER(PluginProcessMsg_CreateChannel, OnCreateChannel) IPC_MESSAGE_HANDLER(PluginProcessMsg_PluginMessage, OnPluginMessage) +#if defined(OS_MACOSX) + IPC_MESSAGE_HANDLER(PluginProcessMsg_PluginFocusNotify, + OnPluginFocusNotify) +#endif IPC_END_MESSAGE_MAP() } @@ -138,6 +143,20 @@ void PluginThread::OnPluginMessage(const std::vector<unsigned char> &data) { ChildProcess::current()->ReleaseProcess(); } +#if defined(OS_MACOSX) +void PluginThread::OnPluginFocusNotify(uint32 instance_id) { + WebPluginDelegateImpl* instance = + reinterpret_cast<WebPluginDelegateImpl*>(instance_id); + std::set<WebPluginDelegateImpl*> active_delegates = + WebPluginDelegateImpl::GetActiveDelegates(); + for (std::set<WebPluginDelegateImpl*>::iterator iter = + active_delegates.begin(); + iter != active_delegates.end(); iter++) { + (*iter)->FocusNotify(instance); + } +} +#endif + namespace webkit_glue { #if defined(OS_WIN) diff --git a/chrome/plugin/plugin_thread.h b/chrome/plugin/plugin_thread.h index 435d8c3..b5eeefc 100644 --- a/chrome/plugin/plugin_thread.h +++ b/chrome/plugin/plugin_thread.h @@ -37,6 +37,7 @@ class PluginThread : public ChildThread { void OnPluginMessage(const std::vector<uint8> &data); #if defined(OS_MACOSX) void OnAppActivated(); + void OnPluginFocusNotify(uint32 instance_id); #endif // The plugin module which is preloaded in Init diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index a4dabfb..6807b7b 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -46,6 +46,22 @@ class FinishDestructionTask : public Task { WebPlugin* webplugin_; }; +#if defined(OS_MACOSX) +namespace { + +void FocusNotifier(WebPluginDelegateImpl *instance) { + uint32 process_id = getpid(); + uint32 instance_id = reinterpret_cast<uint32>(instance); + PluginThread* plugin_thread = PluginThread::current(); + if (plugin_thread) { + plugin_thread->Send( + new PluginProcessHostMsg_PluginReceivedFocus(process_id, instance_id)); + } +} + +} +#endif + WebPluginDelegateStub::WebPluginDelegateStub( const std::string& mime_type, int instance_id, PluginChannel* channel) : mime_type_(mime_type), @@ -164,6 +180,9 @@ void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params, params.arg_values, webplugin_, params.load_manually); +#if defined(OS_MACOSX) + delegate_->SetFocusNotifier(FocusNotifier); +#endif } } |