Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: provide a way to specify an additional data source for configuration data #3478

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions include/miral/miral/configuration_data_source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright © Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2 or 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef MIRAL_CONFIGURATION_SOURCE_H
#define MIRAL_CONFIGURATION_SOURCE_H

#include <functional>
#include <map>
#include <string>
#include <memory>

namespace mir { class Server; }

namespace miral
{

/// Used to define another source of configuration data. By default, configuration
/// options are parsed from command line parameters and the Mir configuration file.
/// Using this class, compositor authors can provide another way to set configuration
/// options. For example, one may parse a JSON file to the map and define configuration
/// variable in that way.
class ConfigurationDataSource
{
public:
explicit ConfigurationDataSource(std::function<std::map<std::string, std::string>()> const&);
void operator()(mir::Server& server) const;

struct Self;
std::shared_ptr<Self> self;
};
}

#endif //MIRAL_CONFIGURATION_SOURCE_H
8 changes: 8 additions & 0 deletions include/platform/mir/options/default_configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,17 @@ class DefaultConfiguration : public Configuration
// before the first invocation of the_options() - typically during initialization.
boost::program_options::options_description_easy_init add_options();

void set_options_map(std::map<std::string, std::string> const& options);

private:
// MUST be the first member to ensure it's destroyed last, lest we attempt to
// call destructors in DSOs we've unloaded.
std::vector<std::shared_ptr<SharedLibrary>> platform_libraries;

std::string const config_file;

std::optional<std::map<std::string, std::string>> options_map;

void add_platform_options();
// accessed via the base interface, when access to add_options() has been "lost"
std::shared_ptr<options::Option> the_options() const override;
Expand All @@ -70,6 +74,10 @@ class DefaultConfiguration : public Configuration
boost::program_options::options_description& desc,
ProgramOption& options) const;

virtual void parse_custom(
boost::program_options::options_description& desc,
ProgramOption& options) const;

int const argc;
char const** const argv;
std::function<void(int argc, char const* const* argv)> const unparsed_arguments_handler;
Expand Down
4 changes: 4 additions & 0 deletions include/platform/mir/options/program_option.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class ProgramOption : public Option
boost::program_options::options_description const& description,
std::string const& filename);

void parse_map(
boost::program_options::options_description const& description,
std::map<std::string, std::string> const& map);

bool is_set(char const* name) const override;
bool get(char const* name, bool default_) const override;
std::string get(char const*, char const* default_) const override;
Expand Down
5 changes: 5 additions & 0 deletions src/include/server/mir/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <functional>
#include <memory>
#include <vector>
#include <map>

struct wl_display;

Expand Down Expand Up @@ -186,6 +187,10 @@ class Server
/// 2. $XDG_CONFIG_DIRS (if set, otherwise /etc/xdg)
void set_config_filename(std::string const& config_file);

/// Set an alternative source for configuration data.
void set_configuration_data_source(
std::function<std::map<std::string, std::string>()> const&);

/// Returns the configuration options.
/// This will be null before initialization starts. It will be available
/// when the init_callback has been invoked (and thereafter until the server exits).
Expand Down
1 change: 1 addition & 0 deletions src/miral/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ add_library(miral-external OBJECT
application_authorizer.cpp ${miral_include}/miral/application_authorizer.h
application_info.cpp ${miral_include}/miral/application_info.h
canonical_window_manager.cpp ${miral_include}/miral/canonical_window_manager.h
configuration_data_source.cpp ${miral_include}/miral/configuration_data_source.h
configuration_option.cpp ${miral_include}/miral/configuration_option.h
${miral_include}/miral/command_line_option.h
cursor_theme.cpp ${miral_include}/miral/cursor_theme.h
Expand Down
34 changes: 34 additions & 0 deletions src/miral/configuration_data_source.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright © Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2 or 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "miral/configuration_data_source.h"
#include <mir/server.h>

struct miral::ConfigurationDataSource::Self
{
std::function<std::map<std::string, std::string>()> get_map;
};

miral::ConfigurationDataSource::ConfigurationDataSource(
std::function<std::map<std::string, std::string>()> const& get_map)
: self{std::make_shared<Self>(get_map)}
{
}

void miral::ConfigurationDataSource::operator()(mir::Server& server) const
{
server.set_configuration_data_source(self->get_map);
}
6 changes: 5 additions & 1 deletion src/miral/symbols.map
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ local: *;
MIRAL_5.1 {
global:
extern "C++" {
miral::ConfigurationDataSource::ConfigurationDataSource*;
miral::ConfigurationDataSource::operator*;
miral::Decorations::Decorations*;
miral::Decorations::always_csd*;
miral::Decorations::always_ssd*;
Expand All @@ -469,7 +471,9 @@ global:
miral::IdleListener::on_wake*;
miral::IdleListener::operator*;
miral::WindowManagerTools::move_cursor_to*;
typeinfo?for?miral::IdleListener;
typeinfo?for?miral::ConfigurationDataSource;
typeinfo?for?miral::Decorations;
typeinfo?for?miral::IdleListener;
};
} MIRAL_5.0;

14 changes: 14 additions & 0 deletions src/platform/options/default_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,11 @@ boost::program_options::options_description_easy_init mo::DefaultConfiguration::
return program_options->add_options();
}

