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
3 // found in the LICENSE file.
4
5 #include "ui/aura/window.h"
6
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/aura/client/capture_client.h"
18 #include "ui/aura/client/focus_change_observer.h"
19 #include "ui/aura/client/visibility_client.h"
20 #include "ui/aura/client/window_tree_client.h"
21 #include "ui/aura/test/aura_test_base.h"
22 #include "ui/aura/test/aura_test_utils.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/test/test_windows.h"
25 #include "ui/aura/test/window_test_api.h"
26 #include "ui/aura/window_delegate.h"
27 #include "ui/aura/window_event_dispatcher.h"
28 #include "ui/aura/window_observer.h"
29 #include "ui/aura/window_property.h"
30 #include "ui/aura/window_tree_host.h"
31 #include "ui/base/hit_test.h"
32 #include "ui/compositor/layer.h"
33 #include "ui/compositor/layer_animation_observer.h"
34 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
35 #include "ui/compositor/scoped_layer_animation_settings.h"
36 #include "ui/compositor/test/test_layers.h"
37 #include "ui/events/event.h"
38 #include "ui/events/event_utils.h"
39 #include "ui/events/gestures/gesture_configuration.h"
40 #include "ui/events/keycodes/keyboard_codes.h"
41 #include "ui/events/test/event_generator.h"
42 #include "ui/gfx/canvas.h"
43 #include "ui/gfx/screen.h"
44 #include "ui/gfx/skia_util.h"
45 #include "ui/gfx/vector2d.h"
46
47 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
48 DECLARE_WINDOW_PROPERTY_TYPE(int)
49
50 namespace aura {
51 namespace test {
52
53 class WindowTest : public AuraTestBase {
54 public:
WindowTest()55 WindowTest() : max_separation_(0) {
56 }
57
SetUp()58 virtual void SetUp() OVERRIDE {
59 AuraTestBase::SetUp();
60 // TODO: there needs to be an easier way to do this.
61 max_separation_ = ui::GestureConfiguration::
62 max_separation_for_gesture_touches_in_pixels();
63 ui::GestureConfiguration::
64 set_max_separation_for_gesture_touches_in_pixels(0);
65 }
66
TearDown()67 virtual void TearDown() OVERRIDE {
68 AuraTestBase::TearDown();
69 ui::GestureConfiguration::
70 set_max_separation_for_gesture_touches_in_pixels(max_separation_);
71 }
72
73 private:
74 int max_separation_;
75
76 DISALLOW_COPY_AND_ASSIGN(WindowTest);
77 };
78
79 namespace {
80
81 // Used for verifying destruction methods are invoked.
82 class DestroyTrackingDelegateImpl : public TestWindowDelegate {
83 public:
DestroyTrackingDelegateImpl()84 DestroyTrackingDelegateImpl()
85 : destroying_count_(0),
86 destroyed_count_(0),
87 in_destroying_(false) {}
88
clear_destroying_count()89 void clear_destroying_count() { destroying_count_ = 0; }
destroying_count() const90 int destroying_count() const { return destroying_count_; }
91
clear_destroyed_count()92 void clear_destroyed_count() { destroyed_count_ = 0; }
destroyed_count() const93 int destroyed_count() const { return destroyed_count_; }
94
in_destroying() const95 bool in_destroying() const { return in_destroying_; }
96
OnWindowDestroying(Window * window)97 virtual void OnWindowDestroying(Window* window) OVERRIDE {
98 EXPECT_FALSE(in_destroying_);
99 in_destroying_ = true;
100 destroying_count_++;
101 }
102
OnWindowDestroyed(Window * window)103 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
104 EXPECT_TRUE(in_destroying_);
105 in_destroying_ = false;
106 destroyed_count_++;
107 }
108
109 private:
110 int destroying_count_;
111 int destroyed_count_;
112 bool in_destroying_;
113
114 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl);
115 };
116
117 // Used to verify that when OnWindowDestroying is invoked the parent is also
118 // is in the process of being destroyed.
119 class ChildWindowDelegateImpl : public DestroyTrackingDelegateImpl {
120 public:
ChildWindowDelegateImpl(DestroyTrackingDelegateImpl * parent_delegate)121 explicit ChildWindowDelegateImpl(
122 DestroyTrackingDelegateImpl* parent_delegate)
123 : parent_delegate_(parent_delegate) {
124 }
125
OnWindowDestroying(Window * window)126 virtual void OnWindowDestroying(Window* window) OVERRIDE {
127 EXPECT_TRUE(parent_delegate_->in_destroying());
128 DestroyTrackingDelegateImpl::OnWindowDestroying(window);
129 }
130
131 private:
132 DestroyTrackingDelegateImpl* parent_delegate_;
133
134 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl);
135 };
136
137 // Used to verify that a Window is removed from its parent when
138 // OnWindowDestroyed is called.
139 class DestroyOrphanDelegate : public TestWindowDelegate {
140 public:
DestroyOrphanDelegate()141 DestroyOrphanDelegate() : window_(NULL) {
142 }
143
set_window(Window * window)144 void set_window(Window* window) { window_ = window; }
145
OnWindowDestroyed(Window * window)146 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
147 EXPECT_FALSE(window_->parent());
148 }
149
150 private:
151 Window* window_;
152 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate);
153 };
154
155 // Used in verifying mouse capture.
156 class CaptureWindowDelegateImpl : public TestWindowDelegate {
157 public:
CaptureWindowDelegateImpl()158 CaptureWindowDelegateImpl() {
159 ResetCounts();
160 }
161
ResetCounts()162 void ResetCounts() {
163 capture_changed_event_count_ = 0;
164 capture_lost_count_ = 0;
165 mouse_event_count_ = 0;
166 touch_event_count_ = 0;
167 gesture_event_count_ = 0;
168 }
169
capture_changed_event_count() const170 int capture_changed_event_count() const {
171 return capture_changed_event_count_;
172 }
capture_lost_count() const173 int capture_lost_count() const { return capture_lost_count_; }
mouse_event_count() const174 int mouse_event_count() const { return mouse_event_count_; }
touch_event_count() const175 int touch_event_count() const { return touch_event_count_; }
gesture_event_count() const176 int gesture_event_count() const { return gesture_event_count_; }
177
OnMouseEvent(ui::MouseEvent * event)178 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
179 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
180 capture_changed_event_count_++;
181 mouse_event_count_++;
182 }
OnTouchEvent(ui::TouchEvent * event)183 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
184 touch_event_count_++;
185 }
OnGestureEvent(ui::GestureEvent * event)186 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
187 gesture_event_count_++;
188 }
OnCaptureLost()189 virtual void OnCaptureLost() OVERRIDE {
190 capture_lost_count_++;
191 }
192
193 private:
194 int capture_changed_event_count_;
195 int capture_lost_count_;
196 int mouse_event_count_;
197 int touch_event_count_;
198 int gesture_event_count_;
199
200 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl);
201 };
202
203 // Keeps track of the location of the gesture.
204 class GestureTrackPositionDelegate : public TestWindowDelegate {
205 public:
GestureTrackPositionDelegate()206 GestureTrackPositionDelegate() {}
207
OnGestureEvent(ui::GestureEvent * event)208 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
209 position_ = event->location();
210 event->StopPropagation();
211 }
212
position() const213 const gfx::Point& position() const { return position_; }
214
215 private:
216 gfx::Point position_;
217
218 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate);
219 };
220
getTime()221 base::TimeDelta getTime() {
222 return ui::EventTimeForNow();
223 }
224
225 class SelfEventHandlingWindowDelegate : public TestWindowDelegate {
226 public:
SelfEventHandlingWindowDelegate()227 SelfEventHandlingWindowDelegate() {}
228
ShouldDescendIntoChildForEventHandling(Window * child,const gfx::Point & location)229 virtual bool ShouldDescendIntoChildForEventHandling(
230 Window* child,
231 const gfx::Point& location) OVERRIDE {
232 return false;
233 }
234
235 private:
236 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate);
237 };
238
239 // The delegate deletes itself when the window is being destroyed.
240 class DestroyWindowDelegate : public TestWindowDelegate {
241 public:
DestroyWindowDelegate()242 DestroyWindowDelegate() {}
243
244 private:
~DestroyWindowDelegate()245 virtual ~DestroyWindowDelegate() {}
246
247 // Overridden from WindowDelegate.
OnWindowDestroyed(Window * window)248 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
249 delete this;
250 }
251
252 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate);
253 };
254
255 } // namespace
256
TEST_F(WindowTest,GetChildById)257 TEST_F(WindowTest, GetChildById) {
258 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
259 scoped_ptr<Window> w11(CreateTestWindowWithId(11, w1.get()));
260 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
261 scoped_ptr<Window> w12(CreateTestWindowWithId(12, w1.get()));
262
263 EXPECT_EQ(NULL, w1->GetChildById(57));
264 EXPECT_EQ(w12.get(), w1->GetChildById(12));
265 EXPECT_EQ(w111.get(), w1->GetChildById(111));
266 }
267
268 // Make sure that Window::Contains correctly handles children, grandchildren,
269 // and not containing NULL or parents.
TEST_F(WindowTest,Contains)270 TEST_F(WindowTest, Contains) {
271 Window parent(NULL);
272 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
273 Window child1(NULL);
274 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
275 Window child2(NULL);
276 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
277
278 parent.AddChild(&child1);
279 child1.AddChild(&child2);
280
281 EXPECT_TRUE(parent.Contains(&parent));
282 EXPECT_TRUE(parent.Contains(&child1));
283 EXPECT_TRUE(parent.Contains(&child2));
284
285 EXPECT_FALSE(parent.Contains(NULL));
286 EXPECT_FALSE(child1.Contains(&parent));
287 EXPECT_FALSE(child2.Contains(&child1));
288 }
289
TEST_F(WindowTest,ContainsPointInRoot)290 TEST_F(WindowTest, ContainsPointInRoot) {
291 scoped_ptr<Window> w(
292 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
293 root_window()));
294 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(9, 9)));
295 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(10, 10)));
296 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(14, 14)));
297 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(15, 15)));
298 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(20, 20)));
299 }
300
TEST_F(WindowTest,ContainsPoint)301 TEST_F(WindowTest, ContainsPoint) {
302 scoped_ptr<Window> w(
303 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
304 root_window()));
305 EXPECT_TRUE(w->ContainsPoint(gfx::Point(0, 0)));
306 EXPECT_TRUE(w->ContainsPoint(gfx::Point(4, 4)));
307 EXPECT_FALSE(w->ContainsPoint(gfx::Point(5, 5)));
308 EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10)));
309 }
310
TEST_F(WindowTest,ConvertPointToWindow)311 TEST_F(WindowTest, ConvertPointToWindow) {
312 // Window::ConvertPointToWindow is mostly identical to
313 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
314 // in which case the function just returns.
315 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
316 gfx::Point reference_point(100, 100);
317 gfx::Point test_point = reference_point;
318 Window::ConvertPointToTarget(NULL, w1.get(), &test_point);
319 EXPECT_EQ(reference_point, test_point);
320 }
321
TEST_F(WindowTest,MoveCursorTo)322 TEST_F(WindowTest, MoveCursorTo) {
323 scoped_ptr<Window> w1(
324 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
325 root_window()));
326 scoped_ptr<Window> w11(
327 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
328 scoped_ptr<Window> w111(
329 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
330 scoped_ptr<Window> w1111(
331 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
332
333 Window* root = root_window();
334 root->MoveCursorTo(gfx::Point(10, 10));
335 EXPECT_EQ("10,10",
336 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
337 w1->MoveCursorTo(gfx::Point(10, 10));
338 EXPECT_EQ("20,20",
339 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
340 w11->MoveCursorTo(gfx::Point(10, 10));
341 EXPECT_EQ("25,25",
342 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
343 w111->MoveCursorTo(gfx::Point(10, 10));
344 EXPECT_EQ("30,30",
345 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
346 w1111->MoveCursorTo(gfx::Point(10, 10));
347 EXPECT_EQ("35,35",
348 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
349 }
350
TEST_F(WindowTest,ContainsMouse)351 TEST_F(WindowTest, ContainsMouse) {
352 scoped_ptr<Window> w(
353 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
354 root_window()));
355 w->Show();
356 WindowTestApi w_test_api(w.get());
357 Window* root = root_window();
358 root->MoveCursorTo(gfx::Point(10, 10));
359 EXPECT_TRUE(w_test_api.ContainsMouse());
360 root->MoveCursorTo(gfx::Point(9, 10));
361 EXPECT_FALSE(w_test_api.ContainsMouse());
362 }
363
364 // Test Window::ConvertPointToWindow() with transform to root_window.
TEST_F(WindowTest,MoveCursorToWithTransformRootWindow)365 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
366 gfx::Transform transform;
367 transform.Translate(100.0, 100.0);
368 transform.Rotate(90.0);
369 transform.Scale(2.0, 5.0);
370 host()->SetRootTransform(transform);
371 host()->MoveCursorTo(gfx::Point(10, 10));
372 #if !defined(OS_WIN)
373 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
374 EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
375 #endif
376 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
377 root_window())->GetCursorScreenPoint().ToString());
378 }
379
380 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
TEST_F(WindowTest,MoveCursorToWithTransformWindow)381 TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
382 scoped_ptr<Window> w1(
383 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
384 root_window()));
385
386 gfx::Transform transform1;
387 transform1.Scale(2, 2);
388 w1->SetTransform(transform1);
389 w1->MoveCursorTo(gfx::Point(10, 10));
390 EXPECT_EQ("30,30",
391 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
392
393 gfx::Transform transform2;
394 transform2.Translate(-10, 20);
395 w1->SetTransform(transform2);
396 w1->MoveCursorTo(gfx::Point(10, 10));
397 EXPECT_EQ("10,40",
398 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
399
400 gfx::Transform transform3;
401 transform3.Rotate(90.0);
402 w1->SetTransform(transform3);
403 w1->MoveCursorTo(gfx::Point(5, 5));
404 EXPECT_EQ("5,15",
405 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
406
407 gfx::Transform transform4;
408 transform4.Translate(100.0, 100.0);
409 transform4.Rotate(90.0);
410 transform4.Scale(2.0, 5.0);
411 w1->SetTransform(transform4);
412 w1->MoveCursorTo(gfx::Point(10, 10));
413 EXPECT_EQ("60,130",
414 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
415 }
416
417 // Test Window::ConvertPointToWindow() with complex transforms to both root and
418 // non-root windows.
419 // Test Window::ConvertPointToWindow() with transform to root_window.
TEST_F(WindowTest,MoveCursorToWithComplexTransform)420 TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
421 scoped_ptr<Window> w1(
422 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
423 root_window()));
424 scoped_ptr<Window> w11(
425 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
426 scoped_ptr<Window> w111(
427 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
428 scoped_ptr<Window> w1111(
429 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
430
431 Window* root = root_window();
432
433 // The root window expects transforms that produce integer rects.
434 gfx::Transform root_transform;
435 root_transform.Translate(60.0, 70.0);
436 root_transform.Rotate(-90.0);
437 root_transform.Translate(-50.0, -50.0);
438 root_transform.Scale(2.0, 3.0);
439
440 gfx::Transform transform;
441 transform.Translate(10.0, 20.0);
442 transform.Rotate(10.0);
443 transform.Scale(0.3f, 0.5f);
444 host()->SetRootTransform(root_transform);
445 w1->SetTransform(transform);
446 w11->SetTransform(transform);
447 w111->SetTransform(transform);
448 w1111->SetTransform(transform);
449
450 w1111->MoveCursorTo(gfx::Point(10, 10));
451
452 #if !defined(OS_WIN)
453 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
454 EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
455 #endif
456 EXPECT_EQ("20,53",
457 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
458 }
459
TEST_F(WindowTest,GetEventHandlerForPoint)460 TEST_F(WindowTest, GetEventHandlerForPoint) {
461 scoped_ptr<Window> w1(
462 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
463 root_window()));
464 scoped_ptr<Window> w11(
465 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
466 scoped_ptr<Window> w111(
467 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
468 scoped_ptr<Window> w1111(
469 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
470 scoped_ptr<Window> w12(
471 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25),
472 w1.get()));
473 scoped_ptr<Window> w121(
474 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get()));
475 scoped_ptr<Window> w13(
476 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get()));
477
478 Window* root = root_window();
479 w1->parent()->SetBounds(gfx::Rect(500, 500));
480 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5)));
481 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11)));
482 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16)));
483 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21)));
484 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26)));
485 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431)));
486 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436)));
487 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481)));
488 }
489
TEST_F(WindowTest,GetEventHandlerForPointWithOverride)490 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) {
491 // If our child is flush to our top-left corner he gets events just inside the
492 // window edges.
493 scoped_ptr<Window> parent(
494 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500),
495 root_window()));
496 scoped_ptr<Window> child(
497 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get()));
498 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
499 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
500
501 // We can override the hit test bounds of the parent to make the parent grab
502 // events along that edge.
503 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
504 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
505 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
506 }
507
TEST_F(WindowTest,GetEventHandlerForPointWithOverrideDescendingOrder)508 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) {
509 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate(
510 new SelfEventHandlingWindowDelegate);
511 scoped_ptr<Window> parent(CreateTestWindowWithDelegate(
512 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
513 scoped_ptr<Window> child(
514 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480),
515 parent.get()));
516
517 // We can override ShouldDescendIntoChildForEventHandling to make the parent
518 // grab all events.
519 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
520 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50)));
521 }
522
TEST_F(WindowTest,GetTopWindowContainingPoint)523 TEST_F(WindowTest, GetTopWindowContainingPoint) {
524 Window* root = root_window();
525 root->SetBounds(gfx::Rect(0, 0, 300, 300));
526
527 scoped_ptr<Window> w1(
528 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100),
529 root_window()));
530 scoped_ptr<Window> w11(
531 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get()));
532
533 scoped_ptr<Window> w2(
534 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55),
535 root_window()));
536
537 scoped_ptr<Window> w3(
538 CreateTestWindowWithDelegate(
539 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window()));
540 scoped_ptr<Window> w31(
541 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get()));
542 scoped_ptr<Window> w311(
543 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get()));
544
545 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0)));
546 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5)));
547 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10)));
548 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59)));
549 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60)));
550 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109)));
551 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110)));
552 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200)));
553 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220)));
554 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260)));
555 }
556
TEST_F(WindowTest,GetToplevelWindow)557 TEST_F(WindowTest, GetToplevelWindow) {
558 const gfx::Rect kBounds(0, 0, 10, 10);
559 TestWindowDelegate delegate;
560
561 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
562 scoped_ptr<Window> w11(
563 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get()));
564 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
565 scoped_ptr<Window> w1111(
566 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get()));
567
568 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL);
569 EXPECT_TRUE(w1->GetToplevelWindow() == NULL);
570 EXPECT_EQ(w11.get(), w11->GetToplevelWindow());
571 EXPECT_EQ(w11.get(), w111->GetToplevelWindow());
572 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow());
573 }
574
575 class AddedToRootWindowObserver : public WindowObserver {
576 public:
AddedToRootWindowObserver()577 AddedToRootWindowObserver() : called_(false) {}
578
OnWindowAddedToRootWindow(Window * window)579 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
580 called_ = true;
581 }
582
called() const583 bool called() const { return called_; }
584
585 private:
586 bool called_;
587
588 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver);
589 };
590
TEST_F(WindowTest,WindowAddedToRootWindowShouldNotifyChildAndNotParent)591 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
592 AddedToRootWindowObserver parent_observer;
593 AddedToRootWindowObserver child_observer;
594 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
595 scoped_ptr<Window> child_window(new Window(NULL));
596 child_window->Init(aura::WINDOW_LAYER_TEXTURED);
597 child_window->Show();
598
599 parent_window->AddObserver(&parent_observer);
600 child_window->AddObserver(&child_observer);
601
602 parent_window->AddChild(child_window.get());
603
604 EXPECT_FALSE(parent_observer.called());
605 EXPECT_TRUE(child_observer.called());
606
607 parent_window->RemoveObserver(&parent_observer);
608 child_window->RemoveObserver(&child_observer);
609 }
610
611 // Various destruction assertions.
TEST_F(WindowTest,DestroyTest)612 TEST_F(WindowTest, DestroyTest) {
613 DestroyTrackingDelegateImpl parent_delegate;
614 ChildWindowDelegateImpl child_delegate(&parent_delegate);
615 {
616 scoped_ptr<Window> parent(
617 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
618 root_window()));
619 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get());
620 }
621 // Both the parent and child should have been destroyed.
622 EXPECT_EQ(1, parent_delegate.destroying_count());
623 EXPECT_EQ(1, parent_delegate.destroyed_count());
624 EXPECT_EQ(1, child_delegate.destroying_count());
625 EXPECT_EQ(1, child_delegate.destroyed_count());
626 }
627
628 // Tests that a window is orphaned before OnWindowDestroyed is called.
TEST_F(WindowTest,OrphanedBeforeOnDestroyed)629 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
630 TestWindowDelegate parent_delegate;
631 DestroyOrphanDelegate child_delegate;
632 {
633 scoped_ptr<Window> parent(
634 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
635 root_window()));
636 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0,
637 gfx::Rect(), parent.get()));
638 child_delegate.set_window(child.get());
639 }
640 }
641
642 // Make sure StackChildAtTop moves both the window and layer to the front.
TEST_F(WindowTest,StackChildAtTop)643 TEST_F(WindowTest, StackChildAtTop) {
644 Window parent(NULL);
645 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
646 Window child1(NULL);
647 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
648 Window child2(NULL);
649 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
650
651 parent.AddChild(&child1);
652 parent.AddChild(&child2);
653 ASSERT_EQ(2u, parent.children().size());
654 EXPECT_EQ(&child1, parent.children()[0]);
655 EXPECT_EQ(&child2, parent.children()[1]);
656 ASSERT_EQ(2u, parent.layer()->children().size());
657 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
658 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
659
660 parent.StackChildAtTop(&child1);
661 ASSERT_EQ(2u, parent.children().size());
662 EXPECT_EQ(&child1, parent.children()[1]);
663 EXPECT_EQ(&child2, parent.children()[0]);
664 ASSERT_EQ(2u, parent.layer()->children().size());
665 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
666 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
667 }
668
669 // Make sure StackChildBelow works.
TEST_F(WindowTest,StackChildBelow)670 TEST_F(WindowTest, StackChildBelow) {
671 Window parent(NULL);
672 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
673 Window child1(NULL);
674 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
675 child1.set_id(1);
676 Window child2(NULL);
677 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
678 child2.set_id(2);
679 Window child3(NULL);
680 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
681 child3.set_id(3);
682
683 parent.AddChild(&child1);
684 parent.AddChild(&child2);
685 parent.AddChild(&child3);
686 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
687
688 parent.StackChildBelow(&child1, &child2);
689 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
690
691 parent.StackChildBelow(&child2, &child1);
692 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent));
693
694 parent.StackChildBelow(&child3, &child2);
695 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent));
696
697 parent.StackChildBelow(&child3, &child1);
698 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent));
699 }
700
701 // Various assertions for StackChildAbove.
TEST_F(WindowTest,StackChildAbove)702 TEST_F(WindowTest, StackChildAbove) {
703 Window parent(NULL);
704 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
705 Window child1(NULL);
706 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
707 Window child2(NULL);
708 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
709 Window child3(NULL);
710 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
711
712 parent.AddChild(&child1);
713 parent.AddChild(&child2);
714
715 // Move 1 in front of 2.
716 parent.StackChildAbove(&child1, &child2);
717 ASSERT_EQ(2u, parent.children().size());
718 EXPECT_EQ(&child2, parent.children()[0]);
719 EXPECT_EQ(&child1, parent.children()[1]);
720 ASSERT_EQ(2u, parent.layer()->children().size());
721 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
722 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
723
724 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
725 // in [1, 2, 3].
726 parent.AddChild(&child3);
727 parent.StackChildAbove(&child2, &child1);
728 ASSERT_EQ(3u, parent.children().size());
729 EXPECT_EQ(&child1, parent.children()[0]);
730 EXPECT_EQ(&child2, parent.children()[1]);
731 EXPECT_EQ(&child3, parent.children()[2]);
732 ASSERT_EQ(3u, parent.layer()->children().size());
733 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
734 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
735 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
736
737 // Move 1 in front of 3, resulting in [2, 3, 1].
738 parent.StackChildAbove(&child1, &child3);
739 ASSERT_EQ(3u, parent.children().size());
740 EXPECT_EQ(&child2, parent.children()[0]);
741 EXPECT_EQ(&child3, parent.children()[1]);
742 EXPECT_EQ(&child1, parent.children()[2]);
743 ASSERT_EQ(3u, parent.layer()->children().size());
744 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
745 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]);
746 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]);
747
748 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
749 parent.StackChildAbove(&child1, &child2);
750 ASSERT_EQ(3u, parent.children().size());
751 EXPECT_EQ(&child2, parent.children()[0]);
752 EXPECT_EQ(&child1, parent.children()[1]);
753 EXPECT_EQ(&child3, parent.children()[2]);
754 ASSERT_EQ(3u, parent.layer()->children().size());
755 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
756 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
757 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
758 }
759
760 // Various capture assertions.
TEST_F(WindowTest,CaptureTests)761 TEST_F(WindowTest, CaptureTests) {
762 CaptureWindowDelegateImpl delegate;
763 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
764 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
765 EXPECT_FALSE(window->HasCapture());
766
767 delegate.ResetCounts();
768
769 // Do a capture.
770 window->SetCapture();
771 EXPECT_TRUE(window->HasCapture());
772 EXPECT_EQ(0, delegate.capture_lost_count());
773 EXPECT_EQ(0, delegate.capture_changed_event_count());
774 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
775 generator.PressLeftButton();
776 EXPECT_EQ(1, delegate.mouse_event_count());
777 generator.ReleaseLeftButton();
778
779 EXPECT_EQ(2, delegate.mouse_event_count());
780 delegate.ResetCounts();
781
782 ui::TouchEvent touchev(
783 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
784 DispatchEventUsingWindowDispatcher(&touchev);
785 EXPECT_EQ(1, delegate.touch_event_count());
786 delegate.ResetCounts();
787
788 window->ReleaseCapture();
789 EXPECT_FALSE(window->HasCapture());
790 EXPECT_EQ(1, delegate.capture_lost_count());
791 EXPECT_EQ(1, delegate.capture_changed_event_count());
792 EXPECT_EQ(1, delegate.mouse_event_count());
793 EXPECT_EQ(0, delegate.touch_event_count());
794
795 generator.PressLeftButton();
796 EXPECT_EQ(1, delegate.mouse_event_count());
797
798 ui::TouchEvent touchev2(
799 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
800 DispatchEventUsingWindowDispatcher(&touchev2);
801 EXPECT_EQ(0, delegate.touch_event_count());
802
803 // Removing the capture window from parent should reset the capture window
804 // in the root window.
805 window->SetCapture();
806 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window()));
807 window->parent()->RemoveChild(window.get());
808 EXPECT_FALSE(window->HasCapture());
809 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
810 }
811
TEST_F(WindowTest,TouchCaptureCancelsOtherTouches)812 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
813 CaptureWindowDelegateImpl delegate1;
814 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
815 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window()));
816 CaptureWindowDelegateImpl delegate2;
817 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
818 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window()));
819
820 // Press on w1.
821 ui::TouchEvent press1(
822 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
823 DispatchEventUsingWindowDispatcher(&press1);
824 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
825 EXPECT_EQ(2, delegate1.gesture_event_count());
826 delegate1.ResetCounts();
827
828 // Capturing to w2 should cause the touch to be canceled.
829 w2->SetCapture();
830 EXPECT_EQ(1, delegate1.touch_event_count());
831 EXPECT_EQ(0, delegate2.touch_event_count());
832 delegate1.ResetCounts();
833 delegate2.ResetCounts();
834
835 // Events now go to w2.
836 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
837 DispatchEventUsingWindowDispatcher(&move);
838 EXPECT_EQ(0, delegate1.gesture_event_count());
839 EXPECT_EQ(0, delegate1.touch_event_count());
840 EXPECT_EQ(0, delegate2.gesture_event_count());
841 EXPECT_EQ(1, delegate2.touch_event_count());
842
843 ui::TouchEvent release(
844 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
845 DispatchEventUsingWindowDispatcher(&release);
846 EXPECT_EQ(0, delegate1.gesture_event_count());
847 EXPECT_EQ(0, delegate2.gesture_event_count());
848
849 // A new press is captured by w2.
850 ui::TouchEvent press2(
851 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
852 DispatchEventUsingWindowDispatcher(&press2);
853 EXPECT_EQ(0, delegate1.gesture_event_count());
854 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
855 EXPECT_EQ(2, delegate2.gesture_event_count());
856 delegate1.ResetCounts();
857 delegate2.ResetCounts();
858
859 // And releasing capture changes nothing.
860 w2->ReleaseCapture();
861 EXPECT_EQ(0, delegate1.gesture_event_count());
862 EXPECT_EQ(0, delegate1.touch_event_count());
863 EXPECT_EQ(0, delegate2.gesture_event_count());
864 EXPECT_EQ(0, delegate2.touch_event_count());
865 }
866
TEST_F(WindowTest,TouchCaptureDoesntCancelCapturedTouches)867 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
868 CaptureWindowDelegateImpl delegate;
869 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
870 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window()));
871 base::TimeDelta time = getTime();
872 const int kTimeDelta = 100;
873
874 ui::TouchEvent press(
875 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, time);
876 DispatchEventUsingWindowDispatcher(&press);
877
878 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
879 EXPECT_EQ(2, delegate.gesture_event_count());
880 EXPECT_EQ(1, delegate.touch_event_count());
881 delegate.ResetCounts();
882
883 window->SetCapture();
884 EXPECT_EQ(0, delegate.gesture_event_count());
885 EXPECT_EQ(0, delegate.touch_event_count());
886 delegate.ResetCounts();
887
888 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
889 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
890 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
891 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, time);
892 DispatchEventUsingWindowDispatcher(&move);
893 EXPECT_EQ(1, delegate.touch_event_count());
894 EXPECT_EQ(3, delegate.gesture_event_count());
895 delegate.ResetCounts();
896
897 // Release capture shouldn't change anything.
898 window->ReleaseCapture();
899 EXPECT_EQ(0, delegate.touch_event_count());
900 EXPECT_EQ(0, delegate.gesture_event_count());
901 delegate.ResetCounts();
902
903 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
904 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
905 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, time);
906 DispatchEventUsingWindowDispatcher(&move2);
907 EXPECT_EQ(1, delegate.touch_event_count());
908 EXPECT_EQ(1, delegate.gesture_event_count());
909 delegate.ResetCounts();
910
911 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
912 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
913 ui::TouchEvent release(
914 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, time);
915 DispatchEventUsingWindowDispatcher(&release);
916 EXPECT_EQ(1, delegate.touch_event_count());
917 EXPECT_EQ(2, delegate.gesture_event_count());
918 }
919
920
921 // Assertions around SetCapture() and touch/gestures.
TEST_F(WindowTest,TransferCaptureTouchEvents)922 TEST_F(WindowTest, TransferCaptureTouchEvents) {
923 // Touch on |w1|.
924 CaptureWindowDelegateImpl d1;
925 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
926 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
927 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
928 DispatchEventUsingWindowDispatcher(&p1);
929 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
930 EXPECT_EQ(1, d1.touch_event_count());
931 EXPECT_EQ(2, d1.gesture_event_count());
932 d1.ResetCounts();
933
934 // Touch on |w2| with a different id.
935 CaptureWindowDelegateImpl d2;
936 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
937 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
938 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
939 DispatchEventUsingWindowDispatcher(&p2);
940 EXPECT_EQ(0, d1.touch_event_count());
941 EXPECT_EQ(0, d1.gesture_event_count());
942 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
943 EXPECT_EQ(1, d2.touch_event_count());
944 EXPECT_EQ(2, d2.gesture_event_count());
945 d1.ResetCounts();
946 d2.ResetCounts();
947
948 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
949 // but not |w2|.
950 w2->SetCapture();
951 EXPECT_EQ(1, d1.touch_event_count());
952 EXPECT_EQ(2, d1.gesture_event_count());
953 EXPECT_EQ(0, d2.touch_event_count());
954 EXPECT_EQ(0, d2.gesture_event_count());
955 d1.ResetCounts();
956 d2.ResetCounts();
957
958 CaptureWindowDelegateImpl d3;
959 scoped_ptr<Window> w3(CreateTestWindowWithDelegate(
960 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window()));
961 // Set capture on w3. No new events should be received.
962 // Note this difference in behavior between the first and second capture
963 // is confusing and error prone. http://crbug.com/236930
964 w3->SetCapture();
965 EXPECT_EQ(0, d1.touch_event_count());
966 EXPECT_EQ(0, d1.gesture_event_count());
967 EXPECT_EQ(0, d2.touch_event_count());
968 EXPECT_EQ(0, d2.gesture_event_count());
969 EXPECT_EQ(0, d3.touch_event_count());
970 EXPECT_EQ(0, d3.gesture_event_count());
971
972 // Move touch id originally associated with |w2|. Since capture was transfered
973 // from 2 to 3 only |w3| should get the event.
974 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
975 DispatchEventUsingWindowDispatcher(&m3);
976 EXPECT_EQ(0, d1.touch_event_count());
977 EXPECT_EQ(0, d1.gesture_event_count());
978 EXPECT_EQ(0, d2.touch_event_count());
979 EXPECT_EQ(0, d2.gesture_event_count());
980 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
981 EXPECT_EQ(1, d3.touch_event_count());
982 EXPECT_EQ(3, d3.gesture_event_count());
983 d1.ResetCounts();
984 d2.ResetCounts();
985 d3.ResetCounts();
986
987 // When we release capture, no touches are canceled.
988 w3->ReleaseCapture();
989 EXPECT_EQ(0, d1.touch_event_count());
990 EXPECT_EQ(0, d1.gesture_event_count());
991 EXPECT_EQ(0, d2.touch_event_count());
992 EXPECT_EQ(0, d2.gesture_event_count());
993 EXPECT_EQ(0, d3.touch_event_count());
994 EXPECT_EQ(0, d3.gesture_event_count());
995
996 // And when we move the touch again, |w3| still gets the events.
997 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
998 DispatchEventUsingWindowDispatcher(&m4);
999 EXPECT_EQ(0, d1.touch_event_count());
1000 EXPECT_EQ(0, d1.gesture_event_count());
1001 EXPECT_EQ(0, d2.touch_event_count());
1002 EXPECT_EQ(0, d2.gesture_event_count());
1003 EXPECT_EQ(1, d3.touch_event_count());
1004 EXPECT_EQ(1, d3.gesture_event_count());
1005 d1.ResetCounts();
1006 d2.ResetCounts();
1007 d3.ResetCounts();
1008 }
1009
1010 // Changes capture while capture is already ongoing.
TEST_F(WindowTest,ChangeCaptureWhileMouseDown)1011 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) {
1012 CaptureWindowDelegateImpl delegate;
1013 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1014 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1015 CaptureWindowDelegateImpl delegate2;
1016 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1017 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1018
1019 // Execute the scheduled draws so that mouse events are not
1020 // aggregated.
1021 RunAllPendingInMessageLoop();
1022
1023 EXPECT_FALSE(window->HasCapture());
1024
1025 // Do a capture.
1026 delegate.ResetCounts();
1027 window->SetCapture();
1028 EXPECT_TRUE(window->HasCapture());
1029 EXPECT_EQ(0, delegate.capture_lost_count());
1030 EXPECT_EQ(0, delegate.capture_changed_event_count());
1031 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
1032 generator.PressLeftButton();
1033 EXPECT_EQ(0, delegate.capture_lost_count());
1034 EXPECT_EQ(0, delegate.capture_changed_event_count());
1035 EXPECT_EQ(1, delegate.mouse_event_count());
1036
1037 // Set capture to |w2|, should implicitly unset capture for |window|.
1038 delegate.ResetCounts();
1039 delegate2.ResetCounts();
1040 w2->SetCapture();
1041
1042 generator.MoveMouseTo(gfx::Point(40, 40), 2);
1043 EXPECT_EQ(1, delegate.capture_lost_count());
1044 EXPECT_EQ(1, delegate.capture_changed_event_count());
1045 EXPECT_EQ(1, delegate.mouse_event_count());
1046 EXPECT_EQ(2, delegate2.mouse_event_count());
1047 }
1048
1049 // Verifies capture is reset when a window is destroyed.
TEST_F(WindowTest,ReleaseCaptureOnDestroy)1050 TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
1051 CaptureWindowDelegateImpl delegate;
1052 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1053 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1054 EXPECT_FALSE(window->HasCapture());
1055
1056 // Do a capture.
1057 window->SetCapture();
1058 EXPECT_TRUE(window->HasCapture());
1059
1060 // Destroy the window.
1061 window.reset();
1062
1063 // Make sure the root window doesn't reference the window anymore.
1064 EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler());
1065 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
1066 }
1067
TEST_F(WindowTest,GetBoundsInRootWindow)1068 TEST_F(WindowTest, GetBoundsInRootWindow) {
1069 scoped_ptr<Window> viewport(CreateTestWindowWithBounds(
1070 gfx::Rect(0, 0, 300, 300), root_window()));
1071 scoped_ptr<Window> child(CreateTestWindowWithBounds(
1072 gfx::Rect(0, 0, 100, 100), viewport.get()));
1073 // Sanity check.
1074 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1075
1076 // The |child| window's screen bounds should move along with the |viewport|.
1077 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1078 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1079
1080 // The |child| window is moved to the 0,0 in screen coordinates.
1081 // |GetBoundsInRootWindow()| should return 0,0.
1082 child->SetBounds(gfx::Rect(100, 100, 100, 100));
1083 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1084 }
1085
1086 class MouseEnterExitWindowDelegate : public TestWindowDelegate {
1087 public:
MouseEnterExitWindowDelegate()1088 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1089
OnMouseEvent(ui::MouseEvent * event)1090 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1091 switch (event->type()) {
1092 case ui::ET_MOUSE_ENTERED:
1093 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1094 entered_ = true;
1095 break;
1096 case ui::ET_MOUSE_EXITED:
1097 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1098 exited_ = true;
1099 break;
1100 default:
1101 break;
1102 }
1103 }
1104
entered() const1105 bool entered() const { return entered_; }
exited() const1106 bool exited() const { return exited_; }
1107
1108 // Clear the entered / exited states.
ResetExpectations()1109 void ResetExpectations() {
1110 entered_ = false;
1111 exited_ = false;
1112 }
1113
1114 private:
1115 bool entered_;
1116 bool exited_;
1117
1118 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate);
1119 };
1120
1121
1122 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1123 // mouse transitions from window to window.
TEST_F(WindowTest,MouseEnterExit)1124 TEST_F(WindowTest, MouseEnterExit) {
1125 MouseEnterExitWindowDelegate d1;
1126 scoped_ptr<Window> w1(
1127 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1128 root_window()));
1129 MouseEnterExitWindowDelegate d2;
1130 scoped_ptr<Window> w2(
1131 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1132 root_window()));
1133
1134 ui::test::EventGenerator generator(root_window());
1135 generator.MoveMouseToCenterOf(w1.get());
1136 EXPECT_TRUE(d1.entered());
1137 EXPECT_FALSE(d1.exited());
1138 EXPECT_FALSE(d2.entered());
1139 EXPECT_FALSE(d2.exited());
1140
1141 generator.MoveMouseToCenterOf(w2.get());
1142 EXPECT_TRUE(d1.entered());
1143 EXPECT_TRUE(d1.exited());
1144 EXPECT_TRUE(d2.entered());
1145 EXPECT_FALSE(d2.exited());
1146 }
1147
1148 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
TEST_F(WindowTest,WindowTreeHostExit)1149 TEST_F(WindowTest, WindowTreeHostExit) {
1150 MouseEnterExitWindowDelegate d1;
1151 scoped_ptr<Window> w1(
1152 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1153 root_window()));
1154
1155 ui::test::EventGenerator generator(root_window());
1156 generator.MoveMouseToCenterOf(w1.get());
1157 EXPECT_TRUE(d1.entered());
1158 EXPECT_FALSE(d1.exited());
1159 d1.ResetExpectations();
1160
1161 ui::MouseEvent exit_event(
1162 ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0, 0);
1163 DispatchEventUsingWindowDispatcher(&exit_event);
1164 EXPECT_FALSE(d1.entered());
1165 EXPECT_TRUE(d1.exited());
1166 }
1167
1168 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1169 // mouse transitions from window to window, even if the entered window sets
1170 // and releases capture.
TEST_F(WindowTest,MouseEnterExitWithClick)1171 TEST_F(WindowTest, MouseEnterExitWithClick) {
1172 MouseEnterExitWindowDelegate d1;
1173 scoped_ptr<Window> w1(
1174 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1175 root_window()));
1176 MouseEnterExitWindowDelegate d2;
1177 scoped_ptr<Window> w2(
1178 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1179 root_window()));
1180
1181 ui::test::EventGenerator generator(root_window());
1182 generator.MoveMouseToCenterOf(w1.get());
1183 EXPECT_TRUE(d1.entered());
1184 EXPECT_FALSE(d1.exited());
1185 EXPECT_FALSE(d2.entered());
1186 EXPECT_FALSE(d2.exited());
1187
1188 // Emmulate what Views does on a click by grabbing and releasing capture.
1189 generator.PressLeftButton();
1190 w1->SetCapture();
1191 w1->ReleaseCapture();
1192 generator.ReleaseLeftButton();
1193
1194 generator.MoveMouseToCenterOf(w2.get());
1195 EXPECT_TRUE(d1.entered());
1196 EXPECT_TRUE(d1.exited());
1197 EXPECT_TRUE(d2.entered());
1198 EXPECT_FALSE(d2.exited());
1199 }
1200
TEST_F(WindowTest,MouseEnterExitWhenDeleteWithCapture)1201 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) {
1202 MouseEnterExitWindowDelegate delegate;
1203 scoped_ptr<Window> window(
1204 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50),
1205 root_window()));
1206
1207 ui::test::EventGenerator generator(root_window());
1208 generator.MoveMouseToCenterOf(window.get());
1209 EXPECT_TRUE(delegate.entered());
1210 EXPECT_FALSE(delegate.exited());
1211
1212 // Emmulate what Views does on a click by grabbing and releasing capture.
1213 generator.PressLeftButton();
1214 window->SetCapture();
1215
1216 delegate.ResetExpectations();
1217 generator.MoveMouseTo(0, 0);
1218 EXPECT_FALSE(delegate.entered());
1219 EXPECT_FALSE(delegate.exited());
1220
1221 delegate.ResetExpectations();
1222 window.reset();
1223 EXPECT_FALSE(delegate.entered());
1224 EXPECT_FALSE(delegate.exited());
1225 }
1226
1227 // Verifies that enter / exits are sent if windows appear and are deleted
1228 // under the current mouse position..
TEST_F(WindowTest,MouseEnterExitWithDelete)1229 TEST_F(WindowTest, MouseEnterExitWithDelete) {
1230 MouseEnterExitWindowDelegate d1;
1231 scoped_ptr<Window> w1(
1232 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1233 root_window()));
1234
1235 ui::test::EventGenerator generator(root_window());
1236 generator.MoveMouseToCenterOf(w1.get());
1237 EXPECT_TRUE(d1.entered());
1238 EXPECT_FALSE(d1.exited());
1239 d1.ResetExpectations();
1240
1241 MouseEnterExitWindowDelegate d2;
1242 {
1243 scoped_ptr<Window> w2(
1244 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1245 root_window()));
1246 // Enters / exits can be sent asynchronously.
1247 RunAllPendingInMessageLoop();
1248 EXPECT_FALSE(d1.entered());
1249 EXPECT_TRUE(d1.exited());
1250 EXPECT_TRUE(d2.entered());
1251 EXPECT_FALSE(d2.exited());
1252 d1.ResetExpectations();
1253 d2.ResetExpectations();
1254 }
1255 // Enters / exits can be sent asynchronously.
1256 RunAllPendingInMessageLoop();
1257 EXPECT_TRUE(d2.exited());
1258 EXPECT_TRUE(d1.entered());
1259 }
1260
1261 // Verifies that enter / exits are sent if windows appear and are hidden
1262 // under the current mouse position..
TEST_F(WindowTest,MouseEnterExitWithHide)1263 TEST_F(WindowTest, MouseEnterExitWithHide) {
1264 MouseEnterExitWindowDelegate d1;
1265 scoped_ptr<Window> w1(
1266 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1267 root_window()));
1268
1269 ui::test::EventGenerator generator(root_window());
1270 generator.MoveMouseToCenterOf(w1.get());
1271 EXPECT_TRUE(d1.entered());
1272 EXPECT_FALSE(d1.exited());
1273
1274 MouseEnterExitWindowDelegate d2;
1275 scoped_ptr<Window> w2(
1276 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1277 root_window()));
1278 // Enters / exits can be send asynchronously.
1279 RunAllPendingInMessageLoop();
1280 EXPECT_TRUE(d1.entered());
1281 EXPECT_TRUE(d1.exited());
1282 EXPECT_TRUE(d2.entered());
1283 EXPECT_FALSE(d2.exited());
1284
1285 d1.ResetExpectations();
1286 w2->Hide();
1287 // Enters / exits can be send asynchronously.
1288 RunAllPendingInMessageLoop();
1289 EXPECT_TRUE(d2.exited());
1290 EXPECT_TRUE(d1.entered());
1291 }
1292
TEST_F(WindowTest,MouseEnterExitWithParentHide)1293 TEST_F(WindowTest, MouseEnterExitWithParentHide) {
1294 MouseEnterExitWindowDelegate d1;
1295 scoped_ptr<Window> w1(
1296 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1297 root_window()));
1298 MouseEnterExitWindowDelegate d2;
1299 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1300 w1.get());
1301 ui::test::EventGenerator generator(root_window());
1302 generator.MoveMouseToCenterOf(w2);
1303 // Enters / exits can be send asynchronously.
1304 RunAllPendingInMessageLoop();
1305 EXPECT_TRUE(d2.entered());
1306 EXPECT_FALSE(d2.exited());
1307
1308 d2.ResetExpectations();
1309 w1->Hide();
1310 RunAllPendingInMessageLoop();
1311 EXPECT_FALSE(d2.entered());
1312 EXPECT_TRUE(d2.exited());
1313
1314 w1.reset();
1315 }
1316
TEST_F(WindowTest,MouseEnterExitWithParentDelete)1317 TEST_F(WindowTest, MouseEnterExitWithParentDelete) {
1318 MouseEnterExitWindowDelegate d1;
1319 scoped_ptr<Window> w1(
1320 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1321 root_window()));
1322 MouseEnterExitWindowDelegate d2;
1323 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1324 w1.get());
1325 ui::test::EventGenerator generator(root_window());
1326 generator.MoveMouseToCenterOf(w2);
1327
1328 // Enters / exits can be send asynchronously.
1329 RunAllPendingInMessageLoop();
1330 EXPECT_TRUE(d2.entered());
1331 EXPECT_FALSE(d2.exited());
1332
1333 d2.ResetExpectations();
1334 w1.reset();
1335 RunAllPendingInMessageLoop();
1336 EXPECT_FALSE(d2.entered());
1337 EXPECT_TRUE(d2.exited());
1338 }
1339
1340 // Creates a window with a delegate (w111) that can handle events at a lower
1341 // z-index than a window without a delegate (w12). w12 is sized to fill the
1342 // entire bounds of the container. This test verifies that
1343 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1344 // because it has no children that can handle the event and it has no delegate
1345 // allowing it to handle the event itself.
TEST_F(WindowTest,GetEventHandlerForPoint_NoDelegate)1346 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) {
1347 TestWindowDelegate d111;
1348 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1349 gfx::Rect(0, 0, 500, 500), root_window()));
1350 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11,
1351 gfx::Rect(0, 0, 500, 500), w1.get()));
1352 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1353 gfx::Rect(50, 50, 450, 450), w11.get()));
1354 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12,
1355 gfx::Rect(0, 0, 500, 500), w1.get()));
1356
1357 gfx::Point target_point = w111->bounds().CenterPoint();
1358 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point));
1359 }
1360
1361 class VisibilityWindowDelegate : public TestWindowDelegate {
1362 public:
VisibilityWindowDelegate()1363 VisibilityWindowDelegate()
1364 : shown_(0),
1365 hidden_(0) {
1366 }
1367
shown() const1368 int shown() const { return shown_; }
hidden() const1369 int hidden() const { return hidden_; }
Clear()1370 void Clear() {
1371 shown_ = 0;
1372 hidden_ = 0;
1373 }
1374
OnWindowTargetVisibilityChanged(bool visible)1375 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
1376 if (visible)
1377 shown_++;
1378 else
1379 hidden_++;
1380 }
1381
1382 private:
1383 int shown_;
1384 int hidden_;
1385
1386 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate);
1387 };
1388
1389 // Verifies show/hide propagate correctly to children and the layer.
TEST_F(WindowTest,Visibility)1390 TEST_F(WindowTest, Visibility) {
1391 VisibilityWindowDelegate d;
1392 VisibilityWindowDelegate d2;
1393 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(),
1394 root_window()));
1395 scoped_ptr<Window> w2(
1396 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get()));
1397 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get()));
1398
1399 // Create shows all the windows.
1400 EXPECT_TRUE(w1->IsVisible());
1401 EXPECT_TRUE(w2->IsVisible());
1402 EXPECT_TRUE(w3->IsVisible());
1403 EXPECT_EQ(1, d.shown());
1404
1405 d.Clear();
1406 w1->Hide();
1407 EXPECT_FALSE(w1->IsVisible());
1408 EXPECT_FALSE(w2->IsVisible());
1409 EXPECT_FALSE(w3->IsVisible());
1410 EXPECT_EQ(1, d.hidden());
1411 EXPECT_EQ(0, d.shown());
1412
1413 w2->Show();
1414 EXPECT_FALSE(w1->IsVisible());
1415 EXPECT_FALSE(w2->IsVisible());
1416 EXPECT_FALSE(w3->IsVisible());
1417
1418 w3->Hide();
1419 EXPECT_FALSE(w1->IsVisible());
1420 EXPECT_FALSE(w2->IsVisible());
1421 EXPECT_FALSE(w3->IsVisible());
1422
1423 d.Clear();
1424 w1->Show();
1425 EXPECT_TRUE(w1->IsVisible());
1426 EXPECT_TRUE(w2->IsVisible());
1427 EXPECT_FALSE(w3->IsVisible());
1428 EXPECT_EQ(0, d.hidden());
1429 EXPECT_EQ(1, d.shown());
1430
1431 w3->Show();
1432 EXPECT_TRUE(w1->IsVisible());
1433 EXPECT_TRUE(w2->IsVisible());
1434 EXPECT_TRUE(w3->IsVisible());
1435
1436 // Verify that if an ancestor isn't visible and we change the visibility of a
1437 // child window that OnChildWindowVisibilityChanged() is still invoked.
1438 w1->Hide();
1439 d2.Clear();
1440 w2->Hide();
1441 EXPECT_EQ(1, d2.hidden());
1442 EXPECT_EQ(0, d2.shown());
1443 d2.Clear();
1444 w2->Show();
1445 EXPECT_EQ(0, d2.hidden());
1446 EXPECT_EQ(1, d2.shown());
1447 }
1448
TEST_F(WindowTest,IgnoreEventsTest)1449 TEST_F(WindowTest, IgnoreEventsTest) {
1450 TestWindowDelegate d11;
1451 TestWindowDelegate d12;
1452 TestWindowDelegate d111;
1453 TestWindowDelegate d121;
1454 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1455 gfx::Rect(0, 0, 500, 500), root_window()));
1456 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11,
1457 gfx::Rect(0, 0, 500, 500), w1.get()));
1458 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1459 gfx::Rect(50, 50, 450, 450), w11.get()));
1460 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12,
1461 gfx::Rect(0, 0, 500, 500), w1.get()));
1462 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121,
1463 gfx::Rect(150, 150, 50, 50), w12.get()));
1464
1465 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1466 w12->set_ignore_events(true);
1467 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1468 w12->set_ignore_events(false);
1469
1470 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1471 w121->set_ignore_events(true);
1472 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1473 w12->set_ignore_events(true);
1474 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1475 w111->set_ignore_events(true);
1476 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1477 }
1478
1479 // Tests transformation on the root window.
TEST_F(WindowTest,Transform)1480 TEST_F(WindowTest, Transform) {
1481 gfx::Size size = host()->GetBounds().size();
1482 EXPECT_EQ(gfx::Rect(size),
1483 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1484 gfx::Point()).bounds());
1485
1486 // Rotate it clock-wise 90 degrees.
1487 gfx::Transform transform;
1488 transform.Translate(size.height(), 0);
1489 transform.Rotate(90.0);
1490 host()->SetRootTransform(transform);
1491
1492 // The size should be the transformed size.
1493 gfx::Size transformed_size(size.height(), size.width());
1494 EXPECT_EQ(transformed_size.ToString(),
1495 root_window()->bounds().size().ToString());
1496 EXPECT_EQ(
1497 gfx::Rect(transformed_size).ToString(),
1498 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1499 gfx::Point()).bounds().ToString());
1500
1501 // Host size shouldn't change.
1502 EXPECT_EQ(size.ToString(), host()->GetBounds().size().ToString());
1503 }
1504
TEST_F(WindowTest,TransformGesture)1505 TEST_F(WindowTest, TransformGesture) {
1506 gfx::Size size = host()->GetBounds().size();
1507
1508 scoped_ptr<GestureTrackPositionDelegate> delegate(
1509 new GestureTrackPositionDelegate);
1510 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234,
1511 gfx::Rect(0, 0, 20, 20), root_window()));
1512
1513 // Rotate the root-window clock-wise 90 degrees.
1514 gfx::Transform transform;
1515 transform.Translate(size.height(), 0.0);
1516 transform.Rotate(90.0);
1517 host()->SetRootTransform(transform);
1518
1519 ui::TouchEvent press(
1520 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
1521 DispatchEventUsingWindowDispatcher(&press);
1522 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
1523 }
1524
1525 namespace {
1526 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
1527 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
1528 }
1529
TEST_F(WindowTest,Property)1530 TEST_F(WindowTest, Property) {
1531 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1532
1533 static const char native_prop_key[] = "fnord";
1534
1535 // Non-existent properties should return the default values.
1536 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1537 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1538 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1539
1540 // A set property value should be returned again (even if it's the default
1541 // value).
1542 w->SetProperty(kIntKey, INT_MAX);
1543 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey));
1544 w->SetProperty(kIntKey, -2);
1545 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1546 w->SetProperty(kIntKey, INT_MIN);
1547 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey));
1548
1549 w->SetProperty(kStringKey, static_cast<const char*>(NULL));
1550 EXPECT_EQ(NULL, w->GetProperty(kStringKey));
1551 w->SetProperty(kStringKey, "squeamish");
1552 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1553 w->SetProperty(kStringKey, "ossifrage");
1554 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey));
1555
1556 w->SetNativeWindowProperty(native_prop_key, &*w);
1557 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key));
1558 w->SetNativeWindowProperty(native_prop_key, NULL);
1559 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1560
1561 // ClearProperty should restore the default value.
1562 w->ClearProperty(kIntKey);
1563 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1564 w->ClearProperty(kStringKey);
1565 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1566 }
1567
1568 namespace {
1569
1570 class TestProperty {
1571 public:
TestProperty()1572 TestProperty() {}
~TestProperty()1573 virtual ~TestProperty() {
1574 last_deleted_ = this;
1575 }
last_deleted()1576 static TestProperty* last_deleted() { return last_deleted_; }
1577
1578 private:
1579 static TestProperty* last_deleted_;
1580 DISALLOW_COPY_AND_ASSIGN(TestProperty);
1581 };
1582
1583 TestProperty* TestProperty::last_deleted_ = NULL;
1584
1585 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
1586
1587 } // namespace
1588
TEST_F(WindowTest,OwnedProperty)1589 TEST_F(WindowTest, OwnedProperty) {
1590 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1591 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1592 TestProperty* p1 = new TestProperty();
1593 w->SetProperty(kOwnedKey, p1);
1594 EXPECT_EQ(p1, w->GetProperty(kOwnedKey));
1595 EXPECT_EQ(NULL, TestProperty::last_deleted());
1596
1597 TestProperty* p2 = new TestProperty();
1598 w->SetProperty(kOwnedKey, p2);
1599 EXPECT_EQ(p2, w->GetProperty(kOwnedKey));
1600 EXPECT_EQ(p1, TestProperty::last_deleted());
1601
1602 w->ClearProperty(kOwnedKey);
1603 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1604 EXPECT_EQ(p2, TestProperty::last_deleted());
1605
1606 TestProperty* p3 = new TestProperty();
1607 w->SetProperty(kOwnedKey, p3);
1608 EXPECT_EQ(p3, w->GetProperty(kOwnedKey));
1609 EXPECT_EQ(p2, TestProperty::last_deleted());
1610 w.reset();
1611 EXPECT_EQ(p3, TestProperty::last_deleted());
1612 }
1613
TEST_F(WindowTest,SetBoundsInternalShouldCheckTargetBounds)1614 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
1615 // We cannot short-circuit animations in this test.
1616 ui::ScopedAnimationDurationScaleMode test_duration_mode(
1617 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1618
1619 scoped_ptr<Window> w1(
1620 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1621
1622 EXPECT_FALSE(!w1->layer());
1623 w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
1624 ui::LayerAnimator* animator = w1->layer()->GetAnimator();
1625
1626 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1627 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1628
1629 // Animate to a different position.
1630 {
1631 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1632 w1->SetBounds(gfx::Rect(100, 100, 100, 100));
1633 }
1634
1635 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1636 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString());
1637
1638 // Animate back to the first position. The animation hasn't started yet, so
1639 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1640 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1641 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1642 {
1643 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1644 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1645 }
1646
1647 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1648 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1649
1650 // Confirm that the target bounds are reached.
1651 base::TimeTicks start_time =
1652 w1->layer()->GetAnimator()->last_step_time();
1653
1654 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
1655
1656 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1657 }
1658
1659
1660 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
1661
1662 class WindowObserverTest : public WindowTest,
1663 public WindowObserver {
1664 public:
1665 struct VisibilityInfo {
1666 bool window_visible;
1667 bool visible_param;
1668 };
1669
WindowObserverTest()1670 WindowObserverTest()
1671 : added_count_(0),
1672 removed_count_(0),
1673 destroyed_count_(0),
1674 old_property_value_(-3) {
1675 }
1676
~WindowObserverTest()1677 virtual ~WindowObserverTest() {}
1678
GetVisibilityInfo() const1679 const VisibilityInfo* GetVisibilityInfo() const {
1680 return visibility_info_.get();
1681 }
1682
ResetVisibilityInfo()1683 void ResetVisibilityInfo() {
1684 visibility_info_.reset();
1685 }
1686
1687 // Returns a description of the WindowObserver methods that have been invoked.
WindowObserverCountStateAndClear()1688 std::string WindowObserverCountStateAndClear() {
1689 std::string result(
1690 base::StringPrintf("added=%d removed=%d",
1691 added_count_, removed_count_));
1692 added_count_ = removed_count_ = 0;
1693 return result;
1694 }
1695
DestroyedCountAndClear()1696 int DestroyedCountAndClear() {
1697 int result = destroyed_count_;
1698 destroyed_count_ = 0;
1699 return result;
1700 }
1701
1702 // Return a tuple of the arguments passed in OnPropertyChanged callback.
PropertyChangeInfoAndClear()1703 PropertyChangeInfo PropertyChangeInfoAndClear() {
1704 PropertyChangeInfo result(property_key_, old_property_value_);
1705 property_key_ = NULL;
1706 old_property_value_ = -3;
1707 return result;
1708 }
1709
TransformNotificationsAndClear()1710 std::string TransformNotificationsAndClear() {
1711 std::string result;
1712 for (std::vector<std::pair<int, int> >::iterator it =
1713 transform_notifications_.begin();
1714 it != transform_notifications_.end();
1715 ++it) {
1716 base::StringAppendF(&result, "(%d,%d)", it->first, it->second);
1717 }
1718 transform_notifications_.clear();
1719 return result;
1720 }
1721
1722 private:
OnWindowAdded(Window * new_window)1723 virtual void OnWindowAdded(Window* new_window) OVERRIDE {
1724 added_count_++;
1725 }
1726
OnWillRemoveWindow(Window * window)1727 virtual void OnWillRemoveWindow(Window* window) OVERRIDE {
1728 removed_count_++;
1729 }
1730
OnWindowVisibilityChanged(Window * window,bool visible)1731 virtual void OnWindowVisibilityChanged(Window* window,
1732 bool visible) OVERRIDE {
1733 visibility_info_.reset(new VisibilityInfo);
1734 visibility_info_->window_visible = window->IsVisible();
1735 visibility_info_->visible_param = visible;
1736 }
1737
OnWindowDestroyed(Window * window)1738 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
1739 EXPECT_FALSE(window->parent());
1740 destroyed_count_++;
1741 }
1742
OnWindowPropertyChanged(Window * window,const void * key,intptr_t old)1743 virtual void OnWindowPropertyChanged(Window* window,
1744 const void* key,
1745 intptr_t old) OVERRIDE {
1746 property_key_ = key;
1747 old_property_value_ = old;
1748 }
1749
OnAncestorWindowTransformed(Window * source,Window * window)1750 virtual void OnAncestorWindowTransformed(Window* source,
1751 Window* window) OVERRIDE {
1752 transform_notifications_.push_back(
1753 std::make_pair(source->id(), window->id()));
1754 }
1755
1756 int added_count_;
1757 int removed_count_;
1758 int destroyed_count_;
1759 scoped_ptr<VisibilityInfo> visibility_info_;
1760 const void* property_key_;
1761 intptr_t old_property_value_;
1762 std::vector<std::pair<int, int> > transform_notifications_;
1763
1764 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest);
1765 };
1766
1767 // Various assertions for WindowObserver.
TEST_F(WindowObserverTest,WindowObserver)1768 TEST_F(WindowObserverTest, WindowObserver) {
1769 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1770 w1->AddObserver(this);
1771
1772 // Create a new window as a child of w1, our observer should be notified.
1773 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1774 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1775
1776 // Delete w2, which should result in the remove notification.
1777 w2.reset();
1778 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1779
1780 // Create a window that isn't parented to w1, we shouldn't get any
1781 // notification.
1782 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window()));
1783 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1784
1785 // Similarly destroying w3 shouldn't notify us either.
1786 w3.reset();
1787 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1788 w1->RemoveObserver(this);
1789 }
1790
1791 // Test if OnWindowVisibilityChagned is invoked with expected
1792 // parameters.
TEST_F(WindowObserverTest,WindowVisibility)1793 TEST_F(WindowObserverTest, WindowVisibility) {
1794 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1795 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get()));
1796 w2->AddObserver(this);
1797
1798 // Hide should make the window invisible and the passed visible
1799 // parameter is false.
1800 w2->Hide();
1801 EXPECT_FALSE(!GetVisibilityInfo());
1802 EXPECT_FALSE(!GetVisibilityInfo());
1803 if (!GetVisibilityInfo())
1804 return;
1805 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1806 EXPECT_FALSE(GetVisibilityInfo()->visible_param);
1807
1808 // If parent isn't visible, showing window won't make the window visible, but
1809 // passed visible value must be true.
1810 w1->Hide();
1811 ResetVisibilityInfo();
1812 EXPECT_TRUE(!GetVisibilityInfo());
1813 w2->Show();
1814 EXPECT_FALSE(!GetVisibilityInfo());
1815 if (!GetVisibilityInfo())
1816 return;
1817 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1818 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1819
1820 // If parent is visible, showing window will make the window
1821 // visible and the passed visible value is true.
1822 w1->Show();
1823 w2->Hide();
1824 ResetVisibilityInfo();
1825 w2->Show();
1826 EXPECT_FALSE(!GetVisibilityInfo());
1827 if (!GetVisibilityInfo())
1828 return;
1829 EXPECT_TRUE(GetVisibilityInfo()->window_visible);
1830 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1831 }
1832
1833 // Test if OnWindowDestroyed is invoked as expected.
TEST_F(WindowObserverTest,WindowDestroyed)1834 TEST_F(WindowObserverTest, WindowDestroyed) {
1835 // Delete a window should fire a destroyed notification.
1836 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1837 w1->AddObserver(this);
1838 w1.reset();
1839 EXPECT_EQ(1, DestroyedCountAndClear());
1840
1841 // Observe on child and delete parent window should fire a notification.
1842 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window()));
1843 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent
1844 child->AddObserver(this);
1845 parent.reset();
1846 EXPECT_EQ(1, DestroyedCountAndClear());
1847 }
1848
TEST_F(WindowObserverTest,PropertyChanged)1849 TEST_F(WindowObserverTest, PropertyChanged) {
1850 // Setting property should fire a property change notification.
1851 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1852 w1->AddObserver(this);
1853
1854 static const WindowProperty<int> prop = {-2};
1855 static const char native_prop_key[] = "fnord";
1856
1857 w1->SetProperty(&prop, 1);
1858 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1859 w1->SetProperty(&prop, -2);
1860 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear());
1861 w1->SetProperty(&prop, 3);
1862 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1863 w1->ClearProperty(&prop);
1864 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear());
1865
1866 w1->SetNativeWindowProperty(native_prop_key, &*w1);
1867 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0),
1868 PropertyChangeInfoAndClear());
1869 w1->SetNativeWindowProperty(native_prop_key, NULL);
1870 EXPECT_EQ(PropertyChangeInfo(native_prop_key,
1871 reinterpret_cast<intptr_t>(&*w1)),
1872 PropertyChangeInfoAndClear());
1873
1874 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1875 EXPECT_EQ(PropertyChangeInfo(
1876 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear());
1877 }
1878
TEST_F(WindowObserverTest,AncestorTransformed)1879 TEST_F(WindowObserverTest, AncestorTransformed) {
1880 // Create following window hierarchy:
1881 // root_window
1882 // +-- w1
1883 // +-- w2
1884 // +-- w3
1885 // +-- w4
1886 // Then, apply a transform to |w1| and ensure all its descendants are
1887 // notified.
1888 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1889 w1->AddObserver(this);
1890 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1891 w2->AddObserver(this);
1892 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w1.get()));
1893 w3->AddObserver(this);
1894 scoped_ptr<Window> w4(CreateTestWindowWithId(4, w3.get()));
1895 w4->AddObserver(this);
1896
1897 EXPECT_EQ(std::string(), TransformNotificationsAndClear());
1898
1899 gfx::Transform transform;
1900 transform.Translate(10, 10);
1901 w1->SetTransform(transform);
1902
1903 EXPECT_EQ("(1,1)(1,2)(1,3)(1,4)", TransformNotificationsAndClear());
1904 }
1905
TEST_F(WindowTest,AcquireLayer)1906 TEST_F(WindowTest, AcquireLayer) {
1907 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1908 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1909 ui::Layer* parent = window1->parent()->layer();
1910 EXPECT_EQ(2U, parent->children().size());
1911
1912 WindowTestApi window1_test_api(window1.get());
1913 WindowTestApi window2_test_api(window2.get());
1914
1915 EXPECT_TRUE(window1_test_api.OwnsLayer());
1916 EXPECT_TRUE(window2_test_api.OwnsLayer());
1917
1918 // After acquisition, window1 should not own its layer, but it should still
1919 // be available to the window.
1920 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer());
1921 EXPECT_FALSE(window1_test_api.OwnsLayer());
1922 EXPECT_TRUE(window1_layer.get() == window1->layer());
1923
1924 // The acquired layer's owner should be set NULL and re-acquring
1925 // should return NULL.
1926 EXPECT_FALSE(window1_layer->owner());
1927 scoped_ptr<ui::Layer> window1_layer_reacquired(window1->AcquireLayer());
1928 EXPECT_FALSE(window1_layer_reacquired.get());
1929
1930 // Upon destruction, window1's layer should still be valid, and in the layer
1931 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
1932 window1.reset();
1933 window2.reset();
1934
1935 // This should be set by the window's destructor.
1936 EXPECT_TRUE(window1_layer->delegate() == NULL);
1937 EXPECT_EQ(1U, parent->children().size());
1938 }
1939
1940 // Make sure that properties which should persist from the old layer to the new
1941 // layer actually do.
TEST_F(WindowTest,RecreateLayer)1942 TEST_F(WindowTest, RecreateLayer) {
1943 // Set properties to non default values.
1944 Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
1945 w.set_id(1);
1946 w.Init(aura::WINDOW_LAYER_SOLID_COLOR);
1947 w.SetBounds(gfx::Rect(0, 0, 100, 100));
1948
1949 ui::Layer* layer = w.layer();
1950 layer->SetVisible(false);
1951 layer->SetMasksToBounds(true);
1952
1953 ui::Layer child_layer;
1954 layer->Add(&child_layer);
1955
1956 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
1957 layer = w.layer();
1958 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
1959 EXPECT_FALSE(layer->visible());
1960 EXPECT_EQ(1u, layer->children().size());
1961 EXPECT_TRUE(layer->GetMasksToBounds());
1962 EXPECT_EQ("0,0 100x100", w.bounds().ToString());
1963 EXPECT_EQ("0,0 100x100", layer->bounds().ToString());
1964 }
1965
1966 // Verify that RecreateLayer() stacks the old layer above the newly creatd
1967 // layer.
TEST_F(WindowTest,RecreateLayerZOrder)1968 TEST_F(WindowTest, RecreateLayerZOrder) {
1969 scoped_ptr<Window> w(
1970 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1971 root_window()));
1972 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer());
1973
1974 const std::vector<ui::Layer*>& child_layers =
1975 root_window()->layer()->children();
1976 ASSERT_EQ(2u, child_layers.size());
1977 EXPECT_EQ(w->layer(), child_layers[0]);
1978 EXPECT_EQ(old_layer.get(), child_layers[1]);
1979 }
1980
1981 // Ensure that acquiring a layer then recreating a layer does not crash
1982 // and that RecreateLayer returns null.
TEST_F(WindowTest,AcquireThenRecreateLayer)1983 TEST_F(WindowTest, AcquireThenRecreateLayer) {
1984 scoped_ptr<Window> w(
1985 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1986 root_window()));
1987 scoped_ptr<ui::Layer> acquired_layer(w->AcquireLayer());
1988 scoped_ptr<ui::Layer> doubly_acquired_layer(w->RecreateLayer());
1989 EXPECT_EQ(NULL, doubly_acquired_layer.get());
1990
1991 // Destroy window before layer gets destroyed.
1992 w.reset();
1993 }
1994
TEST_F(WindowTest,StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate)1995 TEST_F(WindowTest, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate) {
1996 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1997 window1->layer()->set_name("1");
1998 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1999 window2->layer()->set_name("2");
2000 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
2001 window3->layer()->set_name("3");
2002
2003 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(root_window()));
2004 EXPECT_EQ("1 2 3",
2005 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2006 window1->layer()->set_delegate(NULL);
2007 root_window()->StackChildAtBottom(window3.get());
2008
2009 // Window 3 should have moved to the bottom.
2010 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window()));
2011 EXPECT_EQ("3 1 2",
2012 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2013 }
2014
2015 class TestVisibilityClient : public client::VisibilityClient {
2016 public:
TestVisibilityClient(Window * root_window)2017 explicit TestVisibilityClient(Window* root_window)
2018 : ignore_visibility_changes_(false) {
2019 client::SetVisibilityClient(root_window, this);
2020 }
~TestVisibilityClient()2021 virtual ~TestVisibilityClient() {
2022 }
2023
set_ignore_visibility_changes(bool ignore_visibility_changes)2024 void set_ignore_visibility_changes(bool ignore_visibility_changes) {
2025 ignore_visibility_changes_ = ignore_visibility_changes;
2026 }
2027
2028 // Overridden from client::VisibilityClient:
UpdateLayerVisibility(aura::Window * window,bool visible)2029 virtual void UpdateLayerVisibility(aura::Window* window,
2030 bool visible) OVERRIDE {
2031 if (!ignore_visibility_changes_)
2032 window->layer()->SetVisible(visible);
2033 }
2034
2035 private:
2036 bool ignore_visibility_changes_;
2037 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient);
2038 };
2039
TEST_F(WindowTest,VisibilityClientIsVisible)2040 TEST_F(WindowTest, VisibilityClientIsVisible) {
2041 TestVisibilityClient client(root_window());
2042
2043 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2044 EXPECT_TRUE(window->IsVisible());
2045 EXPECT_TRUE(window->layer()->visible());
2046
2047 window->Hide();
2048 EXPECT_FALSE(window->IsVisible());
2049 EXPECT_FALSE(window->layer()->visible());
2050 window->Show();
2051
2052 client.set_ignore_visibility_changes(true);
2053 window->Hide();
2054 EXPECT_FALSE(window->IsVisible());
2055 EXPECT_TRUE(window->layer()->visible());
2056 }
2057
2058 // Tests mouse events on window change.
TEST_F(WindowTest,MouseEventsOnWindowChange)2059 TEST_F(WindowTest, MouseEventsOnWindowChange) {
2060 gfx::Size size = host()->GetBounds().size();
2061
2062 ui::test::EventGenerator generator(root_window());
2063 generator.MoveMouseTo(50, 50);
2064
2065 EventCountDelegate d1;
2066 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2067 gfx::Rect(0, 0, 100, 100), root_window()));
2068 RunAllPendingInMessageLoop();
2069 // The format of result is "Enter/Mouse/Leave".
2070 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2071
2072 // Adding new window.
2073 EventCountDelegate d11;
2074 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(
2075 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2076 RunAllPendingInMessageLoop();
2077 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2078 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2079
2080 // Move bounds.
2081 w11->SetBounds(gfx::Rect(0, 0, 10, 10));
2082 RunAllPendingInMessageLoop();
2083 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2084 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2085
2086 w11->SetBounds(gfx::Rect(0, 0, 60, 60));
2087 RunAllPendingInMessageLoop();
2088 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2089 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2090
2091 // Detach, then re-attach.
2092 w1->RemoveChild(w11.get());
2093 RunAllPendingInMessageLoop();
2094 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2095 // Window is detached, so no event is set.
2096 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2097
2098 w1->AddChild(w11.get());
2099 RunAllPendingInMessageLoop();
2100 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2101 // Window is detached, so no event is set.
2102 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2103
2104 // Visibility Change
2105 w11->Hide();
2106 RunAllPendingInMessageLoop();
2107 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2108 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2109
2110 w11->Show();
2111 RunAllPendingInMessageLoop();
2112 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2113 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2114
2115 // Transform: move d11 by 100 100.
2116 gfx::Transform transform;
2117 transform.Translate(100, 100);
2118 w11->SetTransform(transform);
2119 RunAllPendingInMessageLoop();
2120 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2121 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2122
2123 w11->SetTransform(gfx::Transform());
2124 RunAllPendingInMessageLoop();
2125 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2126 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2127
2128 // Closing a window.
2129 w11.reset();
2130 RunAllPendingInMessageLoop();
2131 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2132
2133 // Make sure we don't synthesize events if the mouse
2134 // is outside of the root window.
2135 generator.MoveMouseTo(-10, -10);
2136 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2137
2138 // Adding new windows.
2139 w11.reset(CreateTestWindowWithDelegate(
2140 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2141 RunAllPendingInMessageLoop();
2142 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2143 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2144
2145 // Closing windows
2146 w11.reset();
2147 RunAllPendingInMessageLoop();
2148 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2149 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2150 }
2151
2152 class RootWindowAttachmentObserver : public WindowObserver {
2153 public:
RootWindowAttachmentObserver()2154 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
~RootWindowAttachmentObserver()2155 virtual ~RootWindowAttachmentObserver() {}
2156
added_count() const2157 int added_count() const { return added_count_; }
removed_count() const2158 int removed_count() const { return removed_count_; }
2159
Clear()2160 void Clear() {
2161 added_count_ = 0;
2162 removed_count_ = 0;
2163 }
2164
2165 // Overridden from WindowObserver:
OnWindowAddedToRootWindow(Window * window)2166 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2167 ++added_count_;
2168 }
OnWindowRemovingFromRootWindow(Window * window,Window * new_root)2169 virtual void OnWindowRemovingFromRootWindow(Window* window,
2170 Window* new_root) OVERRIDE {
2171 ++removed_count_;
2172 }
2173
2174 private:
2175 int added_count_;
2176 int removed_count_;
2177
2178 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver);
2179 };
2180
TEST_F(WindowTest,RootWindowAttachment)2181 TEST_F(WindowTest, RootWindowAttachment) {
2182 RootWindowAttachmentObserver observer;
2183
2184 // Test a direct add/remove from the RootWindow.
2185 scoped_ptr<Window> w1(new Window(NULL));
2186 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2187 w1->AddObserver(&observer);
2188
2189 ParentWindow(w1.get());
2190 EXPECT_EQ(1, observer.added_count());
2191 EXPECT_EQ(0, observer.removed_count());
2192
2193 w1.reset();
2194 EXPECT_EQ(1, observer.added_count());
2195 EXPECT_EQ(1, observer.removed_count());
2196
2197 observer.Clear();
2198
2199 // Test an indirect add/remove from the RootWindow.
2200 w1.reset(new Window(NULL));
2201 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2202 Window* w11 = new Window(NULL);
2203 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2204 w11->AddObserver(&observer);
2205 w1->AddChild(w11);
2206 EXPECT_EQ(0, observer.added_count());
2207 EXPECT_EQ(0, observer.removed_count());
2208
2209 ParentWindow(w1.get());
2210 EXPECT_EQ(1, observer.added_count());
2211 EXPECT_EQ(0, observer.removed_count());
2212
2213 w1.reset(); // Deletes w11.
2214 w11 = NULL;
2215 EXPECT_EQ(1, observer.added_count());
2216 EXPECT_EQ(1, observer.removed_count());
2217
2218 observer.Clear();
2219
2220 // Test an indirect add/remove with nested observers.
2221 w1.reset(new Window(NULL));
2222 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2223 w11 = new Window(NULL);
2224 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2225 w11->AddObserver(&observer);
2226 w1->AddChild(w11);
2227 Window* w111 = new Window(NULL);
2228 w111->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2229 w111->AddObserver(&observer);
2230 w11->AddChild(w111);
2231
2232 EXPECT_EQ(0, observer.added_count());
2233 EXPECT_EQ(0, observer.removed_count());
2234
2235 ParentWindow(w1.get());
2236 EXPECT_EQ(2, observer.added_count());
2237 EXPECT_EQ(0, observer.removed_count());
2238
2239 w1.reset(); // Deletes w11 and w111.
2240 w11 = NULL;
2241 w111 = NULL;
2242 EXPECT_EQ(2, observer.added_count());
2243 EXPECT_EQ(2, observer.removed_count());
2244 }
2245
2246 class BoundsChangedWindowObserver : public WindowObserver {
2247 public:
BoundsChangedWindowObserver()2248 BoundsChangedWindowObserver() : root_set_(false) {}
2249
OnWindowBoundsChanged(Window * window,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)2250 virtual void OnWindowBoundsChanged(Window* window,
2251 const gfx::Rect& old_bounds,
2252 const gfx::Rect& new_bounds) OVERRIDE {
2253 root_set_ = window->GetRootWindow() != NULL;
2254 }
2255
root_set() const2256 bool root_set() const { return root_set_; }
2257
2258 private:
2259 bool root_set_;
2260
2261 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver);
2262 };
2263
TEST_F(WindowTest,RootWindowSetWhenReparenting)2264 TEST_F(WindowTest, RootWindowSetWhenReparenting) {
2265 Window parent1(NULL);
2266 parent1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2267 Window parent2(NULL);
2268 parent2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2269 ParentWindow(&parent1);
2270 ParentWindow(&parent2);
2271 parent1.SetBounds(gfx::Rect(10, 10, 300, 300));
2272 parent2.SetBounds(gfx::Rect(20, 20, 300, 300));
2273
2274 BoundsChangedWindowObserver observer;
2275 Window child(NULL);
2276 child.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2277 child.SetBounds(gfx::Rect(5, 5, 100, 100));
2278 parent1.AddChild(&child);
2279
2280 // We need animations to start in order to observe the bounds changes.
2281 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2282 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2283 ui::ScopedLayerAnimationSettings settings1(child.layer()->GetAnimator());
2284 settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
2285 gfx::Rect new_bounds(gfx::Rect(35, 35, 50, 50));
2286 child.SetBounds(new_bounds);
2287
2288 child.AddObserver(&observer);
2289
2290 // Reparenting the |child| will cause it to get moved. During this move
2291 // the window should still have root window set.
2292 parent2.AddChild(&child);
2293 EXPECT_TRUE(observer.root_set());
2294
2295 // Animations should stop and the bounds should be as set before the |child|
2296 // got reparented.
2297 EXPECT_EQ(new_bounds.ToString(), child.GetTargetBounds().ToString());
2298 EXPECT_EQ(new_bounds.ToString(), child.bounds().ToString());
2299 EXPECT_EQ("55,55 50x50", child.GetBoundsInRootWindow().ToString());
2300 }
2301
TEST_F(WindowTest,OwnedByParentFalse)2302 TEST_F(WindowTest, OwnedByParentFalse) {
2303 // By default, a window is owned by its parent. If this is set to false, the
2304 // window will not be destroyed when its parent is.
2305
2306 scoped_ptr<Window> w1(new Window(NULL));
2307 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2308 scoped_ptr<Window> w2(new Window(NULL));
2309 w2->set_owned_by_parent(false);
2310 w2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2311 w1->AddChild(w2.get());
2312
2313 w1.reset();
2314
2315 // We should be able to deref w2 still, but its parent should now be NULL.
2316 EXPECT_EQ(NULL, w2->parent());
2317 }
2318
2319 namespace {
2320
2321 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2322 // OnWindowDestroyed().
2323 class OwningWindowDelegate : public TestWindowDelegate {
2324 public:
OwningWindowDelegate()2325 OwningWindowDelegate() {}
2326
SetOwnedWindow(Window * window)2327 void SetOwnedWindow(Window* window) {
2328 owned_window_.reset(window);
2329 }
2330
OnWindowDestroyed(Window * window)2331 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
2332 owned_window_.reset(NULL);
2333 }
2334
2335 private:
2336 scoped_ptr<Window> owned_window_;
2337
2338 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate);
2339 };
2340
2341 } // namespace
2342
2343 // Creates a window with two child windows. When the first child window is
2344 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2345 // This synthesizes BrowserView and the status bubble. Both are children of the
2346 // same parent and destroying BrowserView triggers it destroying the status
2347 // bubble.
TEST_F(WindowTest,DeleteWindowFromOnWindowDestroyed)2348 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
2349 scoped_ptr<Window> parent(new Window(NULL));
2350 parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2351 OwningWindowDelegate delegate;
2352 Window* c1 = new Window(&delegate);
2353 c1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2354 parent->AddChild(c1);
2355 Window* c2 = new Window(NULL);
2356 c2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2357 parent->AddChild(c2);
2358 delegate.SetOwnedWindow(c2);
2359 parent.reset();
2360 }
2361
2362 namespace {
2363
2364 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2365 // invoked.
2366 class BoundsChangeDelegate : public TestWindowDelegate {
2367 public:
BoundsChangeDelegate()2368 BoundsChangeDelegate() : bounds_changed_(false) {}
2369
clear_bounds_changed()2370 void clear_bounds_changed() { bounds_changed_ = false; }
bounds_changed() const2371 bool bounds_changed() const {
2372 return bounds_changed_;
2373 }
2374
2375 // Window
OnBoundsChanged(const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)2376 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
2377 const gfx::Rect& new_bounds) OVERRIDE {
2378 bounds_changed_ = true;
2379 }
2380
2381 private:
2382 // Was OnBoundsChanged() invoked?
2383 bool bounds_changed_;
2384
2385 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate);
2386 };
2387
2388 } // namespace
2389
2390 // Verifies the delegate is notified when the actual bounds of the layer
2391 // change.
TEST_F(WindowTest,DelegateNotifiedAsBoundsChange)2392 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
2393 BoundsChangeDelegate delegate;
2394
2395 // We cannot short-circuit animations in this test.
2396 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2397 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2398
2399 scoped_ptr<Window> window(
2400 CreateTestWindowWithDelegate(&delegate, 1,
2401 gfx::Rect(0, 0, 100, 100), root_window()));
2402 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2403
2404 delegate.clear_bounds_changed();
2405
2406 // Animate to a different position.
2407 {
2408 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2409 window->SetBounds(gfx::Rect(100, 100, 100, 100));
2410 }
2411
2412 // Bounds shouldn't immediately have changed.
2413 EXPECT_EQ("0,0 100x100", window->bounds().ToString());
2414 EXPECT_FALSE(delegate.bounds_changed());
2415
2416 // Animate to the end, which should notify of the change.
2417 base::TimeTicks start_time =
2418 window->layer()->GetAnimator()->last_step_time();
2419 ui::LayerAnimator* animator = window->layer()->GetAnimator();
2420 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2421 EXPECT_TRUE(delegate.bounds_changed());
2422 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2423 }
2424
2425 // Verifies the delegate is notified when the actual bounds of the layer
2426 // change even when the window is not the layer's delegate
TEST_F(WindowTest,DelegateNotifiedAsBoundsChangeInHiddenLayer)2427 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
2428 BoundsChangeDelegate delegate;
2429
2430 // We cannot short-circuit animations in this test.
2431 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2432 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2433
2434 scoped_ptr<Window> window(
2435 CreateTestWindowWithDelegate(&delegate, 1,
2436 gfx::Rect(0, 0, 100, 100), root_window()));
2437 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2438
2439 delegate.clear_bounds_changed();
2440
2441 // Suppress paint on the window since it is hidden (should reset the layer's
2442 // delegate to NULL)
2443 window->SuppressPaint();
2444 EXPECT_EQ(NULL, window->layer()->delegate());
2445
2446 // Animate to a different position.
2447 {
2448 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2449 window->SetBounds(gfx::Rect(100, 100, 110, 100));
2450 }
2451
2452 // Layer delegate is NULL but we should still get bounds changed notification.
2453 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString());
2454 EXPECT_TRUE(delegate.bounds_changed());
2455
2456 delegate.clear_bounds_changed();
2457
2458 // Animate to the end: will *not* notify of the change since we are hidden.
2459 base::TimeTicks start_time =
2460 window->layer()->GetAnimator()->last_step_time();
2461 ui::LayerAnimator* animator = window->layer()->GetAnimator();
2462 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2463
2464 // No bounds changed notification at the end of animation since layer
2465 // delegate is NULL.
2466 EXPECT_FALSE(delegate.bounds_changed());
2467 EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString());
2468 }
2469
2470 namespace {
2471
2472 // Used by AddChildNotifications to track notification counts.
2473 class AddChildNotificationsObserver : public WindowObserver {
2474 public:
AddChildNotificationsObserver()2475 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2476
CountStringAndReset()2477 std::string CountStringAndReset() {
2478 std::string result = base::IntToString(added_count_) + " " +
2479 base::IntToString(removed_count_);
2480 added_count_ = removed_count_ = 0;
2481 return result;
2482 }
2483
2484 // WindowObserver overrides:
OnWindowAddedToRootWindow(Window * window)2485 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2486 added_count_++;
2487 }
OnWindowRemovingFromRootWindow(Window * window,Window * new_root)2488 virtual void OnWindowRemovingFromRootWindow(Window* window,
2489 Window* new_root) OVERRIDE {
2490 removed_count_++;
2491 }
2492
2493 private:
2494 int added_count_;
2495 int removed_count_;
2496
2497 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver);
2498 };
2499
2500 } // namespace
2501
2502 // Assertions around when root window notifications are sent.
TEST_F(WindowTest,AddChildNotifications)2503 TEST_F(WindowTest, AddChildNotifications) {
2504 AddChildNotificationsObserver observer;
2505 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2506 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window()));
2507 w2->AddObserver(&observer);
2508 w2->Focus();
2509 EXPECT_TRUE(w2->HasFocus());
2510
2511 // Move |w2| to be a child of |w1|.
2512 w1->AddChild(w2.get());
2513 // Sine we moved in the same root, observer shouldn't be notified.
2514 EXPECT_EQ("0 0", observer.CountStringAndReset());
2515 // |w2| should still have focus after moving.
2516 EXPECT_TRUE(w2->HasFocus());
2517 }
2518
2519 // Tests that a delegate that destroys itself when the window is destroyed does
2520 // not break.
TEST_F(WindowTest,DelegateDestroysSelfOnWindowDestroy)2521 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) {
2522 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
2523 new DestroyWindowDelegate(),
2524 0,
2525 gfx::Rect(10, 20, 30, 40),
2526 root_window()));
2527 }
2528
2529 class HierarchyObserver : public WindowObserver {
2530 public:
HierarchyObserver(Window * target)2531 HierarchyObserver(Window* target) : target_(target) {
2532 target_->AddObserver(this);
2533 }
~HierarchyObserver()2534 virtual ~HierarchyObserver() {
2535 target_->RemoveObserver(this);
2536 }
2537
ValidateState(int index,const WindowObserver::HierarchyChangeParams & params) const2538 void ValidateState(
2539 int index,
2540 const WindowObserver::HierarchyChangeParams& params) const {
2541 ParamsMatch(params_[index], params);
2542 }
2543
Reset()2544 void Reset() {
2545 params_.clear();
2546 }
2547
2548 private:
2549 // Overridden from WindowObserver:
OnWindowHierarchyChanging(const HierarchyChangeParams & params)2550 virtual void OnWindowHierarchyChanging(
2551 const HierarchyChangeParams& params) OVERRIDE {
2552 params_.push_back(params);
2553 }
OnWindowHierarchyChanged(const HierarchyChangeParams & params)2554 virtual void OnWindowHierarchyChanged(
2555 const HierarchyChangeParams& params) OVERRIDE {
2556 params_.push_back(params);
2557 }
2558
ParamsMatch(const WindowObserver::HierarchyChangeParams & p1,const WindowObserver::HierarchyChangeParams & p2) const2559 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1,
2560 const WindowObserver::HierarchyChangeParams& p2) const {
2561 EXPECT_EQ(p1.phase, p2.phase);
2562 EXPECT_EQ(p1.target, p2.target);
2563 EXPECT_EQ(p1.new_parent, p2.new_parent);
2564 EXPECT_EQ(p1.old_parent, p2.old_parent);
2565 EXPECT_EQ(p1.receiver, p2.receiver);
2566 }
2567
2568 Window* target_;
2569 std::vector<WindowObserver::HierarchyChangeParams> params_;
2570
2571 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver);
2572 };
2573
2574 // Tests hierarchy change notifications.
TEST_F(WindowTest,OnWindowHierarchyChange)2575 TEST_F(WindowTest, OnWindowHierarchyChange) {
2576 {
2577 // Simple add & remove.
2578 HierarchyObserver oroot(root_window());
2579
2580 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2581 HierarchyObserver o1(w1.get());
2582
2583 // Add.
2584 root_window()->AddChild(w1.get());
2585
2586 WindowObserver::HierarchyChangeParams params;
2587 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2588 params.target = w1.get();
2589 params.old_parent = NULL;
2590 params.new_parent = root_window();
2591 params.receiver = w1.get();
2592 o1.ValidateState(0, params);
2593
2594 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2595 params.receiver = w1.get();
2596 o1.ValidateState(1, params);
2597
2598 params.receiver = root_window();
2599 oroot.ValidateState(0, params);
2600
2601 // Remove.
2602 o1.Reset();
2603 oroot.Reset();
2604
2605 root_window()->RemoveChild(w1.get());
2606
2607 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2608 params.old_parent = root_window();
2609 params.new_parent = NULL;
2610 params.receiver = w1.get();
2611
2612 o1.ValidateState(0, params);
2613
2614 params.receiver = root_window();
2615 oroot.ValidateState(0, params);
2616
2617 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2618 params.receiver = w1.get();
2619 o1.ValidateState(1, params);
2620 }
2621
2622 {
2623 // Add & remove of hierarchy. Tests notification order per documentation in
2624 // WindowObserver.
2625 HierarchyObserver o(root_window());
2626 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2627 Window* w11 = CreateTestWindowWithId(11, w1.get());
2628 w1->AddObserver(&o);
2629 w11->AddObserver(&o);
2630
2631 // Add.
2632 root_window()->AddChild(w1.get());
2633
2634 // Dispatched to target first.
2635 int index = 0;
2636 WindowObserver::HierarchyChangeParams params;
2637 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2638 params.target = w1.get();
2639 params.old_parent = NULL;
2640 params.new_parent = root_window();
2641 params.receiver = w1.get();
2642 o.ValidateState(index++, params);
2643
2644 // Dispatched to target's children.
2645 params.receiver = w11;
2646 o.ValidateState(index++, params);
2647
2648 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2649
2650 // Now process the "changed" phase.
2651 params.receiver = w1.get();
2652 o.ValidateState(index++, params);
2653 params.receiver = w11;
2654 o.ValidateState(index++, params);
2655 params.receiver = root_window();
2656 o.ValidateState(index++, params);
2657
2658 // Remove.
2659 root_window()->RemoveChild(w1.get());
2660 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2661 params.old_parent = root_window();
2662 params.new_parent = NULL;
2663 params.receiver = w1.get();
2664 o.ValidateState(index++, params);
2665 params.receiver = w11;
2666 o.ValidateState(index++, params);
2667 params.receiver = root_window();
2668 o.ValidateState(index++, params);
2669 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2670 params.receiver = w1.get();
2671 o.ValidateState(index++, params);
2672 params.receiver = w11;
2673 o.ValidateState(index++, params);
2674
2675 w1.reset();
2676 }
2677
2678 {
2679 // Reparent. Tests notification order per documentation in WindowObserver.
2680 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2681 Window* w11 = CreateTestWindowWithId(11, w1.get());
2682 Window* w111 = CreateTestWindowWithId(111, w11);
2683 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window()));
2684
2685 HierarchyObserver o(root_window());
2686 w1->AddObserver(&o);
2687 w11->AddObserver(&o);
2688 w111->AddObserver(&o);
2689 w2->AddObserver(&o);
2690
2691 w2->AddChild(w11);
2692
2693 // Dispatched to target first.
2694 int index = 0;
2695 WindowObserver::HierarchyChangeParams params;
2696 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2697 params.target = w11;
2698 params.old_parent = w1.get();
2699 params.new_parent = w2.get();
2700 params.receiver = w11;
2701 o.ValidateState(index++, params);
2702
2703 // Then to target's children.
2704 params.receiver = w111;
2705 o.ValidateState(index++, params);
2706
2707 // Then to target's old parent chain.
2708 params.receiver = w1.get();
2709 o.ValidateState(index++, params);
2710 params.receiver = root_window();
2711 o.ValidateState(index++, params);
2712
2713 // "Changed" phase.
2714 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2715 params.receiver = w11;
2716 o.ValidateState(index++, params);
2717 params.receiver = w111;
2718 o.ValidateState(index++, params);
2719 params.receiver = w2.get();
2720 o.ValidateState(index++, params);
2721 params.receiver = root_window();
2722 o.ValidateState(index++, params);
2723
2724 w1.reset();
2725 w2.reset();
2726 }
2727
2728 }
2729
2730 // Verifies SchedulePaint() on a layerless window results in damaging the right
2731 // thing.
TEST_F(WindowTest,LayerlessWindowSchedulePaint)2732 TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
2733 Window root(NULL);
2734 root.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2735 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2736
2737 Window* layerless_window = new Window(NULL); // Owned by |root|.
2738 layerless_window->Init(WINDOW_LAYER_NONE);
2739 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13));
2740 root.AddChild(layerless_window);
2741
2742 root.layer()->SendDamagedRects();
2743 layerless_window->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2744 // Note the the region is clipped by the parent hence 100 going to 11.
2745 EXPECT_EQ("11,13 11x4",
2746 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2747 ToString());
2748
2749 Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|.
2750 layerless_window2->Init(WINDOW_LAYER_NONE);
2751 layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4));
2752 layerless_window->AddChild(layerless_window2);
2753
2754 root.layer()->SendDamagedRects();
2755 layerless_window2->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2756 // Note the the region is clipped by the |layerless_window| hence 100 going to
2757 // 2.
2758 EXPECT_EQ("12,15 2x2",
2759 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2760 ToString());
2761 }
2762
2763 // Verifies bounds of layerless windows are correctly updated when adding
2764 // removing.
TEST_F(WindowTest,NestedLayerlessWindowsBoundsOnAddRemove)2765 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) {
2766 // Creates the following structure (all children owned by root):
2767 // root
2768 // w1ll 1,2
2769 // w11ll 3,4
2770 // w111 5,6
2771 // w12 7,8
2772 // w121 9,10
2773 //
2774 // ll: layer less, eg no layer
2775 Window root(NULL);
2776 root.Init(WINDOW_LAYER_NOT_DRAWN);
2777 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2778
2779 Window* w1ll = new Window(NULL);
2780 w1ll->Init(WINDOW_LAYER_NONE);
2781 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2782
2783 Window* w11ll = new Window(NULL);
2784 w11ll->Init(WINDOW_LAYER_NONE);
2785 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2786 w1ll->AddChild(w11ll);
2787
2788 Window* w111 = new Window(NULL);
2789 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2790 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2791 w11ll->AddChild(w111);
2792
2793 Window* w12 = new Window(NULL);
2794 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2795 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2796 w1ll->AddChild(w12);
2797
2798 Window* w121 = new Window(NULL);
2799 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2800 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2801 w12->AddChild(w121);
2802
2803 root.AddChild(w1ll);
2804
2805 // All layers should be parented to the root.
2806 EXPECT_EQ(root.layer(), w111->layer()->parent());
2807 EXPECT_EQ(root.layer(), w12->layer()->parent());
2808 EXPECT_EQ(w12->layer(), w121->layer()->parent());
2809
2810 // Ensure bounds are what we expect.
2811 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2812 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2813 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2814 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2815 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2816
2817 // Bounds of layers are relative to the nearest ancestor with a layer.
2818 EXPECT_EQ("8,10 100x100", w12->layer()->bounds().ToString());
2819 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2820 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2821
2822 // Remove and repeat.
2823 root.RemoveChild(w1ll);
2824
2825 EXPECT_TRUE(w111->layer()->parent() == NULL);
2826 EXPECT_TRUE(w12->layer()->parent() == NULL);
2827
2828 // Verify bounds haven't changed again.
2829 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2830 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2831 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2832 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2833 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2834
2835 // Bounds of layers should now match that of windows.
2836 EXPECT_EQ("7,8 100x100", w12->layer()->bounds().ToString());
2837 EXPECT_EQ("5,6 100x100", w111->layer()->bounds().ToString());
2838 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2839
2840 delete w1ll;
2841 }
2842
2843 // Verifies bounds of layerless windows are correctly updated when bounds
2844 // of ancestor changes.
TEST_F(WindowTest,NestedLayerlessWindowsBoundsOnSetBounds)2845 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) {
2846 // Creates the following structure (all children owned by root):
2847 // root
2848 // w1ll 1,2
2849 // w11ll 3,4
2850 // w111 5,6
2851 // w12 7,8
2852 // w121 9,10
2853 //
2854 // ll: layer less, eg no layer
2855 Window root(NULL);
2856 root.Init(WINDOW_LAYER_NOT_DRAWN);
2857 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2858
2859 Window* w1ll = new Window(NULL);
2860 w1ll->Init(WINDOW_LAYER_NONE);
2861 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2862
2863 Window* w11ll = new Window(NULL);
2864 w11ll->Init(WINDOW_LAYER_NONE);
2865 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2866 w1ll->AddChild(w11ll);
2867
2868 Window* w111 = new Window(NULL);
2869 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2870 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2871 w11ll->AddChild(w111);
2872
2873 Window* w12 = new Window(NULL);
2874 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2875 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2876 w1ll->AddChild(w12);
2877
2878 Window* w121 = new Window(NULL);
2879 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2880 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2881 w12->AddChild(w121);
2882
2883 root.AddChild(w1ll);
2884
2885 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2886 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2887 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2888 EXPECT_EQ("11,14 11x12", w111->layer()->bounds().ToString());
2889
2890 // Set back.
2891 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2892 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2893 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2894 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2895
2896 // Setting the bounds of a layerless window needs to adjust the bounds of
2897 // layered children.
2898 w11ll->SetBounds(gfx::Rect(5, 6, 100, 100));
2899 EXPECT_EQ("5,6 100x100", w11ll->bounds().ToString());
2900 EXPECT_EQ("5,6 100x100", w11ll->GetTargetBounds().ToString());
2901 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2902 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2903 EXPECT_EQ("11,14 100x100", w111->layer()->bounds().ToString());
2904
2905 root.RemoveChild(w1ll);
2906
2907 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2908 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2909 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2910 EXPECT_EQ("7,8 11x12", w111->layer()->bounds().ToString());
2911
2912 delete w1ll;
2913 }
2914
2915 namespace {
2916
2917 // Tracks the number of times paint is invoked along with what the clip and
2918 // translate was.
2919 class PaintWindowDelegate : public TestWindowDelegate {
2920 public:
PaintWindowDelegate()2921 PaintWindowDelegate() : paint_count_(0) {}
~PaintWindowDelegate()2922 virtual ~PaintWindowDelegate() {}
2923
most_recent_paint_clip_bounds() const2924 const gfx::Rect& most_recent_paint_clip_bounds() const {
2925 return most_recent_paint_clip_bounds_;
2926 }
2927
most_recent_paint_matrix_offset() const2928 const gfx::Vector2d& most_recent_paint_matrix_offset() const {
2929 return most_recent_paint_matrix_offset_;
2930 }
2931
clear_paint_count()2932 void clear_paint_count() { paint_count_ = 0; }
paint_count() const2933 int paint_count() const { return paint_count_; }
2934
2935 // TestWindowDelegate::
OnPaint(gfx::Canvas * canvas)2936 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
2937 paint_count_++;
2938 canvas->GetClipBounds(&most_recent_paint_clip_bounds_);
2939 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
2940 most_recent_paint_matrix_offset_ = gfx::Vector2d(
2941 SkScalarFloorToInt(matrix.getTranslateX()),
2942 SkScalarFloorToInt(matrix.getTranslateY()));
2943 }
2944
2945 private:
2946 int paint_count_;
2947 gfx::Rect most_recent_paint_clip_bounds_;
2948 gfx::Vector2d most_recent_paint_matrix_offset_;
2949
2950 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate);
2951 };
2952
2953 } // namespace
2954
2955 // Assertions around layerless children being painted when non-layerless window
2956 // is painted.
TEST_F(WindowTest,PaintLayerless)2957 TEST_F(WindowTest, PaintLayerless) {
2958 // Creates the following structure (all children owned by root):
2959 // root
2960 // w1ll 1,2 40x50
2961 // w11ll 3,4 11x12
2962 // w111 5,6
2963 //
2964 // ll: layer less, eg no layer
2965 PaintWindowDelegate w1ll_delegate;
2966 PaintWindowDelegate w11ll_delegate;
2967 PaintWindowDelegate w111_delegate;
2968
2969 Window root(NULL);
2970 root.Init(WINDOW_LAYER_NOT_DRAWN);
2971 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2972
2973 Window* w1ll = new Window(&w1ll_delegate);
2974 w1ll->Init(WINDOW_LAYER_NONE);
2975 w1ll->SetBounds(gfx::Rect(1, 2, 40, 50));
2976 w1ll->Show();
2977 root.AddChild(w1ll);
2978
2979 Window* w11ll = new Window(&w11ll_delegate);
2980 w11ll->Init(WINDOW_LAYER_NONE);
2981 w11ll->SetBounds(gfx::Rect(3, 4, 11, 12));
2982 w11ll->Show();
2983 w1ll->AddChild(w11ll);
2984
2985 Window* w111 = new Window(&w111_delegate);
2986 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2987 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2988 w111->Show();
2989 w11ll->AddChild(w111);
2990
2991 EXPECT_EQ(0, w1ll_delegate.paint_count());
2992 EXPECT_EQ(0, w11ll_delegate.paint_count());
2993 EXPECT_EQ(0, w111_delegate.paint_count());
2994
2995 // Paint the root, this should trigger painting of the two layerless
2996 // descendants but not the layered descendant.
2997 gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true);
2998 static_cast<ui::LayerDelegate&>(root).OnPaintLayer(&canvas);
2999
3000 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up
3001 // and 2 pixels down and to the right.
3002 EXPECT_EQ(1, w1ll_delegate.paint_count());
3003 EXPECT_EQ("-1,-1 42x52",
3004 w1ll_delegate.most_recent_paint_clip_bounds().ToString());
3005 EXPECT_EQ("[1 2]",
3006 w1ll_delegate.most_recent_paint_matrix_offset().ToString());
3007 EXPECT_EQ(1, w11ll_delegate.paint_count());
3008 EXPECT_EQ("-1,-1 13x14",
3009 w11ll_delegate.most_recent_paint_clip_bounds().ToString());
3010 EXPECT_EQ("[4 6]",
3011 w11ll_delegate.most_recent_paint_matrix_offset().ToString());
3012 EXPECT_EQ(0, w111_delegate.paint_count());
3013 }
3014
3015 namespace {
3016
ConvertPointToTargetString(const Window * source,const Window * target)3017 std::string ConvertPointToTargetString(const Window* source,
3018 const Window* target) {
3019 gfx::Point location;
3020 Window::ConvertPointToTarget(source, target, &location);
3021 return location.ToString();
3022 }
3023
3024 } // namespace
3025
3026 // Assertions around Window::ConvertPointToTarget() with layerless windows.
TEST_F(WindowTest,ConvertPointToTargetLayerless)3027 TEST_F(WindowTest, ConvertPointToTargetLayerless) {
3028 // Creates the following structure (all children owned by root):
3029 // root
3030 // w1ll 1,2
3031 // w11ll 3,4
3032 // w111 5,6
3033 // w12 7,8
3034 // w121 9,10
3035 //
3036 // ll: layer less, eg no layer
3037 Window root(NULL);
3038 root.Init(WINDOW_LAYER_NOT_DRAWN);
3039 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3040
3041 Window* w1ll = new Window(NULL);
3042 w1ll->Init(WINDOW_LAYER_NONE);
3043 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
3044
3045 Window* w11ll = new Window(NULL);
3046 w11ll->Init(WINDOW_LAYER_NONE);
3047 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
3048 w1ll->AddChild(w11ll);
3049
3050 Window* w111 = new Window(NULL);
3051 w111->Init(WINDOW_LAYER_NOT_DRAWN);
3052 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
3053 w11ll->AddChild(w111);
3054
3055 Window* w12 = new Window(NULL);
3056 w12->Init(WINDOW_LAYER_NOT_DRAWN);
3057 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
3058 w1ll->AddChild(w12);
3059
3060 Window* w121 = new Window(NULL);
3061 w121->Init(WINDOW_LAYER_NOT_DRAWN);
3062 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
3063 w12->AddChild(w121);
3064
3065 root.AddChild(w1ll);
3066
3067 // w111->w11ll
3068 EXPECT_EQ("5,6", ConvertPointToTargetString(w111, w11ll));
3069
3070 // w111->w1ll
3071 EXPECT_EQ("8,10", ConvertPointToTargetString(w111, w1ll));
3072
3073 // w111->root
3074 EXPECT_EQ("9,12", ConvertPointToTargetString(w111, &root));
3075
3076 // w111->w12
3077 EXPECT_EQ("1,2", ConvertPointToTargetString(w111, w12));
3078
3079 // w111->w121
3080 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111, w121));
3081
3082 // w11ll->w111
3083 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll, w111));
3084
3085 // w11ll->w11ll
3086 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll, w1ll));
3087
3088 // w11ll->root
3089 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll, &root));
3090
3091 // w11ll->w12
3092 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll, w12));
3093 }
3094
3095 #if !defined(NDEBUG)
3096 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
TEST_F(WindowTest,PrintWindowHierarchyNotCrashLayerless)3097 TEST_F(WindowTest, PrintWindowHierarchyNotCrashLayerless) {
3098 Window root(NULL);
3099 root.Init(WINDOW_LAYER_NONE);
3100 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3101 root.PrintWindowHierarchy(0);
3102 }
3103 #endif
3104
3105 namespace {
3106
3107 // See AddWindowsFromString() for details.
CreateWindowFromDescription(const std::string & description,WindowDelegate * delegate)3108 aura::Window* CreateWindowFromDescription(const std::string& description,
3109 WindowDelegate* delegate) {
3110 WindowLayerType window_type = WINDOW_LAYER_NOT_DRAWN;
3111 std::vector<std::string> tokens;
3112 Tokenize(description, ":", &tokens);
3113 DCHECK(!tokens.empty());
3114 std::string name(tokens[0]);
3115 tokens.erase(tokens.begin());
3116 if (!tokens.empty()) {
3117 if (tokens[0] == "ll") {
3118 window_type = WINDOW_LAYER_NONE;
3119 tokens.erase(tokens.begin());
3120 }
3121 DCHECK(tokens.empty()) << "unknown tokens for creating window "
3122 << description;
3123 }
3124 Window* window = new Window(delegate);
3125 window->Init(window_type);
3126 window->SetName(name);
3127 // Window name is only propagated to layer in debug builds.
3128 if (window->layer())
3129 window->layer()->set_name(name);
3130 return window;
3131 }
3132
3133 // Creates and adds a tree of windows to |parent|. |description| consists
3134 // of the following pieces:
3135 // X: Identifies a new window. Consists of a name and optionally ":ll" to
3136 // specify WINDOW_LAYER_NONE, eg "w1:ll".
3137 // []: optionally used to specify the children of the window. Contains any
3138 // number of window identifiers and their corresponding children.
3139 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree:
3140 // a
3141 // a1
3142 // a2 -> WINDOW_LAYER_NONE.
3143 // b
3144 // c
3145 // c1
3146 // NOTE: you must have a space after every token.
AddWindowsFromString(aura::Window * parent,const std::string & description,std::string::size_type start_pos,WindowDelegate * delegate)3147 std::string::size_type AddWindowsFromString(aura::Window* parent,
3148 const std::string& description,
3149 std::string::size_type start_pos,
3150 WindowDelegate* delegate) {
3151 DCHECK(parent);
3152 std::string::size_type end_pos = description.find(' ', start_pos);
3153 while (end_pos != std::string::npos) {
3154 const std::string::size_type part_length = end_pos - start_pos;
3155 const std::string window_description =
3156 description.substr(start_pos, part_length);
3157 if (window_description == "[") {
3158 start_pos = AddWindowsFromString(parent->children().back(),
3159 description,
3160 end_pos + 1,
3161 delegate);
3162 end_pos = description.find(' ', start_pos);
3163 if (end_pos == std::string::npos && start_pos != end_pos)
3164 end_pos = description.length();
3165 } else if (window_description == "]") {
3166 ++end_pos;
3167 break;
3168 } else {
3169 Window* window =
3170 CreateWindowFromDescription(window_description, delegate);
3171 parent->AddChild(window);
3172 start_pos = ++end_pos;
3173 end_pos = description.find(' ', start_pos);
3174 }
3175 }
3176 return end_pos;
3177 }
3178
3179 // Used by BuildRootWindowTreeDescription().
BuildWindowTreeDescription(const aura::Window & window)3180 std::string BuildWindowTreeDescription(const aura::Window& window) {
3181 std::string result;
3182 result += window.name();
3183 if (window.children().empty())
3184 return result;
3185
3186 result += " [ ";
3187 for (size_t i = 0; i < window.children().size(); ++i) {
3188 if (i != 0)
3189 result += " ";
3190 result += BuildWindowTreeDescription(*(window.children()[i]));
3191 }
3192 result += " ]";
3193 return result;
3194 }
3195
3196 // Creates a string from |window|. See AddWindowsFromString() for details of the
3197 // returned string. This does *not* include the layer type in the description,
3198 // on the name.
BuildRootWindowTreeDescription(const aura::Window & window)3199 std::string BuildRootWindowTreeDescription(const aura::Window& window) {
3200 std::string result;
3201 for (size_t i = 0; i < window.children().size(); ++i) {
3202 if (i != 0)
3203 result += " ";
3204 result += BuildWindowTreeDescription(*(window.children()[i]));
3205 }
3206 return result;
3207 }
3208
3209 // Used by BuildRootWindowTreeDescription().
BuildLayerTreeDescription(const ui::Layer & layer)3210 std::string BuildLayerTreeDescription(const ui::Layer& layer) {
3211 std::string result;
3212 result += layer.name();
3213 if (layer.children().empty())
3214 return result;
3215
3216 result += " [ ";
3217 for (size_t i = 0; i < layer.children().size(); ++i) {
3218 if (i != 0)
3219 result += " ";
3220 result += BuildLayerTreeDescription(*(layer.children()[i]));
3221 }
3222 result += " ]";
3223 return result;
3224 }
3225
3226 // Builds a string for all the children of |layer|. The returned string is in
3227 // the same format as AddWindowsFromString() but only includes the name of the
3228 // layers.
BuildRootLayerTreeDescription(const ui::Layer & layer)3229 std::string BuildRootLayerTreeDescription(const ui::Layer& layer) {
3230 std::string result;
3231 for (size_t i = 0; i < layer.children().size(); ++i) {
3232 if (i != 0)
3233 result += " ";
3234 result += BuildLayerTreeDescription(*(layer.children()[i]));
3235 }
3236 return result;
3237 }
3238
3239 // Returns the first window whose name matches |name| in |parent|.
FindWindowByName(aura::Window * parent,const std::string & name)3240 aura::Window* FindWindowByName(aura::Window* parent,
3241 const std::string& name) {
3242 if (parent->name() == name)
3243 return parent;
3244 for (size_t i = 0; i < parent->children().size(); ++i) {
3245 aura::Window* child = FindWindowByName(parent->children()[i], name);
3246 if (child)
3247 return child;
3248 }
3249 return NULL;
3250 }
3251
3252 } // namespace
3253
3254 // Direction to stack.
3255 enum StackType {
3256 STACK_ABOVE,
3257 STACK_BELOW,
3258 STACK_AT_BOTTOM,
3259 STACK_AT_TOP,
3260 };
3261
3262 // Permutations of StackChildAt with various data.
TEST_F(WindowTest,StackChildAtLayerless)3263 TEST_F(WindowTest, StackChildAtLayerless) {
3264 struct TestData {
3265 // Describes the window tree to create. See AddWindowsFromString() for
3266 // details.
3267 const std::string initial_description;
3268
3269 // Identifies the window to move.
3270 const std::string source_window;
3271
3272 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM
3273 // or STACK_AT_TOP.
3274 const std::string target_window;
3275
3276 StackType stack_type;
3277
3278 // Expected window and layer results.
3279 const std::string expected_description;
3280 const std::string expected_layer_description;
3281 } data[] = {
3282 // 1 at top.
3283 {
3284 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3285 "1",
3286 "",
3287 STACK_AT_TOP,
3288 "2 [ 21 ] 1 [ 11 12 ]",
3289 "21 11 12",
3290 },
3291
3292 // 1 at bottom.
3293 {
3294 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3295 "1",
3296 "",
3297 STACK_AT_BOTTOM,
3298 "1 [ 11 12 ] 2 [ 21 ]",
3299 "11 12 21",
3300 },
3301
3302 // 2 at bottom.
3303 {
3304 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3305 "2",
3306 "",
3307 STACK_AT_BOTTOM,
3308 "2 [ 21 ] 1 [ 11 12 ]",
3309 "21 11 12",
3310 },
3311
3312 // 3 below 2.
3313 {
3314 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3315 "3",
3316 "2",
3317 STACK_BELOW,
3318 "1 [ 11 12 ] 3 2 [ 21 ]",
3319 "11 12 21",
3320 },
3321
3322 // 2 below 1.
3323 {
3324 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3325 "2",
3326 "1",
3327 STACK_BELOW,
3328 "2 [ 21 ] 1 [ 11 12 ]",
3329 "21 11 12",
3330 },
3331
3332 // 1 above 3.
3333 {
3334 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3335 "1",
3336 "3",
3337 STACK_ABOVE,
3338 "2 [ 21 ] 3 1 [ 11 12 ]",
3339 "21 11 12",
3340 },
3341
3342 // 1 above 2.
3343 {
3344 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3345 "1",
3346 "2",
3347 STACK_ABOVE,
3348 "2 [ 21 ] 1 [ 11 12 ]",
3349 "21 11 12",
3350 },
3351 };
3352 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
3353 test::TestWindowDelegate delegate;
3354 Window root(NULL);
3355 root.Init(WINDOW_LAYER_NOT_DRAWN);
3356 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3357 AddWindowsFromString(
3358 &root,
3359 data[i].initial_description,
3360 static_cast<std::string::size_type>(0), &delegate);
3361 aura::Window* source = FindWindowByName(&root, data[i].source_window);
3362 ASSERT_TRUE(source != NULL) << "unable to find source window "
3363 << data[i].source_window << " at " << i;
3364 aura::Window* target = FindWindowByName(&root, data[i].target_window);
3365 switch (data[i].stack_type) {
3366 case STACK_ABOVE:
3367 ASSERT_TRUE(target != NULL) << "unable to find target window "
3368 << data[i].target_window << " at " << i;
3369 source->parent()->StackChildAbove(source, target);
3370 break;
3371 case STACK_BELOW:
3372 ASSERT_TRUE(target != NULL) << "unable to find target window "
3373 << data[i].target_window << " at " << i;
3374 source->parent()->StackChildBelow(source, target);
3375 break;
3376 case STACK_AT_BOTTOM:
3377 source->parent()->StackChildAtBottom(source);
3378 break;
3379 case STACK_AT_TOP:
3380 source->parent()->StackChildAtTop(source);
3381 break;
3382 }
3383 EXPECT_EQ(data[i].expected_layer_description,
3384 BuildRootLayerTreeDescription(*root.layer()))
3385 << "layer tree doesn't match at " << i;
3386 EXPECT_EQ(data[i].expected_description,
3387 BuildRootWindowTreeDescription(root))
3388 << "window tree doesn't match at " << i;
3389 }
3390 }
3391
3392 namespace {
3393
3394 class TestLayerAnimationObserver : public ui::LayerAnimationObserver {
3395 public:
TestLayerAnimationObserver()3396 TestLayerAnimationObserver()
3397 : animation_completed_(false),
3398 animation_aborted_(false) {}
~TestLayerAnimationObserver()3399 virtual ~TestLayerAnimationObserver() {}
3400
animation_completed() const3401 bool animation_completed() const { return animation_completed_; }
animation_aborted() const3402 bool animation_aborted() const { return animation_aborted_; }
3403
Reset()3404 void Reset() {
3405 animation_completed_ = false;
3406 animation_aborted_ = false;
3407 }
3408
3409 private:
3410 // ui::LayerAnimationObserver:
OnLayerAnimationEnded(ui::LayerAnimationSequence * sequence)3411 virtual void OnLayerAnimationEnded(
3412 ui::LayerAnimationSequence* sequence) OVERRIDE {
3413 animation_completed_ = true;
3414 }
3415
OnLayerAnimationAborted(ui::LayerAnimationSequence * sequence)3416 virtual void OnLayerAnimationAborted(
3417 ui::LayerAnimationSequence* sequence) OVERRIDE {
3418 animation_aborted_ = true;
3419 }
3420
OnLayerAnimationScheduled(ui::LayerAnimationSequence * sequence)3421 virtual void OnLayerAnimationScheduled(
3422 ui::LayerAnimationSequence* sequence) OVERRIDE {
3423 }
3424
3425 bool animation_completed_;
3426 bool animation_aborted_;
3427
3428 DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver);
3429 };
3430
3431 }
3432
TEST_F(WindowTest,WindowDestroyCompletesAnimations)3433 TEST_F(WindowTest, WindowDestroyCompletesAnimations) {
3434 ui::ScopedAnimationDurationScaleMode test_duration_mode(
3435 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
3436 scoped_refptr<ui::LayerAnimator> animator =
3437 ui::LayerAnimator::CreateImplicitAnimator();
3438 TestLayerAnimationObserver observer;
3439 animator->AddObserver(&observer);
3440 // Make sure destroying a Window completes the animation.
3441 {
3442 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
3443 window->layer()->SetAnimator(animator.get());
3444
3445 gfx::Transform transform;
3446 transform.Scale(0.5f, 0.5f);
3447 window->SetTransform(transform);
3448
3449 EXPECT_TRUE(animator->is_animating());
3450 EXPECT_FALSE(observer.animation_completed());
3451 }
3452 EXPECT_TRUE(animator.get());
3453 EXPECT_FALSE(animator->is_animating());
3454 EXPECT_TRUE(observer.animation_completed());
3455 EXPECT_FALSE(observer.animation_aborted());
3456 animator->RemoveObserver(&observer);
3457 observer.Reset();
3458
3459 animator = ui::LayerAnimator::CreateImplicitAnimator();
3460 animator->AddObserver(&observer);
3461 ui::Layer layer;
3462 layer.SetAnimator(animator.get());
3463 {
3464 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
3465 window->layer()->Add(&layer);
3466
3467 gfx::Transform transform;
3468 transform.Scale(0.5f, 0.5f);
3469 layer.SetTransform(transform);
3470
3471 EXPECT_TRUE(animator->is_animating());
3472 EXPECT_FALSE(observer.animation_completed());
3473 }
3474
3475 EXPECT_TRUE(animator.get());
3476 EXPECT_FALSE(animator->is_animating());
3477 EXPECT_TRUE(observer.animation_completed());
3478 EXPECT_FALSE(observer.animation_aborted());
3479 animator->RemoveObserver(&observer);
3480 }
3481
3482 } // namespace test
3483 } // namespace aura
3484