diff options
author | nduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-27 19:39:42 +0000 |
---|---|---|
committer | nduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-27 19:39:42 +0000 |
commit | 50bd645cfa2824a22f98096cb6a66bbd7cf757f4 (patch) | |
tree | 3cae036733b722b0ec731363179c5fdec5f7e137 /chrome/browser | |
parent | 1bead0713628b2410ffd7ba49700c5901059d07b (diff) | |
download | chromium_src-50bd645cfa2824a22f98096cb6a66bbd7cf757f4.zip chromium_src-50bd645cfa2824a22f98096cb6a66bbd7cf757f4.tar.gz chromium_src-50bd645cfa2824a22f98096cb6a66bbd7cf757f4.tar.bz2 |
When accelerated compositing is enabled, we create a plugin-like pair of windows,
CompositorHostWindow and CompositorWindow inside the RenderWidgetHostView. The host-side
HWND is used to position the compositor output relative to plugins; the GPU process creates the
compositor window as a child of the CompositorHostWindow.
Once we land webkit bugfix 49396, ANGLE issue 3038042, Chromium issue 4671003, this will fix
bugs 54301 and 61516 for windows.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/4815001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67495 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
15 files changed, 294 insertions, 33 deletions
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc index afa904c..c321f97 100644 --- a/chrome/browser/gpu_process_host.cc +++ b/chrome/browser/gpu_process_host.cc @@ -177,6 +177,9 @@ void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) { OnAcceleratedSurfaceSetIOSurface) IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, OnAcceleratedSurfaceBuffersSwapped) +#elif defined(OS_WIN) + IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_CreateCompositorHostWindow, + OnCreateCompositorHostWindow) #endif // If the IO thread does not handle the message then automatically route it // to the UI thread. The UI thread will report an error if it does not @@ -305,8 +308,8 @@ namespace { class BuffersSwappedDispatcher : public Task { public: BuffersSwappedDispatcher( - int32 renderer_id, - int32 render_view_id, + int renderer_id, + int render_view_id, gfx::PluginWindowHandle window, uint64 surface_id, int32 route_id, @@ -338,8 +341,8 @@ class BuffersSwappedDispatcher : public Task { } private: - int32 renderer_id_; - int32 render_view_id_; + int renderer_id_; + int render_view_id_; gfx::PluginWindowHandle window_; uint64 surface_id_; int32 route_id_; @@ -366,6 +369,47 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( params.route_id, params.swap_buffers_count)); } + +#elif defined(OS_WIN) + +namespace { + +void SendDelayedReply(IPC::Message* reply_msg) { + GpuProcessHost::Get()->Send(reply_msg); +} + +void CreateCompositorHostWindowDispatcher( + int renderer_id, + int render_view_id, + IPC::Message* reply_msg) { + RenderViewHost* host = RenderViewHost::FromID(renderer_id, + render_view_id); + if (!host) { + return; + } + + RenderWidgetHostView* view = host->view(); + gfx::PluginWindowHandle id = view->CreateCompositorHostWindow(); + + + GpuHostMsg_CreateCompositorHostWindow::WriteReplyParams(reply_msg, id); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableFunction(&SendDelayedReply, reply_msg)); +} + +} // namespace + +void GpuProcessHost::OnCreateCompositorHostWindow( + int renderer_id, + int render_view_id, + IPC::Message* reply_message) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + NewRunnableFunction(&CreateCompositorHostWindowDispatcher, + renderer_id, render_view_id, reply_message)); +} + #endif void GpuProcessHost::SendEstablishChannelReply( diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h index 4b40a25..8219355 100644 --- a/chrome/browser/gpu_process_host.h +++ b/chrome/browser/gpu_process_host.h @@ -93,6 +93,10 @@ class GpuProcessHost : public BrowserChildProcessHost, public NonThreadSafe { const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params); void OnAcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params); +#elif defined(OS_WIN) + void OnCreateCompositorHostWindow(int renderer_id, + int render_view_id, + IPC::Message* reply_message); #endif // Sends the response for establish channel request to the renderer. diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc index 2e3a531..d8257a8 100644 --- a/chrome/browser/gpu_process_host_ui_shim.cc +++ b/chrome/browser/gpu_process_host_ui_shim.cc @@ -6,6 +6,7 @@ #include "chrome/browser/browser_thread.h" #include "chrome/browser/gpu_process_host.h" +#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/common/child_process_logging.h" #include "chrome/common/gpu_messages.h" @@ -105,6 +106,15 @@ void GpuProcessHostUIShim::OnGraphicsInfoCollected(const GPUInfo& gpu_info) { child_process_logging::SetGpuInfo(gpu_info); } +void GpuProcessHostUIShim::OnScheduleComposite(int renderer_id, + int render_view_id) { + RenderViewHost* host = RenderViewHost::FromID(renderer_id, + render_view_id); + if (!host) { + return; + } + host->ScheduleComposite(); +} void GpuProcessHostUIShim::OnControlMessageReceived( const IPC::Message& message) { DCHECK(CalledOnValidThread()); @@ -112,6 +122,10 @@ void GpuProcessHostUIShim::OnControlMessageReceived( IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message) IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected, OnGraphicsInfoCollected) +#if defined(OS_WIN) + IPC_MESSAGE_HANDLER(GpuHostMsg_ScheduleComposite, + OnScheduleComposite); +#endif IPC_MESSAGE_UNHANDLED_ERROR() IPC_END_MESSAGE_MAP() } diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h index d77c783..eda33d2 100644 --- a/chrome/browser/gpu_process_host_ui_shim.h +++ b/chrome/browser/gpu_process_host_ui_shim.h @@ -62,7 +62,7 @@ class GpuProcessHostUIShim : public IPC::Channel::Sender, // Message handlers. void OnGraphicsInfoCollected(const GPUInfo& gpu_info); - + void OnScheduleComposite(int32 renderer_id, int32 render_view_id); void OnControlMessageReceived(const IPC::Message& message); int last_routing_id_; diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index 4482bbd..caf7d14 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -77,7 +77,7 @@ RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, routing_id_(routing_id), is_loading_(false), is_hidden_(false), - is_gpu_rendering_active_(false), + is_accelerated_compositing_active_(false), repaint_ack_pending_(false), resize_ack_pending_(false), mouse_move_pending_(false), @@ -157,8 +157,8 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) { OnMsgImeUpdateTextInputState) IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition, OnMsgImeCancelComposition) - IPC_MESSAGE_HANDLER(ViewHostMsg_GpuRenderingActivated, - OnMsgGpuRenderingActivated) + IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing, + OnMsgDidActivateAcceleratedCompositing) #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(ViewHostMsg_GetScreenInfo, OnMsgGetScreenInfo) IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnMsgGetWindowRect) @@ -232,7 +232,7 @@ void RenderWidgetHost::WasRestored() { // the backing store exists. bool needs_repainting; if (needs_repainting_on_restore_ || !backing_store || - is_gpu_rendering_active()) { + is_accelerated_compositing_active()) { needs_repainting = true; needs_repainting_on_restore_ = false; } else { @@ -402,8 +402,9 @@ void RenderWidgetHost::DonePaintingToBackingStore() { } void RenderWidgetHost::ScheduleComposite() { - DCHECK(!is_hidden_ || !is_gpu_rendering_active_) << - "ScheduleCompositeAndSync called while hidden!"; + if (is_hidden_ || !is_accelerated_compositing_active_) { + return; + } // Send out a request to the renderer to paint the view if required. if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) { @@ -658,7 +659,7 @@ void RenderWidgetHost::RendererExited() { current_size_.SetSize(0, 0); current_reserved_rect_.SetRect(0, 0, 0, 0); is_hidden_ = false; - is_gpu_rendering_active_ = false; + is_accelerated_compositing_active_ = false; if (view_) { view_->RenderViewGone(); @@ -832,7 +833,7 @@ void RenderWidgetHost::OnMsgUpdateRect( DCHECK(!params.bitmap_rect.IsEmpty()); DCHECK(!params.view_size.IsEmpty()); - if (!is_gpu_rendering_active_) { + if (!is_accelerated_compositing_active_) { const size_t size = params.bitmap_rect.height() * params.bitmap_rect.width() * 4; TransportDIB* dib = process_->GetTransportDIB(params.bitmap); @@ -879,7 +880,7 @@ void RenderWidgetHost::OnMsgUpdateRect( // which attempts to move the plugin windows and in the process could // dispatch other window messages which could cause the view to be // destroyed. - if (view_ && !is_gpu_rendering_active_) { + if (view_ && !is_accelerated_compositing_active_) { view_being_painted_ = true; view_->DidUpdateBackingStore(params.scroll_rect, params.dx, params.dy, params.copy_rects); @@ -977,14 +978,16 @@ void RenderWidgetHost::OnMsgImeCancelComposition() { view_->ImeCancelComposition(); } -void RenderWidgetHost::OnMsgGpuRenderingActivated(bool activated) { +void RenderWidgetHost::OnMsgDidActivateAcceleratedCompositing(bool activated) { #if defined(OS_MACOSX) - bool old_state = is_gpu_rendering_active_; + bool old_state = is_accelerated_compositing_active_; #endif - is_gpu_rendering_active_ = activated; + is_accelerated_compositing_active_ = activated; #if defined(OS_MACOSX) - if (old_state != is_gpu_rendering_active_ && view_) + if (old_state != is_accelerated_compositing_active_ && view_) view_->GpuRenderingStateDidChange(); +#elif defined(OS_WIN) + view_->ShowCompositorHostWindow(is_accelerated_compositing_active_); #elif defined(TOOLKIT_USES_GTK) view_->AcceleratedCompositingActivated(activated); #endif @@ -1089,7 +1092,6 @@ void RenderWidgetHost::OnMsgDestroyPluginContainer(gfx::PluginWindowHandle id) { NOTIMPLEMENTED(); } } - #endif void RenderWidgetHost::PaintBackingStoreRect( diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index 9f2225b..47e4dab 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -203,7 +203,9 @@ class RenderWidgetHost : public IPC::Channel::Listener, virtual void LostCapture(); // Tells us whether the page is rendered directly via the GPU process. - bool is_gpu_rendering_active() { return is_gpu_rendering_active_; } + bool is_accelerated_compositing_active() { + return is_accelerated_compositing_active_; + } // Notifies the RenderWidgetHost that the View was destroyed. void ViewDestroyed(); @@ -484,7 +486,7 @@ class RenderWidgetHost : public IPC::Channel::Listener, const gfx::Rect& caret_rect); void OnMsgImeCancelComposition(); - void OnMsgGpuRenderingActivated(bool activated); + void OnMsgDidActivateAcceleratedCompositing(bool activated); #if defined(OS_MACOSX) void OnMsgGetScreenInfo(gfx::NativeViewId view, @@ -564,7 +566,7 @@ class RenderWidgetHost : public IPC::Channel::Listener, bool is_hidden_; // True when a page is rendered directly via the GPU process. - bool is_gpu_rendering_active_; + bool is_accelerated_compositing_active_; // Set if we are waiting for a repaint ack for the view. bool repaint_ack_pending_; diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index 4ad2c41..8235ebf 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -246,6 +246,12 @@ class RenderWidgetHostView { virtual void AcceleratedCompositingActivated(bool activated) = 0; #endif +#if defined(OS_WIN) + virtual gfx::PluginWindowHandle CreateCompositorHostWindow() = 0; + virtual void WillWmDestroy() = 0; + virtual void ShowCompositorHostWindow(bool show) = 0; +#endif + // Toggles visual muting of the render view area. This is on when a // constrained window is showing. virtual void SetVisuallyDeemphasized(bool deemphasized) = 0; diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index bf39966..aa43529 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -814,7 +814,7 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) { // If the GPU process is rendering directly into the View, // call the compositor directly. RenderWidgetHost* render_widget_host = GetRenderWidgetHost(); - if (render_widget_host->is_gpu_rendering_active()) { + if (render_widget_host->is_accelerated_compositing_active()) { host_->ScheduleComposite(); return; } 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 307eb2e..b0ef7e6 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -745,7 +745,7 @@ void RenderWidgetHostViewMac::DidUpdateBackingStore( if (!is_hidden_) { std::vector<gfx::Rect> rects(copy_rects); - // Because the findbar might be open, we cannot use scrollRect:by: here. For + // Because the findbar might be open, we cannot use scrollRect:by: here. For // now, simply mark all of scroll rect as dirty. if (!scroll_rect.IsEmpty()) rects.push_back(scroll_rect); @@ -1019,8 +1019,8 @@ void RenderWidgetHostViewMac::UpdateRootGpuViewVisibility( // Plugins are destroyed on page navigate. The compositor layer on the other // hand is created on demand and then stays alive until its renderer process // dies (usually on cross-domain navigation). Instead, only a flag - // |is_gpu_rendering_active()| is flipped when the compositor output should be - // shown/hidden. + // |is_accelerated_compositing_active()| is flipped when the compositor output + // should be shown/hidden. // Show/hide the view belonging to the compositor here. plugin_container_manager_.set_gpu_rendering_active(show_gpu_widget); @@ -1085,9 +1085,9 @@ void RenderWidgetHostViewMac::AcknowledgeSwapBuffers( void RenderWidgetHostViewMac::GpuRenderingStateDidChange() { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (GetRenderWidgetHost()->is_gpu_rendering_active()) { + if (GetRenderWidgetHost()->is_accelerated_compositing_active()) { UpdateRootGpuViewVisibility( - GetRenderWidgetHost()->is_gpu_rendering_active()); + GetRenderWidgetHost()->is_accelerated_compositing_active()); } else { needs_gpu_visibility_update_after_repaint_ = true; } @@ -1685,7 +1685,8 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { const gfx::Rect damagedRect([self flipNSRectToRect:dirtyRect]); - if (renderWidgetHostView_->render_widget_host_->is_gpu_rendering_active()) { + if (renderWidgetHostView_->render_widget_host_-> + is_accelerated_compositing_active()) { gfx::Rect gpuRect; gfx::PluginWindowHandle root_handle = diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.cc b/chrome/browser/renderer_host/render_widget_host_view_views.cc index 20797ad..b9f386e 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc @@ -350,7 +350,7 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) { // Don't do any painting if the GPU process is rendering directly // into the View. RenderWidgetHost* render_widget_host = GetRenderWidgetHost(); - if (render_widget_host->is_gpu_rendering_active()) { + if (render_widget_host->is_accelerated_compositing_active()) { return; } @@ -603,7 +603,8 @@ bool RenderWidgetHostViewViews::ContainsNativeView( return false; } -void RenderWidgetHostViewViews::AcceleratedCompositingActivated(bool activated) { +void RenderWidgetHostViewViews::AcceleratedCompositingActivated( + bool activated) { // TODO(anicolao): figure out if we need something here if (activated) NOTIMPLEMENTED(); diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index 3f9b9b1..df78d00 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -281,6 +281,7 @@ RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget) : render_widget_host_(widget), + compositor_host_window_(NULL), track_mouse_leave_(false), ime_notification_(false), capture_enter_key_(false), @@ -382,6 +383,13 @@ void RenderWidgetHostViewWin::SetSize(const gfx::Size& size) { UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE; SetWindowPos(NULL, 0, 0, size.width(), size.height(), swp_flags); + if (compositor_host_window_) { + ::SetWindowPos(compositor_host_window_, + NULL, + 0, 0, + size.width(), size.height(), + SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE); + } render_widget_host_->WasResized(); EnsureTooltip(); } @@ -709,6 +717,26 @@ void RenderWidgetHostViewWin::RenderViewGone() { DestroyWindow(); } +static BOOL CALLBACK AddChildWindowToVector(HWND hwnd, LPARAM lparam) { + std::vector<HWND>* vector = reinterpret_cast<std::vector<HWND>*>(lparam); + vector->push_back(hwnd); + return TRUE; +} + +void RenderWidgetHostViewWin::WillWmDestroy() { + if (!compositor_host_window_) + return; + + std::vector<HWND> all_child_windows; + ::EnumChildWindows(compositor_host_window_, AddChildWindowToVector, + reinterpret_cast<LPARAM>(&all_child_windows)); + if (all_child_windows.size()) { + DCHECK(all_child_windows.size() == 1); + ::ShowWindow(all_child_windows[0], SW_HIDE); + ::SetParent(all_child_windows[0], NULL); + } +} + void RenderWidgetHostViewWin::WillDestroyRenderWidget(RenderWidgetHost* rwh) { if (rwh == render_widget_host_) render_widget_host_ = NULL; @@ -722,6 +750,7 @@ void RenderWidgetHostViewWin::Destroy() { // OnFinalMessage(); close_on_deactivate_ = false; being_destroyed_ = true; + WillWmDestroy(); DestroyWindow(); } @@ -849,7 +878,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) { // If the GPU process is rendering directly into the View, // call the compositor directly. RenderWidgetHost* render_widget_host = GetRenderWidgetHost(); - if (render_widget_host->is_gpu_rendering_active()) { + if (render_widget_host->is_accelerated_compositing_active()) { // We initialize paint_dc here so that BeginPaint()/EndPaint() // get called to validate the region. CPaintDC paint_dc(m_hWnd); @@ -1457,6 +1486,136 @@ void RenderWidgetHostViewWin::Observe(NotificationType type, browser_accessibility_manager_.reset(NULL); } +// Looks through the children windows of the CompositorHostWindow. If the +// compositor child window is found, its size is checked against the host +// window's size. If the child is smaller in either dimensions, we fill +// the host window with white to avoid unseemly cracks. +static void PaintCompositorHostWindow(HWND hWnd) { + PAINTSTRUCT paint; + BeginPaint(hWnd, &paint); + + std::vector<HWND> child_windows; + EnumChildWindows(hWnd, AddChildWindowToVector, + reinterpret_cast<LPARAM>(&child_windows)); + + if (child_windows.size()) { + HWND child = child_windows[0]; + + RECT host_rect, child_rect; + GetClientRect(hWnd, &host_rect); + if (GetClientRect(child, &child_rect)) { + if (child_rect.right < host_rect.right || + child_rect.bottom != host_rect.bottom) { + FillRect(paint.hdc, &host_rect, + static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH))); + } + } + } + EndPaint(hWnd, &paint); +} + +// WndProc for the compositor host window. We use this instead of Default so +// we can drop WM_PAINT and WM_ERASEBKGD messages on the floor. +static LRESULT CALLBACK CompositorHostWindowProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_ERASEBKGND: + return 0; + case WM_DESTROY: + return 0; + case WM_PAINT: + PaintCompositorHostWindow(hWnd); + return 0; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } +} + +// Creates a HWND within the RenderWidgetHostView that will serve as a host +// for a HWND that the GPU process will create. The host window is used +// to Z-position the GPU's window relative to other plugin windows. +gfx::PluginWindowHandle RenderWidgetHostViewWin::CreateCompositorHostWindow() { + DCHECK(!compositor_host_window_); + static ATOM window_class = 0; + if (!window_class) { + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = 0; + wcex.lpfnWndProc = CompositorHostWindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetModuleHandle(NULL); + wcex.hIcon = 0; + wcex.hCursor = 0; + wcex.hbrBackground = NULL; + wcex.lpszMenuName = 0; + wcex.lpszClassName = L"CompositorHostWindowClass"; + wcex.hIconSm = 0; + window_class = RegisterClassEx(&wcex); + DCHECK(window_class); + } + + compositor_host_window_ = CreateWindowEx( + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, + MAKEINTATOM(window_class), 0, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED, + 0, 0, 0, 0, m_hWnd, 0, GetModuleHandle(NULL), 0); + DCHECK(compositor_host_window_); + + // We need to not just "WM_SHOW" the new indow, but reparent it + // below any existing plugin existing windows. + ShowCompositorHostWindow(true); + + return static_cast<gfx::PluginWindowHandle>(compositor_host_window_); +} + +void RenderWidgetHostViewWin::ShowCompositorHostWindow(bool show) { + // When we first create the compositor, we will get a show request from + // the renderer before we have gotten the create request from the GPU. In this + // case, simply ignore the show request. + if (compositor_host_window_ == NULL) + return; + + if (show) { + UINT flags = SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER | + SWP_NOACTIVATE | SWP_DEFERERASE | SWP_SHOWWINDOW; + gfx::Rect rect = GetViewBounds(); + ::SetWindowPos(compositor_host_window_, NULL, 0, 0, + rect.width(), rect.height(), + flags); + + // Get all the child windows of this view, including the compositor window. + std::vector<HWND> all_child_windows; + ::EnumChildWindows(m_hWnd, AddChildWindowToVector, + reinterpret_cast<LPARAM>(&all_child_windows)); + + // Build a list of just the plugin window handles + std::vector<HWND> plugin_windows; + bool compositor_host_window_found = false; + for (size_t i = 0; i < all_child_windows.size(); ++i) { + if (all_child_windows[i] != compositor_host_window_) + plugin_windows.push_back(all_child_windows[i]); + else + compositor_host_window_found = true; + } + DCHECK(compositor_host_window_found); + + // Set all the plugin windows to be "after" the compositor window. + // When the compositor window is created, gets placed above plugins. + for (size_t i = 0; i < plugin_windows.size(); ++i) { + HWND next; + if (i + 1 < plugin_windows.size()) + next = plugin_windows[i+1]; + else + next = compositor_host_window_; + ::SetWindowPos(plugin_windows[i], next, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + } + } else { + ::ShowWindow(compositor_host_window_, SW_HIDE); + } +} + void RenderWidgetHostViewWin::SetAccessibilityFocus(int acc_obj_id) { if (!browser_accessibility_manager_.get() || !render_widget_host_ || diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h index 13609e6..7f0a30e 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -154,6 +154,7 @@ class RenderWidgetHostViewWin const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, const std::vector<gfx::Rect>& copy_rects); virtual void RenderViewGone(); + virtual void WillWmDestroy(); // called by TabContents before DestroyWindow virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh); virtual void Destroy(); virtual void SetTooltipText(const std::wstring& tooltip_text); @@ -161,6 +162,10 @@ class RenderWidgetHostViewWin virtual void SetBackground(const SkBitmap& background); virtual bool ContainsNativeView(gfx::NativeView native_view) const; virtual void SetVisuallyDeemphasized(bool deemphasized); + + virtual gfx::PluginWindowHandle CreateCompositorHostWindow(); + virtual void ShowCompositorHostWindow(bool show); + virtual void OnAccessibilityNotifications( const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params); @@ -265,6 +270,9 @@ class RenderWidgetHostViewWin // The associated Model. RenderWidgetHost* render_widget_host_; + // When we are doing accelerated compositing + HWND compositor_host_window_; + // The cursor for the page. This is passed up from the renderer. WebCursor current_cursor_; 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 65d82e9..e4dc729 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.cc +++ b/chrome/browser/renderer_host/test/test_render_view_host.cc @@ -181,6 +181,17 @@ void TestRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped( void TestRenderWidgetHostView::GpuRenderingStateDidChange() { } +#elif defined(OS_WIN) +gfx::PluginWindowHandle TestRenderWidgetHostView::CreateCompositorHostWindow( + ) { + return gfx::kNullPluginWindow; +} + +void TestRenderWidgetHostView::WillWmDestroy() { +} + +void TestRenderWidgetHostView::ShowCompositorHostWindow(bool show) { +} #endif TestRenderViewHostFactory::TestRenderViewHostFactory( 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 fe6daa7..4f5d355 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.h +++ b/chrome/browser/renderer_host/test/test_render_view_host.h @@ -124,6 +124,10 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { int32 route_id, uint64 swap_buffers_count); virtual void GpuRenderingStateDidChange(); +#elif defined(OS_WIN) + virtual gfx::PluginWindowHandle CreateCompositorHostWindow(); + virtual void WillWmDestroy(); + virtual void ShowCompositorHostWindow(bool show); #endif virtual void SetVisuallyDeemphasized(bool deemphasized) { } diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index c846d62..4a225b2 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -486,8 +486,13 @@ TabContents::~TabContents() { #if defined(OS_WIN) // If we still have a window handle, destroy it. GetNativeView can return // NULL if this contents was part of a window that closed. - if (GetNativeView()) + if (GetNativeView()) { + RenderViewHost* host = render_view_host(); + if (host && host->view()) { + host->view()->WillWmDestroy(); + } ::DestroyWindow(GetNativeView()); + } #endif // OnCloseStarted isn't called in unit tests. |