Converted AxisEvent and ButtonEvent to AxisEventPtr and ButtonEventPtr

This commit is contained in:
Ingo Ruhnke 2010-12-25 13:25:02 +01:00
parent 170a258ff4
commit dcdf06ed2b
12 changed files with 185 additions and 172 deletions

28
TODO
View file

@ -1,5 +1,5 @@
angrPre Release Testing:
====================
Pre Release Testing:
=====================
* check the version number
@ -11,16 +11,36 @@ git tag -s "${TAG}" -m "xboxdrv ${TAG}"
git archive --format=tar --prefix="xboxdrv-linux-${VERSION}/" ${TAG} | bzip2 -c > /tmp/xboxdrv-linux-${VERSION}.tar.bz2
git push --tags
Ubuntu Package:
===============
$ cd ../debian/
$ git-import-orig -u 0.6.1 ~/projects/xboxdrv/htdocs/xboxdrv-linux-0.6.1.tar.bz2
$ dch -v "0.6.1" "New Ubuntu release"
$ git-buildpackage --git-tag --git-builder="debuild -S"
$ sudo pbuilder --build xboxdrv_0.6.1.dsc
$ dput my-ppa xboxdrv_0.6.1_source.changes
Stuff to do before 0.6.1 release:
=================================
* add an --evdev debug mode that displays events
* support for Playstation button names maybe? cross, triangle, circle, square, R3, L3, ...?
* add more example scripts
Stuff to do before 0.7.0 release:
=================================
* add extra checks to make sure the evdev buttons and axis given exist on the current device
* add support for Xbox1 analog face button
* support for Playstation button names maybe? cross, triangle, circle, square, R3, L3, ...?
* unifiy guitar mappings
* allow separate deadzone for each axis

View file

@ -1 +1 @@
0.6.1
0.6.2

View file

