Added support mapping multiple events to the same key, toggled by the time the button is held
This commit is contained in:
parent
d5628cc1b5
commit
8f9f0516e7
7 changed files with 191 additions and 23 deletions
9
NEWS
9
NEWS
|
@ -1,3 +1,12 @@
|
|||
xboxdrv 0.6.2 - (??/???/????)
|
||||
==============================
|
||||
|
||||
* added ability to do toggle buttons
|
||||
* added ability to invert buttons
|
||||
* added ability to send different events depending on how long a
|
||||
button was pressed
|
||||
|
||||
|
||||
xboxdrv 0.6.1 - (21/Dec/2010)
|
||||
==============================
|
||||
|
||||
|
|
|
@ -121,20 +121,53 @@ KeyButtonEvent::from_string(const std::string& str)
|
|||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
int j = 0;
|
||||
for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j)
|
||||
int idx = 0;
|
||||
for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++idx)
|
||||
{
|
||||
if (j == 0)
|
||||
{
|
||||
ev.reset(new KeyButtonEvent());
|
||||
|
||||
boost::char_separator<char> plus_sep("+", "", boost::keep_empty_tokens);
|
||||
tokenizer ev_tokens(*i, plus_sep);
|
||||
int k = 0;
|
||||
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k)
|
||||
{
|
||||
ev->m_codes[k] = str2key_event(*m);
|
||||
}
|
||||
switch(idx)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
ev.reset(new KeyButtonEvent());
|
||||
|
||||
boost::char_separator<char> plus_sep("+", "", boost::keep_empty_tokens);
|
||||
tokenizer ev_tokens(*i, plus_sep);
|
||||
int k = 0;
|
||||
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end() && k < MAX_MODIFIER; ++m, ++k)
|
||||
{
|
||||
ev->m_codes[k] = str2key_event(*m);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
boost::char_separator<char> plus_sep("+", "", boost::keep_empty_tokens);
|
||||
tokenizer ev_tokens(*i, plus_sep);
|
||||
int k = 0;
|
||||
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end() && k < MAX_MODIFIER; ++m, ++k)
|
||||
{
|
||||
ev->m_secondary_codes[k] = str2key_event(*m);
|
||||
}
|
||||
|
||||
ev->m_hold_threshold = 250;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
ev->m_hold_threshold = boost::lexical_cast<int>(*i);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "to many arguments in '" << str << "'";
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,15 +175,21 @@ KeyButtonEvent::from_string(const std::string& str)
|
|||
}
|
||||
|
||||
KeyButtonEvent::KeyButtonEvent() :
|
||||
m_codes()
|
||||
m_state(false),
|
||||
m_codes(),
|
||||
m_secondary_codes(),
|
||||
m_hold_threshold(0),
|
||||
m_hold_counter(0)
|
||||
{
|
||||
std::fill_n(m_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
std::fill_n(m_secondary_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
}
|
||||
|
||||
KeyButtonEvent::KeyButtonEvent(int code) :
|
||||
m_codes()
|
||||
{
|
||||
std::fill_n(m_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
std::fill_n(m_secondary_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
m_codes[0] = UIEvent::create(DEVICEID_AUTO, EV_KEY, code);
|
||||
}
|
||||
|
||||
|
@ -162,17 +201,100 @@ KeyButtonEvent::init(uInput& uinput) const
|
|||
uinput.create_uinput_device(m_codes[i].device_id);
|
||||
uinput.add_key(m_codes[i].device_id, m_codes[i].code);
|
||||
}
|
||||
|
||||
if (m_hold_threshold)
|
||||
{
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.add_key(m_secondary_codes[i].device_id, m_secondary_codes[i].code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyButtonEvent::send(uInput& uinput, bool value) const
|
||||
KeyButtonEvent::send(uInput& uinput, bool value)
|
||||
{
|
||||
value = apply_filter(value);
|
||||
|
||||
// FIXME: should key releases in return
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
if (m_state != value)
|
||||
{
|
||||
uinput.send_key(m_codes[i].device_id, m_codes[i].code, value);
|
||||
m_state = value;
|
||||
|
||||
if (m_hold_threshold == 0)
|
||||
{
|
||||
// FIXME: should handle key releases in reverse order
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].device_id, m_codes[i].code, m_state);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_hold_counter < m_hold_threshold)
|
||||
{
|
||||
if (m_state)
|
||||
{
|
||||
// we are only sending events after release or when
|
||||
// hold_threshold is passed
|
||||
}
|
||||
else
|
||||
{
|
||||
// send both a press and release event after another, aka a "click"
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].device_id, m_codes[i].code, true);
|
||||
}
|
||||
// FIXME: should do this in reverse order
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].device_id, m_codes[i].code, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_state)
|
||||
{
|
||||
// should never happen
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: should do in reverse
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_secondary_codes[i].device_id, m_secondary_codes[i].code, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_state)
|
||||
{
|
||||
m_hold_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyButtonEvent::update(uInput& uinput, int msec_delta)
|
||||
{
|
||||
if (m_state && m_hold_threshold)
|
||||
{
|
||||
if (m_hold_counter < m_hold_threshold &&
|
||||
m_hold_counter + msec_delta >= m_hold_threshold)
|
||||
{
|
||||
// start sending the secondary events
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_secondary_codes[i].device_id, m_secondary_codes[i].code, true);
|
||||
}
|
||||
uinput.sync();
|
||||
}
|
||||
|
||||
if (m_hold_counter < m_hold_threshold)
|
||||
{
|
||||
m_hold_counter += msec_delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,7 +335,7 @@ AbsButtonEvent::init(uInput& uinput) const
|
|||
}
|
||||
|
||||
void
|
||||
AbsButtonEvent::send(uInput& uinput, bool value) const
|
||||
AbsButtonEvent::send(uInput& uinput, bool value)
|
||||
{
|
||||
value = apply_filter(value);
|
||||
|
||||
|
@ -276,7 +398,7 @@ RelButtonEvent::init(uInput& uinput) const
|
|||
}
|
||||
|
||||
void
|
||||
RelButtonEvent::send(uInput& uinput, bool value) const
|
||||
RelButtonEvent::send(uInput& uinput, bool value)
|
||||
{
|
||||
value = apply_filter(value);
|
||||
|
||||
|
|
|
@ -49,7 +49,8 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void init(uInput& uinput) const =0;
|
||||
virtual void send(uInput& uinput, bool value) const =0;
|
||||
virtual void send(uInput& uinput, bool value) =0;
|
||||
virtual void update(uInput& uinput, int msec_delta) =0;
|
||||
|
||||
void set_filters(const std::vector<ButtonFilterPtr>& filters);
|
||||
|
||||
|
@ -69,15 +70,20 @@ public:
|
|||
KeyButtonEvent(int code);
|
||||
|
||||
void init(uInput& uinput) const;
|
||||
void send(uInput& uinput, bool value) const;
|
||||
void send(uInput& uinput, bool value);
|
||||
void update(uInput& uinput, int msec_delta);
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
static const int MAX_MODIFIER = 4;
|
||||
|
||||
bool m_state;
|
||||
// Array is terminated by !is_valid()
|
||||
UIEvent m_codes[MAX_MODIFIER+1];
|
||||
UIEvent m_secondary_codes[MAX_MODIFIER+1];
|
||||
int m_hold_threshold;
|
||||
int m_hold_counter;
|
||||
};
|
||||
|
||||
class AbsButtonEvent : public ButtonEvent
|
||||
|
@ -89,7 +95,8 @@ public:
|
|||
AbsButtonEvent(int code);
|
||||
|
||||
void init(uInput& uinput) const;
|
||||
void send(uInput& uinput, bool value) const;
|
||||
void send(uInput& uinput, bool value);
|
||||
void update(uInput& uinput, int msec_delta) {}
|
||||
|
||||
std::string str() const;
|
||||
|
||||
|
@ -107,12 +114,14 @@ public:
|
|||
RelButtonEvent(const UIEvent& code);
|
||||
|
||||
void init(uInput& uinput) const;
|
||||
void send(uInput& uinput, bool value) const;
|
||||
void send(uInput& uinput, bool value);
|
||||
void update(uInput& uinput, int msec_delta) {}
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
UIEvent m_code;
|
||||
|
||||
int m_value;
|
||||
int m_repeat;
|
||||
};
|
||||
|
|
|
@ -95,4 +95,19 @@ ButtonMap::init(uInput& uinput) const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ButtonMap::update(uInput& uinput, int msec_delta)
|
||||
{
|
||||
for(int shift_code = 0; shift_code < XBOX_BTN_MAX; ++shift_code)
|
||||
{
|
||||
for(int code = 0; code < XBOX_BTN_MAX; ++code)
|
||||
{
|
||||
if (btn_map[shift_code][code])
|
||||
{
|
||||
btn_map[shift_code][code]->update(uinput, msec_delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
|
||||
bool send(uInput& uinput, XboxButton code, bool value) const;
|
||||
bool send(uInput& uinput, XboxButton shift_code, XboxButton code, bool value) const;
|
||||
void update(uInput& uinput, int msec_delta);
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
|
|
@ -320,6 +320,8 @@ uInput::send(Xbox360GuitarMsg& msg)
|
|||
void
|
||||
uInput::update(int msec_delta)
|
||||
{
|
||||
cfg.get_btn_map().update(*this, msec_delta);
|
||||
|
||||
for(std::map<UIEvent, RelRepeat>::iterator i = rel_repeat_lst.begin(); i != rel_repeat_lst.end(); ++i)
|
||||
{
|
||||
i->second.time_count += msec_delta;
|
||||
|
@ -438,6 +440,15 @@ uInput::send_key(int device_id, int ev_code, bool value)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
uInput::sync()
|
||||
{
|
||||
for(uInputDevs::iterator i = uinput_devs.begin(); i != uinput_devs.end(); ++i)
|
||||
{
|
||||
i->second->sync();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
uInput::send_rel_repetitive(const UIEvent& code, int value, int repeat_interval)
|
||||
{
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
|
||||
void send_key(int device_id, int ev_code, bool value);
|
||||
void send_rel_repetitive(const UIEvent& code, int value, int repeat_interval);
|
||||
void sync();
|
||||
|
||||
LinuxUinput* get_uinput(int device_id) const;
|
||||
LinuxUinput* get_force_feedback_uinput() const;
|
||||
|
|
Loading…
Add table
Reference in a new issue