Skip to content

Commit cba45e3

Browse files
authored
feat(settings_revert): use full extended topology as a fallback (#133)
1 parent 2c431bc commit cba45e3

File tree

11 files changed

+104
-96
lines changed

11 files changed

+104
-96
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ jobs:
182182
# Doxygen from Ubuntu is too old, need Doxygen >= 1.10
183183
DOCS=OFF
184184
else
185-
DOCS=ON
185+
DOCS=OFF
186186
fi
187187
188188
cmake \

src/common/include/display_device/settings_manager_interface.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ namespace display_device {
2626
PersistenceSaveFailed, ///< Persistence save failed
2727
};
2828

29+
/**
30+
* @brief Outcome values when trying to revert settings.
31+
*/
32+
enum class RevertResult {
33+
Ok, ///< Settings were reverted successfully
34+
ApiTemporarilyUnavailable, ///< API is temporarily unavailable
35+
TopologyIsInvalid, ///< Topology is invalid
36+
SwitchingTopologyFailed, ///< Switching topology has failed
37+
RevertingPrimaryDeviceFailed, ///< Reverting primary device failed
38+
RevertingDisplayModesFailed, ///< Reverting display modes failed
39+
RevertingHdrStatesFailed, ///< Reverting HDR states failed
40+
PersistenceSaveFailed, ///< Persistence save failed
41+
};
42+
2943
/**
3044
* @brief Default virtual destructor.
3145
*/
@@ -79,7 +93,7 @@ namespace display_device {
7993
* const auto result = iface->revertSettings();
8094
* @examples_end
8195
*/
82-
[[nodiscard]] virtual bool
96+
[[nodiscard]] virtual RevertResult
8397
revertSettings() = 0;
8498

8599
/**
@@ -94,11 +108,11 @@ namespace display_device {
94108
* auto result = iface->applySettings(config);
95109
* if (result == ApplyResult::Ok) {
96110
* // Wait for some time
97-
* if (!iface->revertSettings()) {
111+
* if (iface->revertSettings() != RevertResult::Ok) {
98112
* // Wait for user input
99113
* const bool user_wants_reset { true };
100114
* if (user_wants_reset) {
101-
* result = iface->resetPersistence();
115+
* iface->resetPersistence();
102116
* }
103117
* }
104118
* }

src/windows/include/display_device/windows/settings_manager.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ namespace display_device {
4545
applySettings(const SingleDisplayConfiguration &config) override;
4646

4747
/** For details @see SettingsManagerInterface::revertSettings */
48-
[[nodiscard]] bool
48+
[[nodiscard]] RevertResult
4949
revertSettings() override;
5050

5151
/** For details @see SettingsManagerInterface::resetPersistence */
@@ -107,11 +107,11 @@ namespace display_device {
107107
* @param current_topology Topology before this method is called.
108108
* @param system_settings_touched Indicates whether a "write" operation could have been performed on the OS.
109109
* @param switched_topology [Optional] Indicates whether the current topology was switched to revert settings.
110-
* @returns True on success, false otherwise.
110+
* @returns Result enum indicating success or failure.
111111
* @warning The method assumes that the caller will ensure restoring the topology
112112
* in case of a failure!
113113
*/
114-
[[nodiscard]] bool
114+
[[nodiscard]] RevertResult
115115
revertModifiedSettings(const ActiveTopology &current_topology, bool &system_settings_touched, bool *switched_topology = nullptr);
116116

117117
std::shared_ptr<WinDisplayDeviceInterface> m_dd_api;

src/windows/include/display_device/windows/settings_utils.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
namespace display_device::win_utils {
1919
/**
20-
* @brief Get all the device its in the topology.
20+
* @brief Get all the device ids in the topology.
2121
* @param topology Topology to be "flattened".
2222
* @return Device ids found in the topology.
2323
* @examples
@@ -29,18 +29,16 @@ namespace display_device::win_utils {
2929
flattenTopology(const ActiveTopology &topology);
3030

3131
/**
32-
* @brief Remove all unavailable devices from the topology.
32+
* @brief Create extended topology from all the available devices.
3333
* @param win_dd Interface for interacting with the OS.
34-
* @param topology Topology to be stripped.
35-
* @return Topology with only available devices.
34+
* @return Extended topology with all the available devices.
3635
* @examples
3736
* const WinDisplayDeviceInterface* iface = getIface(...);
38-
* const ActiveTopology topology { { "DeviceId1", "DeviceId2" }, { "DeviceId3" } };
39-
* const auto stripped_topology { stripTopologyOfUnavailableDevices(*iface, topology) };
37+
* const auto extended_topology { stripTopologyOfUnavailableDevices(*iface) };
4038
* @examples_end
4139
*/
4240
ActiveTopology
43-
stripTopologyOfUnavailableDevices(WinDisplayDeviceInterface &win_dd, const ActiveTopology &topology);
41+
createFullExtendedTopology(WinDisplayDeviceInterface &win_dd);
4442

4543
/**
4644
* @brief Get one primary device from the provided topology.
@@ -86,7 +84,7 @@ namespace display_device::win_utils {
8684

8785
/**
8886
* @brief Compute new topology from arbitrary data.
89-
* @param device_prep Specify how to to compute the new topology.
87+
* @param device_prep Specify how to compute the new topology.
9088
* @param configuring_primary_devices Specify whether the `device_to_configure` was unspecified (primary device was selected).
9189
* @param device_to_configure Main device to be configured.
9290
* @param additional_devices_to_configure Additional devices that belong to the same group as `device_to_configure`.

src/windows/settings_manager_apply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ namespace display_device {
172172
if (change_is_needed) {
173173
if (cached_state && !m_dd_api->isTopologyTheSame(cached_state->m_modified.m_topology, new_topology)) {
174174
DD_LOG(warning) << "To apply new display device settings, previous modifications must be undone! Trying to undo them now.";
175-
if (!revertModifiedSettings(topology_before_changes, system_settings_touched)) {
175+
if (revertModifiedSettings(topology_before_changes, system_settings_touched) != RevertResult::Ok) {
176176
DD_LOG(error) << "Failed to apply new configuration, because the previous settings could not be reverted!";
177177
return std::nullopt;
178178
}

src/windows/settings_manager_general.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ namespace display_device {
4949
bool
5050
SettingsManager::resetPersistence() {
5151
// Trying to revert one more time in case we succeed.
52-
if (revertSettings()) {
52+
if (revertSettings() == RevertResult::Ok) {
5353
return true;
5454
}
5555

src/windows/settings_manager_revert.cpp

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file src/windows/settings_manager_revert.cpp
3-
* @brief Definitions for the methods for reverting settings in SettingsManager..
3+
* @brief Definitions for the methods for reverting settings in SettingsManager.
44
*/
55
// class header include
66
#include "display_device/windows/settings_manager.h"
@@ -23,25 +23,25 @@ namespace display_device {
2323
}
2424
} // namespace
2525

26-
bool
26+
SettingsManager::RevertResult
2727
SettingsManager::revertSettings() {
2828
const auto &cached_state { m_persistence_state->getState() };
2929
if (!cached_state) {
30-
return true;
30+
return RevertResult::Ok;
3131
}
3232

3333
const auto api_access { m_dd_api->isApiAccessAvailable() };
3434
DD_LOG(info) << "Trying to revert applied display device settings. API is available: " << toJson(api_access);
3535

3636
if (!api_access) {
37-
return false;
37+
return RevertResult::ApiTemporarilyUnavailable;
3838
}
3939

4040
const auto current_topology { m_dd_api->getCurrentTopology() };
4141
if (!m_dd_api->isTopologyValid(current_topology)) {
4242
DD_LOG(error) << "Retrieved current topology is invalid:\n"
4343
<< toJson(current_topology);
44-
return false;
44+
return RevertResult::TopologyIsInvalid;
4545
}
4646

4747
bool system_settings_touched { false };
@@ -50,8 +50,8 @@ namespace display_device {
5050
win_utils::blankHdrStates(*m_dd_api, m_workarounds.m_hdr_blank_delay);
5151
}
5252
} };
53-
boost::scope::scope_exit topology_prep_guard { [this, &cached_state, &current_topology, &system_settings_touched]() {
54-
auto topology_to_restore { win_utils::stripTopologyOfUnavailableDevices(*m_dd_api, cached_state->m_initial.m_topology) };
53+
boost::scope::scope_exit topology_prep_guard { [this, &current_topology, &system_settings_touched]() {
54+
auto topology_to_restore { win_utils::createFullExtendedTopology(*m_dd_api) };
5555
if (!m_dd_api->isTopologyValid(topology_to_restore)) {
5656
topology_to_restore = current_topology;
5757
}
@@ -66,15 +66,15 @@ namespace display_device {
6666

6767
// We can revert the modified setting independently before playing around with initial topology.
6868
bool switched_to_modified_topology { false };
69-
if (!revertModifiedSettings(current_topology, system_settings_touched, &switched_to_modified_topology)) {
69+
if (const auto result = revertModifiedSettings(current_topology, system_settings_touched, &switched_to_modified_topology); result != RevertResult::Ok) {
7070
// Error already logged
71-
return false;
71+
return result;
7272
}
7373

7474
if (!m_dd_api->isTopologyValid(cached_state->m_initial.m_topology)) {
7575
DD_LOG(error) << "Trying to revert to an invalid initial topology:\n"
7676
<< toJson(cached_state->m_initial.m_topology);
77-
return false;
77+
return RevertResult::TopologyIsInvalid;
7878
}
7979

8080
const bool is_topology_the_same { m_dd_api->isTopologyTheSame(current_topology, cached_state->m_initial.m_topology) };
@@ -83,12 +83,12 @@ namespace display_device {
8383
if (need_to_switch_topology && !m_dd_api->setTopology(cached_state->m_initial.m_topology)) {
8484
DD_LOG(error) << "Failed to change topology to:\n"
8585
<< toJson(cached_state->m_initial.m_topology);
86-
return false;
86+
return RevertResult::SwitchingTopologyFailed;
8787
}
8888

8989
if (!m_persistence_state->persistState(std::nullopt)) {
9090
DD_LOG(error) << "Failed to save reverted settings! Undoing initial topology changes...";
91-
return false;
91+
return RevertResult::PersistenceSaveFailed;
9292
}
9393

9494
if (m_audio_context_api->isCaptured()) {
@@ -97,28 +97,28 @@ namespace display_device {
9797

9898
// Disable guards
9999
topology_prep_guard.set_active(false);
100-
return true;
100+
return RevertResult::Ok;
101101
}
102102

103-
bool
103+
SettingsManager::RevertResult
104104
SettingsManager::revertModifiedSettings(const ActiveTopology &current_topology, bool &system_settings_touched, bool *switched_topology) {
105105
const auto &cached_state { m_persistence_state->getState() };
106106
if (!cached_state || !cached_state->m_modified.hasModifications()) {
107-
return true;
107+
return RevertResult::Ok;
108108
}
109109

110110
if (!m_dd_api->isTopologyValid(cached_state->m_modified.m_topology)) {
111111
DD_LOG(error) << "Trying to revert modified settings using invalid topology:\n"
112112
<< toJson(cached_state->m_modified.m_topology);
113-
return false;
113+
return RevertResult::TopologyIsInvalid;
114114
}
115115

116116
const bool is_topology_the_same { m_dd_api->isTopologyTheSame(current_topology, cached_state->m_modified.m_topology) };
117117
system_settings_touched = !is_topology_the_same;
118118
if (!is_topology_the_same && !m_dd_api->setTopology(cached_state->m_modified.m_topology)) {
119119
DD_LOG(error) << "Failed to change topology to:\n"
120120
<< toJson(cached_state->m_modified.m_topology);
121-
return false;
121+
return RevertResult::SwitchingTopologyFailed;
122122
}
123123
if (switched_topology) {
124124
*switched_topology = !is_topology_the_same;
@@ -135,7 +135,7 @@ namespace display_device {
135135
<< toJson(cached_state->m_modified.m_original_hdr_states);
136136
if (!m_dd_api->setHdrStates(cached_state->m_modified.m_original_hdr_states)) {
137137
// Error already logged
138-
return false;
138+
return RevertResult::RevertingHdrStatesFailed;
139139
}
140140

141141
hdr_guard_fn = win_utils::hdrStateGuardFn(*m_dd_api, current_states);
@@ -152,7 +152,7 @@ namespace display_device {
152152
if (!m_dd_api->setDisplayModes(cached_state->m_modified.m_original_modes)) {
153153
system_settings_touched = true;
154154
// Error already logged
155-
return false;
155+
return RevertResult::RevertingDisplayModesFailed;
156156
}
157157

158158
// It is possible that the display modes will not actually change even though the "current != new" condition is true.
@@ -175,7 +175,7 @@ namespace display_device {
175175
DD_LOG(info) << "Trying to change back the original primary device to: " << toJson(cached_state->m_modified.m_original_primary_device);
176176
if (!m_dd_api->setAsPrimary(cached_state->m_modified.m_original_primary_device)) {
177177
// Error already logged
178-
return false;
178+
return RevertResult::RevertingPrimaryDeviceFailed;
179179
}
180180

181181
primary_guard_fn = win_utils::primaryGuardFn(*m_dd_api, current_primary_device);
@@ -186,13 +186,13 @@ namespace display_device {
186186
cleared_data.m_modified = { cleared_data.m_modified.m_topology };
187187
if (!m_persistence_state->persistState(cleared_data)) {
188188
DD_LOG(error) << "Failed to save reverted settings! Undoing changes to modified topology...";
189-
return false;
189+
return RevertResult::PersistenceSaveFailed;
190190
}
191191

192192
// Disable guards
193193
hdr_guard.set_active(false);
194194
mode_guard.set_active(false);
195195
primary_guard.set_active(false);
196-
return true;
196+
return RevertResult::Ok;
197197
}
198198
} // namespace display_device

src/windows/settings_utils.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,19 @@ namespace display_device::win_utils {
147147
}
148148

149149
ActiveTopology
150-
stripTopologyOfUnavailableDevices(WinDisplayDeviceInterface &win_dd, const ActiveTopology &topology) {
150+
createFullExtendedTopology(WinDisplayDeviceInterface &win_dd) {
151151
const auto devices { win_dd.enumAvailableDevices() };
152152
if (devices.empty()) {
153-
DD_LOG(error) << "Failed to enumerate available devices for stripping topology!";
153+
DD_LOG(error) << "Failed to enumerate available devices for full extended topology!";
154154
return {};
155155
}
156156

157-
return stripTopology(topology, devices);
157+
ActiveTopology topology;
158+
for (const auto &device : devices) {
159+
topology.push_back({ device.m_device_id });
160+
}
161+
162+
return topology;
158163
}
159164

160165
std::string

src/windows/win_api_layer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,12 +612,12 @@ namespace display_device {
612612
return TRUE; }, reinterpret_cast<LPARAM>(&enum_data));
613613

614614
if (!enum_data.m_width) {
615-
DD_LOG(error) << "Failed to get monitor info for " << display_name << "!";
615+
DD_LOG(debug) << "Failed to get monitor info for " << display_name << "!";
616616
return std::nullopt;
617617
}
618618

619619
if (*enum_data.m_width * source_mode.width == 0) {
620-
DD_LOG(error) << "Cannot get display scale for " << display_name << " from a width of 0!";
620+
DD_LOG(debug) << "Cannot get display scale for " << display_name << " from a width of 0!";
621621
return std::nullopt;
622622
}
623623

0 commit comments

Comments
 (0)