Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(572)

Unified Diff: content/browser/renderer_host/legacy_render_widget_host_win.cc

Issue 159713012: Don't track mouse events in HWNDMessageHandler when they are forwarded by the LegacyRenderWidgetHost (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/legacy_render_widget_host_win.cc
===================================================================
--- content/browser/renderer_host/legacy_render_widget_host_win.cc (revision 249762)
+++ content/browser/renderer_host/legacy_render_widget_host_win.cc (working copy)
@@ -13,8 +13,19 @@
#include "ui/base/touch/touch_enabled.h"
#include "ui/gfx/geometry/rect.h"
+namespace {
+
+// This property is set on the parent window when we set capture on it. This
+// is used to retrieve the child window whose bounds we are tracking.
+const wchar_t kCaptureForcedOnParentByTrackingWindow[] =
+ L"CaptureForcedByTrackingWindow";
+
+} // namespace
+
namespace content {
+WNDPROC LegacyRenderWidgetHostHWND::g_parent_original_class_proc = NULL;
+
LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() {
::DestroyWindow(hwnd());
}
@@ -22,13 +33,15 @@
// static
scoped_ptr<LegacyRenderWidgetHostHWND> LegacyRenderWidgetHostHWND::Create(
HWND parent) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableLegacyIntermediateWindow))
+ return scoped_ptr<LegacyRenderWidgetHostHWND>();
+
scoped_ptr<LegacyRenderWidgetHostHWND> legacy_window_instance;
legacy_window_instance.reset(new LegacyRenderWidgetHostHWND(parent));
// If we failed to create the child, or if the switch to disable the legacy
// window is passed in, then return NULL.
- if (!::IsWindow(legacy_window_instance->hwnd()) ||
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableLegacyIntermediateWindow))
+ if (!::IsWindow(legacy_window_instance->hwnd()))
return scoped_ptr<LegacyRenderWidgetHostHWND>();
legacy_window_instance->Init();
@@ -86,6 +99,21 @@
ui::AreTouchEventsEnabled())
RegisterTouchWindow(hwnd(), TWF_WANTPALM);
+ // We superclass the parent window class. This is to ensure that we avoid
+ // messy code tracking if the window was subclassed or not. Superclassing
+ // the parent ensures that we can windows subsequently created.
+ // Note: We never unsubclass. This should be safe.
+ if (!g_parent_original_class_proc) {
sky 2014/02/12 14:36:31 Doesn't this assume the legacy hwnd always has a p
+ g_parent_original_class_proc = reinterpret_cast<WNDPROC>(
+ ::SetClassLong(GetParent(), GCL_WNDPROC,
+ reinterpret_cast<long>(ParentWindowSuperClassProc)));
+ DCHECK(g_parent_original_class_proc);
+ // We need to subclass the first window as the super class does not take
+ // effect until a new window is created.
+ ::SetWindowLong(GetParent(), GWL_WNDPROC,
+ reinterpret_cast<long>(ParentWindowSuperClassProc));
+ }
+
HRESULT hr = ::CreateStdAccessibleObject(
hwnd(), OBJID_WINDOW, IID_IAccessible,
reinterpret_cast<void **>(window_accessible_.Receive()));
@@ -130,12 +158,21 @@
WPARAM w_param,
LPARAM l_param,
BOOL& handled) {
- POINT mouse_coords;
- mouse_coords.x = GET_X_LPARAM(l_param);
- mouse_coords.y = GET_Y_LPARAM(l_param);
- ::MapWindowPoints(hwnd(), GetParent(), &mouse_coords, 1);
- return ::SendMessage(GetParent(), message, w_param,
- MAKELPARAM(mouse_coords.x, mouse_coords.y));
+ // We won't receive mouse messages when capture is with the parent window.
+ // If we receive a mouse move then it means that parent capture was released.
+ // This would happen if we lost focus or if the mouse left our window bounds
+ // and we released capture.
+ if (message == WM_MOUSEMOVE) {
+ if (::GetCapture() != GetParent()) {
+ ::SetCapture(GetParent());
+ ::SetProp(GetParent(), kCaptureForcedOnParentByTrackingWindow, hwnd());
+ }
+ } else if (message == WM_MOUSEWHEEL || message == WM_MOUSEHWHEEL) {
+ return ::SendMessage(GetParent(), message, w_param, l_param);
+ } else {
+ NOTREACHED() << "Unexpected mouse message received: " << message;
+ }
+ return 0;
}
LRESULT LegacyRenderWidgetHostHWND::OnMouseActivate(UINT message,
@@ -181,4 +218,42 @@
return 0;
}
+// static
+LRESULT CALLBACK LegacyRenderWidgetHostHWND::ParentWindowSuperClassProc(
+ HWND window, UINT message, WPARAM w_param, LPARAM l_param) {
+ // To ensure that the LegacyRenderWidgetHostHWND is as less intrusive as
+ // possible, we set capture on the parent window when we receive a
+ // mouse move message for the LegacyRenderWidgetHostHWND hwnd. This ensures
+ // that subsequent mouse messages go to the parent. We need to release this
+ // forced capture on the parent when the mouse cursor leaves the bounds of
+ // the LegacyRenderWidgetHostHWND window which is identified by the
+ // tracking_window local variable below. We only do this when no mouse
+ // buttons are down as in that case capture is released by code in the
+ // default parent mouse event handling.
+ const int mouse_down_flags =
+ MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2;
+ if (message == WM_MOUSEMOVE && ::GetCapture() == window &&
+ !(w_param & mouse_down_flags)) {
+ HWND tracking_window = reinterpret_cast<HWND>(::GetProp(window,
+ kCaptureForcedOnParentByTrackingWindow));
+ if (::IsWindow(tracking_window)) {
+ POINT pt = {0};
+ pt.x = GET_X_LPARAM(l_param);
+ pt.y = GET_Y_LPARAM(l_param);
+ ::ClientToScreen(window, &pt);
+
+ RECT window_rect = {0};
+ ::GetWindowRect(tracking_window, &window_rect);
+ if (!::PtInRect(&window_rect, pt) ||
+ ::WindowFromPoint(pt) != tracking_window) {
+ ::ReleaseCapture();
+ ::RemoveProp(window, kCaptureForcedOnParentByTrackingWindow);
+ }
+ }
+ }
+ DCHECK(g_parent_original_class_proc);
+ return ::CallWindowProc(g_parent_original_class_proc, window, message,
+ w_param, l_param);
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698