mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-11 19:07:33 +08:00
[feat] remember remote display resolutions across connections
This commit is contained in:
@@ -52,6 +52,20 @@ struct DisplayResolutionChange {
|
||||
bool accepted = false;
|
||||
};
|
||||
|
||||
// Persist the native identity, never the display's position in a session.
|
||||
struct DisplayResolutionPreference {
|
||||
std::string display_key;
|
||||
DisplayResolution resolution;
|
||||
};
|
||||
|
||||
inline bool ValidDisplayResolutionPreference(
|
||||
const DisplayResolutionPreference &preference) {
|
||||
return !preference.display_key.empty() &&
|
||||
preference.display_key.size() <= 1024 &&
|
||||
preference.display_key.find('\0') == std::string::npos &&
|
||||
ValidDisplayResolution(preference.resolution);
|
||||
}
|
||||
|
||||
inline bool SupportsDisplayResolution(const DisplayResolutionInfo &display,
|
||||
const DisplayResolutionChange &change) {
|
||||
return display.display_id == change.display_id &&
|
||||
@@ -62,4 +76,4 @@ inline bool SupportsDisplayResolution(const DisplayResolutionInfo &display,
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-11-11
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DISPLAY_RESOLUTION_PREFERENCES_H_
|
||||
#define _DISPLAY_RESOLUTION_PREFERENCES_H_
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "display_resolution.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
inline nlohmann::json DisplayResolutionPreferencesJson(
|
||||
const std::vector<DisplayResolutionPreference> &preferences) {
|
||||
auto result = nlohmann::json::array();
|
||||
for (const auto &preference : preferences)
|
||||
result.push_back({{"display_key", preference.display_key},
|
||||
{"width", preference.resolution.width},
|
||||
{"height", preference.resolution.height}});
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool ReadDisplayResolutionPreferences(
|
||||
const nlohmann::json &values,
|
||||
std::vector<DisplayResolutionPreference> &result) {
|
||||
std::vector<DisplayResolutionPreference> parsed;
|
||||
if (!values.is_array() || values.size() > kMaxResolutionDisplays)
|
||||
return false;
|
||||
try {
|
||||
for (const auto &value : values) {
|
||||
const auto &width = value.at("width");
|
||||
const auto &height = value.at("height");
|
||||
if (!width.is_number_integer() || !height.is_number_integer() ||
|
||||
width < 1 || width > 32768 || height < 1 || height > 32768)
|
||||
return false;
|
||||
DisplayResolutionPreference preference{
|
||||
value.at("display_key").get<std::string>(),
|
||||
{width.get<int>(), height.get<int>()}};
|
||||
if (!ValidDisplayResolutionPreference(preference) ||
|
||||
std::any_of(parsed.begin(), parsed.end(), [&](const auto &existing) {
|
||||
return existing.display_key == preference.display_key;
|
||||
}))
|
||||
return false;
|
||||
parsed.push_back(std::move(preference));
|
||||
}
|
||||
} catch (const nlohmann::json::exception &) {
|
||||
return false;
|
||||
}
|
||||
result = std::move(parsed);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -223,6 +223,8 @@ struct RemoteAction {
|
||||
// Optional host information extension, also returned with resolution status.
|
||||
std::vector<DisplayResolutionInfo> display_resolutions;
|
||||
DisplayResolutionChange resolution_change;
|
||||
// Controller preferences sent with its initial host information.
|
||||
std::vector<DisplayResolutionPreference> preferred_display_resolutions;
|
||||
|
||||
std::string to_json() const;
|
||||
bool from_json(const std::string& json_string);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <remote_action.h>
|
||||
#include <display_resolution_preferences.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
@@ -339,6 +340,9 @@ std::string RemoteAction::ToJson(const RemoteAction& action) {
|
||||
if (!action.display_resolutions.empty())
|
||||
object["host_info"]["display_resolutions"] =
|
||||
DisplayResolutionsJson(action.display_resolutions);
|
||||
if (!action.preferred_display_resolutions.empty())
|
||||
object["host_info"]["preferred_display_resolutions"] =
|
||||
DisplayResolutionPreferencesJson(action.preferred_display_resolutions);
|
||||
break;
|
||||
}
|
||||
case ControlType::invalid:
|
||||
@@ -354,6 +358,7 @@ bool RemoteAction::FromJson(const std::string& json_string,
|
||||
try {
|
||||
const json object = json::parse(json_string);
|
||||
output.display_resolutions.clear();
|
||||
output.preferred_display_resolutions.clear();
|
||||
output.type = static_cast<ControlType>(object.at("type").get<int>());
|
||||
switch (output.type) {
|
||||
case ControlType::display_resolution:
|
||||
@@ -549,6 +554,11 @@ bool RemoteAction::FromJson(const std::string& json_string,
|
||||
ResetHostInfo(output.i);
|
||||
owns_host_info = true;
|
||||
const auto& host_info_object = object.at("host_info");
|
||||
// A corrupt optional preference must not prevent a connection.
|
||||
if (const auto preferences = host_info_object.find("preferred_display_resolutions");
|
||||
preferences != host_info_object.end())
|
||||
ReadDisplayResolutionPreferences(*preferences,
|
||||
output.preferred_display_resolutions);
|
||||
if (const auto modes = host_info_object.find("display_resolutions");
|
||||
modes != host_info_object.end() &&
|
||||
!ReadDisplayResolutions(*modes, output.display_resolutions)) return false;
|
||||
|
||||
Reference in New Issue
Block a user