screen_pinning_controller_unittest.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // Copyright 2016 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/screen_pinning_controller.h"
  5. #include <vector>
  6. #include "ash/accelerators/accelerator_controller_impl.h"
  7. #include "ash/shell.h"
  8. #include "ash/test/ash_test_base.h"
  9. #include "ash/wm/client_controlled_state.h"
  10. #include "ash/wm/screen_pinning_controller.h"
  11. #include "ash/wm/window_state.h"
  12. #include "ash/wm/window_util.h"
  13. #include "ash/wm/wm_event.h"
  14. #include "ui/aura/window.h"
  15. namespace ash {
  16. namespace {
  17. int FindIndex(const std::vector<aura::Window*>& windows,
  18. const aura::Window* target) {
  19. auto iter = std::find(windows.begin(), windows.end(), target);
  20. return iter != windows.end() ? iter - windows.begin() : -1;
  21. }
  22. class TestClientControlledStateDelegate
  23. : public ClientControlledState::Delegate {
  24. public:
  25. ~TestClientControlledStateDelegate() override = default;
  26. void HandleWindowStateRequest(WindowState* state,
  27. chromeos::WindowStateType type) override {}
  28. void HandleBoundsRequest(WindowState* state,
  29. chromeos::WindowStateType type,
  30. const gfx::Rect& requested_bounds,
  31. int64_t display_id) override {}
  32. };
  33. } // namespace
  34. using ScreenPinningControllerTest = AshTestBase;
  35. TEST_F(ScreenPinningControllerTest, IsPinned) {
  36. aura::Window* w1 = CreateTestWindowInShellWithId(0);
  37. wm::ActivateWindow(w1);
  38. window_util::PinWindow(w1, /* trusted */ false);
  39. EXPECT_TRUE(Shell::Get()->screen_pinning_controller()->IsPinned());
  40. }
  41. TEST_F(ScreenPinningControllerTest, OnlyOnePinnedWindow) {
  42. aura::Window* w1 = CreateTestWindowInShellWithId(0);
  43. aura::Window* w2 = CreateTestWindowInShellWithId(1);
  44. wm::ActivateWindow(w1);
  45. window_util::PinWindow(w1, /* trusted */ false);
  46. EXPECT_TRUE(WindowState::Get(w1)->IsPinned());
  47. EXPECT_FALSE(WindowState::Get(w2)->IsPinned());
  48. // Prohibit to pin two (or more) windows.
  49. window_util::PinWindow(w2, /* trusted */ false);
  50. EXPECT_TRUE(WindowState::Get(w1)->IsPinned());
  51. EXPECT_FALSE(WindowState::Get(w2)->IsPinned());
  52. }
  53. TEST_F(ScreenPinningControllerTest, FullscreenInPinnedMode) {
  54. aura::Window* w1 = CreateTestWindowInShellWithId(0);
  55. aura::Window* w2 = CreateTestWindowInShellWithId(1);
  56. wm::ActivateWindow(w1);
  57. window_util::PinWindow(w1, /* trusted */ false);
  58. {
  59. // Window w1 should be in front of w2.
  60. std::vector<aura::Window*> siblings = w1->parent()->children();
  61. int index1 = FindIndex(siblings, w1);
  62. int index2 = FindIndex(siblings, w2);
  63. EXPECT_NE(-1, index1);
  64. EXPECT_NE(-1, index2);
  65. EXPECT_GT(index1, index2);
  66. }
  67. // Set w2 to fullscreen.
  68. {
  69. wm::ActivateWindow(w2);
  70. const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
  71. WindowState::Get(w2)->OnWMEvent(&event);
  72. }
  73. {
  74. // Verify that w1 is still in front of w2.
  75. std::vector<aura::Window*> siblings = w1->parent()->children();
  76. int index1 = FindIndex(siblings, w1);
  77. int index2 = FindIndex(siblings, w2);
  78. EXPECT_NE(-1, index1);
  79. EXPECT_NE(-1, index2);
  80. EXPECT_GT(index1, index2);
  81. }
  82. // Unset w2's fullscreen.
  83. {
  84. wm::ActivateWindow(w2);
  85. const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
  86. WindowState::Get(w2)->OnWMEvent(&event);
  87. }
  88. {
  89. // Verify that w1 is still in front of w2.
  90. std::vector<aura::Window*> siblings = w1->parent()->children();
  91. int index1 = FindIndex(siblings, w1);
  92. int index2 = FindIndex(siblings, w2);
  93. EXPECT_NE(-1, index1);
  94. EXPECT_NE(-1, index2);
  95. EXPECT_GT(index1, index2);
  96. }
  97. // Maximize w2.
  98. {
  99. wm::ActivateWindow(w2);
  100. const WMEvent event(WM_EVENT_TOGGLE_MAXIMIZE);
  101. WindowState::Get(w2)->OnWMEvent(&event);
  102. }
  103. {
  104. // Verify that w1 is still in front of w2.
  105. std::vector<aura::Window*> siblings = w1->parent()->children();
  106. int index1 = FindIndex(siblings, w1);
  107. int index2 = FindIndex(siblings, w2);
  108. EXPECT_NE(-1, index1);
  109. EXPECT_NE(-1, index2);
  110. EXPECT_GT(index1, index2);
  111. }
  112. // Unset w2's maximize.
  113. {
  114. wm::ActivateWindow(w2);
  115. const WMEvent event(WM_EVENT_TOGGLE_MAXIMIZE);
  116. WindowState::Get(w2)->OnWMEvent(&event);
  117. }
  118. {
  119. // Verify that w1 is still in front of w2.
  120. std::vector<aura::Window*> siblings = w1->parent()->children();
  121. int index1 = FindIndex(siblings, w1);
  122. int index2 = FindIndex(siblings, w2);
  123. EXPECT_NE(-1, index1);
  124. EXPECT_NE(-1, index2);
  125. EXPECT_GT(index1, index2);
  126. }
  127. // Restore w1.
  128. WindowState::Get(w1)->Restore();
  129. // Now, fullscreen-ize w2 should put it in front of w1.
  130. {
  131. wm::ActivateWindow(w2);
  132. const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
  133. WindowState::Get(w2)->OnWMEvent(&event);
  134. }
  135. {
  136. // Verify that w1 is still in front of w2.
  137. std::vector<aura::Window*> siblings = w1->parent()->children();
  138. int index1 = FindIndex(siblings, w1);
  139. int index2 = FindIndex(siblings, w2);
  140. EXPECT_NE(-1, index1);
  141. EXPECT_NE(-1, index2);
  142. EXPECT_GT(index2, index1);
  143. }
  144. }
  145. TEST_F(ScreenPinningControllerTest, TrustedPinnedWithAccelerator) {
  146. aura::Window* w1 = CreateTestWindowInShellWithId(0);
  147. wm::ActivateWindow(w1);
  148. window_util::PinWindow(w1, /* trusted */ true);
  149. EXPECT_TRUE(Shell::Get()->screen_pinning_controller()->IsPinned());
  150. Shell::Get()->accelerator_controller()->PerformActionIfEnabled(UNPIN, {});
  151. // The UNPIN accelerator key is disabled for trusted pinned and the window
  152. // must be still pinned.
  153. EXPECT_TRUE(Shell::Get()->screen_pinning_controller()->IsPinned());
  154. }
  155. TEST_F(ScreenPinningControllerTest, ExitUnifiedDisplay) {
  156. display_manager()->SetUnifiedDesktopEnabled(true);
  157. UpdateDisplay("400x300, 500x400");
  158. aura::Window* w1 = CreateTestWindowInShellWithId(0);
  159. wm::ActivateWindow(w1);
  160. auto* window_state = WindowState::Get(w1);
  161. window_util::PinWindow(w1, /*trusted=*/true);
  162. EXPECT_TRUE(window_state->IsPinned());
  163. EXPECT_TRUE(Shell::Get()->screen_pinning_controller()->IsPinned());
  164. UpdateDisplay("300x200");
  165. EXPECT_TRUE(window_state->IsPinned());
  166. EXPECT_TRUE(Shell::Get()->screen_pinning_controller()->IsPinned());
  167. }
  168. TEST_F(ScreenPinningControllerTest, CleanUpObserversAndDimmer) {
  169. // Create a window with ClientControlledState.
  170. auto w = CreateAppWindow(gfx::Rect(), AppType::CHROME_APP, 0);
  171. ash::WindowState* ws = ash::WindowState::Get(w.get());
  172. auto delegate = std::make_unique<TestClientControlledStateDelegate>();
  173. auto state = std::make_unique<ClientControlledState>(std::move(delegate));
  174. ws->SetStateObject(std::move(state));
  175. wm::ActivateWindow(w.get());
  176. // Observer should be added to |w|, and |w->parent()|.
  177. window_util::PinWindow(w.get(), /* truested */ false);
  178. EXPECT_TRUE(WindowState::Get(w.get())->IsPinned());
  179. const aura::Window* container = w->parent();
  180. // Destroying |w| clears |pinned_window_|. The observers should be removed
  181. // even if ClientControlledState doesn't call SetPinnedWindow when
  182. // WindowState::Restore() is called.
  183. w.reset();
  184. // It should clear all child windows in |container| when the pinned window is
  185. // destroyed.
  186. EXPECT_EQ(container->children().size(), 0u);
  187. // Add a sibling window. It should not crash.
  188. CreateTestWindowInShellWithId(2);
  189. }
  190. } // namespace ash