summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm28
-rw-r--r--chrome/common/plugin_messages_internal.h12
-rw-r--r--chrome/plugin/plugin_thread.cc5
-rw-r--r--chrome/plugin/webplugin_delegate_stub.cc8
-rw-r--r--chrome/plugin/webplugin_delegate_stub.h1
-rw-r--r--chrome/renderer/render_view.cc24
-rw-r--r--chrome/renderer/render_view.h4
-rw-r--r--chrome/renderer/render_widget.h4
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc18
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.h1
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h13
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm93
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