Skip to content

Commit

Permalink
feature: provide an extra data source for configuration data
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkae committed Jul 12, 2024
1 parent 5557be6 commit 500140c
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 12 deletions.
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

0 comments on commit 500140c

Please sign in to comment.