Skip to content

Commit

Permalink
Combining the StaticDisplayConfigScribe into the StaticDisplayConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkae committed Oct 17, 2023
1 parent 8838f5c commit d35af64
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 297 deletions.
1 change: 0 additions & 1 deletion src/miral/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ add_library(miral-internal STATIC
mru_window_list.cpp mru_window_list.h
open_desktop_entry.cpp open_desktop_entry.h
static_display_config.cpp static_display_config.h
static_display_configuration_scribe.cpp static_display_configuration_scribe.h
window_info_internal.cpp window_info_internal.h
window_management_trace.cpp window_management_trace.h
xcursor_loader.cpp xcursor_loader.h
Expand Down
138 changes: 81 additions & 57 deletions src/miral/display_configuration_option.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#include "miral/display_configuration_option.h"
#include "static_display_config.h"
#include "static_display_configuration_scribe.h"

#include <mir/graphics/default_display_configuration_policy.h>
#include <mir/graphics/display_configuration.h>
Expand Down Expand Up @@ -62,6 +61,73 @@ bool contains_alpha(MirPixelFormat format)
return (format == mir_pixel_format_abgr_8888 ||
format == mir_pixel_format_argb_8888);
}

struct ParsedOptions
{
enum class ParsedOptionsType
{
none,
side_by_side,
single_opt,
static_opt
};
ParsedOptionsType display_layout;
double scale{0};
bool with_alpha;
std::string static_directory;
};

auto parse_options(mir::Server& server) -> ParsedOptions
{
auto const options = server.get_options();
auto display_layout = options->get<std::string>(display_config_opt);
auto with_alpha = options->get<std::string>(display_alpha_opt) == display_alpha_on;
auto const scale_str = options->get<std::string>(display_scale_opt);
std::string static_directory;

double scale{0};
static double const scale_min = 0.01;
static double const scale_max = 100.0;
try
{
scale = std::stod(scale_str);
}
catch (std::invalid_argument const&)
{
mir::fatal_error("Failed to parse scale '%s' as double", scale_str.c_str());
}
if (scale < scale_min || scale > scale_max)
{
mir::fatal_error("Invalid scale %f, must be between %f and %f", scale, scale_min, scale_max);
}

ParsedOptions::ParsedOptionsType option_type = ParsedOptions::ParsedOptionsType::none;
if (display_layout == sidebyside_opt_val)
{
option_type = ParsedOptions::ParsedOptionsType::side_by_side;
}
else if (display_layout == single_opt_val)
{
option_type = ParsedOptions::ParsedOptionsType::single_opt;
}
else if (display_layout.compare(0, strlen(static_opt_val), static_opt_val) == 0)
{
if (scale != 1.0)
{
mir::fatal_error("Display scale option can't be used with static display configuration");
}
option_type = ParsedOptions::ParsedOptionsType::static_opt;
static_directory = display_layout.substr(strlen(static_opt_val));
}

return {
option_type,
scale,
with_alpha,
static_directory
};
};

}