void mo::DefaultConfiguration::set_options_map(std::map<std::string, std::string> const& options)
{
options_map = options;
}

std::shared_ptr<mo::Option> mo::DefaultConfiguration::the_options() const
{
if (!options)
Expand All @@ -277,6 +282,7 @@ std::shared_ptr<mo::Option> mo::DefaultConfiguration::the_options() const
parse_arguments(*program_options, *options, argc, argv);
parse_environment(*program_options, *options);
parse_config_file(*program_options, *options);
parse_custom(*program_options, *options);
this->options = options;
}
return options;
Expand Down Expand Up @@ -343,3 +349,11 @@ void mo::DefaultConfiguration::parse_config_file(
if (!config_file.empty())
options.parse_file(desc, config_file);
}

void mo::DefaultConfiguration::parse_custom(
boost::program_options::options_description& desc,
mir::options::ProgramOption& options) const
{
if (options_map)
options.parse_map(desc, options_map.value());
}
17 changes: 17 additions & 0 deletions src/platform/options/program_option.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,23 @@ void mo::ProgramOption::parse_file(
po::notify(options);
}

void mo::ProgramOption::parse_map(
po::options_description const& desc,
std::map<std::string, std::string> const& map)
{
boost::program_options::parsed_options opts(&desc);
for (auto const& [key, val] : map)
{
boost::program_options::basic_option<char> opt;
opt.string_key = key;
opt.value.push_back(val);
opts.options.push_back(opt);
}

po::store(opts, options);
po::notify(options);
}

bool mo::ProgramOption::is_set(char const* name) const
{
return options.count(parse_name(name));
Expand Down
7 changes: 7 additions & 0 deletions src/platform/symbols.map
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,10 @@ MIR_PLATFORM_2.17 {
local: *;
};

MIR_PLATFORM_2.18 {
global:
extern "C++" {
mir::options::DefaultConfiguration::set_options_map*;
};
local: *;
} MIR_PLATFORM_2.17;
18 changes: 16 additions & 2 deletions src/server/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ struct mir::Server::Self
std::make_shared<TemporaryCompositeEventFilter>()};

std::function<void(int argc, char const* const* argv)> command_line_hander{};
std::function<std::map<std::string, std::string>()> get_options_map;

/// set a callback to introduce additional configuration options.
/// this will be invoked by run() before server initialisation starts
Expand Down Expand Up @@ -244,7 +245,8 @@ std::shared_ptr<mo::DefaultConfiguration> configuration_options(
int argc,
char const** argv,
std::function<void(int argc, char const* const* argv)> const& command_line_hander,
std::string const& config_file)
std::string const& config_file,
std::function<std::map<std::string, std::string>()> const& get_options_map)
{
std::shared_ptr<mo::DefaultConfiguration> result;

Expand All @@ -253,6 +255,9 @@ std::shared_ptr<mo::DefaultConfiguration> configuration_options(
else
result = std::make_shared<mo::DefaultConfiguration>(argc, argv, config_file);

if (get_options_map)
result->set_options_map(get_options_map());

return result;
}

Expand Down Expand Up @@ -342,6 +347,14 @@ void mir::Server::set_config_filename(std::string const& config_file)
self->config_file = config_file;
}

/// Set an alternative source for configuration data.
void mir::Server::set_configuration_data_source(
std::function<std::map<std::string, std::string>()> const& get_map)
{
verify_setting_allowed(self->server_config);
self->get_options_map = get_map;
}

