zaura_shell_unittest.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. // Copyright 2019 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 "components/exo/wayland/zaura_shell.h"
  5. #include <aura-shell-server-protocol.h>
  6. #include <sys/socket.h>
  7. #include <memory>
  8. #include "ash/session/session_controller_impl.h"
  9. #include "ash/shell.h"
  10. #include "ash/wm/desks/desks_util.h"
  11. #include "ash/wm/window_util.h"
  12. #include "base/time/time.h"
  13. #include "components/exo/buffer.h"
  14. #include "components/exo/test/exo_test_base.h"
  15. #include "components/exo/wayland/scoped_wl.h"
  16. #include "components/exo/wayland/wayland_display_observer.h"
  17. #include "components/exo/wayland/wayland_display_output.h"
  18. #include "components/exo/wayland/wayland_display_util.h"
  19. #include "components/exo/wayland/wl_output.h"
  20. #include "testing/gmock/include/gmock/gmock.h"
  21. #include "testing/gtest/include/gtest/gtest.h"
  22. #include "ui/aura/window_occlusion_tracker.h"
  23. #include "ui/compositor/layer.h"
  24. #include "ui/compositor/layer_animation_observer.h"
  25. #include "ui/compositor/layer_animation_sequence.h"
  26. #include "ui/compositor/layer_animator.h"
  27. #include "ui/compositor/scoped_animation_duration_scale_mode.h"
  28. #include "ui/compositor/scoped_layer_animation_settings.h"
  29. #include "ui/compositor/test/layer_animator_test_controller.h"
  30. #include "ui/gfx/geometry/size_f.h"
  31. #include "ui/views/widget/widget.h"
  32. #include "ui/wm/core/window_util.h"
  33. #include "ui/wm/public/activation_change_observer.h"
  34. #include "ui/wm/public/activation_client.h"
  35. namespace exo {
  36. namespace wayland {
  37. namespace {
  38. constexpr auto kTransitionDuration = base::Seconds(3);
  39. class TestAuraSurface : public AuraSurface {
  40. public:
  41. explicit TestAuraSurface(Surface* surface)
  42. : AuraSurface(surface, /*resource=*/nullptr) {}
  43. TestAuraSurface(const TestAuraSurface&) = delete;
  44. TestAuraSurface& operator=(const TestAuraSurface&) = delete;
  45. float last_sent_occlusion_fraction() const {
  46. return last_sent_occlusion_fraction_;
  47. }
  48. aura::Window::OcclusionState last_sent_occlusion_state() const {
  49. return last_sent_occlusion_state_;
  50. }
  51. int num_occlusion_updates() const { return num_occlusion_updates_; }
  52. protected:
  53. void SendOcclusionFraction(float occlusion_fraction) override {
  54. last_sent_occlusion_fraction_ = occlusion_fraction;
  55. num_occlusion_updates_++;
  56. }
  57. void SendOcclusionState(
  58. const aura::Window::OcclusionState occlusion_state) override {
  59. last_sent_occlusion_state_ = occlusion_state;
  60. }
  61. private:
  62. float last_sent_occlusion_fraction_ = -1.0f;
  63. aura::Window::OcclusionState last_sent_occlusion_state_ =
  64. aura::Window::OcclusionState::UNKNOWN;
  65. int num_occlusion_updates_ = 0;
  66. };
  67. class MockSurfaceDelegate : public SurfaceDelegate {
  68. public:
  69. MOCK_METHOD(void, OnSurfaceCommit, (), (override));
  70. MOCK_METHOD(bool, IsSurfaceSynchronized, (), (const, override));
  71. MOCK_METHOD(bool, IsInputEnabled, (Surface * surface), (const, override));
  72. MOCK_METHOD(void, OnSetFrame, (SurfaceFrameType type), (override));
  73. MOCK_METHOD(void,
  74. OnSetFrameColors,
  75. (SkColor active_color, SkColor inactive_color),
  76. (override));
  77. MOCK_METHOD(void,
  78. OnSetParent,
  79. (Surface * parent, const gfx::Point& position),
  80. (override));
  81. MOCK_METHOD(void, OnSetStartupId, (const char* startup_id), (override));
  82. MOCK_METHOD(void,
  83. OnSetApplicationId,
  84. (const char* application_id),
  85. (override));
  86. MOCK_METHOD(void, SetUseImmersiveForFullscreen, (bool value), (override));
  87. MOCK_METHOD(void, OnActivationRequested, (), (override));
  88. MOCK_METHOD(void, OnNewOutputAdded, (), (override));
  89. MOCK_METHOD(void, OnSetServerStartResize, (), (override));
  90. MOCK_METHOD(void, ShowSnapPreviewToPrimary, (), (override));
  91. MOCK_METHOD(void, ShowSnapPreviewToSecondary, (), (override));
  92. MOCK_METHOD(void, HideSnapPreview, (), (override));
  93. MOCK_METHOD(void, SetSnappedToSecondary, (), (override));
  94. MOCK_METHOD(void, SetSnappedToPrimary, (), (override));
  95. MOCK_METHOD(void, UnsetSnap, (), (override));
  96. MOCK_METHOD(void, SetCanGoBack, (), (override));
  97. MOCK_METHOD(void, UnsetCanGoBack, (), (override));
  98. MOCK_METHOD(void, SetPip, (), (override));
  99. MOCK_METHOD(void, UnsetPip, (), (override));
  100. MOCK_METHOD(void,
  101. SetAspectRatio,
  102. (const gfx::SizeF& aspect_ratio),
  103. (override));
  104. MOCK_METHOD(void, MoveToDesk, (int desk_index), (override));
  105. MOCK_METHOD(void, SetVisibleOnAllWorkspaces, (), (override));
  106. MOCK_METHOD(void,
  107. SetInitialWorkspace,
  108. (const char* initial_workspace),
  109. (override));
  110. MOCK_METHOD(void, Pin, (bool trusted), (override));
  111. MOCK_METHOD(void, Unpin, (), (override));
  112. MOCK_METHOD(void, SetSystemModal, (bool modal), (override));
  113. MOCK_METHOD(SecurityDelegate*, GetSecurityDelegate, (), (override));
  114. };
  115. } // namespace
  116. class ZAuraSurfaceTest : public test::ExoTestBase,
  117. public ::wm::ActivationChangeObserver {
  118. public:
  119. ZAuraSurfaceTest() {}
  120. ZAuraSurfaceTest(const ZAuraSurfaceTest&) = delete;
  121. ZAuraSurfaceTest& operator=(const ZAuraSurfaceTest&) = delete;
  122. ~ZAuraSurfaceTest() override {}
  123. // test::ExoTestBase overrides:
  124. void SetUp() override {
  125. test::ExoTestBase::SetUp();
  126. gfx::Size buffer_size(10, 10);
  127. std::unique_ptr<Buffer> buffer(
  128. new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
  129. surface_ = std::make_unique<Surface>();
  130. surface_->Attach(buffer.get());
  131. aura_surface_ = std::make_unique<TestAuraSurface>(surface_.get());
  132. gfx::Transform transform;
  133. transform.Scale(1.5f, 1.5f);
  134. parent_widget_ = CreateTestWidget();
  135. parent_widget_->SetBounds(gfx::Rect(0, 0, 10, 10));
  136. parent_widget_->GetNativeWindow()->SetTransform(transform);
  137. parent_widget_->GetNativeWindow()->AddChild(surface_->window());
  138. parent_widget_->Show();
  139. surface_->window()->SetBounds(gfx::Rect(5, 5, 10, 10));
  140. surface_->window()->Show();
  141. ash::Shell::Get()->activation_client()->AddObserver(this);
  142. aura_surface_->SetOcclusionTracking(true);
  143. }
  144. void TearDown() override {
  145. ash::Shell::Get()->activation_client()->RemoveObserver(this);
  146. parent_widget_.reset();
  147. aura_surface_.reset();
  148. surface_.reset();
  149. test::ExoTestBase::TearDown();
  150. }
  151. // ::wm::ActivationChangeObserver overrides:
  152. void OnWindowActivated(ActivationReason reason,
  153. aura::Window* gained_active,
  154. aura::Window* lost_active) override {
  155. if (lost_active == parent_widget_->GetNativeWindow()) {
  156. occlusion_fraction_on_activation_loss_ =
  157. aura_surface().last_sent_occlusion_fraction();
  158. }
  159. }
  160. protected:
  161. TestAuraSurface& aura_surface() { return *aura_surface_; }
  162. Surface& surface() { return *surface_; }
  163. views::Widget& parent_widget() { return *parent_widget_; }
  164. float occlusion_fraction_on_activation_loss() const {
  165. return occlusion_fraction_on_activation_loss_;
  166. }
  167. std::unique_ptr<views::Widget> CreateOpaqueWidget(const gfx::Rect& bounds) {
  168. return CreateTestWidget(
  169. /*delegate=*/nullptr,
  170. /*container_id=*/ash::desks_util::GetActiveDeskContainerId(), bounds,
  171. /*show=*/false);
  172. }
  173. private:
  174. std::unique_ptr<TestAuraSurface> aura_surface_;
  175. std::unique_ptr<Surface> surface_;
  176. std::unique_ptr<views::Widget> parent_widget_;
  177. float occlusion_fraction_on_activation_loss_ = -1.0f;
  178. };
  179. TEST_F(ZAuraSurfaceTest, OcclusionTrackingStartsAfterCommit) {
  180. surface().OnWindowOcclusionChanged();
  181. EXPECT_EQ(-1.0f, aura_surface().last_sent_occlusion_fraction());
  182. EXPECT_EQ(aura::Window::OcclusionState::UNKNOWN,
  183. aura_surface().last_sent_occlusion_state());
  184. EXPECT_EQ(0, aura_surface().num_occlusion_updates());
  185. EXPECT_FALSE(surface().IsTrackingOcclusion());
  186. auto widget = CreateOpaqueWidget(gfx::Rect(0, 0, 10, 10));
  187. widget->Show();
  188. surface().Commit();
  189. EXPECT_EQ(0.2f, aura_surface().last_sent_occlusion_fraction());
  190. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  191. aura_surface().last_sent_occlusion_state());
  192. EXPECT_EQ(1, aura_surface().num_occlusion_updates());
  193. EXPECT_TRUE(surface().IsTrackingOcclusion());
  194. }
  195. TEST_F(ZAuraSurfaceTest,
  196. LosingActivationWithNoAnimatingWindowsSendsCorrectOcclusionFraction) {
  197. surface().Commit();
  198. EXPECT_EQ(0.0f, aura_surface().last_sent_occlusion_fraction());
  199. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  200. aura_surface().last_sent_occlusion_state());
  201. EXPECT_EQ(1, aura_surface().num_occlusion_updates());
  202. ::wm::ActivateWindow(parent_widget().GetNativeWindow());
  203. // Creating an opaque window but don't show it.
  204. auto widget = CreateOpaqueWidget(gfx::Rect(0, 0, 10, 10));
  205. // Occlusion sent before de-activation should include that widget.
  206. widget->Show();
  207. EXPECT_EQ(0.2f, occlusion_fraction_on_activation_loss());
  208. EXPECT_EQ(0.2f, aura_surface().last_sent_occlusion_fraction());
  209. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  210. aura_surface().last_sent_occlusion_state());
  211. EXPECT_EQ(2, aura_surface().num_occlusion_updates());
  212. }
  213. TEST_F(ZAuraSurfaceTest,
  214. LosingActivationWithAnimatingWindowsSendsTargetOcclusionFraction) {
  215. surface().Commit();
  216. EXPECT_EQ(0.0f, aura_surface().last_sent_occlusion_fraction());
  217. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  218. aura_surface().last_sent_occlusion_state());
  219. EXPECT_EQ(1, aura_surface().num_occlusion_updates());
  220. ::wm::ActivateWindow(parent_widget().GetNativeWindow());
  221. // Creating an opaque window but don't show it.
  222. auto widget = CreateOpaqueWidget(gfx::Rect(0, 0, 10, 10));
  223. widget->GetNativeWindow()->layer()->SetOpacity(0.0f);
  224. ui::ScopedAnimationDurationScaleMode scoped_animation_duration_scale_mode(
  225. ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
  226. ui::LayerAnimatorTestController test_controller(
  227. ui::LayerAnimator::CreateImplicitAnimator());
  228. ui::ScopedLayerAnimationSettings layer_animation_settings(
  229. test_controller.animator());
  230. layer_animation_settings.SetTransitionDuration(kTransitionDuration);
  231. widget->GetNativeWindow()->layer()->SetAnimator(test_controller.animator());
  232. widget->GetNativeWindow()->layer()->SetOpacity(1.0f);
  233. // Opacity animation uses threaded animation.
  234. test_controller.StartThreadedAnimationsIfNeeded();
  235. test_controller.Step(kTransitionDuration / 3);
  236. // No occlusion updates should happen until the window is de-activated.
  237. EXPECT_EQ(1, aura_surface().num_occlusion_updates());
  238. // Occlusion sent before de-activation should include the window animating
  239. // to be completely opaque.
  240. widget->Show();
  241. EXPECT_EQ(0.2f, occlusion_fraction_on_activation_loss());
  242. EXPECT_EQ(0.2f, aura_surface().last_sent_occlusion_fraction());
  243. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  244. aura_surface().last_sent_occlusion_state());
  245. EXPECT_EQ(2, aura_surface().num_occlusion_updates());
  246. // Explicitly stop animation because threaded animation may have started
  247. // a bit later. |kTransitionDuration| may not be quite enough to reach the
  248. // end.
  249. test_controller.Step(kTransitionDuration / 3);
  250. test_controller.Step(kTransitionDuration / 3);
  251. widget->GetNativeWindow()->layer()->GetAnimator()->StopAnimating();
  252. widget->GetNativeWindow()->layer()->SetAnimator(nullptr);
  253. // Expect the occlusion tracker to send an update after the animation
  254. // finishes.
  255. EXPECT_EQ(0.2f, aura_surface().last_sent_occlusion_fraction());
  256. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  257. aura_surface().last_sent_occlusion_state());
  258. EXPECT_EQ(3, aura_surface().num_occlusion_updates());
  259. }
  260. TEST_F(ZAuraSurfaceTest,
  261. LosingActivationByTriggeringTheLockScreenDoesNotSendOccludedFraction) {
  262. surface().Commit();
  263. EXPECT_EQ(0.0f, aura_surface().last_sent_occlusion_fraction());
  264. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  265. aura_surface().last_sent_occlusion_state());
  266. EXPECT_EQ(1, aura_surface().num_occlusion_updates());
  267. ::wm::ActivateWindow(parent_widget().GetNativeWindow());
  268. // Lock the screen.
  269. views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
  270. auto lock_widget = std::make_unique<views::Widget>();
  271. params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  272. params.context = GetContext();
  273. params.bounds = gfx::Rect(0, 0, 100, 100);
  274. lock_widget->Init(std::move(params));
  275. ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(),
  276. ash::kShellWindowId_LockScreenContainer)
  277. ->AddChild(lock_widget->GetNativeView());
  278. // Simulate real screen locker to change session state to LOCKED
  279. // when it is shown.
  280. auto* controller = ash::Shell::Get()->session_controller();
  281. GetSessionControllerClient()->LockScreen();
  282. lock_widget->Show();
  283. EXPECT_TRUE(controller->IsScreenLocked());
  284. EXPECT_TRUE(lock_widget->GetNativeView()->HasFocus());
  285. // We should have lost focus, but not reported that the window has been
  286. // fully occluded.
  287. EXPECT_NE(parent_widget().GetNativeWindow(),
  288. ash::window_util::GetActiveWindow());
  289. EXPECT_EQ(0.0f, occlusion_fraction_on_activation_loss());
  290. EXPECT_EQ(0.0f, aura_surface().last_sent_occlusion_fraction());
  291. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  292. aura_surface().last_sent_occlusion_state());
  293. }
  294. TEST_F(ZAuraSurfaceTest, OcclusionIncludesOffScreenArea) {
  295. UpdateDisplay("200x150");
  296. gfx::Size buffer_size(80, 100);
  297. std::unique_ptr<Buffer> buffer(
  298. new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
  299. // This is scaled by 1.5 - set the bounds to (-60, 75, 120, 150) in screen
  300. // coordinates so 75% of it is outside of the 100x100 screen.
  301. surface().window()->SetBounds(gfx::Rect(-40, 50, 80, 100));
  302. surface().Attach(buffer.get());
  303. surface().Commit();
  304. surface().OnWindowOcclusionChanged();
  305. EXPECT_EQ(0.75f, aura_surface().last_sent_occlusion_fraction());
  306. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  307. aura_surface().last_sent_occlusion_state());
  308. }
  309. TEST_F(ZAuraSurfaceTest, ZeroSizeWindowSendsZeroOcclusionFraction) {
  310. // Zero sized window should not be occluded.
  311. surface().window()->SetBounds(gfx::Rect(0, 0, 0, 0));
  312. surface().Commit();
  313. surface().OnWindowOcclusionChanged();
  314. EXPECT_EQ(0.0f, aura_surface().last_sent_occlusion_fraction());
  315. EXPECT_EQ(aura::Window::OcclusionState::VISIBLE,
  316. aura_surface().last_sent_occlusion_state());
  317. }
  318. TEST_F(ZAuraSurfaceTest, CanPin) {
  319. MockSurfaceDelegate delegate;
  320. wl_resource resource;
  321. resource.data = &aura_surface();
  322. surface().SetSurfaceDelegate(&delegate);
  323. EXPECT_CALL(delegate, Pin(true));
  324. aura_surface().Pin(true);
  325. }
  326. TEST_F(ZAuraSurfaceTest, CanUnpin) {
  327. MockSurfaceDelegate delegate;
  328. wl_resource resource;
  329. resource.data = &aura_surface();
  330. surface().SetSurfaceDelegate(&delegate);
  331. EXPECT_CALL(delegate, Unpin());
  332. aura_surface().Unpin();
  333. }
  334. TEST_F(ZAuraSurfaceTest, CanSetFullscreenModeToPlain) {
  335. MockSurfaceDelegate delegate;
  336. wl_resource resource;
  337. resource.data = &aura_surface();
  338. surface().SetSurfaceDelegate(&delegate);
  339. EXPECT_CALL(delegate, SetUseImmersiveForFullscreen(false));
  340. aura_surface().SetFullscreenMode(ZAURA_SURFACE_FULLSCREEN_MODE_PLAIN);
  341. }
  342. TEST_F(ZAuraSurfaceTest, CanSetFullscreenModeToImmersive) {
  343. MockSurfaceDelegate delegate;
  344. surface().SetSurfaceDelegate(&delegate);
  345. EXPECT_CALL(delegate, SetUseImmersiveForFullscreen(true));
  346. aura_surface().SetFullscreenMode(ZAURA_SURFACE_FULLSCREEN_MODE_IMMERSIVE);
  347. }
  348. class MockAuraOutput : public AuraOutput {
  349. public:
  350. using AuraOutput::AuraOutput;
  351. MOCK_METHOD(void, SendInsets, (const gfx::Insets&), (override));
  352. MOCK_METHOD(void, SendLogicalTransform, (int32_t), (override));
  353. };
  354. class ZAuraOutputTest : public test::ExoTestBase {
  355. protected:
  356. ZAuraOutputTest() = default;
  357. ZAuraOutputTest(const ZAuraOutputTest&) = delete;
  358. ZAuraOutputTest& operator=(const ZAuraOutputTest&) = delete;
  359. // test::ExxoTestBase:
  360. ~ZAuraOutputTest() override = default;
  361. void SetUp() override {
  362. test::ExoTestBase::SetUp();
  363. int fds[2];
  364. ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds), 0);
  365. wayland_display_.reset(wl_display_create());
  366. client_ = wl_client_create(wayland_display_.get(), fds[0]);
  367. wl_resource* output_resource =
  368. wl_resource_create(client_, &wl_output_interface, kWlOutputVersion, 0);
  369. display_handler_ = std::make_unique<WaylandDisplayHandler>(&display_output_,
  370. output_resource);
  371. }
  372. std::unique_ptr<MockAuraOutput> CreateAuraOutput(int version) {
  373. return std::make_unique<::testing::NiceMock<MockAuraOutput>>(
  374. wl_resource_create(client_, &zaura_output_interface, version, 0),
  375. display_handler_.get());
  376. }
  377. std::unique_ptr<WaylandDisplayHandler> display_handler_;
  378. private:
  379. WaylandDisplayOutput display_output_{0};
  380. std::unique_ptr<wl_display, WlDisplayDeleter> wayland_display_;
  381. wl_client* client_ = nullptr;
  382. };
  383. TEST_F(ZAuraOutputTest, SendInsets) {
  384. auto mock_aura_output = CreateAuraOutput(ZAURA_OUTPUT_INSETS_SINCE_VERSION);
  385. UpdateDisplay("800x600");
  386. display::Display display =
  387. display_manager()->GetDisplayForId(display_manager()->first_display_id());
  388. const gfx::Rect initial_bounds{800, 600};
  389. EXPECT_EQ(display.bounds(), initial_bounds);
  390. const gfx::Rect new_work_area{10, 20, 500, 400};
  391. EXPECT_NE(display.work_area(), new_work_area);
  392. display.set_work_area(new_work_area);
  393. const gfx::Insets expected_insets = initial_bounds.InsetsFrom(new_work_area);
  394. EXPECT_CALL(*mock_aura_output, SendInsets(expected_insets)).Times(1);
  395. mock_aura_output->SendDisplayMetrics(
  396. display, display::DisplayObserver::DISPLAY_METRIC_WORK_AREA);
  397. }
  398. TEST_F(ZAuraOutputTest, SendLogicalTransform) {
  399. auto mock_aura_output =
  400. CreateAuraOutput(ZAURA_OUTPUT_LOGICAL_TRANSFORM_SINCE_VERSION);
  401. UpdateDisplay("800x600");
  402. display::Display display =
  403. display_manager()->GetDisplayForId(display_manager()->first_display_id());
  404. // Make sure the expected calls happen in order.
  405. ::testing::InSequence seq;
  406. EXPECT_EQ(display.rotation(), display::Display::ROTATE_0);
  407. EXPECT_EQ(display.panel_rotation(), display::Display::ROTATE_0);
  408. EXPECT_CALL(*mock_aura_output,
  409. SendLogicalTransform(OutputTransform(display.rotation())))
  410. .Times(1);
  411. mock_aura_output->SendDisplayMetrics(
  412. display, display::DisplayObserver::DISPLAY_METRIC_ROTATION);
  413. display.set_rotation(display::Display::ROTATE_270);
  414. display.set_panel_rotation(display::Display::ROTATE_180);
  415. EXPECT_CALL(*mock_aura_output,
  416. SendLogicalTransform(OutputTransform(display.rotation())))
  417. .Times(1);
  418. mock_aura_output->SendDisplayMetrics(
  419. display, display::DisplayObserver::DISPLAY_METRIC_ROTATION);
  420. display.set_rotation(display::Display::ROTATE_90);
  421. display.set_panel_rotation(display::Display::ROTATE_180);
  422. EXPECT_CALL(*mock_aura_output,
  423. SendLogicalTransform(OutputTransform(display.rotation())))
  424. .Times(1);
  425. mock_aura_output->SendDisplayMetrics(
  426. display, display::DisplayObserver::DISPLAY_METRIC_ROTATION);
  427. display.set_rotation(display::Display::ROTATE_270);
  428. display.set_panel_rotation(display::Display::ROTATE_270);
  429. EXPECT_CALL(*mock_aura_output,
  430. SendLogicalTransform(OutputTransform(display.rotation())))
  431. .Times(1);
  432. mock_aura_output->SendDisplayMetrics(
  433. display, display::DisplayObserver::DISPLAY_METRIC_ROTATION);
  434. }
  435. // Make sure that data associated with wl/aura outputs are destroyd
  436. // properly regardless of which one is destroyed first.
  437. TEST_F(ZAuraOutputTest, DestroyAuraOutput) {
  438. auto mock_aura_output =
  439. CreateAuraOutput(ZAURA_OUTPUT_LOGICAL_TRANSFORM_SINCE_VERSION);
  440. EXPECT_EQ(1u, display_handler_->CountObserversForTesting());
  441. mock_aura_output.reset();
  442. EXPECT_EQ(0u, display_handler_->CountObserversForTesting());
  443. mock_aura_output =
  444. CreateAuraOutput(ZAURA_OUTPUT_LOGICAL_TRANSFORM_SINCE_VERSION);
  445. EXPECT_EQ(1u, display_handler_->CountObserversForTesting());
  446. EXPECT_TRUE(mock_aura_output->HasDisplayHandlerForTesting());
  447. display_handler_.reset();
  448. EXPECT_FALSE(mock_aura_output->HasDisplayHandlerForTesting());
  449. }
  450. } // namespace wayland
  451. } // namespace exo