window_state_unittest.cc 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. // Copyright 2014 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_state.h"
  5. #include <utility>
  6. #include "ash/constants/app_types.h"
  7. #include "ash/metrics/pip_uma.h"
  8. #include "ash/public/cpp/accelerators.h"
  9. #include "ash/public/cpp/shelf_config.h"
  10. #include "ash/public/cpp/window_properties.h"
  11. #include "ash/screen_util.h"
  12. #include "ash/shell.h"
  13. #include "ash/test/ash_test_base.h"
  14. #include "ash/test/test_window_builder.h"
  15. #include "ash/wm/overview/overview_item.h"
  16. #include "ash/wm/overview/overview_test_util.h"
  17. #include "ash/wm/pip/pip_positioner.h"
  18. #include "ash/wm/splitview/split_view_controller.h"
  19. #include "ash/wm/splitview/split_view_divider.h"
  20. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  21. #include "ash/wm/window_resizer.h"
  22. #include "ash/wm/window_state_util.h"
  23. #include "ash/wm/window_util.h"
  24. #include "ash/wm/wm_event.h"
  25. #include "ash/wm/wm_metrics.h"
  26. #include "base/test/metrics/histogram_tester.h"
  27. #include "base/test/scoped_feature_list.h"
  28. #include "chromeos/ui/base/window_state_type.h"
  29. #include "chromeos/ui/wm/features.h"
  30. #include "ui/aura/client/aura_constants.h"
  31. #include "ui/aura/test/test_window_delegate.h"
  32. #include "ui/aura/window.h"
  33. #include "ui/base/hit_test.h"
  34. #include "ui/compositor/layer.h"
  35. #include "ui/compositor/layer_animator.h"
  36. #include "ui/compositor/scoped_animation_duration_scale_mode.h"
  37. #include "ui/display/screen.h"
  38. #include "ui/events/test/event_generator.h"
  39. #include "ui/views/widget/widget.h"
  40. #include "ui/wm/core/window_util.h"
  41. using chromeos::WindowStateType;
  42. namespace ash {
  43. namespace {
  44. class AlwaysMaximizeTestState : public WindowState::State {
  45. public:
  46. explicit AlwaysMaximizeTestState(WindowStateType initial_state_type)
  47. : state_type_(initial_state_type) {}
  48. AlwaysMaximizeTestState(const AlwaysMaximizeTestState&) = delete;
  49. AlwaysMaximizeTestState& operator=(const AlwaysMaximizeTestState&) = delete;
  50. ~AlwaysMaximizeTestState() override = default;
  51. // WindowState::State overrides:
  52. void OnWMEvent(WindowState* window_state, const WMEvent* event) override {
  53. // We don't do anything here.
  54. }
  55. WindowStateType GetType() const override { return state_type_; }
  56. void AttachState(WindowState* window_state,
  57. WindowState::State* previous_state) override {
  58. // We always maximize.
  59. if (state_type_ != WindowStateType::kMaximized) {
  60. window_state->Maximize();
  61. state_type_ = WindowStateType::kMaximized;
  62. }
  63. }
  64. void DetachState(WindowState* window_state) override {}
  65. private:
  66. WindowStateType state_type_;
  67. };
  68. using WindowStateTest = AshTestBase;
  69. using Sample = base::HistogramBase::Sample;
  70. // Test that a window gets properly snapped to the display's edges in a
  71. // multi monitor environment.
  72. TEST_F(WindowStateTest, SnapWindowBasic) {
  73. UpdateDisplay("0+0-500x400, 0+500-600x400");
  74. const gfx::Rect kPrimaryDisplayWorkAreaBounds =
  75. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  76. const gfx::Rect kSecondaryDisplayWorkAreaBounds =
  77. GetSecondaryDisplay().work_area();
  78. std::unique_ptr<aura::Window> window(
  79. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  80. WindowState* window_state = WindowState::Get(window.get());
  81. const WindowSnapWMEvent snap_primary(WM_EVENT_SNAP_PRIMARY);
  82. window_state->OnWMEvent(&snap_primary);
  83. gfx::Rect expected = gfx::Rect(kPrimaryDisplayWorkAreaBounds.x(),
  84. kPrimaryDisplayWorkAreaBounds.y(),
  85. kPrimaryDisplayWorkAreaBounds.width() / 2,
  86. kPrimaryDisplayWorkAreaBounds.height());
  87. EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
  88. const WindowSnapWMEvent snap_secondary(WM_EVENT_SNAP_SECONDARY);
  89. window_state->OnWMEvent(&snap_secondary);
  90. expected.set_x(kPrimaryDisplayWorkAreaBounds.right() - expected.width());
  91. EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
  92. // Move the window to the secondary display.
  93. window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), GetSecondaryDisplay());
  94. window_state->OnWMEvent(&snap_secondary);
  95. expected = gfx::Rect(kSecondaryDisplayWorkAreaBounds.x() +
  96. kSecondaryDisplayWorkAreaBounds.width() / 2,
  97. kSecondaryDisplayWorkAreaBounds.y(),
  98. kSecondaryDisplayWorkAreaBounds.width() / 2,
  99. kSecondaryDisplayWorkAreaBounds.height());
  100. EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
  101. window_state->OnWMEvent(&snap_primary);
  102. expected.set_x(kSecondaryDisplayWorkAreaBounds.x());
  103. EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
  104. }
  105. // Test how the minimum width and maximize behavior specified by the
  106. // aura::WindowDelegate affect snapping in landscape display layout.
  107. TEST_F(WindowStateTest, SnapWindowMinimumSizeLandscape) {
  108. UpdateDisplay("900x600");
  109. const gfx::Rect kWorkAreaBounds =
  110. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  111. aura::test::TestWindowDelegate delegate;
  112. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
  113. &delegate, -1, gfx::Rect(0, 100, kWorkAreaBounds.width() - 1, 100)));
  114. // It should be possible to snap a window with a minimum size.
  115. const int kMinimumWidth = 700;
  116. delegate.set_minimum_size(gfx::Size(kMinimumWidth, 0));
  117. WindowState* window_state = WindowState::Get(window.get());
  118. EXPECT_TRUE(window_state->CanSnap());
  119. const WindowSnapWMEvent snap_secondary(WM_EVENT_SNAP_SECONDARY);
  120. window_state->OnWMEvent(&snap_secondary);
  121. // Expect right snap with the minimum width.
  122. const gfx::Rect expected_right_snap(kWorkAreaBounds.width() - kMinimumWidth,
  123. kWorkAreaBounds.y(), kMinimumWidth,
  124. kWorkAreaBounds.height());
  125. EXPECT_EQ(expected_right_snap, window->GetBoundsInScreen());
  126. // It should not be possible to snap a window if not maximizable.
  127. window->SetProperty(aura::client::kResizeBehaviorKey,
  128. window->GetProperty(aura::client::kResizeBehaviorKey) ^
  129. aura::client::kResizeBehaviorCanMaximize);
  130. EXPECT_FALSE(window_state->CanSnap());
  131. window->SetProperty(aura::client::kResizeBehaviorKey,
  132. window->GetProperty(aura::client::kResizeBehaviorKey) |
  133. aura::client::kResizeBehaviorCanMaximize);
  134. // It should be possible to snap a window if it can be maximized.
  135. EXPECT_TRUE(window_state->CanSnap());
  136. }
  137. // Test that a unresizable snappable property allows the window to be snapped.
  138. TEST_F(WindowStateTest, UnresizableWindowSnap) {
  139. const std::array<bool, 2> orientation_params{false, true};
  140. for (const auto is_landscape : orientation_params) {
  141. UpdateDisplay(is_landscape ? "900x600,200x100" : "600x900,100x200");
  142. auto* const screen = display::Screen::GetScreen();
  143. ASSERT_EQ(2, screen->GetNumDisplays());
  144. const display::Display primary_display = screen->GetAllDisplays()[0];
  145. const display::Display secondary_small_display =
  146. screen->GetAllDisplays()[1];
  147. ASSERT_EQ(is_landscape, primary_display.is_landscape());
  148. ASSERT_EQ(is_landscape, secondary_small_display.is_landscape());
  149. std::unique_ptr<aura::Window> window(
  150. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  151. // Make the window unresizable.
  152. window->SetProperty(aura::client::kResizeBehaviorKey,
  153. aura::client::kResizeBehaviorNone);
  154. auto* const window_state = WindowState::Get(window.get());
  155. EXPECT_FALSE(window_state->CanSnap());
  156. EXPECT_FALSE(window_state->CanSnapOnDisplay(primary_display));
  157. EXPECT_FALSE(window_state->CanSnapOnDisplay(secondary_small_display));
  158. auto* const opposite_orientation_size =
  159. is_landscape ? new gfx::Size(0, 300) : new gfx::Size(300, 0);
  160. window->SetProperty(kUnresizableSnappedSizeKey, opposite_orientation_size);
  161. EXPECT_FALSE(window_state->CanSnap());
  162. EXPECT_FALSE(window_state->CanSnapOnDisplay(primary_display));
  163. EXPECT_FALSE(window_state->CanSnapOnDisplay(secondary_small_display));
  164. auto* const correct_orientation_size =
  165. is_landscape ? new gfx::Size(300, 0) : new gfx::Size(0, 300);
  166. window->SetProperty(kUnresizableSnappedSizeKey, correct_orientation_size);
  167. EXPECT_TRUE(window_state->CanSnap());
  168. EXPECT_TRUE(window_state->CanSnapOnDisplay(primary_display));
  169. EXPECT_FALSE(window_state->CanSnapOnDisplay(secondary_small_display));
  170. window_util::MoveWindowToDisplay(window.get(),
  171. secondary_small_display.id());
  172. EXPECT_FALSE(window_state->CanSnap());
  173. EXPECT_TRUE(window_state->CanSnapOnDisplay(primary_display));
  174. EXPECT_FALSE(window_state->CanSnapOnDisplay(secondary_small_display));
  175. }
  176. }
  177. // Test that a unresizable snappable property doesn't have any effect in tablet
  178. // mode.
  179. TEST_F(WindowStateTest, UnresizableWindowSnapInTablet) {
  180. UpdateDisplay("900x600");
  181. // Enter tablet mode.
  182. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  183. std::unique_ptr<aura::Window> window(
  184. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  185. window->SetProperty(aura::client::kResizeBehaviorKey,
  186. aura::client::kResizeBehaviorNone);
  187. window->SetProperty(kUnresizableSnappedSizeKey, new gfx::Size(300, 0));
  188. auto* const window_state = WindowState::Get(window.get());
  189. EXPECT_FALSE(window_state->CanSnap());
  190. }
  191. // Test that a window's state type can be changed to PIP via a WM transition
  192. // event.
  193. TEST_F(WindowStateTest, CanTransitionToPipWindow) {
  194. std::unique_ptr<aura::Window> window(
  195. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  196. WindowState* window_state = WindowState::Get(window.get());
  197. EXPECT_FALSE(window_state->IsPip());
  198. const WMEvent enter_pip(WM_EVENT_PIP);
  199. window_state->OnWMEvent(&enter_pip);
  200. EXPECT_TRUE(window_state->IsPip());
  201. }
  202. // Test that a PIP window cannot be snapped.
  203. TEST_F(WindowStateTest, PipWindowCannotSnap) {
  204. std::unique_ptr<aura::Window> window(
  205. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  206. WindowState* window_state = WindowState::Get(window.get());
  207. EXPECT_TRUE(window_state->CanSnap());
  208. const WMEvent enter_pip(WM_EVENT_PIP);
  209. window_state->OnWMEvent(&enter_pip);
  210. EXPECT_FALSE(window_state->CanSnap());
  211. }
  212. TEST_F(WindowStateTest, ChromePipWindowUmaMetrics) {
  213. base::HistogramTester histograms;
  214. std::unique_ptr<aura::Window> window(
  215. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  216. WindowState* window_state = WindowState::Get(window.get());
  217. const WMEvent enter_pip(WM_EVENT_PIP);
  218. window_state->OnWMEvent(&enter_pip);
  219. EXPECT_EQ(1, histograms.GetBucketCount(kAshPipEventsHistogramName,
  220. Sample(AshPipEvents::PIP_START)));
  221. EXPECT_EQ(1,
  222. histograms.GetBucketCount(kAshPipEventsHistogramName,
  223. Sample(AshPipEvents::CHROME_PIP_START)));
  224. histograms.ExpectTotalCount(kAshPipEventsHistogramName, 2);
  225. const WMEvent enter_normal(WM_EVENT_NORMAL);
  226. window_state->OnWMEvent(&enter_normal);
  227. EXPECT_EQ(1, histograms.GetBucketCount(kAshPipEventsHistogramName,
  228. Sample(AshPipEvents::PIP_END)));
  229. EXPECT_EQ(1, histograms.GetBucketCount(kAshPipEventsHistogramName,
  230. Sample(AshPipEvents::CHROME_PIP_END)));
  231. histograms.ExpectTotalCount(kAshPipEventsHistogramName, 4);
  232. }
  233. TEST_F(WindowStateTest, AndroidPipWindowUmaMetrics) {
  234. base::HistogramTester histograms;
  235. std::unique_ptr<aura::Window> window(
  236. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  237. window->SetProperty(aura::client::kAppType,
  238. static_cast<int>(ash::AppType::ARC_APP));
  239. WindowState* window_state = WindowState::Get(window.get());
  240. const WMEvent enter_pip(WM_EVENT_PIP);
  241. window_state->OnWMEvent(&enter_pip);
  242. EXPECT_EQ(1, histograms.GetBucketCount(kAshPipEventsHistogramName,
  243. Sample(AshPipEvents::PIP_START)));
  244. EXPECT_EQ(1,
  245. histograms.GetBucketCount(kAshPipEventsHistogramName,
  246. Sample(AshPipEvents::ANDROID_PIP_START)));
  247. histograms.ExpectTotalCount(kAshPipEventsHistogramName, 2);
  248. const WMEvent enter_normal(WM_EVENT_NORMAL);
  249. window_state->OnWMEvent(&enter_normal);
  250. EXPECT_EQ(1, histograms.GetBucketCount(kAshPipEventsHistogramName,
  251. Sample(AshPipEvents::PIP_END)));
  252. EXPECT_EQ(1,
  253. histograms.GetBucketCount(kAshPipEventsHistogramName,
  254. Sample(AshPipEvents::ANDROID_PIP_END)));
  255. histograms.ExpectTotalCount(kAshPipEventsHistogramName, 4);
  256. // Check time count:
  257. histograms.ExpectTotalCount(kAshPipAndroidPipUseTimeHistogramName, 1);
  258. }
  259. TEST_F(WindowStateTest, ChromePipWindowUmaMetricsCountsExitOnDestroy) {
  260. base::HistogramTester histograms;
  261. std::unique_ptr<aura::Window> window(
  262. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  263. WindowState* window_state = WindowState::Get(window.get());
  264. const WMEvent enter_pip(WM_EVENT_PIP);
  265. window_state->OnWMEvent(&enter_pip);
  266. // Destroy the window.
  267. window.reset();
  268. EXPECT_EQ(1, histograms.GetBucketCount(kAshPipEventsHistogramName,
  269. Sample(AshPipEvents::PIP_END)));
  270. EXPECT_EQ(1, histograms.GetBucketCount(kAshPipEventsHistogramName,
  271. Sample(AshPipEvents::CHROME_PIP_END)));
  272. histograms.ExpectTotalCount(kAshPipEventsHistogramName, 4);
  273. }
  274. TEST_F(WindowStateTest, AndroidPipWindowUmaMetricsCountsExitOnDestroy) {
  275. base::HistogramTester histograms;
  276. std::unique_ptr<aura::Window> window(
  277. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  278. window->SetProperty(aura::client::kAppType,
  279. static_cast<int>(ash::AppType::ARC_APP));
  280. WindowState* window_state = WindowState::Get(window.get());
  281. const WMEvent enter_pip(WM_EVENT_PIP);
  282. window_state->OnWMEvent(&enter_pip);
  283. // Destroy the window.
  284. window.reset();
  285. EXPECT_EQ(1, histograms.GetBucketCount(kAshPipEventsHistogramName,
  286. Sample(AshPipEvents::PIP_END)));
  287. EXPECT_EQ(1,
  288. histograms.GetBucketCount(kAshPipEventsHistogramName,
  289. Sample(AshPipEvents::ANDROID_PIP_END)));
  290. histograms.ExpectTotalCount(kAshPipEventsHistogramName, 4);
  291. }
  292. // Test that modal window dialogs can be snapped.
  293. TEST_F(WindowStateTest, SnapModalWindow) {
  294. UpdateDisplay("0+0-600x900");
  295. const gfx::Rect kWorkAreaBounds =
  296. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  297. aura::test::TestWindowDelegate parent_delegate;
  298. std::unique_ptr<aura::Window> parent_window(
  299. CreateTestWindowInShellWithDelegate(
  300. &parent_delegate, -1,
  301. gfx::Rect(kWorkAreaBounds.width(), 0, kWorkAreaBounds.width() / 2,
  302. kWorkAreaBounds.height() - 1)));
  303. aura::test::TestWindowDelegate delegate;
  304. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
  305. &delegate, -1, gfx::Rect(100, 100, 400, 500)));
  306. delegate.set_minimum_size(gfx::Size(200, 300));
  307. WindowState* window_state = WindowState::Get(window.get());
  308. EXPECT_TRUE(window_state->CanSnap());
  309. ::wm::AddTransientChild(parent_window.get(), window.get());
  310. EXPECT_TRUE(window_state->CanSnap());
  311. window->SetProperty(aura::client::kResizeBehaviorKey,
  312. aura::client::kResizeBehaviorCanResize);
  313. EXPECT_FALSE(window_state->CanSnap());
  314. ::wm::RemoveTransientChild(parent_window.get(), window.get());
  315. }
  316. // Test that the minimum size specified by aura::WindowDelegate gets respected.
  317. TEST_F(WindowStateTest, TestRespectMinimumSize) {
  318. UpdateDisplay("0+0-1024x768");
  319. aura::test::TestWindowDelegate delegate;
  320. const gfx::Size minimum_size(gfx::Size(500, 300));
  321. delegate.set_minimum_size(minimum_size);
  322. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
  323. &delegate, -1, gfx::Rect(0, 100, 100, 100)));
  324. // Check that the window has the correct minimum size.
  325. EXPECT_EQ(minimum_size.ToString(), window->bounds().size().ToString());
  326. // Set the size to something bigger - that should work.
  327. gfx::Rect bigger_bounds(700, 500, 700, 500);
  328. window->SetBounds(bigger_bounds);
  329. EXPECT_EQ(bigger_bounds.ToString(), window->bounds().ToString());
  330. // Set the size to something smaller - that should only resize to the smallest
  331. // possible size.
  332. gfx::Rect smaller_bounds(700, 500, 100, 100);
  333. window->SetBounds(smaller_bounds);
  334. EXPECT_EQ(minimum_size.ToString(), window->bounds().size().ToString());
  335. }
  336. // Test that the minimum window size specified by aura::WindowDelegate does not
  337. // exceed the screen size.
  338. TEST_F(WindowStateTest, TestIgnoreTooBigMinimumSize) {
  339. UpdateDisplay("0+0-1024x768");
  340. const gfx::Size work_area_size =
  341. display::Screen::GetScreen()->GetPrimaryDisplay().work_area().size();
  342. const gfx::Size illegal_size(1280, 960);
  343. const gfx::Rect illegal_bounds(gfx::Point(0, 0), illegal_size);
  344. aura::test::TestWindowDelegate delegate;
  345. const gfx::Size minimum_size(illegal_size);
  346. delegate.set_minimum_size(minimum_size);
  347. // The creation should force the window to respect the screen size.
  348. std::unique_ptr<aura::Window> window(
  349. CreateTestWindowInShellWithDelegate(&delegate, -1, illegal_bounds));
  350. EXPECT_EQ(work_area_size.ToString(), window->bounds().size().ToString());
  351. // Trying to set the size to something bigger then the screen size should be
  352. // ignored.
  353. window->SetBounds(illegal_bounds);
  354. EXPECT_EQ(work_area_size.ToString(), window->bounds().size().ToString());
  355. // Maximizing the window should not allow it to go bigger than that either.
  356. WindowState* window_state = WindowState::Get(window.get());
  357. window_state->Maximize();
  358. EXPECT_EQ(work_area_size.ToString(), window->bounds().size().ToString());
  359. }
  360. // Test that the maximum size specified by aura::WindowDelegate gets respected.
  361. TEST_F(WindowStateTest, TestRespectMaximumSize) {
  362. aura::test::TestWindowDelegate delegate;
  363. constexpr gfx::Size max_size(300, 250);
  364. constexpr gfx::Size smaller_size(100, 100);
  365. constexpr gfx::Size larger_size(500, 400);
  366. delegate.set_maximum_size(max_size);
  367. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
  368. &delegate, -1, gfx::Rect(larger_size)));
  369. // Check that the window has the correct maximum size.
  370. EXPECT_EQ(max_size, window->bounds().size());
  371. window->SetBounds(gfx::Rect(smaller_size));
  372. EXPECT_EQ(smaller_size, window->bounds().size());
  373. window->SetBounds(gfx::Rect(larger_size));
  374. EXPECT_EQ(max_size, window->bounds().size());
  375. }
  376. // Tests UpdateSnapRatio. (1) It should have ratio reset when window
  377. // enters snapped state; (2) it should update ratio on bounds event when
  378. // snapped.
  379. TEST_F(WindowStateTest, UpdateSnapWidthRatioTest) {
  380. UpdateDisplay("0+0-900x600");
  381. const gfx::Rect kWorkAreaBounds =
  382. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  383. aura::test::TestWindowDelegate delegate;
  384. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
  385. &delegate, -1, gfx::Rect(100, 100, 100, 100)));
  386. delegate.set_window_component(HTRIGHT);
  387. WindowState* window_state = WindowState::Get(window.get());
  388. const WindowSnapWMEvent cycle_snap_primary(WM_EVENT_CYCLE_SNAP_PRIMARY);
  389. window_state->OnWMEvent(&cycle_snap_primary);
  390. EXPECT_EQ(WindowStateType::kPrimarySnapped, window_state->GetStateType());
  391. gfx::Rect expected =
  392. gfx::Rect(kWorkAreaBounds.x(), kWorkAreaBounds.y(),
  393. kWorkAreaBounds.width() / 2, kWorkAreaBounds.height());
  394. EXPECT_EQ(expected, window->GetBoundsInScreen());
  395. EXPECT_EQ(0.5f, *window_state->snap_ratio());
  396. // Drag to change snapped window width.
  397. const int kIncreasedWidth = 225;
  398. ui::test::EventGenerator* generator = GetEventGenerator();
  399. generator->MoveMouseTo(window->bounds().right(), window->bounds().y());
  400. generator->PressLeftButton();
  401. generator->MoveMouseTo(window->bounds().right() + kIncreasedWidth,
  402. window->bounds().y());
  403. generator->ReleaseLeftButton();
  404. expected.set_width(expected.width() + kIncreasedWidth);
  405. EXPECT_EQ(expected, window->GetBoundsInScreen());
  406. EXPECT_EQ(WindowStateType::kPrimarySnapped, window_state->GetStateType());
  407. EXPECT_EQ(0.75f, *window_state->snap_ratio());
  408. // Another cycle snap left event will restore window state to normal.
  409. window_state->OnWMEvent(&cycle_snap_primary);
  410. EXPECT_EQ(WindowStateType::kNormal, window_state->GetStateType());
  411. EXPECT_TRUE(window_state->snap_ratio());
  412. // Another cycle snap left event will snap window and reset snapped width
  413. // ratio.
  414. window_state->OnWMEvent(&cycle_snap_primary);
  415. EXPECT_EQ(WindowStateType::kPrimarySnapped, window_state->GetStateType());
  416. EXPECT_EQ(0.5f, *window_state->snap_ratio());
  417. }
  418. // Tests that dragging and snapping the snapped window update the width ratio
  419. // correctly (crbug.com/1208969).
  420. TEST_F(WindowStateTest, SnapSnappedWindow) {
  421. ui::ScopedAnimationDurationScaleMode test_duration_mode(
  422. ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
  423. UpdateDisplay("800x600");
  424. const gfx::Rect kWorkAreaBounds =
  425. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  426. aura::test::TestWindowDelegate delegate;
  427. gfx::Size window_normal_size = gfx::Size(800, 100);
  428. std::unique_ptr<aura::Window> window =
  429. TestWindowBuilder()
  430. .SetBounds(gfx::Rect(window_normal_size))
  431. .SetDelegate(&delegate)
  432. .AllowAllWindowStates()
  433. .Build();
  434. delegate.set_window_component(HTCAPTION);
  435. WindowState* window_state = WindowState::Get(window.get());
  436. const WindowSnapWMEvent cycle_snap_primary(WM_EVENT_CYCLE_SNAP_PRIMARY);
  437. window_state->OnWMEvent(&cycle_snap_primary);
  438. // Snap window to primary position (left).
  439. EXPECT_EQ(WindowStateType::kPrimarySnapped, window_state->GetStateType());
  440. gfx::Rect expected =
  441. gfx::Rect(kWorkAreaBounds.x(), kWorkAreaBounds.y(),
  442. kWorkAreaBounds.width() / 2, kWorkAreaBounds.height());
  443. // Wait for the snapped animation to complete and test that the window bound
  444. // is primary-snapped and the snap width ratio is updated.
  445. window->layer()->GetAnimator()->Step(base::TimeTicks::Now() +
  446. base::Seconds(1));
  447. EXPECT_EQ(expected, window->GetBoundsInScreen());
  448. LOG(ERROR) << "pass here";
  449. EXPECT_EQ(0.5f, *window_state->snap_ratio());
  450. LOG(ERROR) << "pass here2";
  451. // Drag the window to unsnap but do not release.
  452. ui::test::EventGenerator* generator = GetEventGenerator();
  453. generator->MoveMouseTo(window->bounds().CenterPoint());
  454. generator->PressLeftButton();
  455. generator->MoveMouseBy(5, 0);
  456. // While dragged, the window size should restore to its normal bound.
  457. EXPECT_EQ(window_normal_size, window->bounds().size());
  458. EXPECT_EQ(1.0f, *window_state->snap_ratio());
  459. LOG(ERROR) << "pass here3";
  460. // Continue dragging the window and snap it back to the same position.
  461. generator->MoveMouseBy(-405, 0);
  462. generator->ReleaseLeftButton();
  463. // The snapped ratio should be correct regardless of whether the animation
  464. // is finished or not.
  465. EXPECT_EQ(0.5f, *window_state->snap_ratio());
  466. }
  467. // Test that snapping left/right preserves the restore bounds.
  468. TEST_F(WindowStateTest, RestoreBounds) {
  469. std::unique_ptr<aura::Window> window(
  470. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  471. WindowState* window_state = WindowState::Get(window.get());
  472. EXPECT_TRUE(window_state->IsNormalStateType());
  473. // 1) Start with restored window with restore bounds set.
  474. gfx::Rect restore_bounds = window->GetBoundsInScreen();
  475. restore_bounds.set_width(restore_bounds.width() + 1);
  476. window_state->SetRestoreBoundsInScreen(restore_bounds);
  477. const WindowSnapWMEvent snap_primary(WM_EVENT_SNAP_PRIMARY);
  478. window_state->OnWMEvent(&snap_primary);
  479. const WindowSnapWMEvent snap_secondary(WM_EVENT_SNAP_SECONDARY);
  480. window_state->OnWMEvent(&snap_secondary);
  481. EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
  482. EXPECT_EQ(restore_bounds.ToString(),
  483. window_state->GetRestoreBoundsInScreen().ToString());
  484. window_state->Restore();
  485. EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
  486. // 2) Start with restored bounds set as a result of maximizing the window.
  487. window_state->Maximize();
  488. gfx::Rect maximized_bounds = window->GetBoundsInScreen();
  489. EXPECT_NE(maximized_bounds.ToString(), restore_bounds.ToString());
  490. EXPECT_EQ(restore_bounds.ToString(),
  491. window_state->GetRestoreBoundsInScreen().ToString());
  492. window_state->OnWMEvent(&snap_primary);
  493. EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
  494. EXPECT_NE(maximized_bounds.ToString(),
  495. window->GetBoundsInScreen().ToString());
  496. EXPECT_EQ(restore_bounds.ToString(),
  497. window_state->GetRestoreBoundsInScreen().ToString());
  498. window_state->Restore();
  499. EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
  500. }
  501. // Test that maximizing an auto managed window, then snapping it puts the window
  502. // at the snapped bounds and not at the auto-managed (centered) bounds.
  503. TEST_F(WindowStateTest, AutoManaged) {
  504. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  505. WindowState* window_state = WindowState::Get(window.get());
  506. window_state->SetWindowPositionManaged(true);
  507. window->Hide();
  508. window->SetBounds(gfx::Rect(100, 100, 100, 100));
  509. window->Show();
  510. window_state->Maximize();
  511. const WindowSnapWMEvent snap_secondary(WM_EVENT_SNAP_SECONDARY);
  512. window_state->OnWMEvent(&snap_secondary);
  513. const gfx::Rect kWorkAreaBounds =
  514. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  515. gfx::Rect expected_snapped_bounds(
  516. kWorkAreaBounds.x() + kWorkAreaBounds.width() / 2, kWorkAreaBounds.y(),
  517. kWorkAreaBounds.width() / 2, kWorkAreaBounds.height());
  518. EXPECT_EQ(expected_snapped_bounds.ToString(),
  519. window->GetBoundsInScreen().ToString());
  520. // The window should still be auto managed despite being right maximized.
  521. EXPECT_TRUE(window_state->GetWindowPositionManaged());
  522. }
  523. // Test that the replacement of a State object works as expected.
  524. TEST_F(WindowStateTest, SimpleStateSwap) {
  525. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  526. WindowState* window_state = WindowState::Get(window.get());
  527. EXPECT_FALSE(window_state->IsMaximized());
  528. window_state->SetStateObject(std::unique_ptr<WindowState::State>(
  529. new AlwaysMaximizeTestState(window_state->GetStateType())));
  530. EXPECT_TRUE(window_state->IsMaximized());
  531. }
  532. // Test that the replacement of a state object, following a restore with the
  533. // original one restores the window to its original state.
  534. TEST_F(WindowStateTest, StateSwapRestore) {
  535. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  536. WindowState* window_state = WindowState::Get(window.get());
  537. EXPECT_FALSE(window_state->IsMaximized());
  538. std::unique_ptr<WindowState::State> old(
  539. window_state->SetStateObject(std::unique_ptr<WindowState::State>(
  540. new AlwaysMaximizeTestState(window_state->GetStateType()))));
  541. EXPECT_TRUE(window_state->IsMaximized());
  542. window_state->SetStateObject(std::move(old));
  543. EXPECT_FALSE(window_state->IsMaximized());
  544. }
  545. // Tests that a window that had same bounds as the work area shrinks after the
  546. // window is maximized and then restored.
  547. TEST_F(WindowStateTest, RestoredWindowBoundsShrink) {
  548. UpdateDisplay("0+0-600x900");
  549. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  550. WindowState* window_state = WindowState::Get(window.get());
  551. EXPECT_FALSE(window_state->IsMaximized());
  552. gfx::Rect work_area =
  553. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  554. window->SetBounds(work_area);
  555. window_state->Maximize();
  556. EXPECT_TRUE(window_state->IsMaximized());
  557. EXPECT_EQ(work_area.ToString(), window->bounds().ToString());
  558. window_state->Restore();
  559. EXPECT_FALSE(window_state->IsMaximized());
  560. EXPECT_NE(work_area.ToString(), window->bounds().ToString());
  561. EXPECT_TRUE(work_area.Contains(window->bounds()));
  562. }
  563. TEST_F(WindowStateTest, DoNotResizeMaximizedWindowInFullscreen) {
  564. const int shelf_inset_first = 600 - ShelfConfig::Get()->shelf_size();
  565. const int shelf_inset_second = 700 - ShelfConfig::Get()->shelf_size();
  566. std::unique_ptr<aura::Window> maximized(CreateTestWindowInShellWithId(0));
  567. std::unique_ptr<aura::Window> fullscreen(CreateTestWindowInShellWithId(1));
  568. WindowState* maximized_state = WindowState::Get(maximized.get());
  569. maximized_state->Maximize();
  570. ASSERT_TRUE(maximized_state->IsMaximized());
  571. EXPECT_EQ(gfx::Rect(0, 0, 800, shelf_inset_first).ToString(),
  572. maximized->GetBoundsInScreen().ToString());
  573. // Entering fullscreen mode will not update the maximized window's size
  574. // under fullscreen.
  575. WMEvent fullscreen_event(WM_EVENT_FULLSCREEN);
  576. WindowState* fullscreen_state = WindowState::Get(fullscreen.get());
  577. fullscreen_state->OnWMEvent(&fullscreen_event);
  578. ASSERT_TRUE(fullscreen_state->IsFullscreen());
  579. ASSERT_TRUE(maximized_state->IsMaximized());
  580. EXPECT_EQ(gfx::Rect(0, 0, 800, shelf_inset_first).ToString(),
  581. maximized->GetBoundsInScreen().ToString());
  582. // Updating display size will update the maximum window size.
  583. UpdateDisplay("900x700");
  584. EXPECT_EQ("0,0 900x700", maximized->GetBoundsInScreen().ToString());
  585. fullscreen.reset();
  586. // Exiting fullscreen will update the maximized window to the work area.
  587. EXPECT_EQ(gfx::Rect(0, 0, 900, shelf_inset_second).ToString(),
  588. maximized->GetBoundsInScreen().ToString());
  589. }
  590. TEST_F(WindowStateTest, TrustedPinned) {
  591. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  592. WindowState* window_state = WindowState::Get(window.get());
  593. EXPECT_FALSE(window_state->IsTrustedPinned());
  594. window_util::PinWindow(window.get(), true /* trusted */);
  595. EXPECT_TRUE(window_state->IsTrustedPinned());
  596. gfx::Rect work_area =
  597. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  598. EXPECT_EQ(work_area.ToString(), window->bounds().ToString());
  599. // Sending non-unpin/non-workspace related event should be ignored.
  600. {
  601. const WMEvent fullscreen_event(WM_EVENT_FULLSCREEN);
  602. window_state->OnWMEvent(&fullscreen_event);
  603. }
  604. EXPECT_TRUE(window_state->IsTrustedPinned());
  605. // Update display triggers workspace event.
  606. UpdateDisplay("300x200");
  607. EXPECT_EQ("0,0 300x200", window->GetBoundsInScreen().ToString());
  608. // Unpin should work.
  609. window_state->Restore();
  610. EXPECT_FALSE(window_state->IsTrustedPinned());
  611. }
  612. TEST_F(WindowStateTest, AllowSetBoundsDirect) {
  613. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  614. WindowState* window_state = WindowState::Get(window.get());
  615. EXPECT_FALSE(window_state->IsMaximized());
  616. gfx::Rect work_area =
  617. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  618. gfx::Rect original_bounds(50, 50, 200, 200);
  619. window->SetBounds(original_bounds);
  620. ASSERT_EQ(original_bounds, window->bounds());
  621. window_state->set_allow_set_bounds_direct(true);
  622. window_state->Maximize();
  623. EXPECT_TRUE(window_state->IsMaximized());
  624. EXPECT_EQ(work_area, window->bounds());
  625. gfx::Rect new_bounds(10, 10, 300, 300);
  626. window->SetBounds(new_bounds);
  627. EXPECT_EQ(new_bounds, window->bounds());
  628. window_state->Restore();
  629. EXPECT_FALSE(window_state->IsMaximized());
  630. EXPECT_EQ(original_bounds, window->bounds());
  631. window_state->set_allow_set_bounds_direct(false);
  632. window_state->Maximize();
  633. EXPECT_TRUE(window_state->IsMaximized());
  634. EXPECT_EQ(work_area, window->bounds());
  635. window->SetBounds(new_bounds);
  636. EXPECT_EQ(work_area, window->bounds());
  637. }
  638. TEST_F(WindowStateTest, FullscreenMinimizedSwitching) {
  639. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  640. WindowState* window_state = WindowState::Get(window.get());
  641. ToggleFullScreen(window_state, nullptr);
  642. ASSERT_TRUE(window_state->IsFullscreen());
  643. // Toggling the fullscreen window should restore to normal.
  644. ToggleFullScreen(window_state, nullptr);
  645. ASSERT_TRUE(window_state->IsNormalStateType());
  646. window_state->Maximize();
  647. ASSERT_TRUE(window_state->IsMaximized());
  648. ToggleFullScreen(window_state, nullptr);
  649. ASSERT_TRUE(window_state->IsFullscreen());
  650. // Toggling the fullscreen window should restore to maximized.
  651. ToggleFullScreen(window_state, nullptr);
  652. ASSERT_TRUE(window_state->IsMaximized());
  653. ToggleFullScreen(window_state, nullptr);
  654. ASSERT_TRUE(window_state->IsFullscreen());
  655. // Minimize from fullscreen.
  656. window_state->Minimize();
  657. ASSERT_TRUE(window_state->IsMinimized());
  658. // Unminimize should restore to fullscreen.
  659. window_state->Unminimize();
  660. ASSERT_TRUE(window_state->IsFullscreen());
  661. // Toggling the fullscreen window should restore to maximized.
  662. ToggleFullScreen(window_state, nullptr);
  663. ASSERT_TRUE(window_state->IsMaximized());
  664. // Minimize from fullscreen.
  665. window_state->Minimize();
  666. ASSERT_TRUE(window_state->IsMinimized());
  667. // Fullscreen a minimized window.
  668. ToggleFullScreen(window_state, nullptr);
  669. ASSERT_TRUE(window_state->IsFullscreen());
  670. // Toggling the fullscreen window should not return to minimized. It should
  671. // return to the state before minimizing and fullscreen.
  672. ToggleFullScreen(window_state, nullptr);
  673. ASSERT_TRUE(window_state->IsMaximized());
  674. }
  675. TEST_F(WindowStateTest, CanConsumeSystemKeys) {
  676. std::unique_ptr<aura::Window> window(
  677. CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
  678. WindowState* window_state = WindowState::Get(window.get());
  679. EXPECT_FALSE(window_state->CanConsumeSystemKeys());
  680. window->SetProperty(kCanConsumeSystemKeysKey, true);
  681. EXPECT_TRUE(window_state->CanConsumeSystemKeys());
  682. }
  683. TEST_F(WindowStateTest,
  684. RestoreStateAfterEnteringPipViaOcculusionAndDismissingPip) {
  685. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  686. WindowState* window_state = WindowState::Get(window.get());
  687. window->Show();
  688. EXPECT_TRUE(window->layer()->visible());
  689. // Ensure a maximized window gets maximized again after it enters PIP via
  690. // occlusion, gets minimized, and unminimized.
  691. window_state->Maximize();
  692. EXPECT_TRUE(window_state->IsMaximized());
  693. const WMEvent enter_pip(WM_EVENT_PIP);
  694. window_state->OnWMEvent(&enter_pip);
  695. EXPECT_TRUE(window_state->IsPip());
  696. window_state->Minimize();
  697. EXPECT_TRUE(window_state->IsMinimized());
  698. window_state->Unminimize();
  699. EXPECT_TRUE(window_state->IsMaximized());
  700. // Ensure a freeform window gets freeform again after it enters PIP via
  701. // occulusion, gets minimized, and unminimized.
  702. ::wm::SetWindowState(window.get(), ui::SHOW_STATE_NORMAL);
  703. window_state->OnWMEvent(&enter_pip);
  704. EXPECT_TRUE(window_state->IsPip());
  705. window_state->Minimize();
  706. EXPECT_TRUE(window_state->IsMinimized());
  707. window_state->Unminimize();
  708. EXPECT_TRUE(window_state->GetStateType() == WindowStateType::kNormal);
  709. }
  710. TEST_F(WindowStateTest, RestoreStateAfterEnterPipViaMinimizeAndDismissingPip) {
  711. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  712. WindowState* window_state = WindowState::Get(window.get());
  713. window->Show();
  714. EXPECT_TRUE(window->layer()->visible());
  715. // Ensure a maximized window gets maximized again after it enters PIP via
  716. // minimize, gets minimized, and unminimized.
  717. window_state->Maximize();
  718. EXPECT_TRUE(window_state->IsMaximized());
  719. window_state->Minimize();
  720. EXPECT_TRUE(window_state->IsMinimized());
  721. const WMEvent enter_pip(WM_EVENT_PIP);
  722. window_state->OnWMEvent(&enter_pip);
  723. EXPECT_TRUE(window_state->IsPip());
  724. window_state->Minimize();
  725. EXPECT_TRUE(window_state->IsMinimized());
  726. window_state->Unminimize();
  727. EXPECT_TRUE(window_state->IsMaximized());
  728. // Ensure a freeform window gets freeform again after it enters PIP via
  729. // minimize, gets minimized, and unminimized.
  730. ::wm::SetWindowState(window.get(), ui::SHOW_STATE_NORMAL);
  731. window_state->Minimize();
  732. EXPECT_TRUE(window_state->IsMinimized());
  733. window_state->OnWMEvent(&enter_pip);
  734. EXPECT_TRUE(window_state->IsPip());
  735. window_state->Minimize();
  736. EXPECT_TRUE(window_state->IsMinimized());
  737. window_state->Unminimize();
  738. EXPECT_TRUE(window_state->GetStateType() == WindowStateType::kNormal);
  739. }
  740. TEST_F(WindowStateTest, SetBoundsUpdatesSizeOfPipRestoreBounds) {
  741. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
  742. WindowState* window_state = WindowState::Get(window.get());
  743. window->Show();
  744. window->SetBounds(gfx::Rect(0, 0, 50, 50));
  745. const WMEvent enter_pip(WM_EVENT_PIP);
  746. window_state->OnWMEvent(&enter_pip);
  747. EXPECT_TRUE(window_state->IsPip());
  748. EXPECT_TRUE(window_state->HasRestoreBounds());
  749. EXPECT_EQ(gfx::Rect(8, 8, 50, 50), window_state->GetRestoreBoundsInScreen());
  750. window_state->window()->SetBounds(gfx::Rect(100, 100, 100, 100));
  751. // SetBounds only updates the size of the restore bounds.
  752. EXPECT_EQ(gfx::Rect(8, 8, 100, 100),
  753. window_state->GetRestoreBoundsInScreen());
  754. }
  755. TEST_F(WindowStateTest, SetBoundsSnapsPipBoundsToScreenEdge) {
  756. UpdateDisplay("600x900");
  757. aura::test::TestWindowDelegate delegate;
  758. delegate.set_minimum_size(gfx::Size(51, 51));
  759. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
  760. &delegate, -1, gfx::Rect(0, 0, 50, 50)));
  761. WindowState* window_state = WindowState::Get(window.get());
  762. window->Show();
  763. const WMEvent enter_pip(WM_EVENT_PIP);
  764. window_state->OnWMEvent(&enter_pip);
  765. window->SetBounds(gfx::Rect(542, 50, 50, 50));
  766. EXPECT_TRUE(window_state->IsPip());
  767. // Ensure that the PIP window is along the right edge of the screen even when
  768. // the new bounds is adjusted by the minimum size.
  769. // 541 (left origin) + 51 (PIP width) + 8 (PIP insets) == 600.
  770. EXPECT_EQ(gfx::Rect(541, 50, 51, 51),
  771. window_state->window()->GetBoundsInScreen());
  772. PipPositioner::SaveSnapFraction(window_state,
  773. window_state->window()->GetBoundsInScreen());
  774. EXPECT_TRUE(PipPositioner::HasSnapFraction(window_state));
  775. EXPECT_EQ(gfx::Rect(541, 50, 51, 51),
  776. PipPositioner::GetPositionAfterMovementAreaChange(window_state));
  777. }
  778. // Make sure the window is transparent only when it is in normal state.
  779. TEST_F(WindowStateTest, OpacityChange) {
  780. std::unique_ptr<aura::Window> window = CreateAppWindow();
  781. WindowState* window_state = WindowState::Get(window.get());
  782. EXPECT_TRUE(window_state->IsNormalStateType());
  783. EXPECT_TRUE(window->GetTransparent());
  784. window_state->Maximize();
  785. EXPECT_TRUE(window_state->IsMaximized());
  786. EXPECT_FALSE(window->GetTransparent());
  787. window_state->Restore();
  788. EXPECT_TRUE(window_state->IsNormalStateType());
  789. EXPECT_TRUE(window->GetTransparent());
  790. window_state->Minimize();
  791. EXPECT_TRUE(window_state->IsMinimized());
  792. EXPECT_FALSE(window->GetTransparent());
  793. window_state->Unminimize();
  794. EXPECT_TRUE(window_state->IsNormalStateType());
  795. EXPECT_TRUE(window->GetTransparent());
  796. ToggleFullScreen(window_state, nullptr);
  797. ASSERT_TRUE(window_state->IsFullscreen());
  798. EXPECT_FALSE(window->GetTransparent());
  799. window_state->Restore();
  800. EXPECT_TRUE(window_state->IsNormalStateType());
  801. EXPECT_TRUE(window->GetTransparent());
  802. const WindowSnapWMEvent snap_primary(WM_EVENT_SNAP_PRIMARY);
  803. window_state->OnWMEvent(&snap_primary);
  804. EXPECT_FALSE(window->GetTransparent());
  805. window_state->Restore();
  806. EXPECT_TRUE(window->GetTransparent());
  807. const WindowSnapWMEvent snap_secondary(WM_EVENT_SNAP_SECONDARY);
  808. window_state->OnWMEvent(&snap_primary);
  809. EXPECT_FALSE(window->GetTransparent());
  810. window_state->OnWMEvent(&snap_primary);
  811. EXPECT_FALSE(window->GetTransparent());
  812. }
  813. // Tests the basic functionalties related to window state restore history stack.
  814. TEST_F(WindowStateTest, WindowStateRestoreHistoryBasicFunctionalites) {
  815. // Start with kDefault window state.
  816. std::unique_ptr<aura::Window> window = CreateAppWindow();
  817. WindowState* window_state = WindowState::Get(window.get());
  818. EXPECT_TRUE(window_state->IsNormalStateType());
  819. const std::vector<chromeos::WindowStateType>& restore_stack =
  820. window_state->window_state_restore_history_for_testing();
  821. EXPECT_TRUE(restore_stack.empty());
  822. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  823. // Transition to kPrimarySnapped window state.
  824. const WindowSnapWMEvent snap_primary(WM_EVENT_SNAP_PRIMARY);
  825. window_state->OnWMEvent(&snap_primary);
  826. EXPECT_EQ(restore_stack.size(), 1u);
  827. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  828. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  829. // Then transition to kMaximized window state.
  830. const WMEvent maximize_event(WM_EVENT_MAXIMIZE);
  831. window_state->OnWMEvent(&maximize_event);
  832. EXPECT_EQ(restore_stack.size(), 2u);
  833. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  834. EXPECT_EQ(restore_stack[1], WindowStateType::kPrimarySnapped);
  835. EXPECT_EQ(window_state->GetRestoreWindowState(),
  836. WindowStateType::kPrimarySnapped);
  837. // Then transition to kFullscreen window state.
  838. const WMEvent fullscreen_event(WM_EVENT_FULLSCREEN);
  839. window_state->OnWMEvent(&fullscreen_event);
  840. EXPECT_EQ(restore_stack.size(), 3u);
  841. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  842. EXPECT_EQ(restore_stack[1], WindowStateType::kPrimarySnapped);
  843. EXPECT_EQ(restore_stack[2], WindowStateType::kMaximized);
  844. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kMaximized);
  845. // Then transition to kMinimized window state.
  846. const WMEvent minimized_event(WM_EVENT_MINIMIZE);
  847. window_state->OnWMEvent(&minimized_event);
  848. EXPECT_EQ(restore_stack.size(), 4u);
  849. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  850. EXPECT_EQ(restore_stack[1], WindowStateType::kPrimarySnapped);
  851. EXPECT_EQ(restore_stack[2], WindowStateType::kMaximized);
  852. EXPECT_EQ(restore_stack[3], WindowStateType::kFullscreen);
  853. EXPECT_EQ(window_state->GetRestoreWindowState(),
  854. WindowStateType::kFullscreen);
  855. // Then start restore from here. It should restore back to kFullscreen window
  856. // state.
  857. window_state->Restore();
  858. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kFullscreen);
  859. EXPECT_EQ(restore_stack.size(), 3u);
  860. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  861. EXPECT_EQ(restore_stack[1], WindowStateType::kPrimarySnapped);
  862. EXPECT_EQ(restore_stack[2], WindowStateType::kMaximized);
  863. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kMaximized);
  864. // Then restore back to kMaximized window state.
  865. window_state->Restore();
  866. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kMaximized);
  867. EXPECT_EQ(restore_stack.size(), 2u);
  868. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  869. EXPECT_EQ(restore_stack[1], WindowStateType::kPrimarySnapped);
  870. EXPECT_EQ(window_state->GetRestoreWindowState(),
  871. WindowStateType::kPrimarySnapped);
  872. // Then restore back to kPrimarySnapped window state.
  873. window_state->Restore();
  874. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kPrimarySnapped);
  875. EXPECT_EQ(restore_stack.size(), 1u);
  876. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  877. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  878. // Then restore back to kNormal window state.
  879. window_state->Restore();
  880. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kNormal);
  881. EXPECT_TRUE(restore_stack.empty());
  882. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  883. // Restore a kNormal window state window will keep the window's kNormal window
  884. // state.
  885. window_state->Restore();
  886. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kNormal);
  887. EXPECT_TRUE(restore_stack.empty());
  888. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  889. }
  890. // Tests that window state transitioning from higher to lower layer will erase
  891. // the window state restore history in between.
  892. TEST_F(WindowStateTest, TransitionFromHighToLowerLayerEraseRestoreHistory) {
  893. // Start with kDefault window state.
  894. std::unique_ptr<aura::Window> window = CreateAppWindow();
  895. WindowState* window_state = WindowState::Get(window.get());
  896. EXPECT_TRUE(window_state->IsNormalStateType());
  897. const std::vector<chromeos::WindowStateType>& restore_stack =
  898. window_state->window_state_restore_history_for_testing();
  899. EXPECT_TRUE(restore_stack.empty());
  900. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  901. // Transition to kPrimarySnapped window state.
  902. const WindowSnapWMEvent snap_primary(WM_EVENT_SNAP_PRIMARY);
  903. window_state->OnWMEvent(&snap_primary);
  904. // Then transition to kMaximized window state.
  905. const WMEvent maximize_event(WM_EVENT_MAXIMIZE);
  906. window_state->OnWMEvent(&maximize_event);
  907. // Then transition to kFullscreen window state.
  908. const WMEvent fullscreen_event(WM_EVENT_FULLSCREEN);
  909. window_state->OnWMEvent(&fullscreen_event);
  910. EXPECT_EQ(restore_stack.size(), 3u);
  911. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  912. EXPECT_EQ(restore_stack[1], WindowStateType::kPrimarySnapped);
  913. EXPECT_EQ(restore_stack[2], WindowStateType::kMaximized);
  914. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kMaximized);
  915. // Now transition back to kPrimarySnapped window state. It should have erased
  916. // any restore history after kPrimarySnapped.
  917. window_state->OnWMEvent(&snap_primary);
  918. EXPECT_EQ(restore_stack.size(), 1u);
  919. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  920. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  921. }
  922. // Tests the restore behaviors when window state transitions in the same layer.
  923. // There are 3 cases: {kNormal & kDefault}, {kPrimarySnapped &
  924. // kSecondarySnapped}, and {kMinimized & kPip}.
  925. TEST_F(WindowStateTest, TransitionInTheSameLayerKeepSameRestoreHistory) {
  926. // First we test kNormal & kDefault.
  927. // Start with kDefault window state.
  928. std::unique_ptr<aura::Window> window = CreateAppWindow();
  929. WindowState* window_state = WindowState::Get(window.get());
  930. EXPECT_TRUE(window_state->IsNormalStateType());
  931. const std::vector<chromeos::WindowStateType>& restore_stack =
  932. window_state->window_state_restore_history_for_testing();
  933. EXPECT_TRUE(restore_stack.empty());
  934. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  935. // Transition to kNormal window state. Since it's on the same layer as
  936. // kDefault, kDefault won't be pushed into the restore history stack.
  937. const WMEvent normal_event(WM_EVENT_NORMAL);
  938. window_state->OnWMEvent(&normal_event);
  939. EXPECT_TRUE(restore_stack.empty());
  940. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  941. // Test kPrimarySnapped & kSecondarySnapped.
  942. // Transition to kPrimarySnapped window state.
  943. const WindowSnapWMEvent snap_primary(WM_EVENT_SNAP_PRIMARY);
  944. window_state->OnWMEvent(&snap_primary);
  945. EXPECT_EQ(restore_stack.size(), 1u);
  946. EXPECT_EQ(restore_stack[0], WindowStateType::kNormal);
  947. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  948. // Transition to kSecondarySnapped window state. Since it's on the same layer
  949. // as kPrimarySnapped, kPrimarySnapped won't be pushed into the restore
  950. // history stack.
  951. const WindowSnapWMEvent snap_secondary(WM_EVENT_SNAP_SECONDARY);
  952. window_state->OnWMEvent(&snap_secondary);
  953. EXPECT_EQ(restore_stack.size(), 1u);
  954. EXPECT_EQ(restore_stack[0], WindowStateType::kNormal);
  955. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  956. // Test kMinimized & kPip.
  957. // Transition to kMinimized window state.
  958. const WMEvent minimized_event(WM_EVENT_MINIMIZE);
  959. window_state->OnWMEvent(&minimized_event);
  960. EXPECT_EQ(restore_stack.size(), 2u);
  961. EXPECT_EQ(restore_stack[0], WindowStateType::kNormal);
  962. EXPECT_EQ(restore_stack[1], WindowStateType::kSecondarySnapped);
  963. EXPECT_EQ(window_state->GetRestoreWindowState(),
  964. WindowStateType::kSecondarySnapped);
  965. // Transition to kPip Window state. Since it's on the same layer as
  966. // kMinimized, kMinimized won't be pushed into the restore history stack.
  967. const WMEvent pip_event(WM_EVENT_PIP);
  968. window_state->OnWMEvent(&pip_event);
  969. EXPECT_EQ(restore_stack.size(), 2u);
  970. EXPECT_EQ(restore_stack[0], WindowStateType::kNormal);
  971. EXPECT_EQ(restore_stack[1], WindowStateType::kSecondarySnapped);
  972. EXPECT_EQ(window_state->GetRestoreWindowState(),
  973. WindowStateType::kSecondarySnapped);
  974. }
  975. // Test the restore behaviors of kPinned and kTrustedPinned window state. They
  976. // are different with kFullscreen restore behaviors.
  977. TEST_F(WindowStateTest, PinnedRestoreTest) {
  978. // Start with kDefault window state.
  979. std::unique_ptr<aura::Window> window = CreateAppWindow();
  980. WindowState* window_state = WindowState::Get(window.get());
  981. EXPECT_TRUE(window_state->IsNormalStateType());
  982. const std::vector<chromeos::WindowStateType>& restore_stack =
  983. window_state->window_state_restore_history_for_testing();
  984. EXPECT_TRUE(restore_stack.empty());
  985. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  986. // Transition to kPrimarySnapped window state.
  987. const WindowSnapWMEvent snap_primary(WM_EVENT_SNAP_PRIMARY);
  988. window_state->OnWMEvent(&snap_primary);
  989. // Then transition to kMaximized window state.
  990. const WMEvent maximize_event(WM_EVENT_MAXIMIZE);
  991. window_state->OnWMEvent(&maximize_event);
  992. EXPECT_EQ(restore_stack.size(), 2u);
  993. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  994. EXPECT_EQ(restore_stack[1], WindowStateType::kPrimarySnapped);
  995. EXPECT_EQ(window_state->GetRestoreWindowState(),
  996. WindowStateType::kPrimarySnapped);
  997. // Then transition to kPinned window state. Since kPinned window state is not
  998. // supported in the window state restore history layer, the restore history
  999. // stack will be cleared. It can only restore back to kNormal window state.
  1000. const WMEvent pinned_event(WM_EVENT_PIN);
  1001. window_state->OnWMEvent(&pinned_event);
  1002. EXPECT_TRUE(restore_stack.empty());
  1003. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  1004. window_state->Restore();
  1005. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kNormal);
  1006. EXPECT_TRUE(restore_stack.empty());
  1007. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  1008. // Same should happen for kTrustedPinned as well.
  1009. window_state->OnWMEvent(&snap_primary);
  1010. window_state->OnWMEvent(&maximize_event);
  1011. EXPECT_EQ(restore_stack.size(), 2u);
  1012. EXPECT_EQ(window_state->GetRestoreWindowState(),
  1013. WindowStateType::kPrimarySnapped);
  1014. const WMEvent trusted_pinned_event(WM_EVENT_TRUSTED_PIN);
  1015. window_state->OnWMEvent(&trusted_pinned_event);
  1016. EXPECT_TRUE(restore_stack.empty());
  1017. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  1018. window_state->Restore();
  1019. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kNormal);
  1020. EXPECT_TRUE(restore_stack.empty());
  1021. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  1022. }
  1023. // Test the restore behaviors of kMinimized and kPip window state. They are both
  1024. // viewed as the final state in the restore layer.
  1025. TEST_F(WindowStateTest, MinimizedAndPipRestoreTest) {
  1026. // Start with kDefault window state.
  1027. std::unique_ptr<aura::Window> window = CreateAppWindow();
  1028. WindowState* window_state = WindowState::Get(window.get());
  1029. EXPECT_TRUE(window_state->IsNormalStateType());
  1030. const std::vector<chromeos::WindowStateType>& restore_stack =
  1031. window_state->window_state_restore_history_for_testing();
  1032. EXPECT_TRUE(restore_stack.empty());
  1033. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  1034. // Maximize the window.
  1035. const WMEvent maximize_event(WM_EVENT_MAXIMIZE);
  1036. window_state->OnWMEvent(&maximize_event);
  1037. EXPECT_EQ(restore_stack.size(), 1u);
  1038. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  1039. // kPip window can be minimized to kMinimized window state, but restoring from
  1040. // kMinimized window state can't restore back to kPip window state.
  1041. const WMEvent pip_event(WM_EVENT_PIP);
  1042. window_state->OnWMEvent(&pip_event);
  1043. EXPECT_EQ(restore_stack.size(), 2u);
  1044. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  1045. EXPECT_EQ(restore_stack[1], WindowStateType::kMaximized);
  1046. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kMaximized);
  1047. const WMEvent minimized_event(WM_EVENT_MINIMIZE);
  1048. window_state->OnWMEvent(&minimized_event);
  1049. EXPECT_EQ(restore_stack.size(), 2u);
  1050. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  1051. EXPECT_EQ(restore_stack[1], WindowStateType::kMaximized);
  1052. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kMaximized);
  1053. // Restore the minimized window. It should go back to pre-pip window state.
  1054. window_state->Restore();
  1055. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kMaximized);
  1056. EXPECT_EQ(restore_stack.size(), 1u);
  1057. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  1058. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  1059. // Similarly, if the pre-pip window state is kMinimized, restoring from kPip
  1060. // should go back to the pre-minimized window state.
  1061. window_state->OnWMEvent(&minimized_event);
  1062. EXPECT_EQ(restore_stack.size(), 2u);
  1063. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  1064. EXPECT_EQ(restore_stack[1], WindowStateType::kMaximized);
  1065. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kMaximized);
  1066. window_state->OnWMEvent(&pip_event);
  1067. EXPECT_EQ(restore_stack.size(), 2u);
  1068. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  1069. EXPECT_EQ(restore_stack[1], WindowStateType::kMaximized);
  1070. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kMaximized);
  1071. // Restore the Pip window. It should go back to pre-minimized window state.
  1072. window_state->Restore();
  1073. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kMaximized);
  1074. EXPECT_EQ(restore_stack.size(), 1u);
  1075. EXPECT_EQ(restore_stack[0], WindowStateType::kDefault);
  1076. EXPECT_EQ(window_state->GetRestoreWindowState(), WindowStateType::kNormal);
  1077. }
  1078. // Tests the restore behavior for default or normal window.
  1079. TEST_F(WindowStateTest, NormalOrDefaultRestore) {
  1080. // Start with kDefault window state.
  1081. std::unique_ptr<aura::Window> window = CreateAppWindow();
  1082. WindowState* window_state = WindowState::Get(window.get());
  1083. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kDefault);
  1084. // Restoring a kDefault window will change its window state to kNormal.
  1085. window_state->Restore();
  1086. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kNormal);
  1087. // Restoring kNormal window will do nothing.
  1088. window_state->Restore();
  1089. EXPECT_EQ(window_state->GetStateType(), WindowStateType::kNormal);
  1090. }
  1091. TEST_F(WindowStateTest, WindowSnapActionSourceUmaMetrics) {
  1092. UpdateDisplay("800x600");
  1093. base::HistogramTester histograms;
  1094. std::unique_ptr<aura::Window> window(CreateAppWindow());
  1095. WindowState* window_state = WindowState::Get(window.get());
  1096. // Use WMEvent to directly snap the window.
  1097. WindowSnapWMEvent snap_primary(WM_EVENT_SNAP_PRIMARY);
  1098. window_state->OnWMEvent(&snap_primary);
  1099. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1100. WindowSnapActionSource::kOthers, 1);
  1101. window_state->Maximize();
  1102. // Drag the window to the screen edge to snap.
  1103. std::unique_ptr<WindowResizer> resizer(CreateWindowResizer(
  1104. window.get(), gfx::PointF(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_TOUCH));
  1105. resizer->Drag(gfx::PointF(0, 400), 0);
  1106. resizer->CompleteDrag();
  1107. resizer.reset();
  1108. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1109. WindowSnapActionSource::kDragWindowToEdgeToSnap,
  1110. 1);
  1111. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1112. WindowSnapActionSource::kOthers, 1);
  1113. window_state->Maximize();
  1114. // Use keyboard to snap a window.
  1115. AcceleratorController::Get()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT,
  1116. {});
  1117. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1118. WindowSnapActionSource::kKeyboardShortcutToSnap,
  1119. 1);
  1120. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1121. WindowSnapActionSource::kOthers, 1);
  1122. window_state->Maximize();
  1123. // Restore the maximized window to snap window state.
  1124. window_state->Restore();
  1125. histograms.ExpectBucketCount(
  1126. kWindowSnapActionSourceHistogram,
  1127. WindowSnapActionSource::kSnapByWindowStateRestore, 1);
  1128. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1129. WindowSnapActionSource::kOthers, 1);
  1130. window_state->Maximize();
  1131. // Drag or select overview window to snap window.
  1132. ui::test::EventGenerator* generator = GetEventGenerator();
  1133. EnterOverview();
  1134. ASSERT_TRUE(GetOverviewSession());
  1135. const gfx::Point center_point =
  1136. gfx::ToRoundedPoint(GetOverviewSession()
  1137. ->GetOverviewItemForWindow(window.get())
  1138. ->target_bounds()
  1139. .CenterPoint());
  1140. generator->MoveMouseTo(center_point);
  1141. generator->DragMouseTo(gfx::Point(0, 400));
  1142. histograms.ExpectBucketCount(
  1143. kWindowSnapActionSourceHistogram,
  1144. WindowSnapActionSource::kDragOrSelectOverviewWindowToSnap, 1);
  1145. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1146. WindowSnapActionSource::kOthers, 1);
  1147. window_state->Maximize();
  1148. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  1149. EXPECT_TRUE(Shell::Get()->tablet_mode_controller()->InTabletMode());
  1150. // Use keyboard to snap the window in tablet mode.
  1151. AcceleratorController::Get()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT,
  1152. {});
  1153. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1154. WindowSnapActionSource::kKeyboardShortcutToSnap,
  1155. 2);
  1156. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1157. WindowSnapActionSource::kOthers, 1);
  1158. // Auto-snap in splitview.
  1159. std::unique_ptr<aura::Window> window2(CreateAppWindow());
  1160. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1161. WindowSnapActionSource::kAutoSnapBySplitview, 1);
  1162. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1163. WindowSnapActionSource::kOthers, 1);
  1164. // Resize in splitview.
  1165. auto* split_view_controller =
  1166. SplitViewController::Get(Shell::GetPrimaryRootWindow());
  1167. auto* split_view_divider = split_view_controller->split_view_divider();
  1168. gfx::Rect divider_bounds =
  1169. split_view_divider->GetDividerBoundsInScreen(false);
  1170. split_view_controller->StartResize(divider_bounds.CenterPoint());
  1171. gfx::Rect display_bounds =
  1172. screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
  1173. window.get());
  1174. gfx::Point resize_point(display_bounds.width() * 0.33f, 0);
  1175. split_view_controller->Resize(resize_point);
  1176. // This should not cause any metrics change.
  1177. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1178. WindowSnapActionSource::kOthers, 1);
  1179. split_view_controller->EndResize(resize_point);
  1180. histograms.ExpectBucketCount(kWindowSnapActionSourceHistogram,
  1181. WindowSnapActionSource::kOthers, 1);
  1182. }
  1183. // Test how the minimum height specified by the aura::WindowDelegate affects
  1184. // snapping in portrait display layout.
  1185. TEST_F(WindowStateTest, SnapWindowMinimumSizePortrait) {
  1186. UpdateDisplay("600x900");
  1187. const gfx::Rect kWorkAreaBounds =
  1188. display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  1189. aura::test::TestWindowDelegate delegate;
  1190. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
  1191. &delegate, -1, gfx::Rect(0, 100, kWorkAreaBounds.width() - 1, 100)));
  1192. // It should be possible to snap a window with a minimum width that is larger
  1193. // a half screen width in horizontal snap layout and snap a window with a
  1194. // minimum height that is longer than a half screen height in vertical snap
  1195. // layout.
  1196. const gfx::Size kMinimumSize = gfx::Size(0, 500);
  1197. delegate.set_minimum_size(kMinimumSize);
  1198. WindowState* window_state = WindowState::Get(window.get());
  1199. EXPECT_TRUE(window_state->CanSnap());
  1200. const WindowSnapWMEvent snap_secondary(WM_EVENT_SNAP_SECONDARY);
  1201. window_state->OnWMEvent(&snap_secondary);
  1202. // Expect right snap for horizontal snap layout with the minimum width and
  1203. // bottom snap for vertical snap layout with the minimum height.
  1204. const gfx::Rect expected_snap = gfx::Rect(
  1205. kWorkAreaBounds.x(), kWorkAreaBounds.height() - kMinimumSize.height(),
  1206. kWorkAreaBounds.width(), kMinimumSize.height());
  1207. EXPECT_EQ(expected_snap, window->GetBoundsInScreen());
  1208. }
  1209. // TODO(skuhne): Add more unit test to verify the correctness for the restore
  1210. // operation.
  1211. } // namespace
  1212. } // namespace ash