diff options
Diffstat (limited to 'chrome/views')
-rw-r--r-- | chrome/views/controls/text_field.cc | 12 | ||||
-rw-r--r-- | chrome/views/view_unittest.cc | 121 |
2 files changed, 133 insertions, 0 deletions
diff --git a/chrome/views/controls/text_field.cc b/chrome/views/controls/text_field.cc index 1485427..875453a 100644 --- a/chrome/views/controls/text_field.cc +++ b/chrome/views/controls/text_field.cc @@ -24,6 +24,7 @@ #include "chrome/common/win_util.h" #include "chrome/views/controls/hwnd_view.h" #include "chrome/views/controls/menu/menu.h" +#include "chrome/views/focus/focus_util_win.h" #include "chrome/views/widget/widget.h" #include "grit/generated_resources.h" #include "skia/ext/skia_utils_win.h" @@ -83,6 +84,7 @@ class TextField::Edit MSG_WM_MBUTTONDOWN(OnNonLButtonDown) MSG_WM_MOUSEMOVE(OnMouseMove) MSG_WM_MOUSELEAVE(OnMouseLeave) + MESSAGE_HANDLER_EX(WM_MOUSEWHEEL, OnMouseWheel) MSG_WM_NCCALCSIZE(OnNCCalcSize) MSG_WM_NCPAINT(OnNCPaint) MSG_WM_RBUTTONDOWN(OnNonLButtonDown) @@ -130,6 +132,7 @@ class TextField::Edit void OnLButtonDown(UINT keys, const CPoint& point); void OnLButtonUp(UINT keys, const CPoint& point); void OnMouseLeave(); + LRESULT OnMouseWheel(UINT message, WPARAM w_param, LPARAM l_param); void OnMouseMove(UINT keys, const CPoint& point); int OnNCCalcSize(BOOL w_param, LPARAM l_param); void OnNCPaint(HRGN region); @@ -626,6 +629,15 @@ void TextField::Edit::OnMouseLeave() { SetContainsMouse(false); } +LRESULT TextField::Edit::OnMouseWheel(UINT message, + WPARAM w_param, LPARAM l_param) { + // Reroute the mouse-wheel to the window under the mouse pointer if + // applicable. + if (views::RerouteMouseWheel(m_hWnd, w_param, l_param)) + return 0; + return DefWindowProc(message, w_param, l_param);; +} + void TextField::Edit::OnMouseMove(UINT keys, const CPoint& point) { SetContainsMouse(true); // Clamp the selection to the visible text so the user can't drag to select diff --git a/chrome/views/view_unittest.cc b/chrome/views/view_unittest.cc index 182bfac..8b57200 100644 --- a/chrome/views/view_unittest.cc +++ b/chrome/views/view_unittest.cc @@ -10,6 +10,10 @@ #include "chrome/common/notification_service.h" #include "chrome/views/background.h" #include "chrome/views/controls/button/checkbox.h" +#if defined(OS_WIN) +#include "chrome/views/controls/button/native_button_win.h" +#endif +#include "chrome/views/controls/scroll_view.h" #include "chrome/views/controls/text_field.h" #include "chrome/views/event.h" #include "chrome/views/view.h" @@ -702,6 +706,123 @@ TEST_F(ViewTest, TextFieldCutCopyPaste) { } #endif +#if defined(OS_WIN) +//////////////////////////////////////////////////////////////////////////////// +// Mouse-wheel message rerouting +//////////////////////////////////////////////////////////////////////////////// +class ButtonTest : public NativeButton { + public: + ButtonTest(ButtonListener* listener, const std::wstring& label) + : NativeButton(listener, label) { + } + + HWND GetHWND() { + return static_cast<NativeButtonWin*>(native_wrapper_)->GetHWND(); + } +}; + +class CheckboxTest : public Checkbox { + public: + explicit CheckboxTest(const std::wstring& label) : Checkbox(label) { + } + + HWND GetHWND() { + return static_cast<NativeCheckboxWin*>(native_wrapper_)->GetHWND(); + } +}; + +class ScrollableTestView : public View { + public: + ScrollableTestView() { } + + virtual gfx::Size GetPreferredSize() { + return gfx::Size(100, 10000); + } + + virtual void Layout() { + SizeToPreferredSize(); + } +}; + +class TestViewWithControls : public View { + public: + TestViewWithControls() { + button_ = new ButtonTest(NULL, L"Button"); + checkbox_ = new CheckboxTest(L"My checkbox"); + text_field_ = new TextField(); + AddChildView(button_); + AddChildView(checkbox_); + AddChildView(text_field_); + } + + ButtonTest* button_; + CheckboxTest* checkbox_; + TextField* text_field_; +}; + +class SimpleWindowDelegate : public WindowDelegate { + public: + SimpleWindowDelegate(View* contents) : contents_(contents) { } + + virtual void DeleteDelegate() { delete this; } + + virtual View* GetContentsView() { return contents_; } + + private: + View* contents_; +}; + +// Tests that the mouse-wheel messages are correctly rerouted to the window +// under the mouse. +TEST_F(ViewTest, RerouteMouseWheelTest) { + TestViewWithControls* view_with_controls = new TestViewWithControls(); + views::Window* window1 = + views::Window::CreateChromeWindow( + NULL, gfx::Rect(0, 0, 100, 100), + new SimpleWindowDelegate(view_with_controls)); + window1->Show(); + ScrollView* scroll_view = new ScrollView(); + scroll_view->SetContents(new ScrollableTestView()); + views::Window* window2 = + views::Window::CreateChromeWindow(NULL, gfx::Rect(200, 200, 100, 100), + new SimpleWindowDelegate(scroll_view)); + window2->Show(); + EXPECT_EQ(0, scroll_view->GetVisibleRect().y()); + + // Make the window1 active, as this is what it would be in real-world. + window1->Activate(); + + // Let's send a mouse-wheel message to the different controls and check that + // it is rerouted to the window under the mouse (effectively scrolling the + // scroll-view). + + // First to the Window's HWND. + ::SendMessage(view_with_controls->GetWidget()->GetNativeView(), + WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250)); + EXPECT_EQ(20, scroll_view->GetVisibleRect().y()); + + // Then the button. + ::SendMessage(view_with_controls->button_->GetHWND(), + WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250)); + EXPECT_EQ(40, scroll_view->GetVisibleRect().y()); + + // Then the check-box. + ::SendMessage(view_with_controls->checkbox_->GetHWND(), + WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250)); + EXPECT_EQ(60, scroll_view->GetVisibleRect().y()); + + // Then the text-field. + ::SendMessage(view_with_controls->text_field_->GetNativeComponent(), + WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250)); + EXPECT_EQ(80, scroll_view->GetVisibleRect().y()); + + // Ensure we don't scroll when the mouse is not over that window. + ::SendMessage(view_with_controls->text_field_->GetNativeComponent(), + WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(50, 50)); + EXPECT_EQ(80, scroll_view->GetVisibleRect().y()); +} +#endif + //////////////////////////////////////////////////////////////////////////////// // Dialogs' default button //////////////////////////////////////////////////////////////////////////////// |