Skip to content

Commit f1cb666

Browse files
authored
feat: Make device enumeration more resilient (#72)
1 parent 5f442f5 commit f1cb666

2 files changed

Lines changed: 78 additions & 31 deletions

File tree

src/windows/win_display_device_general.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ namespace display_device {
5050
const auto source_id_index { data.m_active_source.value_or(0) };
5151
const auto &best_path { display_data->m_paths.at(data.m_source_id_to_path_index.at(source_id_index)) };
5252
const auto friendly_name { m_w_api->getFriendlyName(best_path) };
53+
const bool is_active { win_utils::isActive(best_path) };
54+
const auto source_mode { is_active ? win_utils::getSourceMode(win_utils::getSourceIndex(best_path, display_data->m_modes), display_data->m_modes) : nullptr };
55+
const auto display_name { is_active ? m_w_api->getDisplayName(best_path) : std::string {} }; // Inactive devices can have multiple display names, so it's just meaningless use any
5356

54-
if (win_utils::isActive(best_path)) {
55-
const auto source_mode { win_utils::getSourceMode(win_utils::getSourceIndex(best_path, display_data->m_modes), display_data->m_modes) };
56-
if (!source_mode) {
57-
// Error already logged
58-
return {};
59-
}
57+
if (is_active && !source_mode) {
58+
DD_LOG(warning) << "Device " << device_id << " is missing source mode!";
59+
}
6060

61-
const auto display_name { m_w_api->getDisplayName(best_path) };
61+
if (source_mode) {
6262
const Rational refresh_rate { best_path.targetInfo.refreshRate.Denominator > 0 ?
6363
Rational { best_path.targetInfo.refreshRate.Numerator, best_path.targetInfo.refreshRate.Denominator } :
6464
Rational { 0, 1 } };
@@ -80,7 +80,7 @@ namespace display_device {
8080
else {
8181
available_devices.push_back(
8282
{ device_id,
83-
std::string {}, // Inactive devices can have multiple display names, so it's just meaningless use any
83+
display_name,
8484
friendly_name,
8585
std::nullopt });
8686
}

tests/unit/windows/test_win_display_device_general.cpp

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -201,42 +201,89 @@ TEST_F_S_MOCKED(EnumAvailableDevices) {
201201
EXPECT_EQ(m_win_dd.enumAvailableDevices(), expected_list);
202202
}
203203

204-
TEST_F_S_MOCKED(EnumAvailableDevices, FailedToGetDisplayData) {
204+
TEST_F_S_MOCKED(EnumAvailableDevices, MissingSourceModes) {
205+
auto pam_missing_modes { ut_consts::PAM_3_ACTIVE };
206+
pam_missing_modes->m_paths.resize(2);
207+
pam_missing_modes->m_modes.resize(1);
208+
209+
InSequence sequence;
205210
EXPECT_CALL(*m_layer, queryDisplayConfig(display_device::QueryType::All))
206211
.Times(1)
207-
.WillOnce(Return(ut_consts::PAM_NULL));
212+
.WillOnce(Return(pam_missing_modes))
213+
.RetiresOnSaturation();
208214

209-
EXPECT_EQ(m_win_dd.enumAvailableDevices(), display_device::EnumeratedDeviceList {});
215+
for (int i = 1; i <= 2; ++i) {
216+
EXPECT_CALL(*m_layer, getMonitorDevicePath(_))
217+
.Times(1)
218+
.WillOnce(Return("Path" + std::to_string(i)))
219+
.RetiresOnSaturation();
220+
EXPECT_CALL(*m_layer, getDeviceId(_))
221+
.Times(1)
222+
.WillOnce(Return("DeviceId" + std::to_string(i)))
223+
.RetiresOnSaturation();
224+
EXPECT_CALL(*m_layer, getDisplayName(_))
225+
.Times(1)
226+
.WillOnce(Return("DisplayName" + std::to_string(i)))
227+
.RetiresOnSaturation();
228+
}
229+
230+
EXPECT_CALL(*m_layer, getFriendlyName(_))
231+
.Times(1)
232+
.WillOnce(Return("FriendlyName1"))
233+
.RetiresOnSaturation();
234+
EXPECT_CALL(*m_layer, getDisplayName(_))
235+
.Times(1)
236+
.WillOnce(Return("DisplayName1"))
237+
.RetiresOnSaturation();
238+
EXPECT_CALL(*m_layer, getDisplayScale(_, _))
239+
.Times(1)
240+
.WillOnce(Return(std::nullopt))
241+
.RetiresOnSaturation();
242+
EXPECT_CALL(*m_layer, getHdrState(_))
243+
.Times(1)
244+
.WillOnce(Return(std::nullopt))
245+
.RetiresOnSaturation();
246+
247+
EXPECT_CALL(*m_layer, getFriendlyName(_))
248+
.Times(1)
249+
.WillOnce(Return("FriendlyName2"))
250+
.RetiresOnSaturation();
251+
EXPECT_CALL(*m_layer, getDisplayName(_))
252+
.Times(1)
253+
.WillOnce(Return("DisplayName2"))
254+
.RetiresOnSaturation();
255+
256+
const display_device::EnumeratedDeviceList expected_list {
257+
{ "DeviceId1",
258+
"DisplayName1",
259+
"FriendlyName1",
260+
display_device::EnumeratedDevice::Info {
261+
{ 1920, 1080 },
262+
display_device::Rational { 0, 1 },
263+
display_device::Rational { 120, 1 },
264+
true,
265+
{ 0, 0 },
266+
std::nullopt } },
267+
{ "DeviceId2",
268+
"DisplayName2",
269+
"FriendlyName2",
270+
std::nullopt }
271+
};
272+
EXPECT_EQ(m_win_dd.enumAvailableDevices(), expected_list);
210273
}
211274

212-
TEST_F_S_MOCKED(EnumAvailableDevices, FailedToCollectSourceData) {
275+
TEST_F_S_MOCKED(EnumAvailableDevices, FailedToGetDisplayData) {
213276
EXPECT_CALL(*m_layer, queryDisplayConfig(display_device::QueryType::All))
214277
.Times(1)
215-
.WillOnce(Return(ut_consts::PAM_EMPTY));
278+
.WillOnce(Return(ut_consts::PAM_NULL));
216279

217280
EXPECT_EQ(m_win_dd.enumAvailableDevices(), display_device::EnumeratedDeviceList {});
218281
}
219282

220-
TEST_F_S_MOCKED(EnumAvailableDevices, NoDisplayModes) {
221-
auto pam_no_modes { ut_consts::PAM_3_ACTIVE };
222-
pam_no_modes->m_paths.resize(1);
223-
pam_no_modes->m_modes.clear();
224-
283+
TEST_F_S_MOCKED(EnumAvailableDevices, FailedToCollectSourceData) {
225284
EXPECT_CALL(*m_layer, queryDisplayConfig(display_device::QueryType::All))
226285
.Times(1)
227-
.WillOnce(Return(pam_no_modes));
228-
EXPECT_CALL(*m_layer, getMonitorDevicePath(_))
229-
.Times(1)
230-
.WillOnce(Return("Path1"));
231-
EXPECT_CALL(*m_layer, getDeviceId(_))
232-
.Times(1)
233-
.WillOnce(Return("DeviceId1"));
234-
EXPECT_CALL(*m_layer, getDisplayName(_))
235-
.Times(1)
236-
.WillOnce(Return("DisplayName1"));
237-
EXPECT_CALL(*m_layer, getFriendlyName(_))
238-
.Times(1)
239-
.WillOnce(Return("FriendlyName1"));
286+
.WillOnce(Return(ut_consts::PAM_EMPTY));
240287

241288
EXPECT_EQ(m_win_dd.enumAvailableDevices(), display_device::EnumeratedDeviceList {});
242289
}

0 commit comments

Comments
 (0)