App ordering support for legacy clients
This commit is contained in:
@@ -592,6 +592,7 @@ namespace config {
|
||||
"ipv4", // Address family
|
||||
platf::appdata().string() + "/sunshine.log", // log file
|
||||
false, // notify_pre_releases
|
||||
false, // legacy_ordering
|
||||
{}, // prep commands
|
||||
{}, // server commands
|
||||
};
|
||||
@@ -1284,6 +1285,7 @@ namespace config {
|
||||
bool_f(vars, "enable_discovery", sunshine.enable_discovery);
|
||||
bool_f(vars, "envvar_compatibility_mode", sunshine.envvar_compatibility_mode);
|
||||
bool_f(vars, "notify_pre_releases", sunshine.notify_pre_releases);
|
||||
bool_f(vars, "legacy_ordering", sunshine.legacy_ordering);
|
||||
|
||||
int port = sunshine.port;
|
||||
int_between_f(vars, "port"s, port, {1024 + nvhttp::PORT_HTTPS, 65535 - rtsp_stream::RTSP_SETUP_PORT});
|
||||
|
||||
@@ -280,6 +280,7 @@ namespace config {
|
||||
|
||||
std::string log_file;
|
||||
bool notify_pre_releases;
|
||||
bool legacy_ordering;
|
||||
std::vector<prep_cmd_t> prep_cmds;
|
||||
std::vector<server_cmd_t> server_cmds;
|
||||
};
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "utility.h"
|
||||
#include "uuid.h"
|
||||
#include "video.h"
|
||||
#include "zwpad.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "platform/windows/virtual_display.h"
|
||||
@@ -1069,7 +1070,16 @@ namespace nvhttp {
|
||||
if (!!(named_cert_p->perm & PERM::_all_actions)) {
|
||||
auto current_appid = proc::proc.running();
|
||||
auto should_hide_inactive_apps = config::input.enable_input_only_mode && current_appid > 0 && current_appid != proc::input_only_app_id;
|
||||
for (auto &app : proc::proc.get_apps()) {
|
||||
|
||||
auto app_list = proc::proc.get_apps();
|
||||
|
||||
size_t bits;
|
||||
if (config::sunshine.legacy_ordering) {
|
||||
bits = zwpad::pad_width_for_count(app_list.size());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < app_list.size(); i++) {
|
||||
auto& app = app_list[i];
|
||||
auto appid = util::from_view(app.id);
|
||||
if (should_hide_inactive_apps) {
|
||||
if (
|
||||
@@ -1085,10 +1095,15 @@ namespace nvhttp {
|
||||
}
|
||||
}
|
||||
|
||||
auto app_name = app.name;
|
||||
if (config::sunshine.legacy_ordering) {
|
||||
zwpad::pad_for_ordering(app.name, bits, i);
|
||||
}
|
||||
|
||||
pt::ptree app_node;
|
||||
|
||||
app_node.put("IsHdrSupported"s, video::active_hevc_mode == 3 ? 1 : 0);
|
||||
app_node.put("AppTitle"s, app.name);
|
||||
app_node.put("AppTitle"s, app_name);
|
||||
app_node.put("UUID", app.uuid);
|
||||
app_node.put("IDX", app.idx);
|
||||
app_node.put("ID", app.id);
|
||||
|
||||
61
src/zwpad.h
Normal file
61
src/zwpad.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// zero_width_pad.hpp
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <bit> // std::bit_width – C++20
|
||||
#include <stdexcept>
|
||||
|
||||
namespace zwpad
|
||||
{
|
||||
// Two distinct zero-width characters.
|
||||
// U+200B ZERO WIDTH SPACE – “0”
|
||||
// U+200C ZERO WIDTH NON-JOINER – “1”
|
||||
inline constexpr char8_t ZW0[] = u8"\u200B";
|
||||
inline constexpr char8_t ZW1[] = u8"\u200C";
|
||||
|
||||
/// \brief Encode \p index with a fixed-width binary prefix made of
|
||||
/// zero-width code-points and append the original text.
|
||||
///
|
||||
/// \param text The payload you actually want to keep visible.
|
||||
/// \param padBits How many zero-width *digits* to prepend.
|
||||
/// (Usually: std::bit_width(count-1).)
|
||||
/// \param index Position in the ordered set, **0-based**.
|
||||
///
|
||||
/// \return A UTF-8 std::string whose first \p padBits characters are
|
||||
/// either U+200B or U+200C, followed by \p text.
|
||||
///
|
||||
/// The lexical order of the resulting strings corresponds to the
|
||||
/// numerical order of *index* because U+200B < U+200C.
|
||||
///
|
||||
inline std::string
|
||||
pad_for_ordering(std::string_view text,
|
||||
std::size_t padBits,
|
||||
std::size_t index)
|
||||
{
|
||||
if (padBits == 0)
|
||||
throw std::invalid_argument("padBits must be > 0");
|
||||
if (index >= (std::size_t{1} << padBits))
|
||||
throw std::out_of_range("index does not fit into padBits");
|
||||
|
||||
std::string out;
|
||||
out.reserve(padBits * 3 + text.size()); // each ZW char is 3-byte UTF-8
|
||||
|
||||
for (std::size_t bit = 0; bit < padBits; ++bit)
|
||||
{
|
||||
// Emit the *most* significant bit first.
|
||||
const bool one = (index >> (padBits - 1 - bit)) & 1;
|
||||
out += one ? reinterpret_cast<const char*>(ZW1)
|
||||
: reinterpret_cast<const char*>(ZW0);
|
||||
}
|
||||
out.append(text);
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Convenience: compute the minimal pad width from the total count.
|
||||
[[nodiscard]]
|
||||
inline std::size_t pad_width_for_count(std::size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
throw std::invalid_argument("count must be > 0");
|
||||
return std::bit_width(count - 1); // e.g. count==8 → 3 bits
|
||||
}
|
||||
} // namespace zwpad
|
||||
Reference in New Issue
Block a user