window_tree_host_unittest.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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 "ui/aura/window_tree_host.h"
  5. #include "base/containers/contains.h"
  6. #include "base/test/bind.h"
  7. #include "base/test/scoped_feature_list.h"
  8. #include "build/build_config.h"
  9. #include "build/chromeos_buildflags.h"
  10. #include "ui/aura/native_window_occlusion_tracker.h"
  11. #include "ui/aura/test/aura_test_base.h"
  12. #include "ui/aura/test/aura_test_utils.h"
  13. #include "ui/aura/test/test_screen.h"
  14. #include "ui/aura/test/window_event_dispatcher_test_api.h"
  15. #include "ui/aura/window.h"
  16. #include "ui/aura/window_tree_host_platform.h"
  17. #include "ui/base/ime/input_method.h"
  18. #include "ui/base/ui_base_features.h"
  19. #include "ui/compositor/compositor.h"
  20. #include "ui/compositor/layer.h"
  21. #include "ui/compositor/test/draw_waiter_for_test.h"
  22. #include "ui/events/event_rewriter.h"
  23. #include "ui/events/keycodes/dom/dom_code.h"
  24. #include "ui/events/test/test_event_rewriter.h"
  25. #include "ui/platform_window/stub/stub_window.h"
  26. #if BUILDFLAG(IS_WIN)
  27. #include "ui/aura/native_window_occlusion_tracker_win.h"
  28. #endif
  29. namespace aura {
  30. namespace {
  31. // A convenient wrapper that makes it easy to invoke this method inside an
  32. // EXPECT_EQ statement.
  33. gfx::Point ConvertDIPToPixels(const WindowTreeHost* host, gfx::Point point) {
  34. host->ConvertDIPToPixels(&point);
  35. return point;
  36. }
  37. // A convenient wrapper that makes it easy to invoke this method inside an
  38. // EXPECT_EQ statement.
  39. gfx::PointF ConvertDIPToPixels(const WindowTreeHost* host, gfx::PointF point) {
  40. host->ConvertDIPToPixels(&point);
  41. return point;
  42. }
  43. // A convenient wrapper that makes it easy to invoke this method inside an
  44. // EXPECT_EQ statement.
  45. gfx::Point ConvertPixelsToDIP(const WindowTreeHost* host, gfx::Point point) {
  46. host->ConvertPixelsToDIP(&point);
  47. return point;
  48. }
  49. // A convenient wrapper that makes it easy to invoke this method inside an
  50. // EXPECT_EQ statement.
  51. gfx::PointF ConvertPixelsToDIP(const WindowTreeHost* host, gfx::PointF point) {
  52. host->ConvertPixelsToDIP(&point);
  53. return point;
  54. }
  55. } // namespace
  56. using WindowTreeHostTest = test::AuraTestBase;
  57. TEST_F(WindowTreeHostTest, DPIWindowSize) {
  58. constexpr gfx::Rect starting_bounds(
  59. aura::test::AuraTestHelper::kDefaultHostSize);
  60. EXPECT_EQ(starting_bounds.size(), host()->compositor()->size());
  61. EXPECT_EQ(starting_bounds, host()->GetBoundsInPixels());
  62. EXPECT_EQ(starting_bounds, root_window()->bounds());
  63. test_screen()->SetDeviceScaleFactor(1.5f);
  64. EXPECT_EQ(starting_bounds, host()->GetBoundsInPixels());
  65. // Size should be rounded up after scaling.
  66. EXPECT_EQ(gfx::Rect(0, 0, 534, 400), root_window()->bounds());
  67. gfx::Transform transform;
  68. transform.Translate(0, -1.1f);
  69. host()->SetRootTransform(transform);
  70. EXPECT_EQ(gfx::Rect(0, 1, 534, 401), root_window()->bounds());
  71. EXPECT_EQ(starting_bounds, host()->GetBoundsInPixels());
  72. EXPECT_EQ(gfx::Rect(0, 1, 534, 401), root_window()->bounds());
  73. }
  74. TEST_F(WindowTreeHostTest,
  75. ShouldHaveExactRootWindowBoundsWithDisplayRotation1xScale) {
  76. test_screen()->SetDeviceScaleFactor(1.f);
  77. host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 300));
  78. test_screen()->SetDisplayRotation(display::Display::ROTATE_0);
  79. EXPECT_EQ(host()->GetBoundsInPixels(), gfx::Rect(0, 0, 400, 300));
  80. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().rotation(),
  81. display::Display::ROTATE_0);
  82. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel(),
  83. gfx::Size(400, 300));
  84. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().bounds(),
  85. gfx::Rect(0, 0, 400, 300));
  86. EXPECT_EQ(gfx::Rect(400, 300), host()->window()->bounds());
  87. host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 300));
  88. test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
  89. EXPECT_EQ(host()->GetBoundsInPixels(), gfx::Rect(0, 0, 400, 300));
  90. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().rotation(),
  91. display::Display::ROTATE_90);
  92. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel(),
  93. gfx::Size(300, 400));
  94. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().bounds(),
  95. gfx::Rect(0, 0, 300, 400));
  96. EXPECT_EQ(gfx::Rect(300, 400), host()->window()->bounds());
  97. host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 300));
  98. test_screen()->SetDisplayRotation(display::Display::ROTATE_180);
  99. EXPECT_EQ(host()->GetBoundsInPixels(), gfx::Rect(0, 0, 400, 300));
  100. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().rotation(),
  101. display::Display::ROTATE_180);
  102. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel(),
  103. gfx::Size(400, 300));
  104. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().bounds(),
  105. gfx::Rect(0, 0, 400, 300));
  106. EXPECT_EQ(gfx::Rect(400, 300), host()->window()->bounds());
  107. host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 300));
  108. test_screen()->SetDisplayRotation(display::Display::ROTATE_270);
  109. EXPECT_EQ(host()->GetBoundsInPixels(), gfx::Rect(0, 0, 400, 300));
  110. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().rotation(),
  111. display::Display::ROTATE_270);
  112. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel(),
  113. gfx::Size(300, 400));
  114. EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().bounds(),
  115. gfx::Rect(0, 0, 300, 400));
  116. EXPECT_EQ(gfx::Rect(300, 400), host()->window()->bounds());
  117. }
  118. #if BUILDFLAG(IS_CHROMEOS_ASH)
  119. TEST_F(WindowTreeHostTest, HoldPointerMovesOnChildResizing) {
  120. aura::WindowEventDispatcher* dispatcher = host()->dispatcher();
  121. aura::test::WindowEventDispatcherTestApi dispatcher_api(dispatcher);
  122. EXPECT_FALSE(dispatcher_api.HoldingPointerMoves());
  123. // Signal to the ui::Compositor that a child is resizing. This will
  124. // immediately trigger input throttling.
  125. host()->compositor()->OnChildResizing();
  126. // Pointer moves should be throttled until the next commit. This has the
  127. // effect of prioritizing the resize event above other operations in aura.
  128. EXPECT_TRUE(dispatcher_api.HoldingPointerMoves());
  129. // Wait for a CompositorFrame to be activated.
  130. ui::DrawWaiterForTest::WaitForCompositingEnded(host()->compositor());
  131. // Pointer moves should be routed normally after commit.
  132. EXPECT_FALSE(dispatcher_api.HoldingPointerMoves());
  133. }
  134. #endif
  135. #if !BUILDFLAG(IS_CHROMEOS_ASH)
  136. // Tests if scale factor changes take effect. Previously a scale factor change
  137. // wouldn't take effect without a bounds change. For context see
  138. // https://crbug.com/1087626
  139. TEST_F(WindowTreeHostTest, ShouldHandleTextScale) {
  140. constexpr gfx::Rect starting_bounds(
  141. aura::test::AuraTestHelper::kDefaultHostSize);
  142. auto asserter = [&](float test_scale_factor) {
  143. test_screen()->SetDeviceScaleFactor(test_scale_factor, false);
  144. EXPECT_EQ(starting_bounds, host()->GetBoundsInPixels());
  145. // Size should be rounded up after scaling.
  146. EXPECT_EQ(
  147. gfx::ScaleToEnclosingRect(starting_bounds, 1.0f / test_scale_factor),
  148. root_window()->bounds());
  149. EXPECT_EQ(test_scale_factor, host()->device_scale_factor());
  150. };
  151. asserter(1.0f);
  152. asserter(1.05f);
  153. asserter(1.5f);
  154. }
  155. #endif
  156. TEST_F(WindowTreeHostTest, NoRewritesPostIME) {
  157. ui::test::TestEventRewriter event_rewriter;
  158. host()->AddEventRewriter(&event_rewriter);
  159. ui::KeyEvent key_event('A', ui::VKEY_A, ui::DomCode::NONE, 0);
  160. ui::EventDispatchDetails details =
  161. host()->GetInputMethod()->DispatchKeyEvent(&key_event);
  162. ASSERT_TRUE(!details.dispatcher_destroyed && !details.target_destroyed);
  163. EXPECT_EQ(0, event_rewriter.events_seen());
  164. host()->RemoveEventRewriter(&event_rewriter);
  165. }
  166. TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldRespectScaleFactor) {
  167. const int width_in_pixels = 400;
  168. const int height_in_pixels = 300;
  169. const int width_in_dip = 200;
  170. const int height_in_dip = 150;
  171. host()->SetBoundsInPixels(gfx::Rect(0, 0, width_in_pixels, height_in_pixels));
  172. test_screen()->SetDisplayRotation(display::Display::ROTATE_0);
  173. test_screen()->SetDeviceScaleFactor(2.f);
  174. EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(0, 0)), gfx::Point(0, 0));
  175. EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(width_in_dip, 0)),
  176. gfx::Point(width_in_pixels, 0));
  177. EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(0, height_in_dip)),
  178. gfx::Point(0, height_in_pixels));
  179. }
  180. TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldRespectRotation) {
  181. const int width_in_pixels = 400;
  182. const int height_in_pixels = 300;
  183. const int width_in_dip = 300;
  184. const int height_in_dip = 400;
  185. host()->SetBoundsInPixels(gfx::Rect(0, 0, width_in_pixels, height_in_pixels));
  186. test_screen()->SetDeviceScaleFactor(1.f);
  187. test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
  188. EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(0, 0)),
  189. gfx::Point(width_in_pixels, 0));
  190. EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(width_in_dip, 0)),
  191. gfx::Point(width_in_pixels, height_in_pixels));
  192. EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(width_in_dip, height_in_dip)),
  193. gfx::Point(0, height_in_pixels));
  194. EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(0, height_in_dip)),
  195. gfx::Point(0, 0));
  196. }
  197. TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldWorkWithPointF) {
  198. host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 400));
  199. test_screen()->SetDisplayRotation(display::Display::ROTATE_0);
  200. test_screen()->SetDeviceScaleFactor(2.f);
  201. EXPECT_EQ(ConvertDIPToPixels(host(), gfx::PointF(5.3f, 0)),
  202. gfx::PointF(10.6f, 0));
  203. }
  204. TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldRespectScaleFactor) {
  205. const int width_in_pixels = 400;
  206. const int height_in_pixels = 300;
  207. const int width_in_dip = 200;
  208. const int height_in_dip = 150;
  209. host()->SetBoundsInPixels(gfx::Rect(0, 0, width_in_pixels, height_in_pixels));
  210. test_screen()->SetDisplayRotation(display::Display::ROTATE_0);
  211. test_screen()->SetDeviceScaleFactor(2.f);
  212. EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(0, 0)), gfx::Point(0, 0));
  213. EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(width_in_pixels, 0)),
  214. gfx::Point(width_in_dip, 0));
  215. EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(0, height_in_pixels)),
  216. gfx::Point(0, height_in_dip));
  217. }
  218. TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldRespectRotation) {
  219. const int width_in_pixels = 400;
  220. const int height_in_pixels = 300;
  221. const int width_in_dip = 300;
  222. const int height_in_dip = 400;
  223. host()->SetBoundsInPixels(gfx::Rect(0, 0, width_in_pixels, height_in_pixels));
  224. test_screen()->SetDeviceScaleFactor(1.f);
  225. test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
  226. EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(0, 0)),
  227. gfx::Point(0, height_in_dip));
  228. EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(width_in_pixels, 0)),
  229. gfx::Point(0, 0));
  230. EXPECT_EQ(
  231. ConvertPixelsToDIP(host(), gfx::Point(width_in_pixels, height_in_pixels)),
  232. gfx::Point(width_in_dip, 0));
  233. EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(0, height_in_pixels)),
  234. gfx::Point(width_in_dip, height_in_dip));
  235. }
  236. TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldWorkWithPointF) {
  237. host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 400));
  238. test_screen()->SetDisplayRotation(display::Display::ROTATE_0);
  239. test_screen()->SetDeviceScaleFactor(2.f);
  240. EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::PointF(10.6f, 0)),
  241. gfx::PointF(5.3f, 0));
  242. }
  243. class TestWindow : public ui::StubWindow {
  244. public:
  245. explicit TestWindow(ui::PlatformWindowDelegate* delegate)
  246. : StubWindow(delegate, false, gfx::Rect(400, 600)) {}
  247. TestWindow(const TestWindow&) = delete;
  248. TestWindow& operator=(const TestWindow&) = delete;
  249. ~TestWindow() override {}
  250. private:
  251. // ui::StubWindow
  252. void Close() override {
  253. // It is possible for the window to receive capture-change messages during
  254. // destruction, for example on Windows (see crbug.com/770670).
  255. delegate()->OnLostCapture();
  256. }
  257. };
  258. class TestWindowTreeHost : public WindowTreeHostPlatform {
  259. public:
  260. TestWindowTreeHost() {
  261. SetPlatformWindow(std::make_unique<TestWindow>(this));
  262. CreateCompositor();
  263. }
  264. TestWindowTreeHost(const TestWindowTreeHost&) = delete;
  265. TestWindowTreeHost& operator=(const TestWindowTreeHost&) = delete;
  266. };
  267. TEST_F(WindowTreeHostTest, LostCaptureDuringTearDown) {
  268. #if BUILDFLAG(IS_WIN)
  269. base::test::ScopedFeatureList scoped_feature_list;
  270. scoped_feature_list.InitAndDisableFeature(
  271. features::kApplyNativeOcclusionToCompositor);
  272. #endif
  273. TestWindowTreeHost host;
  274. }
  275. #if BUILDFLAG(IS_WIN)
  276. class WindowTreeHostWithReleaseTest : public test::AuraTestBase {
  277. public:
  278. // AuraTestBase:
  279. void SetUp() override {
  280. // Disable the headless check as the bots run with CHROME_HEADLESS set.
  281. NativeWindowOcclusionTracker::SetHeadlessCheckEnabled(false);
  282. scoped_feature_list_.InitWithFeaturesAndParameters(
  283. {
  284. {features::kCalculateNativeWinOcclusion, {}},
  285. {features::kApplyNativeOcclusionToCompositor,
  286. {{features::kApplyNativeOcclusionToCompositorType,
  287. features::kApplyNativeOcclusionToCompositorTypeRelease}}},
  288. },
  289. {});
  290. AuraTestBase::SetUp();
  291. }
  292. void TearDown() override {
  293. test::AuraTestBase::TearDown();
  294. NativeWindowOcclusionTracker::SetHeadlessCheckEnabled(true);
  295. }
  296. private:
  297. base::test::ScopedFeatureList scoped_feature_list_;
  298. };
  299. cc::Layer* ccLayerFromUiLayer(ui::Layer* layer) {
  300. return static_cast<ui::LayerAnimationDelegate*>(layer)->GetCcLayer();
  301. }
  302. bool WaitForFrame(WindowTreeHost* host) {
  303. base::RunLoop run_loop;
  304. bool got_frame = false;
  305. host->compositor()->RequestPresentationTimeForNextFrame(
  306. base::BindLambdaForTesting(
  307. [&](const gfx::PresentationFeedback& feedback) {
  308. got_frame = true;
  309. run_loop.Quit();
  310. }));
  311. run_loop.Run();
  312. return got_frame;
  313. }
  314. TEST_F(WindowTreeHostWithReleaseTest, ToggleOccluded) {
  315. host()->Show();
  316. // This tests needs to drive native occlusion. If native occlusion is
  317. // used, it'll conflict with this test.
  318. NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  319. ASSERT_TRUE(NativeWindowOcclusionTracker::
  320. IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  321. cc::Layer* host_window_cc_layer =
  322. ccLayerFromUiLayer(host()->window()->layer());
  323. const cc::Layer* compositor_root_layer = host_window_cc_layer->parent();
  324. EXPECT_NE(nullptr, compositor_root_layer);
  325. host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  326. // The compositor shouldn't actually hide immediately, it needs a frame to
  327. // be generated.
  328. EXPECT_TRUE(host()->compositor()->IsVisible());
  329. EXPECT_EQ(nullptr, host_window_cc_layer->parent());
  330. ASSERT_TRUE(WaitForFrame(host()));
  331. EXPECT_FALSE(host()->compositor()->IsVisible());
  332. host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  333. EXPECT_TRUE(host()->compositor()->IsVisible());
  334. EXPECT_EQ(compositor_root_layer, host_window_cc_layer->parent());
  335. }
  336. TEST_F(WindowTreeHostWithReleaseTest, ShowWhileTransitioningToHidden) {
  337. host()->Show();
  338. // This tests needs to drive native occlusion. If native occlusion is
  339. // used, it'll conflict with this test.
  340. NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  341. ASSERT_TRUE(NativeWindowOcclusionTracker::
  342. IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  343. cc::Layer* host_window_cc_layer =
  344. ccLayerFromUiLayer(host()->window()->layer());
  345. const cc::Layer* compositor_root_layer = host_window_cc_layer->parent();
  346. EXPECT_NE(nullptr, compositor_root_layer);
  347. host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  348. // The compositor shouldn't actually hide immediately, it needs a frame to
  349. // be generated.
  350. EXPECT_TRUE(host()->compositor()->IsVisible());
  351. EXPECT_EQ(nullptr, host_window_cc_layer->parent());
  352. host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  353. EXPECT_TRUE(host()->compositor()->IsVisible());
  354. EXPECT_EQ(compositor_root_layer, host_window_cc_layer->parent());
  355. }
  356. TEST_F(WindowTreeHostWithReleaseTest, VideoCaptureLockForcesVisible) {
  357. ASSERT_TRUE(NativeWindowOcclusionTracker::
  358. IsNativeWindowOcclusionTrackingAlwaysEnabled(host()));
  359. // This tests needs to drive native occlusion. If native occlusion is
  360. // used, it'll conflict with this test.
  361. NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(host());
  362. host()->Show();
  363. host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  364. ASSERT_TRUE(WaitForFrame(host()));
  365. EXPECT_FALSE(host()->compositor()->IsVisible());
  366. std::unique_ptr<WindowTreeHost::VideoCaptureLock> lock =
  367. host()->CreateVideoCaptureLock();
  368. EXPECT_TRUE(host()->compositor()->IsVisible());
  369. host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  370. EXPECT_TRUE(host()->compositor()->IsVisible());
  371. host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  372. EXPECT_TRUE(host()->compositor()->IsVisible());
  373. ASSERT_TRUE(WaitForFrame(host()));
  374. EXPECT_TRUE(host()->compositor()->IsVisible());
  375. lock.reset();
  376. ASSERT_TRUE(WaitForFrame(host()));
  377. EXPECT_FALSE(host()->compositor()->IsVisible());
  378. host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  379. EXPECT_TRUE(host()->compositor()->IsVisible());
  380. ASSERT_TRUE(WaitForFrame(host()));
  381. EXPECT_TRUE(host()->compositor()->IsVisible());
  382. }
  383. class WindowTreeHostWithThrottleTest : public test::AuraTestBase {
  384. public:
  385. // AuraTestBase:
  386. void SetUp() override {
  387. // Disable the headless check as the bots run with CHROME_HEADLESS set.
  388. NativeWindowOcclusionTracker::SetHeadlessCheckEnabled(false);
  389. scoped_feature_list_.InitWithFeaturesAndParameters(
  390. {
  391. {features::kCalculateNativeWinOcclusion, {}},
  392. {features::kApplyNativeOcclusionToCompositor,
  393. {{features::kApplyNativeOcclusionToCompositorType,
  394. features::kApplyNativeOcclusionToCompositorTypeThrottle}}},
  395. },
  396. {});
  397. AuraTestBase::SetUp();
  398. }
  399. void TearDown() override {
  400. test::AuraTestBase::TearDown();
  401. NativeWindowOcclusionTracker::SetHeadlessCheckEnabled(true);
  402. }
  403. private:
  404. base::test::ScopedFeatureList scoped_feature_list_;
  405. };
  406. TEST_F(WindowTreeHostWithThrottleTest, DISABLED_Basic) {
  407. host()->Show();
  408. EXPECT_TRUE(host()->compositor()->IsVisible());
  409. EXPECT_TRUE(test::GetThrottledHosts().empty());
  410. host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  411. EXPECT_TRUE(host()->compositor()->IsVisible());
  412. EXPECT_TRUE(base::Contains(test::GetThrottledHosts(), host()));
  413. host()->SetNativeWindowOcclusionState(Window::OcclusionState::VISIBLE, {});
  414. EXPECT_TRUE(test::GetThrottledHosts().empty());
  415. EXPECT_TRUE(host()->compositor()->IsVisible());
  416. }
  417. TEST_F(WindowTreeHostWithThrottleTest, DISABLED_CallHideDirectly) {
  418. host()->Show();
  419. EXPECT_TRUE(host()->compositor()->IsVisible());
  420. EXPECT_TRUE(test::GetThrottledHosts().empty());
  421. host()->SetNativeWindowOcclusionState(Window::OcclusionState::OCCLUDED, {});
  422. EXPECT_TRUE(host()->compositor()->IsVisible());
  423. EXPECT_TRUE(base::Contains(test::GetThrottledHosts(), host()));
  424. host()->Hide();
  425. EXPECT_TRUE(test::GetThrottledHosts().empty());
  426. EXPECT_FALSE(host()->compositor()->IsVisible());
  427. }
  428. #endif // BUILDFLAG(IS_WIN)
  429. } // namespace aura