genode/repos/os/src/server/input_merger/main.cc

142 lines
3.0 KiB
C++

/*
* \brief Input event merger
* \author Christian Prochaska
* \date 2014-09-29
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <input/component.h>
#include <input_session/connection.h>
#include <os/static_root.h>
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <base/attached_dataspace.h>
#include <base/heap.h>
#include <base/session_label.h>
#include <util/list.h>
namespace Input_merger
{
using namespace Genode;
struct Input_source;
struct Main;
typedef List<Input_source> Input_sources;
typedef String<Session_label::capacity()> Label;
}
struct Input_merger::Input_source : Input_sources::Element
{
Input::Connection conn;
Input::Session_component &sink;
Genode::Signal_handler<Input_source> event_handler;
void handle_events()
{
conn.for_each_event([&] (Input::Event const &e) { sink.submit(e); });
}
Input_source(Genode::Env &env, Label const &label, Input::Session_component &sink)
:
conn(env, label.string()), sink(sink),
event_handler(env.ep(), *this, &Input_source::handle_events)
{
conn.sigh(event_handler);
}
};
/******************
** Main program **
******************/
struct Input_merger::Main
{
Env &env;
Attached_rom_dataspace config_rom { env, "config" };
Heap heap { env.ram(), env.rm() };
Input_sources input_source_list { };
/*
* Input session provided to our client
*/
Input::Session_component input_session_component { env, env.ram() };
/*
* Attach root interface to the entry point
*/
Static_root<Input::Session> input_root { env.ep().manage(input_session_component) };
void handle_config_update()
{
config_rom.update();
while (Input_source *input_source = input_source_list.first()) {
input_source_list.remove(input_source);
destroy(heap, input_source);
}
config_rom.xml().for_each_sub_node("input", [&] (Xml_node input_node) {
try {
Label label = input_node.attribute_value("label", Label());
try {
Input_source *input_source = new (heap)
Input_source(env, label.string(), input_session_component);
input_source_list.insert(input_source);
} catch (Genode::Service_denied) {
error("parent denied input source '", label, "'");
}
} catch (Xml_node::Nonexistent_attribute) {
error("ignoring invalid input node '", input_node);
}
});
}
Signal_handler<Main> config_update_handler
{ env.ep(), *this, &Main::handle_config_update };
/**
* Constructor
*/
Main(Genode::Env &env) : env(env)
{
input_session_component.event_queue().enabled(true);
/*
* Apply initial configuration
*/
handle_config_update();
/*
* Register signal handler
*/
config_rom.sigh(config_update_handler);
/*
* Announce service
*/
env.parent().announce(env.ep().manage(input_root));
}
};
void Component::construct(Genode::Env &env) { static Input_merger::Main inst(env); }