Correctly track texture cleared state for sharing
[chromium-blink-merge.git] / ui / display / chromeos / x11 / native_display_event_dispatcher_x11_unittest.cc
blob750f0e09de35fe0ea9d51837852c329260c6fa2d
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.
5 #include <X11/extensions/Xrandr.h>
7 #undef Bool
8 #undef None
10 #include "base/test/simple_test_tick_clock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/display/chromeos/x11/display_mode_x11.h"
13 #include "ui/display/chromeos/x11/display_snapshot_x11.h"
14 #include "ui/display/chromeos/x11/native_display_delegate_x11.h"
15 #include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
17 namespace ui {
19 namespace {
21 DisplaySnapshotX11* CreateOutput(int64_t id,
22 DisplayConnectionType type,
23 RROutput output,
24 RRCrtc crtc) {
25 static const DisplayModeX11* kDefaultDisplayMode =
26 new DisplayModeX11(gfx::Size(1, 1), false, 60.0f, 20);
28 DisplaySnapshotX11* snapshot = new DisplaySnapshotX11(
29 id,
30 gfx::Point(0, 0),
31 gfx::Size(0, 0),
32 type,
33 false,
34 false,
35 std::string(),
36 std::vector<const DisplayMode*>(1, kDefaultDisplayMode),
37 kDefaultDisplayMode,
38 NULL,
39 output,
40 crtc,
41 0);
43 return snapshot;
46 DisplaySnapshotX11* CreateExternalOutput(RROutput output, RRCrtc crtc) {
47 return CreateOutput(static_cast<int64_t>(output),
48 DISPLAY_CONNECTION_TYPE_UNKNOWN,
49 output,
50 crtc);
53 DisplaySnapshotX11* CreateInternalOutput(RROutput output, RRCrtc crtc) {
54 return CreateOutput(0,
55 DISPLAY_CONNECTION_TYPE_INTERNAL,
56 output,
57 crtc);
60 class TestHelperDelegate : public NativeDisplayDelegateX11::HelperDelegate {
61 public:
62 TestHelperDelegate();
63 ~TestHelperDelegate() override;
65 int num_calls_update_xrandr_config() const {
66 return num_calls_update_xrandr_config_;
69 int num_calls_notify_observers() const { return num_calls_notify_observers_; }
71 void set_cached_outputs(const std::vector<DisplaySnapshot*>& outputs) {
72 cached_outputs_ = outputs;
75 // NativeDisplayDelegateX11::HelperDelegate overrides:
76 void UpdateXRandRConfiguration(const base::NativeEvent& event) override;
77 const std::vector<DisplaySnapshot*>& GetCachedDisplays() const override;
78 void NotifyDisplayObservers() override;
80 private:
81 int num_calls_update_xrandr_config_;
82 int num_calls_notify_observers_;
84 std::vector<DisplaySnapshot*> cached_outputs_;
86 DISALLOW_COPY_AND_ASSIGN(TestHelperDelegate);
89 TestHelperDelegate::TestHelperDelegate()
90 : num_calls_update_xrandr_config_(0), num_calls_notify_observers_(0) {}
92 TestHelperDelegate::~TestHelperDelegate() {}
94 void TestHelperDelegate::UpdateXRandRConfiguration(
95 const base::NativeEvent& event) {
96 ++num_calls_update_xrandr_config_;
99 const std::vector<DisplaySnapshot*>& TestHelperDelegate::GetCachedDisplays()
100 const {
101 return cached_outputs_;
104 void TestHelperDelegate::NotifyDisplayObservers() {
105 ++num_calls_notify_observers_;
108 ////////////////////////////////////////////////////////////////////////////////
109 // NativeDisplayEventDispatcherX11Test
111 class NativeDisplayEventDispatcherX11Test : public testing::Test {
112 public:
113 NativeDisplayEventDispatcherX11Test();
114 ~NativeDisplayEventDispatcherX11Test() override;
116 protected:
117 void DispatchScreenChangeEvent();
118 void DispatchOutputChangeEvent(RROutput output,
119 RRCrtc crtc,
120 RRMode mode,
121 bool connected);
123 int xrandr_event_base_;
124 scoped_ptr<TestHelperDelegate> helper_delegate_;
125 scoped_ptr<NativeDisplayEventDispatcherX11> dispatcher_;
126 base::SimpleTestTickClock* test_tick_clock_; // Owned by |dispatcher_|.
128 private:
129 DISALLOW_COPY_AND_ASSIGN(NativeDisplayEventDispatcherX11Test);
132 NativeDisplayEventDispatcherX11Test::NativeDisplayEventDispatcherX11Test()
133 : xrandr_event_base_(10),
134 helper_delegate_(new TestHelperDelegate()),
135 dispatcher_(new NativeDisplayEventDispatcherX11(helper_delegate_.get(),
136 xrandr_event_base_)),
137 test_tick_clock_(new base::SimpleTestTickClock) {
138 test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1));
139 dispatcher_->SetTickClockForTest(
140 scoped_ptr<base::TickClock>(test_tick_clock_));
143 NativeDisplayEventDispatcherX11Test::~NativeDisplayEventDispatcherX11Test() {}
145 void NativeDisplayEventDispatcherX11Test::DispatchScreenChangeEvent() {
146 XRRScreenChangeNotifyEvent event = {0};
147 event.type = xrandr_event_base_ + RRScreenChangeNotify;
149 dispatcher_->DispatchEvent(reinterpret_cast<const PlatformEvent>(&event));
152 void NativeDisplayEventDispatcherX11Test::DispatchOutputChangeEvent(
153 RROutput output,
154 RRCrtc crtc,
155 RRMode mode,
156 bool connected) {
157 XRROutputChangeNotifyEvent event = {0};
158 event.type = xrandr_event_base_ + RRNotify;
159 event.subtype = RRNotify_OutputChange;
160 event.output = output;
161 event.crtc = crtc;
162 event.mode = mode;
163 event.connection = connected ? RR_Connected : RR_Disconnected;
165 dispatcher_->DispatchEvent(reinterpret_cast<const PlatformEvent>(&event));
168 } // namespace
170 TEST_F(NativeDisplayEventDispatcherX11Test, OnScreenChangedEvent) {
171 DispatchScreenChangeEvent();
172 EXPECT_EQ(1, helper_delegate_->num_calls_update_xrandr_config());
173 EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
176 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnFirstEvent) {
177 DispatchOutputChangeEvent(1, 10, 20, true);
178 EXPECT_EQ(0, helper_delegate_->num_calls_update_xrandr_config());
179 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
182 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationAfterSecondEvent) {
183 DispatchOutputChangeEvent(1, 10, 20, true);
185 // Simulate addition of the first output to the cached output list.
186 ScopedVector<DisplaySnapshot> outputs;
187 outputs.push_back(CreateExternalOutput(1, 10));
188 helper_delegate_->set_cached_outputs(outputs.get());
190 DispatchOutputChangeEvent(2, 11, 20, true);
191 EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
194 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDisconnect) {
195 ScopedVector<DisplaySnapshot> outputs;
196 outputs.push_back(CreateExternalOutput(1, 10));
197 helper_delegate_->set_cached_outputs(outputs.get());
199 DispatchOutputChangeEvent(1, 10, 20, false);
200 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
203 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnModeChange) {
204 ScopedVector<DisplaySnapshot> outputs;
205 outputs.push_back(CreateExternalOutput(1, 10));
206 helper_delegate_->set_cached_outputs(outputs.get());
208 DispatchOutputChangeEvent(1, 10, 21, true);
209 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
212 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnSecondOutput) {
213 ScopedVector<DisplaySnapshot> outputs;
214 outputs.push_back(CreateExternalOutput(1, 10));
215 helper_delegate_->set_cached_outputs(outputs.get());
217 DispatchOutputChangeEvent(2, 11, 20, true);
218 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
221 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDifferentCrtc) {
222 ScopedVector<DisplaySnapshot> outputs;
223 outputs.push_back(CreateExternalOutput(1, 10));
224 helper_delegate_->set_cached_outputs(outputs.get());
226 DispatchOutputChangeEvent(1, 11, 20, true);
227 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
230 TEST_F(NativeDisplayEventDispatcherX11Test,
231 CheckNotificationOnSecondOutputDisconnect) {
232 ScopedVector<DisplaySnapshot> outputs;
233 outputs.push_back(CreateExternalOutput(1, 10));
234 outputs.push_back(CreateExternalOutput(2, 11));
235 helper_delegate_->set_cached_outputs(outputs.get());
237 DispatchOutputChangeEvent(2, 11, 20, false);
238 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
241 TEST_F(NativeDisplayEventDispatcherX11Test,
242 AvoidDuplicateNotificationOnSecondOutputDisconnect) {
243 ScopedVector<DisplaySnapshot> outputs;
244 outputs.push_back(CreateExternalOutput(1, 10));
245 outputs.push_back(CreateExternalOutput(2, 11));
246 helper_delegate_->set_cached_outputs(outputs.get());
248 DispatchOutputChangeEvent(2, 11, 20, false);
249 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
251 // Simulate removal of second output from cached output list.
252 outputs.erase(outputs.begin() + 1);
253 helper_delegate_->set_cached_outputs(outputs.get());
255 DispatchOutputChangeEvent(2, 11, 20, false);
256 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
259 TEST_F(NativeDisplayEventDispatcherX11Test,
260 ForceUpdateAfterCacheExpiration) {
261 // +1 to compenstate a possible rounding error.
262 const int kHalfOfExpirationMs =
263 NativeDisplayEventDispatcherX11::kUseCacheAfterStartupMs / 2 + 1;
265 ScopedVector<DisplaySnapshot> outputs;
266 outputs.push_back(CreateExternalOutput(1, 10));
267 outputs.push_back(CreateExternalOutput(2, 11));
268 helper_delegate_->set_cached_outputs(outputs.get());
270 EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
272 // Duplicated event will be ignored during the startup.
273 DispatchOutputChangeEvent(2, 11, 20, true);
274 EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
276 test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
277 kHalfOfExpirationMs));
279 // Duplicated event will still be ignored.
280 DispatchOutputChangeEvent(2, 11, 20, true);
281 EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
283 // The startup timeout has been elapsed. Duplicated event
284 // should not be ignored.
285 test_tick_clock_->Advance(
286 base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
287 DispatchOutputChangeEvent(2, 11, 20, true);
288 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
290 // Sending the same event immediately shoudldn't be ignored.
291 DispatchOutputChangeEvent(2, 11, 20, true);
292 EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
294 // Advancing time further should not change the behavior.
295 test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
296 kHalfOfExpirationMs));
297 DispatchOutputChangeEvent(2, 11, 20, true);
298 EXPECT_EQ(3, helper_delegate_->num_calls_notify_observers());
300 test_tick_clock_->Advance(
301 base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
302 DispatchOutputChangeEvent(2, 11, 20, true);
303 EXPECT_EQ(4, helper_delegate_->num_calls_notify_observers());
306 TEST_F(NativeDisplayEventDispatcherX11Test,
307 UpdateMissingExternalDisplayId) {
308 ScopedVector<DisplaySnapshot> outputs;
309 outputs.push_back(CreateInternalOutput(1, 10));
310 helper_delegate_->set_cached_outputs(outputs.get());
312 ASSERT_EQ(0, helper_delegate_->num_calls_notify_observers());
314 // Internal display's ID can be zero and not updated.
315 DispatchOutputChangeEvent(1, 10, 20, true);
316 EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
318 outputs.clear();
319 outputs.push_back(CreateOutput(0, DISPLAY_CONNECTION_TYPE_UNKNOWN, 2, 11));
320 helper_delegate_->set_cached_outputs(outputs.get());
322 // External display should be updated if the id is zero.
323 DispatchOutputChangeEvent(2, 11, 20, true);
324 EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
327 } // namespace ui