@ -28,77 +28,75 @@
#include "uinput.hpp"
#include "uinput_deviceid.hpp"
AxisEvent
AxisEventPtr
AxisEvent::invalid()
{
AxisEvent ev;
ev.type = -1;
return ev;
return AxisEventPtr();
}
AxisEvent
AxisEventPtr
AxisEvent::create_abs(int device_id, int code, int min, int max, int fuzz, int flat)
{
AxisEvent ev;
ev.type = EV_ABS;
ev.abs.code = UIEvent::create(device_id, EV_ABS, code);
ev.abs.min = min;
ev.abs.max = max;
ev.abs.fuzz = fuzz;
ev.abs.flat = flat;
AxisEventPtr ev(new AxisEvent);
ev->type = EV_ABS;
ev->abs.code = UIEvent::create(device_id, EV_ABS, code);
ev->abs.min = min;
ev->abs.max = max;
ev->abs.fuzz = fuzz;
ev->abs.flat = flat;
return ev;
}
AxisEvent
AxisEventPtr
AxisEvent::create_rel(int device_id, int code, int repeat, float value)
{
AxisEvent ev;
ev.type = EV_REL;
ev.rel.code = UIEvent::create(device_id, EV_REL, code);
ev.rel.value = value;
ev.rel.repeat = repeat;
AxisEventPtr ev(new AxisEvent);
ev->type = EV_REL;
ev->rel.code = UIEvent::create(device_id, EV_REL, code);
ev->rel.value = value;
ev->rel.repeat = repeat;
return ev;
}
AxisEvent
AxisEventPtr
AxisEvent::create_key()
{
AxisEvent ev;
ev.type = EV_KEY;
std::fill_n(ev.key.up_codes, MAX_MODIFIER+1, UIEvent::invalid());
std::fill_n(ev.key.down_codes, MAX_MODIFIER+1, UIEvent::invalid());
ev.key.threshold = 8000;
AxisEventPtr ev(new AxisEvent);
ev->type = EV_KEY;
std::fill_n(ev->key.up_codes, MAX_MODIFIER+1, UIEvent::invalid());
std::fill_n(ev->key.down_codes, MAX_MODIFIER+1, UIEvent::invalid());
ev->key.threshold = 8000;
return ev;
}
AxisEvent
AxisEventPtr
AxisEvent::create_rel()
{
AxisEvent ev;
ev.type = EV_REL;
ev.rel.code = UIEvent::invalid();
ev.rel.value = 5;
ev.rel.repeat = 10;
AxisEventPtr ev(new AxisEvent);
ev->type = EV_REL;
ev->rel.code = UIEvent::invalid();
ev->rel.value = 5;
ev->rel.repeat = 10;
return ev;
}
AxisEvent
AxisEventPtr
AxisEvent::create_abs()
{
AxisEvent ev;
ev.type = EV_ABS;
ev.abs.code = UIEvent::invalid();
ev.abs.min = -32768; // FIXME: this must be properly set
ev.abs.max = 32767;
ev.abs.fuzz = 0;
ev.abs.flat = 0;
AxisEventPtr ev(new AxisEvent);
ev->type = EV_ABS;
ev->abs.code = UIEvent::invalid();
ev->abs.min = -32768; // FIXME: this must be properly set
ev->abs.max = 32767;
ev->abs.fuzz = 0;
ev->abs.flat = 0;
return ev;
}
AxisEvent
AxisEventPtr
AxisEvent::from_string(const std::string& str)
{
AxisEvent ev;
AxisEventPtr ev(new AxisEvent);
switch (get_event_type(str))
{
@ -123,12 +121,12 @@ AxisEvent::from_string(const std::string& str)
assert(!"AxisEvent::from_string(): should never be reached");
}
//std::cout << "AxisEvent::from_string():\n in: " << str << "\n out: " << ev.str() << std::endl;
//std::cout << "AxisEvent::from_string():\n in: " << str << "\n out: " << ev->str() << std::endl;
return ev;
}
AxisEvent
AxisEventPtr
AxisEvent::abs_from_string(const std::string& str)
{
boost::char_separator<char> sep(":", "", boost::keep_empty_tokens);
@ -160,19 +158,19 @@ AxisEvent::abs_from_string(const std::string& str)
}
else
{
AxisEvent ev = create_abs(DEVICEID_AUTO, code, -1, -1, 0, 0);
AxisEventPtr ev = create_abs(DEVICEID_AUTO, code, -1, -1, 0, 0);
return ev;
}
}
AxisEvent
AxisEventPtr
AxisEvent::rel_from_string(const std::string& str)
{
boost::char_separator<char> sep(":", "", boost::keep_empty_tokens);
boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
AxisEvent ev = create_rel();
AxisEventPtr ev = create_rel();
int j = 0;
for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j)
@ -180,15 +178,15 @@ AxisEvent::rel_from_string(const std::string& str)
switch(j)
{
case 0:
ev.rel.code = str2rel_event(*i);
ev->rel.code = str2rel_event(*i);
break;
case 1:
ev.rel.value = boost::lexical_cast<int>(*i);
ev->rel.value = boost::lexical_cast<int>(*i);
break;
case 2:
ev.rel.repeat = boost::lexical_cast<int>(*i);
ev->rel.repeat = boost::lexical_cast<int>(*i);
break;
default:
@ -204,14 +202,14 @@ AxisEvent::rel_from_string(const std::string& str)
return ev;
}
AxisEvent
AxisEventPtr
AxisEvent::key_from_string(const std::string& str)
{
boost::char_separator<char> sep(":", "", boost::keep_empty_tokens);
boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
AxisEvent ev = create_key();
AxisEventPtr ev = create_key();
int j = 0;
for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j)
@ -225,7 +223,7 @@ AxisEvent::key_from_string(const std::string& str)
int k = 0;
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k)
{
ev.key.up_codes[k] = str2key_event(*m);
ev->key.up_codes[k] = str2key_event(*m);
}
}
break;
@ -237,13 +235,13 @@ AxisEvent::key_from_string(const std::string& str)
int k = 0;
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k)
{
ev.key.down_codes[k] = str2key_event(*m);
ev->key.down_codes[k] = str2key_event(*m);
}
}
break;
case 2:
ev.key.threshold = boost::lexical_cast<int>(*i);
ev->key.threshold = boost::lexical_cast<int>(*i);
break;
default:
@ -264,17 +262,9 @@ AxisEvent::AxisEvent() :
{
}
bool
AxisEvent::is_valid() const
{
return type != -1;
}
void
AxisEvent::init(uInput& uinput) const
{
assert(is_valid());
switch(type)
{
case EV_KEY:
@ -307,8 +297,6 @@ AxisEvent::init(uInput& uinput) const
void
AxisEvent::send(uInput& uinput, int old_value, int value) const
{
assert(is_valid());
switch(type)
{
case EV_ABS:

View file

@ -20,44 +20,46 @@
#define HEADER_XBOXDRV_AXIS_EVENT_HPP
#include <string>
#include <boost/shared_ptr.hpp>
#include "uinput_deviceid.hpp"
class uInput;
class AxisEvent;
typedef boost::shared_ptr<AxisEvent> AxisEventPtr;
class AxisEvent
{
public:
static const int MAX_MODIFIER = 4;
static AxisEvent invalid();
static AxisEvent create_abs(int device_id, int code, int min, int max, int fuzz, int flat);
static AxisEvent create_rel(int device_id, int code, int repeat = 10, float value = 5);
static AxisEventPtr invalid();
static AxisEventPtr create_abs(int device_id, int code, int min, int max, int fuzz, int flat);
static AxisEventPtr create_rel(int device_id, int code, int repeat = 10, float value = 5);
static AxisEvent create_key();
static AxisEvent create_rel();
static AxisEvent create_abs();
static AxisEventPtr create_key();
static AxisEventPtr create_rel();
static AxisEventPtr create_abs();
/** If an AbsAxisEvent gets created the user has to set min/max! */
static AxisEvent from_string(const std::string& str);
/** If an AxisEvent gets created the user has to set min/max with set_axis_range() */
static AxisEventPtr from_string(const std::string& str);
private:
static AxisEvent abs_from_string(const std::string& str);
static AxisEvent rel_from_string(const std::string& str);
static AxisEvent key_from_string(const std::string& str);
static AxisEventPtr abs_from_string(const std::string& str);
static AxisEventPtr rel_from_string(const std::string& str);
static AxisEventPtr key_from_string(const std::string& str);
public:
AxisEvent();
void set_axis_range(int min, int max);
void init(uInput& uinput) const;
void send(uInput& uinput, int old_value, int value) const;
bool is_valid() const;
std::string str() const;
void set_axis_range(int min, int max);
private:
/** EV_KEY, EV_ABS, EV_REL */
int type;

View file

@ -25,24 +25,24 @@ AxisMap::AxisMap() :
}
void
AxisMap::bind(XboxAxis code, const AxisEvent& event)
AxisMap::bind(XboxAxis code, AxisEventPtr event)
{
m_axis_map[XBOX_BTN_UNKNOWN][code] = event;
}
void
AxisMap::bind(XboxButton shift_code, XboxAxis code, const AxisEvent& event)
AxisMap::bind(XboxButton shift_code, XboxAxis code, AxisEventPtr event)
{
m_axis_map[shift_code][code] = event;
}
AxisEvent
AxisEventPtr
AxisMap::lookup(XboxAxis code) const
{
return m_axis_map[XBOX_BTN_UNKNOWN][code];
}
AxisEvent
AxisEventPtr
AxisMap::lookup(XboxButton shift_code, XboxAxis code) const
{
return m_axis_map[shift_code][code];

View file

@ -27,16 +27,16 @@
class AxisMap
{
private:
AxisEvent m_axis_map[XBOX_BTN_MAX][XBOX_AXIS_MAX];
AxisEventPtr m_axis_map[XBOX_BTN_MAX][XBOX_AXIS_MAX];
public:
AxisMap();
void bind(XboxAxis code, const AxisEvent& event);
void bind(XboxButton shift_code, XboxAxis code, const AxisEvent& event);
void bind(XboxAxis code, AxisEventPtr event);
void bind(XboxButton shift_code, XboxAxis code, AxisEventPtr event);
AxisEvent lookup(XboxAxis code) const;
AxisEvent lookup(XboxButton shift_code, XboxAxis code) const;
AxisEventPtr lookup(XboxAxis code) const;
AxisEventPtr lookup(XboxButton shift_code, XboxAxis code) const;
void clear();
};

View file

@ -28,58 +28,56 @@
#include "uinput.hpp"
#include "uinput_deviceid.hpp"
ButtonEvent
ButtonEventPtr
ButtonEvent::invalid()
{
ButtonEvent ev;
ev.type = -1;
return ev;
return ButtonEventPtr();
}
ButtonEvent
ButtonEventPtr
ButtonEvent::create_abs(int code)
{
ButtonEvent ev;
ev.type = EV_ABS;
ev.abs.code = UIEvent::create(DEVICEID_AUTO, EV_ABS, code);
ev.abs.value = 1;
ButtonEventPtr ev(new ButtonEvent);
ev->type = EV_ABS;
ev->abs.code = UIEvent::create(DEVICEID_AUTO, EV_ABS, code);
ev->abs.value = 1;
return ev;
}
ButtonEvent
ButtonEventPtr
ButtonEvent::create_key(int code)
{
ButtonEvent ev;
ev.type = EV_KEY;
std::fill_n(ev.key.codes, MAX_MODIFIER + 1, UIEvent::invalid());
ev.key.codes[0] = UIEvent::create(DEVICEID_AUTO, EV_KEY, code);
ButtonEventPtr ev(new ButtonEvent);
ev->type = EV_KEY;
std::fill_n(ev->key.codes, MAX_MODIFIER + 1, UIEvent::invalid());
ev->key.codes[0] = UIEvent::create(DEVICEID_AUTO, EV_KEY, code);
return ev;
}
ButtonEvent
ButtonEventPtr
ButtonEvent::create_key()
{
ButtonEvent ev;
ev.type = EV_KEY;
std::fill_n(ev.key.codes, MAX_MODIFIER + 1, UIEvent::invalid());
ButtonEventPtr ev(new ButtonEvent);
ev->type = EV_KEY;
std::fill_n(ev->key.codes, MAX_MODIFIER + 1, UIEvent::invalid());
return ev;
}
ButtonEvent
ButtonEventPtr
ButtonEvent::create_rel(int code)
{
ButtonEvent ev;
ev.type = EV_REL;
ev.rel.code = UIEvent::create(DEVICEID_AUTO, EV_REL, code);
ev.rel.value = 3;
ev.rel.repeat = 100;
ButtonEventPtr ev(new ButtonEvent);
ev->type = EV_REL;
ev->rel.code = UIEvent::create(DEVICEID_AUTO, EV_REL, code);
ev->rel.value = 3;
ev->rel.repeat = 100;
return ev;
}
ButtonEvent
ButtonEventPtr
ButtonEvent::from_string(const std::string& str)
{
ButtonEvent ev;
ButtonEventPtr ev;
boost::char_separator<char> sep(":", "", boost::keep_empty_tokens);
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
@ -99,14 +97,14 @@ ButtonEvent::from_string(const std::string& str)
int k = 0;
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k)
{
ev.key.codes[k] = str2key_event(*m);
ev->key.codes[k] = str2key_event(*m);
}
break;
}
case EV_REL:
ev = ButtonEvent::create_rel(-1); // FIXME: Hack
ev.rel.code = str2rel_event(*i);
ev->rel.code = str2rel_event(*i);
break;
case EV_ABS:
@ -125,12 +123,12 @@ ButtonEvent::from_string(const std::string& str)
}
else
{
switch (ev.type)
switch (ev->type)
{
case EV_REL:
switch(j) {
case 1: ev.rel.value = boost::lexical_cast<int>(*i); break;
case 2: ev.rel.repeat = boost::lexical_cast<int>(*i); break;
case 1: ev->rel.value = boost::lexical_cast<int>(*i); break;
case 2: ev->rel.repeat = boost::lexical_cast<int>(*i); break;
}
break;
@ -141,7 +139,7 @@ ButtonEvent::from_string(const std::string& str)
}
if (false)
std::cout << "ButtonEvent::from_string():\n in: " << str << "\n out: " << ev.str() << std::endl;
std::cout << "ButtonEvent::from_string():\n in: " << str << "\n out: " << ev->str() << std::endl;
return ev;
}

View file

@ -20,26 +20,31 @@
#define HEADER_XBOXDRV_BUTTON_EVENT_HPP
#include <string>
#include <boost/shared_ptr.hpp>
#include "uinput_deviceid.hpp"
class uInput;
class ButtonEvent;
struct ButtonEvent
typedef boost::shared_ptr<ButtonEvent> ButtonEventPtr;
class ButtonEvent
{
public:
static const int MAX_MODIFIER = 4;
static ButtonEvent invalid();
static ButtonEvent create_key(int code);
static ButtonEvent create_key();
static ButtonEvent create_abs(int code);
static ButtonEvent create_rel(int code);
static ButtonEvent from_string(const std::string& str);
static ButtonEventPtr invalid();
static ButtonEventPtr create_key(int code);
static ButtonEventPtr create_key();
static ButtonEventPtr create_abs(int code);
static ButtonEventPtr create_rel(int code);
static ButtonEventPtr from_string(const std::string& str);
public:
private:
ButtonEvent();
public:
void init(uInput& uinput) const;
void send(uInput& uinput, bool value) const;

View file

@ -24,24 +24,24 @@ ButtonMap::ButtonMap()
}
void
ButtonMap::bind(XboxButton code, const ButtonEvent& event)
ButtonMap::bind(XboxButton code, ButtonEventPtr event)
{
btn_map[XBOX_BTN_UNKNOWN][code] = event;
}
void
ButtonMap::bind(XboxButton shift_code, XboxButton code, const ButtonEvent& event)
ButtonMap::bind(XboxButton shift_code, XboxButton code, ButtonEventPtr event)
{
btn_map[shift_code][code] = event;
}
ButtonEvent
ButtonEventPtr
ButtonMap::lookup(XboxButton code) const
{
return btn_map[XBOX_BTN_UNKNOWN][code];
}
ButtonEvent
ButtonEventPtr
ButtonMap::lookup(XboxButton shift_code, XboxButton code) const
{
return btn_map[shift_code][code];

View file

@ -27,16 +27,16 @@
class ButtonMap
{
private:
ButtonEvent btn_map[XBOX_BTN_MAX][XBOX_BTN_MAX];
ButtonEventPtr btn_map[XBOX_BTN_MAX][XBOX_BTN_MAX];
public:
ButtonMap();
void bind(XboxButton code, const ButtonEvent& event);
void bind(XboxButton shift_code, XboxButton code, const ButtonEvent& event);
void bind(XboxButton code, ButtonEventPtr event);
void bind(XboxButton shift_code, XboxButton code, ButtonEventPtr event);
ButtonEvent lookup(XboxButton code) const;
ButtonEvent lookup(XboxButton shift_code, XboxButton code) const;
ButtonEventPtr lookup(XboxButton code) const;
ButtonEventPtr lookup(XboxButton shift_code, XboxButton code) const;
void clear();
};

View file

@ -252,7 +252,7 @@ void set_ui_button_map(ButtonMap& ui_button_map, const std::string& str)
else
{
std::string btn_str = str.substr(0, i);
ButtonEvent event = ButtonEvent::from_string(str.substr(i+1, str.size()-i));
ButtonEventPtr event = ButtonEvent::from_string(str.substr(i+1, str.size()-i));
std::string::size_type j = btn_str.find('+');
if (j == std::string::npos)
@ -753,7 +753,7 @@ CommandLineParser::print_version() const
void
CommandLineParser::set_ui_axismap(const std::string& name, const std::string& value)
{
AxisEvent event = AxisEvent::from_string(value);
AxisEventPtr event = AxisEvent::from_string(value);
std::string::size_type j = name.find('+');
if (j == std::string::npos)
@ -762,8 +762,8 @@ CommandLineParser::set_ui_axismap(const std::string& name, const std::string& va
if (axis != XBOX_AXIS_UNKNOWN)
{
event.set_axis_range(get_axis_min(axis),
get_axis_max(axis));
event->set_axis_range(get_axis_min(axis),
get_axis_max(axis));
//std::cout << "set_ui_axismap: " << name << " = " << value << std::endl;
@ -781,8 +781,8 @@ CommandLineParser::set_ui_axismap(const std::string& name, const std::string& va
if (axis != XBOX_AXIS_UNKNOWN)
{
event.set_axis_range(get_axis_min(axis),
get_axis_max(axis));
event->set_axis_range(get_axis_min(axis),
get_axis_max(axis));
//std::cout << "set_ui_axismap: " << name << " = " << value << std::endl;
@ -799,7 +799,7 @@ void
CommandLineParser::set_ui_buttonmap(const std::string& name, const std::string& value)
{
std::string btn_str = name;
ButtonEvent event = ButtonEvent::from_string(value);
ButtonEventPtr event = ButtonEvent::from_string(value);
std::string::size_type j = btn_str.find('+');
if (j == std::string::npos)

View file

@ -458,15 +458,15 @@ uInput::send_button(XboxButton code, bool value)
{
if (button_state[i])
{
const ButtonEvent& event = cfg.get_btn_map().lookup(code, static_cast<XboxButton>(i));
if (event.is_valid())
const ButtonEventPtr& event = cfg.get_btn_map().lookup(code, static_cast<XboxButton>(i));
if (event->is_valid())
{
for(int j = 0; j < XBOX_BTN_MAX; ++j) // iterate over all shift buttons
{
const ButtonEvent& event2 = cfg.get_btn_map().lookup(static_cast<XboxButton>(j),
const ButtonEventPtr& event2 = cfg.get_btn_map().lookup(static_cast<XboxButton>(j),
static_cast<XboxButton>(i));
if (event2.is_valid())
event2.send(*this, false);
if (event2->is_valid())
event2->send(*this, false);
}
}
}
@ -477,10 +477,10 @@ uInput::send_button(XboxButton code, bool value)
{
if (button_state[i]) // shift button is pressed
{
const ButtonEvent& event = cfg.get_btn_map().lookup(static_cast<XboxButton>(i), code);
if (event.is_valid())
const ButtonEventPtr& event = cfg.get_btn_map().lookup(static_cast<XboxButton>(i), code);
if (event->is_valid())
{
event.send(*this, value);
event->send(*this, value);
// exit after the first successful event, so we don't send
// multiple events for the same button
return;
@ -489,9 +489,9 @@ uInput::send_button(XboxButton code, bool value)
}
// Non shifted button events
const ButtonEvent& event = cfg.get_btn_map().lookup(code);
if (event.is_valid())
event.send(*this, value);
const ButtonEventPtr& event = cfg.get_btn_map().lookup(code);
if (event->is_valid())
event->send(*this, value);
}
}
}
@ -587,10 +587,10 @@ uInput::send_axis(XboxAxis code, int32_t value)
{
if (button_state[shift])
{
const AxisEvent& event = cfg.get_axis_map().lookup(static_cast<XboxButton>(shift), code);
if (event.is_valid())
const AxisEventPtr& event = cfg.get_axis_map().lookup(static_cast<XboxButton>(shift), code);
if (event)
{
event.send(*this, old_value, value);
event->send(*this, old_value, value);
event_send = true;
}
}
@ -599,10 +599,10 @@ uInput::send_axis(XboxAxis code, int32_t value)
// sending regular axis, if no shifted events where send
if (!event_send)
{
const AxisEvent& event = cfg.get_axis_map().lookup(code);
if (event.is_valid())
const AxisEventPtr& event = cfg.get_axis_map().lookup(code);
if (event)
{
event.send(*this, old_value, value);
event->send(*this, old_value, value);
}
}
}
@ -615,9 +615,9 @@ uInput::add_axis(XboxAxis code)
{
for(int shift = 0; shift < XBOX_BTN_MAX; ++shift)
{
const AxisEvent& event = cfg.get_axis_map(n).lookup(static_cast<XboxButton>(shift), code);
if (event.is_valid())
event.init(*this);
const AxisEventPtr& event = cfg.get_axis_map(n).lookup(static_cast<XboxButton>(shift), code);
if (event)
event->init(*this);
}
}
}
@ -629,9 +629,9 @@ uInput::add_button(XboxButton code)
{
for(int i = 0; i < XBOX_BTN_MAX; ++i)
{
const ButtonEvent& event = cfg.get_btn_map(n).lookup(static_cast<XboxButton>(i), code);
if (event.is_valid())
event.init(*this);
const ButtonEventPtr& event = cfg.get_btn_map(n).lookup(static_cast<XboxButton>(i), code);
if (event->is_valid())
event->init(*this);
}
}
}