Index: chrome/browser/renderer_host/render_widget_host_view_win.cc |
=================================================================== |
--- chrome/browser/renderer_host/render_widget_host_view_win.cc (revision 66779) |
+++ chrome/browser/renderer_host/render_widget_host_view_win.cc (working copy) |
@@ -279,6 +279,7 @@ |
RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget) |
: render_widget_host_(widget), |
+ compositor_host_window_(NULL), |
track_mouse_leave_(false), |
ime_notification_(false), |
capture_enter_key_(false), |
@@ -379,6 +380,13 @@ |
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(); |
} |
@@ -706,6 +714,26 @@ |
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; |
@@ -719,6 +747,7 @@ |
// OnFinalMessage(); |
close_on_deactivate_ = false; |
being_destroyed_ = true; |
+ WillWmDestroy(); |
DestroyWindow(); |
} |
@@ -846,7 +875,7 @@ |
// 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); |
@@ -1454,6 +1483,136 @@ |
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_ || |