diff options
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.mm | 28 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 12 | ||||
-rw-r--r-- | chrome/plugin/plugin_thread.cc | 5 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.cc | 8 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.h | 1 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 24 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 4 | ||||
-rw-r--r-- | chrome/renderer/render_widget.h | 4 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 18 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.h | 1 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 13 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 93 |
12 files changed, 147 insertions, 64 deletions
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 382fafb..fcf55eb 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -51,26 +51,6 @@ 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 -------------------------------------------------------- @@ -157,10 +137,6 @@ 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(); @@ -513,10 +489,6 @@ 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 7c10168..b1af5b0 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -49,9 +49,8 @@ IPC_BEGIN_MESSAGES(PluginProcess) #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. + // plugin instance has received focus, the instance IDs is passed as a + // parameter; if focus has been taken away from a plugin, 0 is passed. IPC_MESSAGE_CONTROL1(PluginProcessMsg_PluginFocusNotify, uint32 /* instance ID */) #endif @@ -226,8 +225,11 @@ IPC_BEGIN_MESSAGES(Plugin) WebCursor /* cursor type*/) #if defined(OS_MACOSX) - IPC_SYNC_MESSAGE_ROUTED1_0(PluginMsg_SetWindowFocus, - bool /* has_focus */) + IPC_MESSAGE_ROUTED1(PluginMsg_SetWindowFocus, + bool /* has_focus */) + + IPC_MESSAGE_ROUTED1(PluginMsg_SetContainerVisibility, + bool /* is_visible */) #endif IPC_SYNC_MESSAGE_ROUTED2_0(PluginMsg_WillSendRequest, diff --git a/chrome/plugin/plugin_thread.cc b/chrome/plugin/plugin_thread.cc index fb02ac5..0a9ef12 100644 --- a/chrome/plugin/plugin_thread.cc +++ b/chrome/plugin/plugin_thread.cc @@ -149,14 +149,15 @@ void PluginThread::OnPluginMessage(const std::vector<unsigned char> &data) { #if defined(OS_MACOSX) void PluginThread::OnPluginFocusNotify(uint32 instance_id) { - WebPluginDelegateImpl* instance = + WebPluginDelegateImpl* focused_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); + WebPluginDelegateImpl* instance = *iter; + instance->FocusChanged(instance == focused_instance); } } #endif diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index 253d7cf..cf6e842 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -123,6 +123,8 @@ void WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) { OnSendJavaScriptStream) #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(PluginMsg_SetWindowFocus, OnSetWindowFocus) + IPC_MESSAGE_HANDLER(PluginMsg_SetContainerVisibility, + OnSetContainerVisibility) #endif IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveManualResponse, OnDidReceiveManualResponse) @@ -338,7 +340,11 @@ void WebPluginDelegateStub::OnSendJavaScriptStream(const GURL& url, void WebPluginDelegateStub::OnSetWindowFocus(bool has_focus) { delegate_->SetWindowHasFocus(has_focus); } -#endif + +void WebPluginDelegateStub::OnSetContainerVisibility(bool is_visible) { + delegate_->SetContainerVisibility(is_visible); +} +#endif // OS_MACOSX void WebPluginDelegateStub::OnDidReceiveManualResponse( const GURL& url, diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h index 5728fdd..b783832 100644 --- a/chrome/plugin/webplugin_delegate_stub.h +++ b/chrome/plugin/webplugin_delegate_stub.h @@ -80,6 +80,7 @@ class WebPluginDelegateStub : public IPC::Channel::Listener, #if defined(OS_MACOSX) void OnSetWindowFocus(bool has_focus); + void OnSetContainerVisibility(bool is_visible); #endif void OnDidReceiveManualResponse( diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 388d934..e959f14 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -4179,6 +4179,30 @@ void RenderView::DidHandleKeyEvent() { edit_commands_.clear(); } +#if defined(OS_MACOSX) +void RenderView::OnWasHidden() { + RenderWidget::OnWasHidden(); + + // Inform plugins that their container is no longer visible. + std::set<WebPluginDelegateProxy*>::iterator plugin_it; + for (plugin_it = plugin_delegates_.begin(); + plugin_it != plugin_delegates_.end(); ++plugin_it) { + (*plugin_it)->SetContainerVisibility(false); + } +} + +void RenderView::OnWasRestored(bool needs_repainting) { + RenderWidget::OnWasRestored(needs_repainting); + + // Inform plugins that their container is now visible. + std::set<WebPluginDelegateProxy*>::iterator plugin_it; + for (plugin_it = plugin_delegates_.begin(); + plugin_it != plugin_delegates_.end(); ++plugin_it) { + (*plugin_it)->SetContainerVisibility(true); + } +} +#endif // OS_MACOSX + void RenderView::EnsureDocumentTag() { // TODO(darin): There's actually no reason for this to be here. We should // have the browser side manage the document tag. diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 25d598f..dbf4440 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -476,6 +476,10 @@ class RenderView : public RenderWidget, const gfx::Rect& resizer_rect); virtual void DidPaint(); virtual void DidHandleKeyEvent(); +#if OS_MACOSX + virtual void OnWasHidden(); + virtual void OnWasRestored(bool needs_repainting); +#endif private: // For unit tests. diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index 4cf033e..86f2a17 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -140,8 +140,8 @@ class RenderWidget : public IPC::Channel::Listener, void OnCreatingNewAck(gfx::NativeViewId parent); virtual void OnResize(const gfx::Size& new_size, const gfx::Rect& resizer_rect); - void OnWasHidden(); - void OnWasRestored(bool needs_repainting); + virtual void OnWasHidden(); + virtual void OnWasRestored(bool needs_repainting); void OnUpdateRectAck(); void OnRequestMoveAck(); void OnHandleInputEvent(const IPC::Message& message); diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 94ddc2a..da19300 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -860,7 +860,23 @@ int WebPluginDelegateProxy::GetProcessId() { #if defined(OS_MACOSX) void WebPluginDelegateProxy::SetWindowFocus(bool window_has_focus) { - Send(new PluginMsg_SetWindowFocus(instance_id_, window_has_focus)); + IPC::Message* msg = new PluginMsg_SetWindowFocus(instance_id_, + window_has_focus); + // Make sure visibility events are delivered in the right order relative to + // sync messages they might interact with (Paint, HandleEvent, etc.). + msg->set_unblock(true); + Send(msg); +} + +void WebPluginDelegateProxy::SetContainerVisibility(bool is_visible) { + // TODO(stuartmorgan): Split this into two messages, and send location and + // focus information with the "became visible" version since the plugins in a + // hidden tab will not have been getting live updates. + IPC::Message* msg = new PluginMsg_SetWindowFocus(instance_id_, is_visible); + // Make sure visibility events are delivered in the right order relative to + // sync messages they might interact with (Paint, HandleEvent, etc.). + msg->set_unblock(true); + Send(msg); } #endif // OS_MACOSX diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h index 7df5838..c0ce498 100644 --- a/chrome/renderer/webplugin_delegate_proxy.h +++ b/chrome/renderer/webplugin_delegate_proxy.h @@ -73,6 +73,7 @@ class WebPluginDelegateProxy #if defined(OS_MACOSX) virtual void SetWindowFocus(bool window_has_focus); + virtual void SetContainerVisibility(bool is_visible); #endif // IPC::Channel::Listener implementation: diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index ce19bb5..eb05e27 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -119,14 +119,11 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { static WebPluginDelegateImpl* GetActiveDelegate(); // Returns a vector of currently active delegates in this process. static std::set<WebPluginDelegateImpl*> GetActiveDelegates(); - // Informs the delegate which plugin instance has just received keyboard focus - // so that it can notify the plugin as appropriate. If |process_id| and - // |instance_id| are both 0, this signifies that no plugin has keyboard - // focus. - void FocusNotify(WebPluginDelegateImpl* focused_delegate); + // Informs the delegate that it has gained or lost focus. + void FocusChanged(bool has_focus); // Set a notifier function that gets called when the delegate is accepting // the focus. If no notifier function has been set, the delegate will just - // call FocusNotify(this). This is used in a multiprocess environment to + // call FocusChanged(true). This is used in a multiprocess environment to // propagate focus notifications to all running plugin processes. void SetFocusNotifier(void (*notifier)(WebPluginDelegateImpl*)) { focus_notifier_ = notifier; @@ -135,6 +132,8 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { void SetWindowHasFocus(bool has_focus); // Returns whether or not the window the plugin is in has focus. bool GetWindowHasFocus() const { return containing_window_has_focus_; } + // Informs the plugin that its tab has been hidden or shown. + void SetContainerVisibility(bool is_visible); // Informs the delegate that the plugin set a Carbon ThemeCursor. void SetThemeCursor(ThemeCursor cursor); // Informs the delegate that the plugin set a Carbon Cursor. @@ -362,6 +361,8 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { void (*focus_notifier_)(WebPluginDelegateImpl* notifier); bool containing_window_has_focus_; + bool container_is_visible_; + bool have_called_set_window_; #endif // Called by the message filter hook when the plugin enters a modal loop. diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm index 0fe6ed6..02d1dcb 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm +++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm @@ -177,6 +177,8 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( have_focus_(false), focus_notifier_(NULL), containing_window_has_focus_(false), + container_is_visible_(false), + have_called_set_window_(false), handle_event_depth_(0), user_gesture_message_posted_(this), user_gesture_msg_factory_(this) { @@ -267,13 +269,18 @@ void WebPluginDelegateImpl::PlatformInitialize() { break; } + // TODO(stuartmorgan): We need real plugin container visibility information + // when the plugin is initialized; for now, assume it's visible. + // None of the calls SetContainerVisibility would make are useful at this + // point, so we just set the initial state directly. + container_is_visible_ = true; + #ifndef NP_NO_CARBON // If the plugin wants Carbon events, hook up to the source of idle events. if (instance()->event_model() == NPEventModelCarbon) UpdateIdleEventRate(); #endif plugin_->SetWindow(NULL); - } void WebPluginDelegateImpl::PlatformDestroyInstance() { @@ -436,7 +443,7 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { window_.clipRect.top = window_.y; window_.clipRect.right = window_.clipRect.left; window_.clipRect.bottom = window_.clipRect.top; - if (!clip_rect_.IsEmpty()) { + if (container_is_visible_ && !clip_rect_.IsEmpty()) { // We never tell plugins that they are only partially visible; because the // drawing target doesn't change size, the positioning of what plugins drew // would be wrong, as would any transforms they did on the context. @@ -450,10 +457,14 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { NPError err = instance()->NPP_SetWindow(&window_); - // TODO(stuartmorgan): We need real window information when the plugin is - // initialized (location, window focus, visibility, etc.); for now, just - // start off assuming window focus. - SetWindowHasFocus(true); + // Plugins expect to get an initial window focus call if they are in an active + // window when they get their first SetWindow call. + if (!have_called_set_window_) { + // TODO(stuartmorgan): We need real window information about the initial + // window state; for now, assume window focus. + SetWindowHasFocus(true); + have_called_set_window_ = true; + } DCHECK(err == NPERR_NO_ERROR); } @@ -467,12 +478,15 @@ std::set<WebPluginDelegateImpl*> WebPluginDelegateImpl::GetActiveDelegates() { return *delegates; } -void WebPluginDelegateImpl::FocusNotify(WebPluginDelegateImpl* delegate) { - have_focus_ = (delegate == this); +void WebPluginDelegateImpl::FocusChanged(bool has_focus) { + if (has_focus == have_focus_) + return; + have_focus_ = has_focus; ScopedActiveDelegate active_delegate(this); switch (instance()->event_model()) { +#ifndef NP_NO_CARBON case NPEventModelCarbon: { NPEvent focus_event = { 0 }; if (have_focus_) @@ -483,6 +497,7 @@ void WebPluginDelegateImpl::FocusNotify(WebPluginDelegateImpl* delegate) { instance()->NPP_HandleEvent(&focus_event); break; } +#endif case NPEventModelCocoa: { NPCocoaEvent focus_event; memset(&focus_event, 0, sizeof(focus_event)); @@ -498,19 +513,59 @@ void WebPluginDelegateImpl::SetFocus() { if (focus_notifier_) focus_notifier_(this); else - FocusNotify(this); + FocusChanged(true); } void WebPluginDelegateImpl::SetWindowHasFocus(bool has_focus) { + if (has_focus == containing_window_has_focus_) + return; containing_window_has_focus_ = has_focus; - if (instance()->event_model() == NPEventModelCocoa) { - ScopedActiveDelegate active_delegate(this); - NPCocoaEvent focus_event; - memset(&focus_event, 0, sizeof(focus_event)); - focus_event.type = NPCocoaEventWindowFocusChanged; - focus_event.data.focus.hasFocus = has_focus; - instance()->NPP_HandleEvent(reinterpret_cast<NPEvent*>(&focus_event)); + ScopedActiveDelegate active_delegate(this); + switch (instance()->event_model()) { +#ifndef NP_NO_CARBON + case NPEventModelCarbon: { + NPEvent focus_event = { 0 }; + focus_event.what = activateEvt; + if (has_focus) + focus_event.modifiers |= activeFlag; + focus_event.message = reinterpret_cast<unsigned long>(cg_context_.window); + focus_event.when = TickCount(); + instance()->NPP_HandleEvent(&focus_event); + break; + } +#endif + case NPEventModelCocoa: { + NPCocoaEvent focus_event; + memset(&focus_event, 0, sizeof(focus_event)); + focus_event.type = NPCocoaEventWindowFocusChanged; + focus_event.data.focus.hasFocus = has_focus; + instance()->NPP_HandleEvent(reinterpret_cast<NPEvent*>(&focus_event)); + } + } +} + +void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) { + if (is_visible == container_is_visible_) + return; + container_is_visible_ = is_visible; + + // TODO(stuartmorgan): We may need to remember whether we had focus, and + // restore it ourselves when we become visible again. Revisit once SetFocus + // is actually being called in all the cases it should be, at which point + // we'll know whether or not that's handled for us by WebKit. + if (!is_visible) + FocusChanged(false); + + // If the plugin is changing visibility, let the plugin know. If it's scrolled + // off screen (i.e., clip_rect_ is empty), then container visibility doesn't + // change anything. + if (!clip_rect_.IsEmpty()) { +#ifndef NP_NO_CARBON + if (instance()->event_model() == NPEventModelCarbon) + UpdateIdleEventRate(); +#endif + WindowlessSetWindow(true); } } @@ -571,10 +626,10 @@ void WebPluginDelegateImpl::UpdateDummyWindowBoundsWithOffset( } void WebPluginDelegateImpl::UpdateIdleEventRate() { - if (clip_rect_.IsEmpty()) - CarbonIdleEventSource::SharedInstance()->RegisterHiddenDelegate(this); - else + if (container_is_visible_ && !clip_rect_.IsEmpty()) CarbonIdleEventSource::SharedInstance()->RegisterVisibleDelegate(this); + else + CarbonIdleEventSource::SharedInstance()->RegisterHiddenDelegate(this); } #endif // !NP_NO_CARBON |