window_util_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // Copyright (c) 2013 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. #include "ash/wm/window_util.h"
  5. #include "ash/test/ash_test_base.h"
  6. #include "ash/wm/window_positioning_utils.h"
  7. #include "ash/wm/window_state.h"
  8. #include "ash/wm/wm_event.h"
  9. #include "base/containers/contains.h"
  10. #include "ui/aura/test/test_windows.h"
  11. #include "ui/aura/window.h"
  12. #include "ui/display/screen.h"
  13. #include "ui/events/base_event_utils.h"
  14. #include "ui/wm/core/window_util.h"
  15. namespace ash {
  16. namespace window_util {
  17. namespace {
  18. std::string GetAdjustedBounds(const gfx::Rect& visible,
  19. gfx::Rect to_be_adjusted) {
  20. AdjustBoundsToEnsureMinimumWindowVisibility(visible, &to_be_adjusted);
  21. return to_be_adjusted.ToString();
  22. }
  23. class FakeWindowState : public WindowState::State {
  24. public:
  25. explicit FakeWindowState() = default;
  26. FakeWindowState(const FakeWindowState&) = delete;
  27. FakeWindowState& operator=(const FakeWindowState&) = delete;
  28. ~FakeWindowState() override = default;
  29. // WindowState::State overrides:
  30. void OnWMEvent(WindowState* window_state, const WMEvent* event) override {
  31. if (event->type() == WM_EVENT_MINIMIZE)
  32. was_visible_on_minimize_ = window_state->window()->IsVisible();
  33. }
  34. chromeos::WindowStateType GetType() const override {
  35. return chromeos::WindowStateType::kNormal;
  36. }
  37. void AttachState(WindowState* window_state,
  38. WindowState::State* previous_state) override {}
  39. void DetachState(WindowState* window_state) override {}
  40. bool was_visible_on_minimize() { return was_visible_on_minimize_; }
  41. private:
  42. bool was_visible_on_minimize_ = true;
  43. };
  44. } // namespace
  45. using WindowUtilTest = AshTestBase;
  46. TEST_F(WindowUtilTest, CenterWindow) {
  47. UpdateDisplay("500x400, 600x400");
  48. std::unique_ptr<aura::Window> window(
  49. CreateTestWindowInShellWithBounds(gfx::Rect(12, 20, 100, 100)));
  50. WindowState* window_state = WindowState::Get(window.get());
  51. EXPECT_FALSE(window_state->bounds_changed_by_user());
  52. CenterWindow(window.get());
  53. // Centring window is considered as a user's action.
  54. EXPECT_TRUE(window_state->bounds_changed_by_user());
  55. EXPECT_EQ("200,126 100x100", window->bounds().ToString());
  56. EXPECT_EQ("200,126 100x100", window->GetBoundsInScreen().ToString());
  57. window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), GetSecondaryDisplay());
  58. CenterWindow(window.get());
  59. EXPECT_EQ("250,126 100x100", window->bounds().ToString());
  60. EXPECT_EQ("750,126 100x100", window->GetBoundsInScreen().ToString());
  61. }
  62. TEST_F(WindowUtilTest, AdjustBoundsToEnsureMinimumVisibility) {
  63. const gfx::Rect visible_bounds(0, 0, 100, 100);
  64. EXPECT_EQ("0,0 90x90",
  65. GetAdjustedBounds(visible_bounds, gfx::Rect(0, 0, 90, 90)));
  66. EXPECT_EQ("0,0 100x100",
  67. GetAdjustedBounds(visible_bounds, gfx::Rect(0, 0, 150, 150)));
  68. EXPECT_EQ("-50,0 100x100",
  69. GetAdjustedBounds(visible_bounds, gfx::Rect(-50, -50, 150, 150)));
  70. EXPECT_EQ("-75,10 100x100",
  71. GetAdjustedBounds(visible_bounds, gfx::Rect(-100, 10, 150, 150)));
  72. EXPECT_EQ("75,75 100x100",
  73. GetAdjustedBounds(visible_bounds, gfx::Rect(100, 100, 150, 150)));
  74. // For windows that have smaller dimensions than kMinimumOnScreenArea,
  75. // we should adjust bounds accordingly, leaving no white space.
  76. EXPECT_EQ("50,80 20x20",
  77. GetAdjustedBounds(visible_bounds, gfx::Rect(50, 80, 20, 20)));
  78. EXPECT_EQ("80,50 20x20",
  79. GetAdjustedBounds(visible_bounds, gfx::Rect(80, 50, 20, 20)));
  80. EXPECT_EQ("0,50 20x20",
  81. GetAdjustedBounds(visible_bounds, gfx::Rect(0, 50, 20, 20)));
  82. EXPECT_EQ("50,0 20x20",
  83. GetAdjustedBounds(visible_bounds, gfx::Rect(50, 0, 20, 20)));
  84. EXPECT_EQ("50,80 20x20",
  85. GetAdjustedBounds(visible_bounds, gfx::Rect(50, 100, 20, 20)));
  86. EXPECT_EQ("80,50 20x20",
  87. GetAdjustedBounds(visible_bounds, gfx::Rect(100, 50, 20, 20)));
  88. EXPECT_EQ("0,50 20x20",
  89. GetAdjustedBounds(visible_bounds, gfx::Rect(-10, 50, 20, 20)));
  90. EXPECT_EQ("50,0 20x20",
  91. GetAdjustedBounds(visible_bounds, gfx::Rect(50, -10, 20, 20)));
  92. const gfx::Rect visible_bounds_right(200, 50, 100, 100);
  93. EXPECT_EQ("210,60 90x90", GetAdjustedBounds(visible_bounds_right,
  94. gfx::Rect(210, 60, 90, 90)));
  95. EXPECT_EQ("210,60 100x100", GetAdjustedBounds(visible_bounds_right,
  96. gfx::Rect(210, 60, 150, 150)));
  97. EXPECT_EQ("125,50 100x100",
  98. GetAdjustedBounds(visible_bounds_right, gfx::Rect(0, 0, 150, 150)));
  99. EXPECT_EQ("275,50 100x100", GetAdjustedBounds(visible_bounds_right,
  100. gfx::Rect(300, 20, 150, 150)));
  101. EXPECT_EQ(
  102. "125,125 100x100",
  103. GetAdjustedBounds(visible_bounds_right, gfx::Rect(-100, 150, 150, 150)));
  104. const gfx::Rect visible_bounds_left(-200, -50, 100, 100);
  105. EXPECT_EQ("-190,-40 90x90", GetAdjustedBounds(visible_bounds_left,
  106. gfx::Rect(-190, -40, 90, 90)));
  107. EXPECT_EQ(
  108. "-190,-40 100x100",
  109. GetAdjustedBounds(visible_bounds_left, gfx::Rect(-190, -40, 150, 150)));
  110. EXPECT_EQ(
  111. "-250,-40 100x100",
  112. GetAdjustedBounds(visible_bounds_left, gfx::Rect(-250, -40, 150, 150)));
  113. EXPECT_EQ(
  114. "-275,-50 100x100",
  115. GetAdjustedBounds(visible_bounds_left, gfx::Rect(-400, -60, 150, 150)));
  116. EXPECT_EQ("-125,0 100x100",
  117. GetAdjustedBounds(visible_bounds_left, gfx::Rect(0, 0, 150, 150)));
  118. }
  119. TEST_F(WindowUtilTest, MoveWindowToDisplay) {
  120. UpdateDisplay("500x400, 600x400");
  121. std::unique_ptr<aura::Window> window(
  122. CreateTestWindowInShellWithBounds(gfx::Rect(12, 20, 100, 100)));
  123. display::Screen* screen = display::Screen::GetScreen();
  124. const int64_t original_display_id =
  125. screen->GetDisplayNearestWindow(window.get()).id();
  126. EXPECT_EQ(screen->GetPrimaryDisplay().id(), original_display_id);
  127. const int original_container_id = window->parent()->GetId();
  128. const aura::Window* original_root = window->GetRootWindow();
  129. ASSERT_EQ(2, screen->GetNumDisplays());
  130. const int64_t secondary_display_id = screen->GetAllDisplays()[1].id();
  131. EXPECT_NE(original_display_id, secondary_display_id);
  132. EXPECT_TRUE(MoveWindowToDisplay(window.get(), secondary_display_id));
  133. EXPECT_EQ(secondary_display_id,
  134. screen->GetDisplayNearestWindow(window.get()).id());
  135. EXPECT_EQ(original_container_id, window->parent()->GetId());
  136. EXPECT_NE(original_root, window->GetRootWindow());
  137. EXPECT_TRUE(MoveWindowToDisplay(window.get(), original_display_id));
  138. EXPECT_EQ(original_display_id,
  139. screen->GetDisplayNearestWindow(window.get()).id());
  140. EXPECT_EQ(original_container_id, window->parent()->GetId());
  141. EXPECT_EQ(original_root, window->GetRootWindow());
  142. }
  143. // Tests that locking and unlocking the screen does not alter the display of a
  144. // window moved by MoveWindowToDisplay.
  145. TEST_F(WindowUtilTest, MoveWindowToDisplayAndLockScreen) {
  146. UpdateDisplay("500x400, 600x400");
  147. auto window = CreateTestWindow(gfx::Rect(12, 20, 100, 100));
  148. display::Screen* screen = display::Screen::GetScreen();
  149. ASSERT_EQ(2, screen->GetNumDisplays());
  150. const int64_t primary_display_id = screen->GetAllDisplays()[0].id();
  151. const int64_t secondary_display_id = screen->GetAllDisplays()[1].id();
  152. ASSERT_EQ(primary_display_id,
  153. screen->GetDisplayNearestWindow(window.get()).id());
  154. EXPECT_TRUE(MoveWindowToDisplay(window.get(), secondary_display_id));
  155. EXPECT_EQ(secondary_display_id,
  156. screen->GetDisplayNearestWindow(window.get()).id());
  157. // Tests that after locking and unlocking the screen the window remains on the
  158. // secondary display.
  159. GetSessionControllerClient()->LockScreen();
  160. GetSessionControllerClient()->UnlockScreen();
  161. EXPECT_EQ(secondary_display_id,
  162. screen->GetDisplayNearestWindow(window.get()).id());
  163. // Move the window to the primary display. Tests that after locking and
  164. // unlocking the screen the window remains on the secondary display.
  165. EXPECT_TRUE(MoveWindowToDisplay(window.get(), primary_display_id));
  166. GetSessionControllerClient()->LockScreen();
  167. GetSessionControllerClient()->UnlockScreen();
  168. EXPECT_EQ(primary_display_id,
  169. screen->GetDisplayNearestWindow(window.get()).id());
  170. }
  171. TEST_F(WindowUtilTest, EnsureTransientRoots) {
  172. // Create two windows which have no transient children or parents. Test that
  173. // neither of them get removed when running EnsureTransientRoots.
  174. auto window1 = CreateTestWindow();
  175. auto window2 = CreateTestWindow();
  176. std::vector<aura::Window*> window_list = {window1.get(), window2.get()};
  177. EnsureTransientRoots(&window_list);
  178. ASSERT_EQ(2u, window_list.size());
  179. // Create two windows whose transient roots are |window1|. One is a direct
  180. // transient child and one is a transient descendant. Test that both get
  181. // removed when calling EnsureTransientRoots.
  182. auto descendant1 = CreateTestWindow();
  183. auto descendant2 = CreateTestWindow();
  184. ::wm::AddTransientChild(descendant1.get(), descendant2.get());
  185. ::wm::AddTransientChild(window1.get(), descendant1.get());
  186. window_list.push_back(descendant1.get());
  187. window_list.push_back(descendant2.get());
  188. EnsureTransientRoots(&window_list);
  189. ASSERT_EQ(2u, window_list.size());
  190. ASSERT_TRUE(base::Contains(window_list, window1.get()));
  191. ASSERT_TRUE(base::Contains(window_list, window2.get()));
  192. // Create a window which has a transient parent that is not in |window_list|.
  193. // Test that the window is replaced with its transient root when calling
  194. // EnsureTransientRoots.
  195. auto window3 = CreateTestWindow();
  196. auto descendant3 = CreateTestWindow();
  197. ::wm::AddTransientChild(window3.get(), descendant3.get());
  198. window_list.push_back(descendant3.get());
  199. EnsureTransientRoots(&window_list);
  200. EXPECT_EQ(3u, window_list.size());
  201. EXPECT_TRUE(base::Contains(window_list, window3.get()));
  202. EXPECT_FALSE(base::Contains(window_list, descendant3.get()));
  203. // Create two windows which have the same transient parent that is not in
  204. // |window_list|. Test that one of the windows is replaced with its transient
  205. // root and the other is removed from |window_list| when calling
  206. // EnsureTransientRoots.
  207. auto window4 = CreateTestWindow();
  208. auto descendant4 = CreateTestWindow();
  209. auto descendant5 = CreateTestWindow();
  210. ::wm::AddTransientChild(window4.get(), descendant4.get());
  211. ::wm::AddTransientChild(window4.get(), descendant5.get());
  212. window_list.push_back(descendant4.get());
  213. window_list.push_back(descendant5.get());
  214. EnsureTransientRoots(&window_list);
  215. EXPECT_EQ(4u, window_list.size());
  216. EXPECT_TRUE(base::Contains(window_list, window4.get()));
  217. EXPECT_FALSE(base::Contains(window_list, descendant4.get()));
  218. EXPECT_FALSE(base::Contains(window_list, descendant5.get()));
  219. }
  220. TEST_F(WindowUtilTest,
  221. MinimizeAndHideWithoutAnimationMinimizesArcWindowsBeforeHiding) {
  222. auto window = CreateTestWindow();
  223. auto* state = new FakeWindowState();
  224. WindowState::Get(window.get())
  225. ->SetStateObject(std::unique_ptr<WindowState::State>(state));
  226. std::vector<aura::Window*> windows = {window.get()};
  227. MinimizeAndHideWithoutAnimation(windows);
  228. EXPECT_FALSE(window->IsVisible());
  229. EXPECT_TRUE(state->was_visible_on_minimize());
  230. }
  231. TEST_F(WindowUtilTest, InteriorTargeter) {
  232. auto window = CreateTestWindow();
  233. window->SetBounds(gfx::Rect(0, 0, 100, 100));
  234. WindowState::Get(window.get())->Maximize();
  235. InstallResizeHandleWindowTargeterForWindow(window.get());
  236. auto* child = aura::test::CreateTestWindowWithDelegateAndType(
  237. aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
  238. aura::client::WINDOW_TYPE_UNKNOWN, 1, gfx::Rect(window->bounds().size()),
  239. window.get(),
  240. /*show_on_creation=*/true);
  241. ui::EventTarget* root_target = window->GetRootWindow();
  242. auto* targeter = root_target->GetEventTargeter();
  243. {
  244. ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(0, 0), gfx::Point(0, 0),
  245. ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
  246. EXPECT_EQ(child, targeter->FindTargetForEvent(root_target, &mouse));
  247. }
  248. // InteriorEventTargeter is now active and should pass an event at the edge to
  249. // its parent.
  250. WindowState::Get(window.get())->Restore();
  251. {
  252. ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(0, 0), gfx::Point(0, 0),
  253. ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
  254. EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
  255. }
  256. }
  257. } // namespace window_util
  258. } // namespace ash