/* * \brief Input event structure * \author Norman Feske * \date 2006-08-16 */ /* * Copyright (C) 2006-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. */ #ifndef _INCLUDE__INPUT__EVENT_H_ #define _INCLUDE__INPUT__EVENT_H_ #include #include #include #include namespace Input { using Codepoint = Genode::Codepoint; struct Touch_id { unsigned value; }; /* * Event attributes */ struct Press { Keycode key; }; struct Press_char { Keycode key; Codepoint codepoint; }; struct Release { Keycode key; }; struct Wheel { int x, y; }; struct Focus_enter { }; struct Focus_leave { }; struct Hover_leave { }; struct Absolute_motion { int x, y; }; struct Relative_motion { int x, y; }; struct Touch { Touch_id id; float x, y; }; struct Touch_release { Touch_id id; }; struct Seq_number { unsigned value; }; struct Axis { enum class Id : unsigned { LX = 1, LY, LT, RX, RY, RT } id; float value; }; class Event; class Binding; } class Input::Event { private: enum Type { INVALID, PRESS, RELEASE, REL_MOTION, ABS_MOTION, WHEEL, FOCUS_ENTER, FOCUS_LEAVE, HOVER_LEAVE, TOUCH, TOUCH_RELEASE, SEQ_NUMBER, AXIS }; Type _type = INVALID; struct Attr { union { Press_char press; Release release; Wheel wheel; Absolute_motion abs_motion; Relative_motion rel_motion; Touch touch; Touch_release touch_release; Seq_number seq_number; Axis axis; }; } _attr { }; static bool _valid(Keycode key) { return key > KEY_RESERVED && key < KEY_MAX; } /** * Return point representation of attribute 'a' */ template static Genode::Point _xy(T const &a) { return Genode::Point(a.x, a.y); } friend class Input::Binding; public: /** * Default constructor creates an invalid event * * This constructor can be used for creating an array of events. */ Event() { } /* * Constructors for creating input events of various types * * These constructors can be used implicitly for the given attribute * types for assignments or for passing an event as return value. */ Event(Press_char arg) : _type(PRESS) { _attr.press = arg; } Event(Press arg) : Event(Press_char{arg.key, Codepoint{Codepoint::INVALID}}) { } Event(Release arg) : _type(RELEASE) { _attr.release = arg; } Event(Relative_motion arg) : _type(REL_MOTION) { _attr.rel_motion = arg; } Event(Absolute_motion arg) : _type(ABS_MOTION) { _attr.abs_motion = arg; } Event(Wheel arg) : _type(WHEEL) { _attr.wheel = arg; } Event(Focus_enter) : _type(FOCUS_ENTER) { } Event(Focus_leave) : _type(FOCUS_LEAVE) { } Event(Hover_leave) : _type(HOVER_LEAVE) { } Event(Touch arg) : _type(TOUCH) { _attr.touch = arg; } Event(Touch_release arg) : _type(TOUCH_RELEASE) { _attr.touch_release = arg; } Event(Seq_number arg) : _type(SEQ_NUMBER) { _attr.seq_number = arg; } Event(Axis arg) : _type(AXIS) { _attr.axis = arg; } /************************************ ** Methods for handling the event ** ************************************/ bool valid() const { return _type != INVALID; } bool press() const { return _type == PRESS; } bool release() const { return _type == RELEASE; } bool absolute_motion() const { return _type == ABS_MOTION; } bool relative_motion() const { return _type == REL_MOTION; } bool wheel() const { return _type == WHEEL; } bool focus_enter() const { return _type == FOCUS_ENTER; } bool focus_leave() const { return _type == FOCUS_LEAVE; } bool hover_leave() const { return _type == HOVER_LEAVE; } bool touch() const { return _type == TOUCH; } bool touch_release() const { return _type == TOUCH_RELEASE; } bool seq_number() const { return _type == SEQ_NUMBER; } bool axis() const { return _type == AXIS; } bool key_press(Keycode key) const { return press() && _attr.press.key == key; } bool key_release(Keycode key) const { return release() && _attr.release.key == key; } void handle_press(auto const &fn) const { if (press() && _valid(_attr.press.key)) fn(_attr.press.key, _attr.press.codepoint); } void handle_repeat(auto const &fn) const { if (key_press(KEY_UNKNOWN) && _attr.press.codepoint.valid()) fn(_attr.press.codepoint); } void handle_release(auto const &fn) const { if (release() && _valid(_attr.release.key)) fn(_attr.release.key); } void handle_relative_motion(auto const &fn) const { if (relative_motion()) fn(_attr.rel_motion.x, _attr.rel_motion.y); } void handle_absolute_motion(auto const &fn) const { if (absolute_motion()) fn(_attr.abs_motion.x, _attr.abs_motion.y); } void handle_wheel(auto const &fn) const { if (wheel()) fn(_attr.wheel.x, _attr.wheel.y); } void handle_touch(auto const &fn) const { if (touch()) fn(_attr.touch.id, _attr.touch.x, _attr.touch.y); } void handle_touch_release(auto const &fn) const { if (touch_release()) fn(_attr.touch_release.id); } void handle_seq_number(auto const &fn) const { if (seq_number()) fn(_attr.seq_number); } void handle_axis(auto const &fn) const { if (axis()) fn(_attr.axis.id, _attr.axis.value); } inline void print(Genode::Output &out) const; }; void Input::Event::print(Genode::Output &out) const { using Genode::print; switch (_type) { case INVALID: print(out, "INVALID"); break; case PRESS: print(out, "PRESS ", key_name(_attr.press.key), " ", _attr.press.codepoint.value); break; case RELEASE: print(out, "RELEASE ", key_name(_attr.release.key)); break; case REL_MOTION: print(out, "REL_MOTION ", _xy(_attr.rel_motion)); break; case ABS_MOTION: print(out, "ABS_MOTION ", _xy(_attr.abs_motion)); break; case WHEEL: print(out, "WHEEL ", _xy(_attr.wheel)); break; case FOCUS_ENTER: print(out, "FOCUS_ENTER"); break; case FOCUS_LEAVE: print(out, "FOCUS_LEAVE"); break; case HOVER_LEAVE: print(out, "HOVER_LEAVE"); break; case TOUCH_RELEASE: print(out, "TOUCH_RELEASE ", _attr.touch.id.value); break; case TOUCH: print(out, "TOUCH ", _attr.touch.id.value, " ", _xy(_attr.touch)); break; case SEQ_NUMBER: print(out, "SEQ_NUMBER ", _attr.seq_number.value); break; case AXIS: print(out, "AXIS ", unsigned(_attr.axis.id), " ", _attr.axis.value); break; }; } #endif /* _INCLUDE__INPUT__EVENT_H_ */