| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2015 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 |
| 5 #include "content/browser/media/capture/cursor_renderer_aura.h" |
| 6 |
| 7 #include "base/files/file_path.h" |
| 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/path_service.h" |
| 10 #include "base/test/simple_test_tick_clock.h" |
| 11 #include "base/time/time.h" |
| 12 #include "media/base/video_frame.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 #include "ui/aura/env.h" |
| 15 #include "ui/aura/test/aura_test_base.h" |
| 16 #include "ui/aura/test/test_windows.h" |
| 17 #include "ui/aura/window.h" |
| 18 #include "ui/base/resource/resource_bundle.h" |
| 19 #include "ui/events/event.h" |
| 20 #include "ui/events/event_utils.h" |
| 21 #include "ui/wm/core/default_activation_client.h" |
| 22 #include "ui/wm/core/window_util.h" |
| 23 |
| 24 namespace content { |
| 25 |
| 26 using aura::test::AuraTestBase; |
| 27 |
| 28 class CursorRendererAuraTest : public AuraTestBase { |
| 29 public: |
| 30 CursorRendererAuraTest() {} |
| 31 ~CursorRendererAuraTest() override {} |
| 32 |
| 33 void SetUp() override { |
| 34 AuraTestBase::SetUp(); |
| 35 // This is needed to avoid duplicate initialization across tests that leads |
| 36 // to a failure. |
| 37 if (!ui::ResourceBundle::HasSharedInstance()) { |
| 38 // Initialize the shared global resource bundle that has bitmap |
| 39 // resources needed by CursorRenderer |
| 40 base::FilePath pak_file; |
| 41 bool r = PathService::Get(base::DIR_MODULE, &pak_file); |
| 42 DCHECK(r); |
| 43 pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak")); |
| 44 ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file); |
| 45 } |
| 46 |
| 47 window_.reset(aura::test::CreateTestWindowWithBounds( |
| 48 gfx::Rect(0, 0, 800, 600), root_window())); |
| 49 cursor_renderer_.reset(new CursorRendererAura(window_.get())); |
| 50 new wm::DefaultActivationClient(root_window()); |
| 51 } |
| 52 |
| 53 void TearDown() override { |
| 54 cursor_renderer_.reset(); |
| 55 window_.reset(); |
| 56 AuraTestBase::TearDown(); |
| 57 } |
| 58 |
| 59 void SetTickClock(base::SimpleTestTickClock* clock) { |
| 60 cursor_renderer_->tick_clock_ = clock; |
| 61 } |
| 62 |
| 63 base::TimeDelta Now() { |
| 64 return cursor_renderer_->tick_clock_->NowTicks() - base::TimeTicks(); |
| 65 } |
| 66 |
| 67 bool CursorDisplayed() { return cursor_renderer_->cursor_displayed_; } |
| 68 |
| 69 void RenderCursorOnVideoFrame( |
| 70 const scoped_refptr<media::VideoFrame>& target) { |
| 71 cursor_renderer_->RenderOnVideoFrame(target); |
| 72 } |
| 73 |
| 74 void SnapshotCursorState(gfx::Rect region_in_frame) { |
| 75 cursor_renderer_->SnapshotCursorState(region_in_frame); |
| 76 } |
| 77 |
| 78 void MoveMouseCursorWithinWindow() { |
| 79 gfx::Point point1(20, 20); |
| 80 ui::MouseEvent event1(ui::ET_MOUSE_MOVED, point1, point1, Now(), 0, 0); |
| 81 cursor_renderer_->OnMouseEvent(&event1); |
| 82 gfx::Point point2(60, 60); |
| 83 ui::MouseEvent event2(ui::ET_MOUSE_MOVED, point2, point2, Now(), 0, 0); |
| 84 cursor_renderer_->OnMouseEvent(&event2); |
| 85 aura::Env::GetInstance()->set_last_mouse_location(point2); |
| 86 } |
| 87 |
| 88 void MoveMouseCursorWithinWindow(gfx::Point point) { |
| 89 ui::MouseEvent event(ui::ET_MOUSE_MOVED, point, point, Now(), 0, 0); |
| 90 cursor_renderer_->OnMouseEvent(&event); |
| 91 aura::Env::GetInstance()->set_last_mouse_location(point); |
| 92 } |
| 93 |
| 94 void MoveMouseCursorOutsideWindow() { |
| 95 gfx::Point point(1000, 1000); |
| 96 ui::MouseEvent event1(ui::ET_MOUSE_MOVED, point, point, Now(), 0, 0); |
| 97 cursor_renderer_->OnMouseEvent(&event1); |
| 98 aura::Env::GetInstance()->set_last_mouse_location(point); |
| 99 } |
| 100 |
| 101 // A very simple test of whether there are any non-zero pixels |
| 102 // in the region |rect| within |frame|. |
| 103 bool NonZeroPixelsInRegion(scoped_refptr<media::VideoFrame> frame, |
| 104 gfx::Rect rect) { |
| 105 bool y_found = false, u_found = false, v_found = false; |
| 106 for (int y = rect.y(); y < rect.bottom(); ++y) { |
| 107 uint8* yplane = frame->data(media::VideoFrame::kYPlane) + |
| 108 y * frame->row_bytes(media::VideoFrame::kYPlane); |
| 109 uint8* uplane = frame->data(media::VideoFrame::kUPlane) + |
| 110 (y / 2) * frame->row_bytes(media::VideoFrame::kUPlane); |
| 111 uint8* vplane = frame->data(media::VideoFrame::kVPlane) + |
| 112 (y / 2) * frame->row_bytes(media::VideoFrame::kVPlane); |
| 113 for (int x = rect.x(); x < rect.right(); ++x) { |
| 114 if (yplane[x] != 0) |
| 115 y_found = true; |
| 116 if (uplane[x / 2]) |
| 117 u_found = true; |
| 118 if (vplane[x / 2]) |
| 119 v_found = true; |
| 120 } |
| 121 } |
| 122 return (y_found && u_found && v_found); |
| 123 } |
| 124 |
| 125 protected: |
| 126 scoped_ptr<aura::Window> window_; |
| 127 scoped_ptr<CursorRendererAura> cursor_renderer_; |
| 128 }; |
| 129 |
| 130 TEST_F(CursorRendererAuraTest, CursorDuringMouseMovement) { |
| 131 // Keep window activated. |
| 132 wm::ActivateWindow(window_.get()); |
| 133 |
| 134 EXPECT_FALSE(CursorDisplayed()); |
| 135 |
| 136 base::SimpleTestTickClock clock; |
| 137 SetTickClock(&clock); |
| 138 |
| 139 // Cursor displayed after mouse movement. |
| 140 MoveMouseCursorWithinWindow(); |
| 141 EXPECT_TRUE(CursorDisplayed()); |
| 142 |
| 143 // Cursor not be displayed after idle period. |
| 144 clock.Advance(base::TimeDelta::FromSeconds(5)); |
| 145 SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| 146 EXPECT_FALSE(CursorDisplayed()); |
| 147 |
| 148 // Cursor displayed with mouse movement following idle period. |
| 149 MoveMouseCursorWithinWindow(); |
| 150 SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| 151 EXPECT_TRUE(CursorDisplayed()); |
| 152 |
| 153 // Cursor not displayed if mouse outside the window |
| 154 MoveMouseCursorOutsideWindow(); |
| 155 SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| 156 EXPECT_FALSE(CursorDisplayed()); |
| 157 } |
| 158 |
| 159 TEST_F(CursorRendererAuraTest, CursorOnActiveWindow) { |
| 160 EXPECT_FALSE(CursorDisplayed()); |
| 161 |
| 162 // Cursor displayed after mouse movement. |
| 163 MoveMouseCursorWithinWindow(); |
| 164 EXPECT_TRUE(CursorDisplayed()); |
| 165 |
| 166 // Cursor not be displayed if a second window is activated. |
| 167 scoped_ptr<aura::Window> window2(aura::test::CreateTestWindowWithBounds( |
| 168 gfx::Rect(0, 0, 800, 600), root_window())); |
| 169 wm::ActivateWindow(window2.get()); |
| 170 SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| 171 EXPECT_FALSE(CursorDisplayed()); |
| 172 |
| 173 // Cursor displayed if window activated again. |
| 174 MoveMouseCursorWithinWindow(); |
| 175 wm::ActivateWindow(window_.get()); |
| 176 SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| 177 EXPECT_TRUE(CursorDisplayed()); |
| 178 } |
| 179 |
| 180 TEST_F(CursorRendererAuraTest, CursorRenderedOnFrame) { |
| 181 // Keep window activated. |
| 182 wm::ActivateWindow(window_.get()); |
| 183 |
| 184 EXPECT_FALSE(CursorDisplayed()); |
| 185 |
| 186 gfx::Size size(800, 600); |
| 187 scoped_refptr<media::VideoFrame> frame = |
| 188 media::VideoFrame::CreateZeroInitializedFrame(media::PIXEL_FORMAT_YV12, |
| 189 size, gfx::Rect(size), size, |
| 190 base::TimeDelta()); |
| 191 |
| 192 MoveMouseCursorWithinWindow(gfx::Point(60, 60)); |
| 193 SnapshotCursorState(gfx::Rect(size)); |
| 194 EXPECT_TRUE(CursorDisplayed()); |
| 195 |
| 196 EXPECT_FALSE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70))); |
| 197 RenderCursorOnVideoFrame(frame); |
| 198 EXPECT_TRUE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70))); |
| 199 } |
| 200 |
| 201 } // namespace content |
| OLD | NEW |