auto mir::Server::get_options() const -> std::shared_ptr<options::Option>
{
verify_accessing_allowed(self->server_config);
Expand Down Expand Up @@ -378,7 +391,8 @@ void mir::Server::apply_settings()
{
if (self->server_config) return;

auto const options = configuration_options(self->argc, self->argv, self->command_line_hander, self->config_file);
auto const options = configuration_options(
self->argc, self->argv, self->command_line_hander, self->config_file, self->get_options_map);
self->add_configuration_options(*options);

auto const config = std::make_shared<ServerConfiguration>(options, self);
Expand Down
17 changes: 9 additions & 8 deletions src/server/symbols.map
Original file line number Diff line number Diff line change
Expand Up @@ -1344,12 +1344,13 @@ local: *;
MIR_SERVER_INTERNAL_2.18 {
global:
extern "C++" {
mir::DefaultServerConfiguration::the_led_observer_registrar*;
mir::DecorationStrategy::?DecorationStrategy*;
mir::DecorationStrategy::DecorationStrategy*;
mir::DecorationStrategy::operator*;
mir::DefaultServerConfiguration::set_the_decoration_strategy*;
mir::DefaultServerConfiguration::the_decoration_strategy*;
mir::DefaultServerConfiguration::the_led_observer_registrar*;
mir::Server::set_configuration_data_source*;
mir::Server::set_the_decoration_strategy*;
mir::Server::the_decoration_strategy*;
mir::Server::the_idle_handler*;
Expand All @@ -1369,6 +1370,9 @@ global:
mir::input::receiver::XKBMapperRegistrar::xkb_modifiers*;
mir::shell::IdleHandlerObserver::?IdleHandlerObserver*;
mir::shell::IdleHandlerObserver::IdleHandlerObserver*;
non-virtual?thunk?to?mir::DecorationStrategy::?DecorationStrategy*;
non-virtual?thunk?to?mir::DefaultServerConfiguration::set_the_decoration_strategy*;
non-virtual?thunk?to?mir::DefaultServerConfiguration::the_decoration_strategy*;
non-virtual?thunk?to?mir::DefaultServerConfiguration::the_led_observer_registrar*;
non-virtual?thunk?to?mir::input::receiver::XKBMapperRegistrar::clear_all_keymaps*;
non-virtual?thunk?to?mir::input::receiver::XKBMapperRegistrar::clear_keymap_for_device*;
Expand All @@ -1382,19 +1386,16 @@ global:
non-virtual?thunk?to?mir::input::receiver::XKBMapperRegistrar::unregister_interest*;
non-virtual?thunk?to?mir::input::receiver::XKBMapperRegistrar::xkb_modifiers*;
non-virtual?thunk?to?mir::shell::IdleHandlerObserver::?IdleHandlerObserver*;
typeinfo?for?mir::input::receiver::XKBMapperRegistrar;
typeinfo?for?mir::shell::IdleHandlerObserver;
vtable?for?mir::input::receiver::XKBMapperRegistrar;
vtable?for?mir::shell::IdleHandlerObserver;
non-virtual?thunk?to?mir::DecorationStrategy::?DecorationStrategy*;
non-virtual?thunk?to?mir::DefaultServerConfiguration::set_the_decoration_strategy*;
non-virtual?thunk?to?mir::DefaultServerConfiguration::the_decoration_strategy*;
non-virtual?thunk?to?mir::shell::IdleHandlerObserver::?IdleHandlerObserver*;
typeinfo?for?mir::DecorationStrategy;
typeinfo?for?mir::input::receiver::XKBMapperRegistrar;
typeinfo?for?mir::shell::IdleHandlerObserver;
typeinfo?for?mir::shell::IdleHandlerObserver;
virtual?thunk?to?mir::DefaultServerConfiguration::set_the_decoration_strategy*;
virtual?thunk?to?mir::DefaultServerConfiguration::the_decoration_strategy*;
vtable?for?mir::DecorationStrategy;
vtable?for?mir::input::receiver::XKBMapperRegistrar;
vtable?for?mir::shell::IdleHandlerObserver;
vtable?for?mir::shell::IdleHandlerObserver;
};
} MIR_SERVER_INTERNAL_2.17;
Expand Down
13 changes: 12 additions & 1 deletion tools/symbols_map_generator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,19 @@ class LibraryInfo(TypedDict):
header_directories: list[HeaderDirectory]
map_file: str

def get_version_from_library_version_str(version: str) -> str:
"""
Given a string like MIR_SERVER_INTERNAL_5.0.0, returns the version
string (e.g. 5.0.0)
"""
s = version.split("_")
return s[len(s) - 1]


def get_major_version_from_str(version: str) -> int:
"""
Given a string like 5.0.0, returns the major version (e.g. 5).
"""
return int(version.split('.')[0])


Expand Down Expand Up @@ -482,7 +493,7 @@ def main():

# Remake the stanzas for the previous symbols
for symbol in previous_symbols:
major = get_major_version_from_str(symbol.version)
major = get_major_version_from_str(get_version_from_library_version_str(symbol.version))

# If we are going up by a major version, then we should add
# all existing symbols to the new stanza
Expand Down
Loading