diff options
3 files changed, 88 insertions, 8 deletions
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index a0c54fa..28162bc 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -50,6 +50,10 @@ #include "ui/gfx/screen.h" #include "ui/gfx/skia_util.h" +#if defined(OS_WIN) +#include "ui/base/win/hidden_window.h" +#endif + using WebKit::WebScreenInfo; using WebKit::WebTouchEvent; @@ -71,6 +75,41 @@ const int kMouseLockBorderPercentage = 15; // resized frame from a renderer. const int kResizeLockTimeoutMs = 67; +#if defined(OS_WIN) +// Used to associate a plugin HWND with its RenderWidgetHostViewAura instance. +const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner"; + +BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) { + RenderWidgetHostViewAura* widget = + reinterpret_cast<RenderWidgetHostViewAura*>(param); + if (GetProp(window, kWidgetOwnerProperty) == widget) { + // Properties set on HWNDs must be removed to avoid leaks. + RemoveProp(window, kWidgetOwnerProperty); + RenderWidgetHostViewBase::DetachPluginWindowsCallback(window); + } + return TRUE; +} + +BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) { + RenderWidgetHostViewAura* widget = + reinterpret_cast<RenderWidgetHostViewAura*>(param); + if (GetProp(window, kWidgetOwnerProperty) == widget) + SetParent(window, ui::GetHiddenWindow()); + return TRUE; +} + +BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) { + RenderWidgetHostViewAura* widget = + reinterpret_cast<RenderWidgetHostViewAura*>(param); + + HWND parent = + widget->GetNativeView()->GetRootWindow()->GetAcceleratedWidget(); + if (GetProp(window, kWidgetOwnerProperty) == widget) + SetParent(window, parent); + return TRUE; +} +#endif + ui::TouchStatus DecideTouchStatus(const WebKit::WebTouchEvent& event, WebKit::WebTouchPoint* point) { if (event.type == WebKit::WebInputEvent::TouchEnd && @@ -310,6 +349,11 @@ void RenderWidgetHostViewAura::WasShown() { } AdjustSurfaceProtection(); + +#if defined(OS_WIN) + LPARAM lparam = reinterpret_cast<LPARAM>(this); + EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam); +#endif } void RenderWidgetHostViewAura::WasHidden() { @@ -326,6 +370,13 @@ void RenderWidgetHostViewAura::WasHidden() { } AdjustSurfaceProtection(); + +#if defined(OS_WIN) + HWND parent = window_->GetRootWindow()->GetAcceleratedWidget(); + LPARAM lparam = reinterpret_cast<LPARAM>(this); + + EnumChildWindows(parent, HideWindowsCallback, lparam); +#endif } void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) { @@ -392,6 +443,18 @@ void RenderWidgetHostViewAura::MovePluginWindows( moves[i].window_rect.Offset(view_bounds.origin()); } MovePluginWindowsHelper(parent, moves); + + // Make sure each plugin window (or its wrapper if it exists) has a pointer to + // |this|. + for (size_t i = 0; i < moves.size(); ++i) { + HWND window = moves[i].window; + if (GetParent(window) != parent) { + window = GetParent(window); + DCHECK(GetParent(window) == parent); + } + if (!GetProp(window, kWidgetOwnerProperty)) + CHECK(SetProp(window, kWidgetOwnerProperty, this)); + } #endif // defined(OS_WIN) } @@ -1297,10 +1360,16 @@ void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged( void RenderWidgetHostViewAura::OnWindowDestroying() { #if defined(OS_WIN) - if (window_->GetRootWindow()) { - HWND parent = window_->GetRootWindow()->GetAcceleratedWidget(); - DetachPluginsHelper(parent); + HWND parent = NULL; + // If the tab was hidden and it's closed, host_->is_hidden would have been + // reset to false in RenderWidgetHostImpl::RendererExited. + if (!window_->GetRootWindow() || host_->is_hidden()) { + parent = ui::GetHiddenWindow(); + } else { + parent = window_->GetRootWindow()->GetAcceleratedWidget(); } + LPARAM lparam = reinterpret_cast<LPARAM>(this); + EnumChildWindows(parent, WindowDestroyingCallback, lparam); #endif } diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index 935fc11..4053413 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc @@ -186,17 +186,22 @@ BOOL CALLBACK PainEnumChildProc(HWND hwnd, LPARAM lparam) { } // Windows callback for OnDestroy to detach the plugin windows. -BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) { +BOOL CALLBACK DetachPluginWindowsCallbackInternal(HWND window, LPARAM param) { + RenderWidgetHostViewBase::DetachPluginWindowsCallback(window); + return TRUE; +} + +} // namespace + +// static +void RenderWidgetHostViewBase::DetachPluginWindowsCallback(HWND window) { if (webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(window) && !IsHungAppWindow(window)) { ::ShowWindow(window, SW_HIDE); SetParent(window, NULL); } - return TRUE; } -} // namespace - // static void RenderWidgetHostViewBase::MovePluginWindowsHelper( HWND parent, @@ -331,7 +336,7 @@ void RenderWidgetHostViewBase::DetachPluginsHelper(HWND parent) { // away. This will prevent the plugin windows from getting destroyed // automatically. The detached plugin windows will get cleaned up in proper // sequence as part of the usual cleanup when the plugin instance goes away. - EnumChildWindows(parent, DetachPluginWindowsCallback, NULL); + EnumChildWindows(parent, DetachPluginWindowsCallbackInternal, NULL); } #endif // OS_WIN diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 2c9c828..c1eb02d 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h @@ -66,6 +66,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase // Notification that a resize or move session ended on the native widget. void UpdateScreenInfo(); +#if defined(OS_WIN) + // The callback that DetachPluginsHelper calls for each child window. Call + // this directly if you want to do custom filtering on plugin windows first. + static void DetachPluginWindowsCallback(HWND window); +#endif + protected: // Interface class only, do not construct. RenderWidgetHostViewBase(); |