/*
* \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_ */