PixelFormatSelector::PixelFormatSelector(
Expand Down Expand Up @@ -127,36 +193,18 @@ void miral::display_configuration_options(mir::Server& server)
server.add_configuration_option(display_alpha_opt, display_alpha_descr, display_alpha_off);
server.add_configuration_option(display_scale_opt, display_scale_descr, display_scale_default);

// Try to create the display config scribe
server.override_the_display_configuration_author([&] -> std::shared_ptr<mg::DisplayConfigurationScribe>
{
auto const options = server.get_options();
auto display_layout = options->get<std::string>(display_config_opt);
auto const scale_str = options->get<std::string>(display_scale_opt);

double scale{0};
try
{
scale = std::stod(scale_str);
}
catch (std::invalid_argument const&)
{
mir::fatal_error("Failed to parse scale '%s' as double", scale_str.c_str());
}

if (display_layout.compare(0, strlen(static_opt_val), static_opt_val) == 0)
auto options = parse_options(server);
if (options.display_layout == ParsedOptions::ParsedOptionsType::static_opt)
{
if (scale != 1.0)
{
mir::fatal_error("Display scale option can't be used with static display configuration");
}

return std::make_shared<StaticDisplayConfigurationScribe>(display_layout.substr(strlen(static_opt_val)));
return std::make_shared<StaticDisplayConfig>(options.static_directory);
}

class NullDisplayConfigurationScribe : public mg::DisplayConfigurationScribe
class NullDisplayConfigurationScribe : public mir::graphics::DisplayConfigurationScribe
{
void write(mg::DisplayConfiguration const&) override {};
public:
void write(const mir::graphics::DisplayConfiguration&) override {}
};

return std::make_shared<NullDisplayConfigurationScribe>();
Expand All @@ -166,54 +214,30 @@ void miral::display_configuration_options(mir::Server& server)
[&](std::shared_ptr<mg::DisplayConfigurationPolicy> const& wrapped)
-> std::shared_ptr<mg::DisplayConfigurationPolicy>
{
auto const options = server.get_options();
auto display_layout = options->get<std::string>(display_config_opt);
auto with_alpha = options->get<std::string>(display_alpha_opt) == display_alpha_on;
auto const scale_str = options->get<std::string>(display_scale_opt);

double scale{0};
static double const scale_min = 0.01;
static double const scale_max = 100.0;
try
{
scale = std::stod(scale_str);
}
catch (std::invalid_argument const&)
{
mir::fatal_error("Failed to parse scale '%s' as double", scale_str.c_str());
}
if (scale < scale_min || scale > scale_max)
{
mir::fatal_error("Invalid scale %f, must be between %f and %f", scale, scale_min, scale_max);
}

auto options = parse_options(server);
auto layout_selector = wrapped;

if (display_layout == sidebyside_opt_val)
if (options.display_layout == ParsedOptions::ParsedOptionsType::side_by_side)
{
layout_selector = std::make_shared<mg::SideBySideDisplayConfigurationPolicy>();
}
else if (display_layout == single_opt_val)
else if (options.display_layout == ParsedOptions::ParsedOptionsType::single_opt)
{
layout_selector = std::make_shared<mg::SingleDisplayConfigurationPolicy>();
}
else if (display_layout.compare(0, strlen(static_opt_val), static_opt_val) == 0)
else if (options.display_layout == ParsedOptions::ParsedOptionsType::static_opt)
{
if (scale != 1.0)
{
mir::fatal_error("Display scale option can't be used with static display configuration");
}
auto sdc = std::make_shared<StaticDisplayConfig>(display_layout.substr(strlen(static_opt_val)));
auto sdc = std::make_shared<StaticDisplayConfig>(options.static_directory);
server.add_init_callback([sdc, &server]{ sdc->init_auto_reload(server); });
layout_selector = std::move(sdc);
}

if (scale != 1.0)
if (options.scale != 1.0)
{
layout_selector = std::make_shared<ScaleSetter>(layout_selector, scale);
layout_selector = std::make_shared<ScaleSetter>(layout_selector, options.scale);
}

// Whatever the layout select a pixel format with requested alpha
return std::make_shared<PixelFormatSelector>(layout_selector, with_alpha);
return std::make_shared<PixelFormatSelector>(layout_selector, options.with_alpha);
});
}
155 changes: 133 additions & 22 deletions src/miral/static_display_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "miral/command_line_option.h"
#include "miral/display_configuration.h"
#include "miral/runner.h"
#include "static_display_configuration_scribe.h"

#include "yaml-cpp/yaml.h"
#include <string.h>
Expand All @@ -44,18 +43,46 @@ using namespace mir::geometry;

namespace
{
// A table of known layout strategies that can be used when `display-layout` doesn't match
// the configuration file, and will be added to the generated .display configuration
const struct {
std::string name;
std::function<void(mg::DisplayConfiguration& conf)> strategy;
} layout_strategies[] =
{
{"default", [](auto& config) { miral::YamlFileDisplayConfig::apply_default_configuration(config); }},
{"side_by_side", [](auto& config) { mg::SideBySideDisplayConfigurationPolicy{}.apply_to(config); }}
};

char const* const card_id = "card-id";
char const* const state = "state";
char const* const state_enabled = "enabled";
char const* const state_disabled = "disabled";
char const* const position = "position";
char const* const mode = "mode";
char const* const orientation = "orientation";
char const* const scale = "scale";
char const* const group = "group";
char const* const orientation_value[] = { "normal", "left", "inverted", "right" };
char const* const layout_suffix = "-layout";

auto as_string(MirOrientation orientation) -> char const*
{
return orientation_value[orientation/90];
}

auto as_orientation(std::string const& orientation) -> mir::optional_value<MirOrientation>
{
if (orientation == miral::YamlFileDisplayConfig::orientation_value[3])
if (orientation == orientation_value[3])
return mir_orientation_right;

if (orientation == miral::YamlFileDisplayConfig::orientation_value[2])
if (orientation == orientation_value[2])
return mir_orientation_inverted;

if (orientation == miral::YamlFileDisplayConfig::orientation_value[1])
if (orientation == orientation_value[1])
return mir_orientation_left;

if (orientation == miral::YamlFileDisplayConfig::orientation_value[0])
if (orientation == orientation_value[0])
return mir_orientation_normal;

return {};
Expand All @@ -78,22 +105,6 @@ auto select_mode_index(size_t mode_index, std::vector<mg::DisplayConfigurationMo
extern "C" { char const* basename(char const*); }
#endif

char const* const miral::YamlFileDisplayConfig::card_id = "card-id";
char const* const miral::YamlFileDisplayConfig::state = "state";
char const* const miral::YamlFileDisplayConfig::state_enabled = "enabled";
char const* const miral::YamlFileDisplayConfig::state_disabled = "disabled";
char const* const miral::YamlFileDisplayConfig::position = "position";
char const* const miral::YamlFileDisplayConfig::mode = "mode";
char const* const miral::YamlFileDisplayConfig::orientation = "orientation";
char const* const miral::YamlFileDisplayConfig::scale = "scale";
char const* const miral::YamlFileDisplayConfig::group = "group";
char const* const miral::YamlFileDisplayConfig::orientation_value[] = { "normal", "left", "inverted", "right" };
char const* const miral::YamlFileDisplayConfig::layout_suffix = "-layout";
const miral::YamlFileDisplayConfig::LayoutStrategy miral::YamlFileDisplayConfig::layout_strategies[2] = {
{"default", [](auto& c) { miral::YamlFileDisplayConfig::apply_default_configuration(c); }},
{"side_by_side", [](auto& c) { mg::SideBySideDisplayConfigurationPolicy{}.apply_to(c); }}
};

miral::StaticDisplayConfig::StaticDisplayConfig(std::string const& filename) :
ReloadingYamlFileDisplayConfig(::basename(filename.c_str()))
{
Expand All @@ -111,6 +122,7 @@ miral::StaticDisplayConfig::StaticDisplayConfig(std::string const& filename) :
mir::log_info("Cannot read static display configuration file: '" + filename + "'");
}
}

namespace
{
auto error_prefix(std::string const& filename)
Expand Down Expand Up @@ -312,7 +324,7 @@ void miral::YamlFileDisplayConfig::apply_to(mg::DisplayConfiguration& conf)
out << "layouts:"
"\n " << layout << ": # the current layout";

StaticDisplayConfigurationScribe::serialize_configuration(out, conf);
serialize_configuration(out, conf);
out << "8>< ---------------------------------------------------";
mir::log_info(out.str());
}
Expand Down Expand Up @@ -573,4 +585,103 @@ void miral::ReloadingYamlFileDisplayConfig::check_for_layout_override()
layout_file >> new_layout;
select_layout(new_layout);
}
}

void miral::ReloadingYamlFileDisplayConfig::write(const mir::graphics::DisplayConfiguration &conf)
{
if (!config_path_.has_value())
{
mir::log_debug("Nowhere to write display configuration template: Neither XDG_CONFIG_HOME or HOME is set");
}
else
{
auto const filename = config_path_.value() + "/" + basename;

if (access(filename.c_str(), F_OK))
{
std::ofstream out{filename};

out << "layouts:"
"\n# keys here are layout labels (used for atomically switching between them)."
"\n# The yaml anchor 'the_default' is used to alias the 'default' label"
"\n";

for (auto const& strategy : layout_strategies)
{
auto const resulting_layout = conf.clone();
strategy.strategy(*resulting_layout);

out << "\n " << strategy.name << ":";
serialize_configuration(out, *resulting_layout);
}

mir::log_debug(
"%s display configuration template: %s",
out ? "Wrote" : "Failed writing",
filename.c_str());
}
}
}

void miral::YamlFileDisplayConfig::serialize_configuration(std::ostream& out, mg::DisplayConfiguration& conf)
{
out << "\n cards:"
"\n # a list of cards (currently matched by card-id)";

std::map<mg::DisplayConfigurationCardId, std::ostringstream> card_map;

conf.for_each_output([&card_map](mg::UserDisplayConfigurationOutput const& conf_output)
{
serialize_output_configuration(card_map[conf_output.card_id], conf_output);
});

for (auto const& co : card_map)
{
out << "\n"
"\n - card-id: " << co.first.as_value()
<< co.second.str();
}
}

void miral::YamlFileDisplayConfig::serialize_output_configuration(
std::ostream& out, mg::UserDisplayConfigurationOutput const& conf_output)
{
out << "\n " << conf_output.name << ':';

if (conf_output.connected && conf_output.modes.size() > 0)
{
out << "\n # This output supports the following modes:";
for (size_t i = 0; i < conf_output.modes.size(); ++i)
{
if (i) out << ',';
if ((i % 5) != 2) out << ' ';
else out << "\n # ";
out << conf_output.modes[i];
}
out << "\n #"
"\n # Uncomment the following to enforce the selected configuration."
"\n # Or amend as desired."
"\n #"
"\n state: " << (conf_output.used ? state_enabled : state_disabled)
<< "\t# {enabled, disabled}, defaults to enabled";

if (conf_output.used) // The following are only set when used
{
out << "\n mode: " << conf_output.modes[conf_output.current_mode_index]
<< "\t# Defaults to preferred mode"
"\n position: [" << conf_output.top_left.x << ", " << conf_output.top_left.y << ']'
<< "\t# Defaults to [0, 0]"
"\n orientation: " << as_string(conf_output.orientation)
<< "\t# {normal, left, right, inverted}, defaults to normal"
"\n scale: " << conf_output.scale
<< "\n group: " << conf_output.logical_group_id.as_value()
<< "\t# Outputs with the same non-zero value are treated as a single display";
}
}
else
{
out << "\n # (disconnected)";
}

out << "\n";
}
Loading

0 comments on commit d35af64

Please sign in to comment.