OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/aura/window.h" | 5 #include "ui/aura/window.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
17 #include "ui/aura/client/capture_client.h" | 17 #include "ui/aura/client/capture_client.h" |
18 #include "ui/aura/client/focus_change_observer.h" | 18 #include "ui/aura/client/focus_change_observer.h" |
19 #include "ui/aura/client/visibility_client.h" | 19 #include "ui/aura/client/visibility_client.h" |
20 #include "ui/aura/client/window_tree_client.h" | 20 #include "ui/aura/client/window_tree_client.h" |
21 #include "ui/aura/layout_manager.h" | |
22 #include "ui/aura/root_window.h" | 21 #include "ui/aura/root_window.h" |
23 #include "ui/aura/root_window_observer.h" | 22 #include "ui/aura/root_window_observer.h" |
24 #include "ui/aura/test/aura_test_base.h" | 23 #include "ui/aura/test/aura_test_base.h" |
25 #include "ui/aura/test/event_generator.h" | 24 #include "ui/aura/test/event_generator.h" |
26 #include "ui/aura/test/test_window_delegate.h" | 25 #include "ui/aura/test/test_window_delegate.h" |
27 #include "ui/aura/test/test_windows.h" | 26 #include "ui/aura/test/test_windows.h" |
28 #include "ui/aura/test/window_test_api.h" | 27 #include "ui/aura/test/window_test_api.h" |
29 #include "ui/aura/window_delegate.h" | 28 #include "ui/aura/window_delegate.h" |
30 #include "ui/aura/window_observer.h" | 29 #include "ui/aura/window_observer.h" |
31 #include "ui/aura/window_property.h" | 30 #include "ui/aura/window_property.h" |
(...skipping 1544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1576 transform.Translate(size.height(), 0.0); | 1575 transform.Translate(size.height(), 0.0); |
1577 transform.Rotate(90.0); | 1576 transform.Rotate(90.0); |
1578 dispatcher()->host()->SetTransform(transform); | 1577 dispatcher()->host()->SetTransform(transform); |
1579 | 1578 |
1580 ui::TouchEvent press( | 1579 ui::TouchEvent press( |
1581 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime()); | 1580 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime()); |
1582 dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press); | 1581 dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press); |
1583 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString()); | 1582 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString()); |
1584 } | 1583 } |
1585 | 1584 |
1586 // Various assertions for transient children. | |
1587 TEST_F(WindowTest, TransientChildren) { | |
1588 scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window())); | |
1589 scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get())); | |
1590 scoped_ptr<Window> w3(CreateTestWindowWithId(3, parent.get())); | |
1591 Window* w2 = CreateTestWindowWithId(2, parent.get()); | |
1592 w1->AddTransientChild(w2); // w2 is now owned by w1. | |
1593 // Stack w1 at the top (end), this should force w2 to be last (on top of w1). | |
1594 parent->StackChildAtTop(w1.get()); | |
1595 ASSERT_EQ(3u, parent->children().size()); | |
1596 EXPECT_EQ(w2, parent->children().back()); | |
1597 | |
1598 // Destroy w1, which should also destroy w3 (since it's a transient child). | |
1599 w1.reset(); | |
1600 w2 = NULL; | |
1601 ASSERT_EQ(1u, parent->children().size()); | |
1602 EXPECT_EQ(w3.get(), parent->children()[0]); | |
1603 | |
1604 w1.reset(CreateTestWindowWithId(4, parent.get())); | |
1605 w2 = CreateTestWindowWithId(5, w3.get()); | |
1606 w1->AddTransientChild(w2); | |
1607 parent->StackChildAtTop(w3.get()); | |
1608 // Stack w1 at the top (end), this shouldn't affect w2 since it has a | |
1609 // different parent. | |
1610 parent->StackChildAtTop(w1.get()); | |
1611 ASSERT_EQ(2u, parent->children().size()); | |
1612 EXPECT_EQ(w3.get(), parent->children()[0]); | |
1613 EXPECT_EQ(w1.get(), parent->children()[1]); | |
1614 | |
1615 // Hiding parent should hide transient children. | |
1616 EXPECT_TRUE(w2->IsVisible()); | |
1617 w1->Hide(); | |
1618 EXPECT_FALSE(w2->IsVisible()); | |
1619 } | |
1620 | |
1621 namespace { | 1585 namespace { |
1622 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2); | 1586 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2); |
1623 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish"); | 1587 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish"); |
1624 } | 1588 } |
1625 | 1589 |
1626 TEST_F(WindowTest, Property) { | 1590 TEST_F(WindowTest, Property) { |
1627 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window())); | 1591 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window())); |
1628 | 1592 |
1629 static const char native_prop_key[] = "fnord"; | 1593 static const char native_prop_key[] = "fnord"; |
1630 | 1594 |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2049 ui::test::ChildLayerNamesAsString(*root_window()->layer())); | 2013 ui::test::ChildLayerNamesAsString(*root_window()->layer())); |
2050 window1->layer()->set_delegate(NULL); | 2014 window1->layer()->set_delegate(NULL); |
2051 root_window()->StackChildAtBottom(window3.get()); | 2015 root_window()->StackChildAtBottom(window3.get()); |
2052 | 2016 |
2053 // Window 3 should have moved to the bottom. | 2017 // Window 3 should have moved to the bottom. |
2054 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window())); | 2018 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window())); |
2055 EXPECT_EQ("3 1 2", | 2019 EXPECT_EQ("3 1 2", |
2056 ui::test::ChildLayerNamesAsString(*root_window()->layer())); | 2020 ui::test::ChildLayerNamesAsString(*root_window()->layer())); |
2057 } | 2021 } |
2058 | 2022 |
2059 TEST_F(WindowTest, StackWindowsWhoseLayersHaveNoDelegate) { | |
2060 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window())); | |
2061 window1->layer()->set_name("1"); | |
2062 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window())); | |
2063 window2->layer()->set_name("2"); | |
2064 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window())); | |
2065 window3->layer()->set_name("3"); | |
2066 | |
2067 // This brings |window1| (and its layer) to the front. | |
2068 root_window()->StackChildAbove(window1.get(), window3.get()); | |
2069 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window())); | |
2070 EXPECT_EQ("2 3 1", | |
2071 ui::test::ChildLayerNamesAsString(*root_window()->layer())); | |
2072 | |
2073 // Since |window1| does not have a delegate, |window2| should not move in | |
2074 // front of it, nor should its layer. | |
2075 window1->layer()->set_delegate(NULL); | |
2076 root_window()->StackChildAbove(window2.get(), window1.get()); | |
2077 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(root_window())); | |
2078 EXPECT_EQ("3 2 1", | |
2079 ui::test::ChildLayerNamesAsString(*root_window()->layer())); | |
2080 | |
2081 // It should still be possible to stack |window3| immediately below |window1|. | |
2082 root_window()->StackChildBelow(window3.get(), window1.get()); | |
2083 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window())); | |
2084 EXPECT_EQ("2 3 1", | |
2085 ui::test::ChildLayerNamesAsString(*root_window()->layer())); | |
2086 | |
2087 // Since neither |window3| nor |window1| have a delegate, |window2| should | |
2088 // not move in front of either. | |
2089 window3->layer()->set_delegate(NULL); | |
2090 root_window()->StackChildBelow(window2.get(), window1.get()); | |
2091 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window())); | |
2092 EXPECT_EQ("2 3 1", | |
2093 ui::test::ChildLayerNamesAsString(*root_window()->layer())); | |
2094 } | |
2095 | |
2096 TEST_F(WindowTest, StackTransientsWhoseLayersHaveNoDelegate) { | |
2097 // Create a window with several transients, then a couple windows on top. | |
2098 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window())); | |
2099 scoped_ptr<Window> window11(CreateTransientChild(11, window1.get())); | |
2100 scoped_ptr<Window> window12(CreateTransientChild(12, window1.get())); | |
2101 scoped_ptr<Window> window13(CreateTransientChild(13, window1.get())); | |
2102 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window())); | |
2103 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window())); | |
2104 | |
2105 EXPECT_EQ("1 11 12 13 2 3", ChildWindowIDsAsString(root_window())); | |
2106 | |
2107 // Remove the delegates of a couple of transients, as if they are closing | |
2108 // and animating out. | |
2109 window11->layer()->set_delegate(NULL); | |
2110 window13->layer()->set_delegate(NULL); | |
2111 | |
2112 // Move window1 to the front. All transients should move with it, and their | |
2113 // order should be preserved. | |
2114 root_window()->StackChildAtTop(window1.get()); | |
2115 | |
2116 EXPECT_EQ("2 3 1 11 12 13", ChildWindowIDsAsString(root_window())); | |
2117 } | |
2118 | |
2119 class TestVisibilityClient : public client::VisibilityClient { | 2023 class TestVisibilityClient : public client::VisibilityClient { |
2120 public: | 2024 public: |
2121 explicit TestVisibilityClient(Window* root_window) | 2025 explicit TestVisibilityClient(Window* root_window) |
2122 : ignore_visibility_changes_(false) { | 2026 : ignore_visibility_changes_(false) { |
2123 client::SetVisibilityClient(root_window, this); | 2027 client::SetVisibilityClient(root_window, this); |
2124 } | 2028 } |
2125 virtual ~TestVisibilityClient() { | 2029 virtual ~TestVisibilityClient() { |
2126 } | 2030 } |
2127 | 2031 |
2128 void set_ignore_visibility_changes(bool ignore_visibility_changes) { | 2032 void set_ignore_visibility_changes(bool ignore_visibility_changes) { |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2246 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset()); | 2150 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset()); |
2247 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset()); | 2151 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset()); |
2248 | 2152 |
2249 // Closing windows | 2153 // Closing windows |
2250 w11.reset(); | 2154 w11.reset(); |
2251 RunAllPendingInMessageLoop(); | 2155 RunAllPendingInMessageLoop(); |
2252 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset()); | 2156 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset()); |
2253 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset()); | 2157 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset()); |
2254 } | 2158 } |
2255 | 2159 |
2256 class StackingMadrigalLayoutManager : public LayoutManager { | |
2257 public: | |
2258 explicit StackingMadrigalLayoutManager(Window* root_window) | |
2259 : root_window_(root_window) { | |
2260 root_window_->SetLayoutManager(this); | |
2261 } | |
2262 virtual ~StackingMadrigalLayoutManager() { | |
2263 } | |
2264 | |
2265 private: | |
2266 // Overridden from LayoutManager: | |
2267 virtual void OnWindowResized() OVERRIDE {} | |
2268 virtual void OnWindowAddedToLayout(Window* child) OVERRIDE {} | |
2269 virtual void OnWillRemoveWindowFromLayout(Window* child) OVERRIDE {} | |
2270 virtual void OnWindowRemovedFromLayout(Window* child) OVERRIDE {} | |
2271 virtual void OnChildWindowVisibilityChanged(Window* child, | |
2272 bool visible) OVERRIDE { | |
2273 Window::Windows::const_iterator it = root_window_->children().begin(); | |
2274 Window* last_window = NULL; | |
2275 for (; it != root_window_->children().end(); ++it) { | |
2276 if (*it == child && last_window) { | |
2277 if (!visible) | |
2278 root_window_->StackChildAbove(last_window, *it); | |
2279 else | |
2280 root_window_->StackChildAbove(*it, last_window); | |
2281 break; | |
2282 } | |
2283 last_window = *it; | |
2284 } | |
2285 } | |
2286 virtual void SetChildBounds(Window* child, | |
2287 const gfx::Rect& requested_bounds) OVERRIDE { | |
2288 SetChildBoundsDirect(child, requested_bounds); | |
2289 } | |
2290 | |
2291 Window* root_window_; | |
2292 | |
2293 DISALLOW_COPY_AND_ASSIGN(StackingMadrigalLayoutManager); | |
2294 }; | |
2295 | |
2296 class StackingMadrigalVisibilityClient : public client::VisibilityClient { | |
2297 public: | |
2298 explicit StackingMadrigalVisibilityClient(Window* root_window) | |
2299 : ignored_window_(NULL) { | |
2300 client::SetVisibilityClient(root_window, this); | |
2301 } | |
2302 virtual ~StackingMadrigalVisibilityClient() { | |
2303 } | |
2304 | |
2305 void set_ignored_window(Window* ignored_window) { | |
2306 ignored_window_ = ignored_window; | |
2307 } | |
2308 | |
2309 private: | |
2310 // Overridden from client::VisibilityClient: | |
2311 virtual void UpdateLayerVisibility(Window* window, bool visible) OVERRIDE { | |
2312 if (!visible) { | |
2313 if (window == ignored_window_) | |
2314 window->layer()->set_delegate(NULL); | |
2315 else | |
2316 window->layer()->SetVisible(visible); | |
2317 } else { | |
2318 window->layer()->SetVisible(visible); | |
2319 } | |
2320 } | |
2321 | |
2322 Window* ignored_window_; | |
2323 | |
2324 DISALLOW_COPY_AND_ASSIGN(StackingMadrigalVisibilityClient); | |
2325 }; | |
2326 | |
2327 // This test attempts to reconstruct a circumstance that can happen when the | |
2328 // aura client attempts to manipulate the visibility and delegate of a layer | |
2329 // independent of window visibility. | |
2330 // A use case is where the client attempts to keep a window visible onscreen | |
2331 // even after code has called Hide() on the window. The use case for this would | |
2332 // be that window hides are animated (e.g. the window fades out). To prevent | |
2333 // spurious updating the client code may also clear window's layer's delegate, | |
2334 // so that the window cannot attempt to paint or update it further. The window | |
2335 // uses the presence of a NULL layer delegate as a signal in stacking to note | |
2336 // that the window is being manipulated by such a use case and its stacking | |
2337 // should not be adjusted. | |
2338 // One issue that can arise when a window opens two transient children, and the | |
2339 // first is hidden. Subsequent attempts to activate the transient parent can | |
2340 // result in the transient parent being stacked above the second transient | |
2341 // child. A fix is made to Window::StackAbove to prevent this, and this test | |
2342 // verifies this fix. | |
2343 TEST_F(WindowTest, StackingMadrigal) { | |
2344 new StackingMadrigalLayoutManager(root_window()); | |
2345 StackingMadrigalVisibilityClient visibility_client(root_window()); | |
2346 | |
2347 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window())); | |
2348 scoped_ptr<Window> window11(CreateTransientChild(11, window1.get())); | |
2349 | |
2350 visibility_client.set_ignored_window(window11.get()); | |
2351 | |
2352 window11->Show(); | |
2353 window11->Hide(); | |
2354 | |
2355 // As a transient, window11 should still be stacked above window1, even when | |
2356 // hidden. | |
2357 EXPECT_TRUE(WindowIsAbove(window11.get(), window1.get())); | |
2358 EXPECT_TRUE(LayerIsAbove(window11.get(), window1.get())); | |
2359 | |
2360 // A new transient should still be above window1. It will appear behind | |
2361 // window11 because we don't stack windows on top of targets with NULL | |
2362 // delegates. | |
2363 scoped_ptr<Window> window12(CreateTransientChild(12, window1.get())); | |
2364 window12->Show(); | |
2365 | |
2366 EXPECT_TRUE(WindowIsAbove(window12.get(), window1.get())); | |
2367 EXPECT_TRUE(LayerIsAbove(window12.get(), window1.get())); | |
2368 | |
2369 // In earlier versions of the StackChildAbove() method, attempting to stack | |
2370 // window1 above window12 at this point would actually restack the layers | |
2371 // resulting in window12's layer being below window1's layer (though the | |
2372 // windows themselves would still be correctly stacked, so events would pass | |
2373 // through.) | |
2374 root_window()->StackChildAbove(window1.get(), window12.get()); | |
2375 | |
2376 // Both window12 and its layer should be stacked above window1. | |
2377 EXPECT_TRUE(WindowIsAbove(window12.get(), window1.get())); | |
2378 EXPECT_TRUE(LayerIsAbove(window12.get(), window1.get())); | |
2379 } | |
2380 | |
2381 // Test for an issue where attempting to stack a primary window on top of a | |
2382 // transient with a NULL layer delegate causes that primary window to be moved, | |
2383 // but the layer order not changed to match. http://crbug.com/112562 | |
2384 TEST_F(WindowTest, StackOverClosingTransient) { | |
2385 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window())); | |
2386 scoped_ptr<Window> transient1(CreateTransientChild(11, window1.get())); | |
2387 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window())); | |
2388 scoped_ptr<Window> transient2(CreateTransientChild(21, window2.get())); | |
2389 | |
2390 // Both windows and layers are stacked in creation order. | |
2391 Window* root = root_window(); | |
2392 ASSERT_EQ(4u, root->children().size()); | |
2393 EXPECT_EQ(root->children()[0], window1.get()); | |
2394 EXPECT_EQ(root->children()[1], transient1.get()); | |
2395 EXPECT_EQ(root->children()[2], window2.get()); | |
2396 EXPECT_EQ(root->children()[3], transient2.get()); | |
2397 ASSERT_EQ(4u, root->layer()->children().size()); | |
2398 EXPECT_EQ(root->layer()->children()[0], window1->layer()); | |
2399 EXPECT_EQ(root->layer()->children()[1], transient1->layer()); | |
2400 EXPECT_EQ(root->layer()->children()[2], window2->layer()); | |
2401 EXPECT_EQ(root->layer()->children()[3], transient2->layer()); | |
2402 EXPECT_EQ("1 11 2 21", ChildWindowIDsAsString(root_window())); | |
2403 | |
2404 // This brings window1 and its transient to the front. | |
2405 root->StackChildAtTop(window1.get()); | |
2406 EXPECT_EQ("2 21 1 11", ChildWindowIDsAsString(root_window())); | |
2407 | |
2408 EXPECT_EQ(root->children()[0], window2.get()); | |
2409 EXPECT_EQ(root->children()[1], transient2.get()); | |
2410 EXPECT_EQ(root->children()[2], window1.get()); | |
2411 EXPECT_EQ(root->children()[3], transient1.get()); | |
2412 EXPECT_EQ(root->layer()->children()[0], window2->layer()); | |
2413 EXPECT_EQ(root->layer()->children()[1], transient2->layer()); | |
2414 EXPECT_EQ(root->layer()->children()[2], window1->layer()); | |
2415 EXPECT_EQ(root->layer()->children()[3], transient1->layer()); | |
2416 | |
2417 // Pretend we're closing the top-most transient, then bring window2 to the | |
2418 // front. This mimics activating a browser window while the status bubble | |
2419 // is fading out. The transient should stay topmost. | |
2420 transient1->layer()->set_delegate(NULL); | |
2421 root->StackChildAtTop(window2.get()); | |
2422 | |
2423 EXPECT_EQ(root->children()[0], window1.get()); | |
2424 EXPECT_EQ(root->children()[1], window2.get()); | |
2425 EXPECT_EQ(root->children()[2], transient2.get()); | |
2426 EXPECT_EQ(root->children()[3], transient1.get()); | |
2427 EXPECT_EQ(root->layer()->children()[0], window1->layer()); | |
2428 EXPECT_EQ(root->layer()->children()[1], window2->layer()); | |
2429 EXPECT_EQ(root->layer()->children()[2], transient2->layer()); | |
2430 EXPECT_EQ(root->layer()->children()[3], transient1->layer()); | |
2431 | |
2432 // Close the transient. Remaining windows are stable. | |
2433 transient1.reset(); | |
2434 | |
2435 ASSERT_EQ(3u, root->children().size()); | |
2436 EXPECT_EQ(root->children()[0], window1.get()); | |
2437 EXPECT_EQ(root->children()[1], window2.get()); | |
2438 EXPECT_EQ(root->children()[2], transient2.get()); | |
2439 ASSERT_EQ(3u, root->layer()->children().size()); | |
2440 EXPECT_EQ(root->layer()->children()[0], window1->layer()); | |
2441 EXPECT_EQ(root->layer()->children()[1], window2->layer()); | |
2442 EXPECT_EQ(root->layer()->children()[2], transient2->layer()); | |
2443 | |
2444 // Open another window on top. | |
2445 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window())); | |
2446 | |
2447 ASSERT_EQ(4u, root->children().size()); | |
2448 EXPECT_EQ(root->children()[0], window1.get()); | |
2449 EXPECT_EQ(root->children()[1], window2.get()); | |
2450 EXPECT_EQ(root->children()[2], transient2.get()); | |
2451 EXPECT_EQ(root->children()[3], window3.get()); | |
2452 ASSERT_EQ(4u, root->layer()->children().size()); | |
2453 EXPECT_EQ(root->layer()->children()[0], window1->layer()); | |
2454 EXPECT_EQ(root->layer()->children()[1], window2->layer()); | |
2455 EXPECT_EQ(root->layer()->children()[2], transient2->layer()); | |
2456 EXPECT_EQ(root->layer()->children()[3], window3->layer()); | |
2457 | |
2458 // Pretend we're closing the topmost non-transient window, then bring | |
2459 // window2 to the top. It should not move. | |
2460 window3->layer()->set_delegate(NULL); | |
2461 root->StackChildAtTop(window2.get()); | |
2462 | |
2463 ASSERT_EQ(4u, root->children().size()); | |
2464 EXPECT_EQ(root->children()[0], window1.get()); | |
2465 EXPECT_EQ(root->children()[1], window2.get()); | |
2466 EXPECT_EQ(root->children()[2], transient2.get()); | |
2467 EXPECT_EQ(root->children()[3], window3.get()); | |
2468 ASSERT_EQ(4u, root->layer()->children().size()); | |
2469 EXPECT_EQ(root->layer()->children()[0], window1->layer()); | |
2470 EXPECT_EQ(root->layer()->children()[1], window2->layer()); | |
2471 EXPECT_EQ(root->layer()->children()[2], transient2->layer()); | |
2472 EXPECT_EQ(root->layer()->children()[3], window3->layer()); | |
2473 | |
2474 // Bring window1 to the top. It should move ahead of window2, but not | |
2475 // ahead of window3 (with NULL delegate). | |
2476 root->StackChildAtTop(window1.get()); | |
2477 | |
2478 ASSERT_EQ(4u, root->children().size()); | |
2479 EXPECT_EQ(root->children()[0], window2.get()); | |
2480 EXPECT_EQ(root->children()[1], transient2.get()); | |
2481 EXPECT_EQ(root->children()[2], window1.get()); | |
2482 EXPECT_EQ(root->children()[3], window3.get()); | |
2483 ASSERT_EQ(4u, root->layer()->children().size()); | |
2484 EXPECT_EQ(root->layer()->children()[0], window2->layer()); | |
2485 EXPECT_EQ(root->layer()->children()[1], transient2->layer()); | |
2486 EXPECT_EQ(root->layer()->children()[2], window1->layer()); | |
2487 EXPECT_EQ(root->layer()->children()[3], window3->layer()); | |
2488 } | |
2489 | |
2490 class RootWindowAttachmentObserver : public WindowObserver { | 2160 class RootWindowAttachmentObserver : public WindowObserver { |
2491 public: | 2161 public: |
2492 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {} | 2162 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {} |
2493 virtual ~RootWindowAttachmentObserver() {} | 2163 virtual ~RootWindowAttachmentObserver() {} |
2494 | 2164 |
2495 int added_count() const { return added_count_; } | 2165 int added_count() const { return added_count_; } |
2496 int removed_count() const { return removed_count_; } | 2166 int removed_count() const { return removed_count_; } |
2497 | 2167 |
2498 void Clear() { | 2168 void Clear() { |
2499 added_count_ = 0; | 2169 added_count_ = 0; |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3000 o.ValidateState(index++, params); | 2670 o.ValidateState(index++, params); |
3001 params.receiver = root_window(); | 2671 params.receiver = root_window(); |
3002 o.ValidateState(index++, params); | 2672 o.ValidateState(index++, params); |
3003 | 2673 |
3004 w1.reset(); | 2674 w1.reset(); |
3005 w2.reset(); | 2675 w2.reset(); |
3006 } | 2676 } |
3007 | 2677 |
3008 } | 2678 } |
3009 | 2679 |
3010 namespace { | |
3011 | |
3012 // Used by NotifyDelegateAfterDeletingTransients. Adds a string to a vector when | |
3013 // OnWindowDestroyed() is invoked so that destruction order can be verified. | |
3014 class DestroyedTrackingDelegate : public TestWindowDelegate { | |
3015 public: | |
3016 explicit DestroyedTrackingDelegate(const std::string& name, | |
3017 std::vector<std::string>* results) | |
3018 : name_(name), | |
3019 results_(results) {} | |
3020 | |
3021 virtual void OnWindowDestroyed() OVERRIDE { | |
3022 results_->push_back(name_); | |
3023 } | |
3024 | |
3025 private: | |
3026 const std::string name_; | |
3027 std::vector<std::string>* results_; | |
3028 | |
3029 DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingDelegate); | |
3030 }; | |
3031 | |
3032 } // namespace | |
3033 | |
3034 // Verifies the delegate is notified of destruction after transients are | |
3035 // destroyed. | |
3036 TEST_F(WindowTest, NotifyDelegateAfterDeletingTransients) { | |
3037 std::vector<std::string> destruction_order; | |
3038 | |
3039 DestroyedTrackingDelegate parent_delegate("parent", &destruction_order); | |
3040 scoped_ptr<Window> parent(new Window(&parent_delegate)); | |
3041 parent->Init(ui::LAYER_NOT_DRAWN); | |
3042 | |
3043 DestroyedTrackingDelegate transient_delegate("transient", &destruction_order); | |
3044 Window* transient = new Window(&transient_delegate); // Owned by |parent|. | |
3045 transient->Init(ui::LAYER_NOT_DRAWN); | |
3046 parent->AddTransientChild(transient); | |
3047 parent.reset(); | |
3048 | |
3049 ASSERT_EQ(2u, destruction_order.size()); | |
3050 EXPECT_EQ("transient", destruction_order[0]); | |
3051 EXPECT_EQ("parent", destruction_order[1]); | |
3052 } | |
3053 | |
3054 // Verifies SchedulePaint() on a layerless window results in damaging the right | 2680 // Verifies SchedulePaint() on a layerless window results in damaging the right |
3055 // thing. | 2681 // thing. |
3056 TEST_F(WindowTest, LayerlessWindowSchedulePaint) { | 2682 TEST_F(WindowTest, LayerlessWindowSchedulePaint) { |
3057 Window root(NULL); | 2683 Window root(NULL); |
3058 root.Init(ui::LAYER_NOT_DRAWN); | 2684 root.Init(ui::LAYER_NOT_DRAWN); |
3059 root.SetBounds(gfx::Rect(0, 0, 100, 100)); | 2685 root.SetBounds(gfx::Rect(0, 0, 100, 100)); |
3060 | 2686 |
3061 Window* layerless_window = new Window(NULL); // Owned by |root|. | 2687 Window* layerless_window = new Window(NULL); // Owned by |root|. |
3062 layerless_window->InitWithWindowLayerType(WINDOW_LAYER_NONE); | 2688 layerless_window->InitWithWindowLayerType(WINDOW_LAYER_NONE); |
3063 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13)); | 2689 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13)); |
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3708 BuildRootLayerTreeDescription(*root.layer())) | 3334 BuildRootLayerTreeDescription(*root.layer())) |
3709 << "layer tree doesn't match at " << i; | 3335 << "layer tree doesn't match at " << i; |
3710 EXPECT_EQ(data[i].expected_description, | 3336 EXPECT_EQ(data[i].expected_description, |
3711 BuildRootWindowTreeDescription(root)) | 3337 BuildRootWindowTreeDescription(root)) |
3712 << "window tree doesn't match at " << i; | 3338 << "window tree doesn't match at " << i; |
3713 } | 3339 } |
3714 } | 3340 } |
3715 | 3341 |
3716 } // namespace test | 3342 } // namespace test |
3717 } // namespace aura | 3343 } // namespace aura |
OLD | NEW |