diff --git a/repos/os/include/genode_c_api/event.h b/repos/os/include/genode_c_api/event.h new file mode 100644 index 0000000000..5b95e0fc10 --- /dev/null +++ b/repos/os/include/genode_c_api/event.h @@ -0,0 +1,96 @@ +/* + * \brief C interface to Genode's event session + * \author Norman Feske + * \date 2021-09-29 + */ + +/* + * Copyright (C) 2021 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. + */ + +#ifndef _INCLUDE__GENODE_C_API__EVENT_H_ +#define _INCLUDE__GENODE_C_API__EVENT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize event-session handling + */ +void genode_event_init(struct genode_env *, + struct genode_allocator *); + + +struct genode_event; /* definition is private to the implementation */ + + +/**************************** + ** Event-session lifetime ** + ****************************/ + +struct genode_event_args +{ + char const *label; +}; + +struct genode_event *genode_event_create(struct genode_event_args const *); + +void genode_event_destroy(struct genode_event *); + + +/********************** + ** Event submission ** + **********************/ + +struct genode_event_touch_args +{ + unsigned finger; + unsigned xpos; + unsigned ypos; + unsigned width; +}; + + +struct genode_event_submit; + + +/** + * Interface called by 'genode_event_generator_t' to submit events + */ +struct genode_event_submit +{ + void (*touch) (struct genode_event_submit *, + struct genode_event_touch_args const *); + + void (*touch_release) (struct genode_event_submit *, unsigned finger); +}; + + +/** + * Context private to 'genode_event_generator_t' + */ +struct genode_event_generator_ctx; + + +typedef void (*genode_event_generator_t) + (struct genode_event_generator_ctx *, struct genode_event_submit *); + + +/** + * Generate batch of events + */ +void genode_event_generate(struct genode_event *, + genode_event_generator_t, + struct genode_event_generator_ctx *); + +#ifdef __cplusplus +} +#endif + +#endif /* _INCLUDE__GENODE_C_API__EVENT_H_ */ diff --git a/repos/os/src/lib/genode_c_api/event.cc b/repos/os/src/lib/genode_c_api/event.cc new file mode 100644 index 0000000000..ac21372685 --- /dev/null +++ b/repos/os/src/lib/genode_c_api/event.cc @@ -0,0 +1,134 @@ +/* + * \brief C interface to Genode's event session + * \author Norman Feske + * \date 2021-09-29 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include +#include +#include +#include + +using namespace Genode; + +static Env *_env_ptr; +static Allocator *_alloc_ptr; +static Registry> _event_sessions { }; + + +struct genode_event : private Noncopyable, private Interface +{ + private: + + Env &_env; + Allocator &_alloc; + + Session_label const _session_label; + + Event::Connection _connection { _env, _session_label.string() }; + + public: + + genode_event(Env &env, Allocator &alloc, + Session_label const &session_label) + : + _env(env), _alloc(alloc), _session_label(session_label) + { } + + template + void with_batch(FN const &fn) + { + _connection.with_batch(fn); + } + +}; + + +void genode_event_init(genode_env *env_ptr, + genode_allocator *alloc_ptr) +{ + _env_ptr = env_ptr; + _alloc_ptr = alloc_ptr; +} + + +namespace { + + struct Submit : genode_event_submit + { + Event::Session_client::Batch &batch; + + template + static void _with_batch(struct genode_event_submit *myself, FN const &fn) + { + fn(static_cast(myself)->batch); + } + + static void _touch(struct genode_event_submit *myself, + struct genode_event_touch_args const *args) + { + Input::Touch_id id { (int)args->finger }; + + _with_batch(myself, [&] (Event::Session_client::Batch &batch) { + batch.submit(Input::Touch { id, (float)args->xpos, (float)args->ypos }); }); + } + + static void _touch_release(struct genode_event_submit *myself, + unsigned finger) + { + Input::Touch_id id { (int)finger }; + + _with_batch(myself, [&] (Event::Session_client::Batch &batch) { + batch.submit(Input::Touch_release { id }); }); + } + + Submit(Event::Session_client::Batch &batch) + : + batch(batch) + { + touch = _touch; + touch_release = _touch_release; + }; + + }; +} + + +void genode_event_generate(struct genode_event *event_session, + genode_event_generator_t generator_fn, + struct genode_event_generator_ctx *ctx) +{ + event_session->with_batch([&] (Event::Session_client::Batch &batch) { + + Submit submit { batch }; + + (*generator_fn)(ctx, &submit); + }); +} + + +struct genode_event *genode_event_create(struct genode_event_args const *args) +{ + if (!_env_ptr || !_alloc_ptr) { + error("genode_event_create: missing call of genode_event_init"); + return nullptr; + } + + return new (*_alloc_ptr) + Registered(_event_sessions, *_env_ptr, *_alloc_ptr, + Session_label(args->label)); +} + + +void genode_event_destroy(struct genode_event *event_ptr) +{ + destroy(*_alloc_ptr, event_ptr); +}