| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <map> | 5 #include <map> |
| 6 | 6 |
| 7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/rand_util.h" | 8 #include "base/rand_util.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "grit/ui_strings.h" | 12 #include "grit/ui_strings.h" |
| 13 #include "ui/base/accelerators/accelerator.h" | 13 #include "ui/base/accelerators/accelerator.h" |
| 14 #include "ui/base/clipboard/clipboard.h" | 14 #include "ui/base/clipboard/clipboard.h" |
| 15 #include "ui/base/l10n/l10n_util.h" | 15 #include "ui/base/l10n/l10n_util.h" |
| 16 #include "ui/compositor/compositor.h" | 16 #include "ui/compositor/compositor.h" |
| 17 #include "ui/compositor/layer.h" | 17 #include "ui/compositor/layer.h" |
| 18 #include "ui/compositor/layer_animator.h" | 18 #include "ui/compositor/layer_animator.h" |
| 19 #include "ui/compositor/test/draw_waiter_for_test.h" | 19 #include "ui/compositor/test/draw_waiter_for_test.h" |
| 20 #include "ui/events/event.h" | 20 #include "ui/events/event.h" |
| 21 #include "ui/events/gestures/gesture_recognizer.h" | |
| 22 #include "ui/events/keycodes/keyboard_codes.h" | 21 #include "ui/events/keycodes/keyboard_codes.h" |
| 23 #include "ui/gfx/canvas.h" | 22 #include "ui/gfx/canvas.h" |
| 24 #include "ui/gfx/path.h" | 23 #include "ui/gfx/path.h" |
| 25 #include "ui/gfx/transform.h" | 24 #include "ui/gfx/transform.h" |
| 26 #include "ui/views/background.h" | 25 #include "ui/views/background.h" |
| 27 #include "ui/views/controls/native/native_view_host.h" | 26 #include "ui/views/controls/native/native_view_host.h" |
| 28 #include "ui/views/controls/scroll_view.h" | 27 #include "ui/views/controls/scroll_view.h" |
| 29 #include "ui/views/controls/textfield/textfield.h" | 28 #include "ui/views/controls/textfield/textfield.h" |
| 30 #include "ui/views/focus/view_storage.h" | 29 #include "ui/views/focus/view_storage.h" |
| 31 #include "ui/views/test/views_test_base.h" | 30 #include "ui/views/test/views_test_base.h" |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 view->ReorderChildView(view_b, a); | 169 view->ReorderChildView(view_b, a); |
| 171 } | 170 } |
| 172 | 171 |
| 173 if (!view->layer() && base::RandDouble() < 0.1) | 172 if (!view->layer() && base::RandDouble() < 0.1) |
| 174 view->SetPaintToLayer(true); | 173 view->SetPaintToLayer(true); |
| 175 | 174 |
| 176 if (base::RandDouble() < 0.1) | 175 if (base::RandDouble() < 0.1) |
| 177 view->SetVisible(!view->visible()); | 176 view->SetVisible(!view->visible()); |
| 178 } | 177 } |
| 179 | 178 |
| 180 // Convenience to make constructing a GestureEvent simpler. | |
| 181 class GestureEventForTest : public ui::GestureEvent { | |
| 182 public: | |
| 183 GestureEventForTest(ui::EventType type, int x, int y, int flags) | |
| 184 : GestureEvent(x, y, flags, base::TimeDelta(), | |
| 185 ui::GestureEventDetails(type, 0.0f, 0.0f)) { | |
| 186 } | |
| 187 | |
| 188 private: | |
| 189 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest); | |
| 190 }; | |
| 191 | |
| 192 } // namespace | 179 } // namespace |
| 193 | 180 |
| 194 namespace views { | 181 namespace views { |
| 195 | 182 |
| 196 typedef ViewsTestBase ViewTest; | 183 typedef ViewsTestBase ViewTest; |
| 197 | 184 |
| 198 // A derived class for testing purpose. | 185 // A derived class for testing purpose. |
| 199 class TestView : public View { | 186 class TestView : public View { |
| 200 public: | 187 public: |
| 201 TestView() | 188 TestView() |
| 202 : View(), | 189 : View(), |
| 203 delete_on_pressed_(false), | 190 delete_on_pressed_(false), |
| 204 native_theme_(NULL), | 191 native_theme_(NULL), |
| 205 can_process_events_within_subtree_(true) {} | 192 can_process_events_within_subtree_(true) {} |
| 206 virtual ~TestView() {} | 193 virtual ~TestView() {} |
| 207 | 194 |
| 208 // Reset all test state | 195 // Reset all test state |
| 209 void Reset() { | 196 void Reset() { |
| 210 did_change_bounds_ = false; | 197 did_change_bounds_ = false; |
| 211 last_mouse_event_type_ = 0; | 198 last_mouse_event_type_ = 0; |
| 212 location_.SetPoint(0, 0); | 199 location_.SetPoint(0, 0); |
| 213 received_mouse_enter_ = false; | 200 received_mouse_enter_ = false; |
| 214 received_mouse_exit_ = false; | 201 received_mouse_exit_ = false; |
| 215 last_gesture_event_type_ = 0; | |
| 216 last_gesture_event_was_handled_ = false; | |
| 217 last_clip_.setEmpty(); | 202 last_clip_.setEmpty(); |
| 218 accelerator_count_map_.clear(); | 203 accelerator_count_map_.clear(); |
| 219 can_process_events_within_subtree_ = true; | 204 can_process_events_within_subtree_ = true; |
| 220 } | 205 } |
| 221 | 206 |
| 222 // Exposed as public for testing. | 207 // Exposed as public for testing. |
| 223 void DoFocus() { | 208 void DoFocus() { |
| 224 views::View::Focus(); | 209 views::View::Focus(); |
| 225 } | 210 } |
| 226 | 211 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 238 return can_process_events_within_subtree_; | 223 return can_process_events_within_subtree_; |
| 239 } | 224 } |
| 240 | 225 |
| 241 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; | 226 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; |
| 242 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; | 227 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; |
| 243 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; | 228 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; |
| 244 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; | 229 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; |
| 245 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; | 230 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; |
| 246 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; | 231 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; |
| 247 | 232 |
| 248 // Ignores GestureEvent by default. | |
| 249 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; | |
| 250 | |
| 251 virtual void Paint(gfx::Canvas* canvas, const CullSet& cull_set) OVERRIDE; | 233 virtual void Paint(gfx::Canvas* canvas, const CullSet& cull_set) OVERRIDE; |
| 252 virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE; | 234 virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE; |
| 253 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; | 235 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; |
| 254 | 236 |
| 255 virtual void OnNativeThemeChanged(const ui::NativeTheme* native_theme) | 237 virtual void OnNativeThemeChanged(const ui::NativeTheme* native_theme) |
| 256 OVERRIDE; | 238 OVERRIDE; |
| 257 | 239 |
| 258 // OnBoundsChanged. | 240 // OnBoundsChanged. |
| 259 bool did_change_bounds_; | 241 bool did_change_bounds_; |
| 260 gfx::Rect new_bounds_; | 242 gfx::Rect new_bounds_; |
| 261 | 243 |
| 262 // MouseEvent. | 244 // MouseEvent. |
| 263 int last_mouse_event_type_; | 245 int last_mouse_event_type_; |
| 264 gfx::Point location_; | 246 gfx::Point location_; |
| 265 bool received_mouse_enter_; | 247 bool received_mouse_enter_; |
| 266 bool received_mouse_exit_; | 248 bool received_mouse_exit_; |
| 267 bool delete_on_pressed_; | 249 bool delete_on_pressed_; |
| 268 | 250 |
| 269 // Painting. | 251 // Painting. |
| 270 std::vector<gfx::Rect> scheduled_paint_rects_; | 252 std::vector<gfx::Rect> scheduled_paint_rects_; |
| 271 | 253 |
| 272 // GestureEvent | |
| 273 int last_gesture_event_type_; | |
| 274 bool last_gesture_event_was_handled_; | |
| 275 | |
| 276 // Painting. | 254 // Painting. |
| 277 SkRect last_clip_; | 255 SkRect last_clip_; |
| 278 | 256 |
| 279 // Accelerators. | 257 // Accelerators. |
| 280 std::map<ui::Accelerator, int> accelerator_count_map_; | 258 std::map<ui::Accelerator, int> accelerator_count_map_; |
| 281 | 259 |
| 282 // Native theme. | 260 // Native theme. |
| 283 const ui::NativeTheme* native_theme_; | 261 const ui::NativeTheme* native_theme_; |
| 284 | 262 |
| 285 // Value to return from CanProcessEventsWithinSubtree(). | 263 // Value to return from CanProcessEventsWithinSubtree(). |
| 286 bool can_process_events_within_subtree_; | 264 bool can_process_events_within_subtree_; |
| 287 }; | 265 }; |
| 288 | 266 |
| 289 // A view subclass that consumes all Gesture events for testing purposes. | |
| 290 class TestViewConsumeGesture : public TestView { | |
| 291 public: | |
| 292 TestViewConsumeGesture() : TestView() {} | |
| 293 virtual ~TestViewConsumeGesture() {} | |
| 294 | |
| 295 protected: | |
| 296 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { | |
| 297 last_gesture_event_type_ = event->type(); | |
| 298 location_.SetPoint(event->x(), event->y()); | |
| 299 event->StopPropagation(); | |
| 300 } | |
| 301 | |
| 302 private: | |
| 303 DISALLOW_COPY_AND_ASSIGN(TestViewConsumeGesture); | |
| 304 }; | |
| 305 | |
| 306 // A view subclass that ignores all Gesture events. | |
| 307 class TestViewIgnoreGesture: public TestView { | |
| 308 public: | |
| 309 TestViewIgnoreGesture() : TestView() {} | |
| 310 virtual ~TestViewIgnoreGesture() {} | |
| 311 | |
| 312 private: | |
| 313 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { | |
| 314 } | |
| 315 | |
| 316 DISALLOW_COPY_AND_ASSIGN(TestViewIgnoreGesture); | |
| 317 }; | |
| 318 | |
| 319 // A view subclass that ignores all scroll-gesture events, but consume all other | |
| 320 // gesture events. | |
| 321 class TestViewIgnoreScrollGestures : public TestViewConsumeGesture { | |
| 322 public: | |
| 323 TestViewIgnoreScrollGestures() {} | |
| 324 virtual ~TestViewIgnoreScrollGestures() {} | |
| 325 | |
| 326 private: | |
| 327 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { | |
| 328 if (event->IsScrollGestureEvent()) | |
| 329 return; | |
| 330 TestViewConsumeGesture::OnGestureEvent(event); | |
| 331 } | |
| 332 | |
| 333 DISALLOW_COPY_AND_ASSIGN(TestViewIgnoreScrollGestures); | |
| 334 }; | |
| 335 | |
| 336 //////////////////////////////////////////////////////////////////////////////// | 267 //////////////////////////////////////////////////////////////////////////////// |
| 337 // OnBoundsChanged | 268 // OnBoundsChanged |
| 338 //////////////////////////////////////////////////////////////////////////////// | 269 //////////////////////////////////////////////////////////////////////////////// |
| 339 | 270 |
| 340 void TestView::OnBoundsChanged(const gfx::Rect& previous_bounds) { | 271 void TestView::OnBoundsChanged(const gfx::Rect& previous_bounds) { |
| 341 did_change_bounds_ = true; | 272 did_change_bounds_ = true; |
| 342 new_bounds_ = bounds(); | 273 new_bounds_ = bounds(); |
| 343 } | 274 } |
| 344 | 275 |
| 345 TEST_F(ViewTest, OnBoundsChanged) { | 276 TEST_F(ViewTest, OnBoundsChanged) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 gfx::Point point(110, 120); | 403 gfx::Point point(110, 120); |
| 473 ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, point, point, | 404 ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, point, point, |
| 474 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | 405 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
| 475 root->OnMousePressed(pressed); | 406 root->OnMousePressed(pressed); |
| 476 EXPECT_EQ(0, v1->child_count()); | 407 EXPECT_EQ(0, v1->child_count()); |
| 477 | 408 |
| 478 widget->CloseNow(); | 409 widget->CloseNow(); |
| 479 } | 410 } |
| 480 | 411 |
| 481 //////////////////////////////////////////////////////////////////////////////// | 412 //////////////////////////////////////////////////////////////////////////////// |
| 482 // GestureEvent | |
| 483 //////////////////////////////////////////////////////////////////////////////// | |
| 484 | |
| 485 void TestView::OnGestureEvent(ui::GestureEvent* event) { | |
| 486 } | |
| 487 | |
| 488 TEST_F(ViewTest, ScrollGestureEvent) { | |
| 489 // Views hierarchy for non delivery of GestureEvent. | |
| 490 TestView* v1 = new TestViewConsumeGesture(); | |
| 491 v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); | |
| 492 | |
| 493 TestView* v2 = new TestViewIgnoreScrollGestures(); | |
| 494 v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100)); | |
| 495 | |
| 496 TestView* v3 = new TestViewIgnoreGesture(); | |
| 497 v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100)); | |
| 498 | |
| 499 scoped_ptr<Widget> widget(new Widget()); | |
| 500 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | |
| 501 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 502 params.bounds = gfx::Rect(50, 50, 650, 650); | |
| 503 widget->Init(params); | |
| 504 internal::RootView* root = | |
| 505 static_cast<internal::RootView*>(widget->GetRootView()); | |
| 506 ui::EventDispatchDetails details; | |
| 507 | |
| 508 root->AddChildView(v1); | |
| 509 v1->AddChildView(v2); | |
| 510 v2->AddChildView(v3); | |
| 511 | |
| 512 // |v3| completely obscures |v2|, but all the gesture events on |v3| should | |
| 513 // reach |v2| because |v3| doesn't process any gesture events. However, since | |
| 514 // |v2| does process gesture events, gesture events on |v3| or |v2| should not | |
| 515 // reach |v1|. | |
| 516 | |
| 517 v1->Reset(); | |
| 518 v2->Reset(); | |
| 519 v3->Reset(); | |
| 520 | |
| 521 // Gesture on |v3| | |
| 522 GestureEventForTest g1(ui::ET_GESTURE_TAP, 110, 110, 0); | |
| 523 details = root->OnEventFromSource(&g1); | |
| 524 EXPECT_FALSE(details.dispatcher_destroyed); | |
| 525 EXPECT_FALSE(details.target_destroyed); | |
| 526 | |
| 527 EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_); | |
| 528 EXPECT_EQ(gfx::Point(10, 10), v2->location_); | |
| 529 EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_); | |
| 530 | |
| 531 v2->Reset(); | |
| 532 | |
| 533 // Send scroll gestures on |v3|. The gesture should reach |v2|, however, | |
| 534 // since it does not process scroll-gesture events, these events should reach | |
| 535 // |v1|. | |
| 536 GestureEventForTest gscroll_begin(ui::ET_GESTURE_SCROLL_BEGIN, 115, 115, 0); | |
| 537 details = root->OnEventFromSource(&gscroll_begin); | |
| 538 EXPECT_FALSE(details.dispatcher_destroyed); | |
| 539 EXPECT_FALSE(details.target_destroyed); | |
| 540 | |
| 541 EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_); | |
| 542 EXPECT_EQ(ui::ET_GESTURE_SCROLL_BEGIN, v1->last_gesture_event_type_); | |
| 543 v1->Reset(); | |
| 544 | |
| 545 // Send a second tap on |v1|. The event should reach |v2| since it is the | |
| 546 // default gesture handler, and not |v1| (even though it is the view under the | |
| 547 // point, and is the scroll event handler). | |
| 548 GestureEventForTest second_tap(ui::ET_GESTURE_TAP, 70, 70, 0); | |
| 549 details = root->OnEventFromSource(&second_tap); | |
| 550 EXPECT_FALSE(details.dispatcher_destroyed); | |
| 551 EXPECT_FALSE(details.target_destroyed); | |
| 552 | |
| 553 EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_); | |
| 554 EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_); | |
| 555 v2->Reset(); | |
| 556 | |
| 557 GestureEventForTest gscroll_end(ui::ET_GESTURE_SCROLL_END, 50, 50, 0); | |
| 558 details = root->OnEventFromSource(&gscroll_end); | |
| 559 EXPECT_FALSE(details.dispatcher_destroyed); | |
| 560 EXPECT_FALSE(details.target_destroyed); | |
| 561 | |
| 562 EXPECT_EQ(ui::ET_GESTURE_SCROLL_END, v1->last_gesture_event_type_); | |
| 563 v1->Reset(); | |
| 564 | |
| 565 // Simulate an up so that RootView is no longer targetting |v3|. | |
| 566 GestureEventForTest g1_up(ui::ET_GESTURE_END, 110, 110, 0); | |
| 567 details = root->OnEventFromSource(&g1_up); | |
| 568 EXPECT_FALSE(details.dispatcher_destroyed); | |
| 569 EXPECT_FALSE(details.target_destroyed); | |
| 570 | |
| 571 EXPECT_EQ(ui::ET_GESTURE_END, v2->last_gesture_event_type_); | |
| 572 | |
| 573 v1->Reset(); | |
| 574 v2->Reset(); | |
| 575 v3->Reset(); | |
| 576 | |
| 577 // Gesture on |v1| | |
| 578 GestureEventForTest g2(ui::ET_GESTURE_TAP, 80, 80, 0); | |
| 579 details = root->OnEventFromSource(&g2); | |
| 580 EXPECT_FALSE(details.dispatcher_destroyed); | |
| 581 EXPECT_FALSE(details.target_destroyed); | |
| 582 | |
| 583 EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_); | |
| 584 EXPECT_EQ(gfx::Point(80, 80), v1->location_); | |
| 585 EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_); | |
| 586 | |
| 587 // Send event |g1| again. Even though the coordinates target |v3| it should go | |
| 588 // to |v1| as that is the view the touch was initially down on. | |
| 589 v1->last_gesture_event_type_ = ui::ET_UNKNOWN; | |
| 590 v3->last_gesture_event_type_ = ui::ET_UNKNOWN; | |
| 591 details = root->OnEventFromSource(&g1); | |
| 592 EXPECT_FALSE(details.dispatcher_destroyed); | |
| 593 EXPECT_FALSE(details.target_destroyed); | |
| 594 | |
| 595 EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_); | |
| 596 EXPECT_EQ(ui::ET_UNKNOWN, v3->last_gesture_event_type_); | |
| 597 EXPECT_EQ("110,110", v1->location_.ToString()); | |
| 598 | |
| 599 widget->CloseNow(); | |
| 600 } | |
| 601 | |
| 602 //////////////////////////////////////////////////////////////////////////////// | |
| 603 // Painting | 413 // Painting |
| 604 //////////////////////////////////////////////////////////////////////////////// | 414 //////////////////////////////////////////////////////////////////////////////// |
| 605 | 415 |
| 606 void TestView::Paint(gfx::Canvas* canvas, const CullSet& cull_set) { | 416 void TestView::Paint(gfx::Canvas* canvas, const CullSet& cull_set) { |
| 607 canvas->sk_canvas()->getClipBounds(&last_clip_); | 417 canvas->sk_canvas()->getClipBounds(&last_clip_); |
| 608 } | 418 } |
| 609 | 419 |
| 610 void TestView::SchedulePaintInRect(const gfx::Rect& rect) { | 420 void TestView::SchedulePaintInRect(const gfx::Rect& rect) { |
| 611 scheduled_paint_rects_.push_back(rect); | 421 scheduled_paint_rects_.push_back(rect); |
| 612 View::SchedulePaintInRect(rect); | 422 View::SchedulePaintInRect(rect); |
| (...skipping 3212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3825 // notification. | 3635 // notification. |
| 3826 TestView* test_view_child_2 = new TestView(); | 3636 TestView* test_view_child_2 = new TestView(); |
| 3827 test_view->AddChildView(test_view_child_2); | 3637 test_view->AddChildView(test_view_child_2); |
| 3828 EXPECT_TRUE(test_view_child_2->native_theme_); | 3638 EXPECT_TRUE(test_view_child_2->native_theme_); |
| 3829 EXPECT_EQ(widget->GetNativeTheme(), test_view_child_2->native_theme_); | 3639 EXPECT_EQ(widget->GetNativeTheme(), test_view_child_2->native_theme_); |
| 3830 | 3640 |
| 3831 widget->CloseNow(); | 3641 widget->CloseNow(); |
| 3832 } | 3642 } |
| 3833 | 3643 |
| 3834 } // namespace views | 3644 } // namespace views |
| OLD | NEW |