1 #include "keyboard.hpp"
6 void keyboard::do_register_modifier(const std::string
& name
, modifier
& mod
) throw(std::bad_alloc
)
9 modifiers
[name
] = &mod
;
12 void keyboard::do_unregister_modifier(const std::string
& name
) throw()
14 umutex_class
u(mutex
);
15 modifiers
.erase(name
);
18 modifier
& keyboard::lookup_modifier(const std::string
& name
) throw(std::runtime_error
)
20 modifier
* m
= try_lookup_modifier(name
);
22 throw std::runtime_error("No such modifier");
26 modifier
* keyboard::try_lookup_modifier(const std::string
& name
) throw()
28 umutex_class
u(mutex
);
29 if(!modifiers
.count(name
))
31 return modifiers
[name
];
34 std::list
<modifier
*> keyboard::all_modifiers() throw(std::bad_alloc
)
36 umutex_class
u(mutex
);
37 std::list
<modifier
*> r
;
38 for(auto i
: modifiers
)
39 r
.push_back(i
.second
);
43 void keyboard::do_register_key(const std::string
& name
, key
& key
) throw(std::bad_alloc
)
45 umutex_class
u(mutex
);
49 void keyboard::do_unregister_key(const std::string
& name
) throw()
51 umutex_class
u(mutex
);
55 key
& keyboard::lookup_key(const std::string
& name
) throw(std::runtime_error
)
57 key
* m
= try_lookup_key(name
);
59 throw std::runtime_error("No such key");
63 key
* keyboard::try_lookup_key(const std::string
& name
) throw()
65 umutex_class
u(mutex
);
71 std::list
<key
*> keyboard::all_keys() throw(std::bad_alloc
)
73 umutex_class
u(mutex
);
76 r
.push_back(i
.second
);
80 void keyboard::set_exclusive(event_listener
* listener
) throw()
82 umutex_class
u(mutex
);
84 i
.second
->set_exclusive(listener
);
87 void keyboard::set_current_key(key
* key
) throw()
89 umutex_class
u(mutex
);
93 key
* keyboard::get_current_key() throw()
95 umutex_class
u(mutex
);
99 keyboard::keyboard() throw(std::bad_alloc
)
100 : modifier_proxy(*this), key_proxy(*this)
102 register_queue
<keyboard::_modifier_proxy
, modifier
>::do_ready(modifier_proxy
, true);
103 register_queue
<keyboard::_key_proxy
, key
>::do_ready(key_proxy
, true);
106 keyboard::~keyboard() throw()
108 register_queue
<keyboard::_modifier_proxy
, modifier
>::do_ready(modifier_proxy
, false);
109 register_queue
<keyboard::_key_proxy
, key
>::do_ready(key_proxy
, false);
112 void modifier_set::add(modifier
& mod
, bool really
) throw(std::bad_alloc
)
118 void modifier_set::remove(modifier
& mod
, bool really
) throw(std::bad_alloc
)
124 modifier_set
modifier_set::construct(keyboard
& kbd
, const std::string
& _modifiers
)
125 throw(std::bad_alloc
, std::runtime_error
)
128 std::string modifiers
= _modifiers
;
129 while(modifiers
!= "") {
130 std::string mod
= modifiers
;
132 size_t split
= modifiers
.find_first_of(",");
133 if(split
< modifiers
.length()) {
134 mod
= modifiers
.substr(0, split
);
135 rest
= modifiers
.substr(split
+ 1);
137 set
.add(kbd
.lookup_modifier(mod
));
143 bool modifier_set::valid(modifier_set
& mask
) throw(std::bad_alloc
)
145 //No element can be together with its linkage group.
147 modifier
* j
= i
->get_link();
148 if(j
&& set
.count(j
))
151 for(auto i
: mask
.set
) {
152 modifier
* j
= i
->get_link();
153 if(j
&& mask
.set
.count(j
))
156 //For every element of set, it or its linkage group must be in mask.
158 modifier
* j
= i
->get_link();
159 if(!mask
.set
.count(i
) && !mask
.set
.count(j
? j
: i
))
165 bool modifier_set::operator==(const modifier_set
& m
) const throw()
176 bool modifier_set::operator<(const modifier_set
& m
) const throw()
178 auto i1
= set
.begin();
179 auto i2
= m
.set
.begin();
180 for(; i1
!= set
.end() && i2
!= m
.set
.end(); i1
++, i2
++) {
181 if((uint64_t)*i1
< (uint64_t)*i2
)
183 if((uint64_t)*i1
> (uint64_t)*i2
)
186 return (i2
!= m
.set
.end());
189 modifier_set::operator std::string() const throw(std::bad_alloc
)
193 r
= r
+ ((r
!= "") ? "," : "") + i
->get_name();
197 std::ostream
& operator<<(std::ostream
& os
, const modifier_set
& m
)
201 os
<< i
->get_name() << " ";
206 bool modifier_set::triggers(const modifier_set
& trigger
, const modifier_set
& mask
)
207 throw(std::bad_alloc
)
209 for(auto i
: mask
.set
) {
210 bool trigger_exact
= trigger
.set
.count(i
);
211 bool trigger_ingroup
= false;
212 for(auto j
: trigger
.set
)
213 if(j
->get_link() == i
)
214 trigger_ingroup
= true;
215 bool trigger_none
= !trigger_exact
&& !trigger_ingroup
;
217 //If trigger_exact is set, then this key or a key in this group must be pressed.
221 any
= any
|| (j
== i
|| j
->get_link() == i
);
225 //If trigger_ingroup is set, then exactly that set of keys in group must be pressed.
226 if(trigger_ingroup
) {
227 for(auto j
: i
->get_keyboard().all_modifiers()) {
228 if(j
->get_link() != i
)
229 continue; //Not interested.
230 if((set
.count(j
) > 0) != (trigger
.set
.count(j
) > 0))
234 //If trigger_none is set, then this key nor keys in this key group can't be pressed.
238 any
= any
|| (j
== i
|| j
->get_link() == i
);
246 int32_t mouse_calibration::get_calibrated_value(int32_t x
) const throw()
251 event::~event() throw() {}
252 event_key::~event_key() throw() {}
253 event_axis::~event_axis() throw() {}
254 event_hat::~event_hat() throw() {}
255 event_mouse::~event_mouse() throw() {}
256 event_listener::~event_listener() throw() {}
260 register_queue
<keyboard::_key_proxy
, key
>::do_unregister(kbd
.key_proxy
, name
);
263 event_key::event_key(uint32_t chngmask
)
264 : event(chngmask
, keytype::KBD_KEYTYPE_KEY
)
268 event_axis::event_axis(int32_t _state
, uint32_t chngmask
)
269 : event(chngmask
, keytype::KBD_KEYTYPE_AXIS
)
274 event_hat::event_hat(uint32_t chngmask
)
275 : event(chngmask
, keytype::KBD_KEYTYPE_HAT
)
279 event_mouse::event_mouse(int32_t _state
, const mouse_calibration
& _cal
)
280 : event(0, keytype::KBD_KEYTYPE_MOUSE
)
286 int32_t event_key::get_state() const throw() { return (get_change_mask() & 1) != 0; }
287 int32_t event_axis::get_state() const throw() { return state
; }
288 int32_t event_mouse::get_state() const throw() { return state
; }
290 int32_t event_hat::get_state() const throw()
293 uint32_t m
= get_change_mask();
301 key::key(keyboard
& keyb
, const std::string
& _name
, const std::string
& _clazz
,
302 keytype _type
) throw(std::bad_alloc
)
303 : kbd(keyb
), clazz(_clazz
), name(_name
), type(_type
)
305 exclusive_listener
= NULL
;
306 register_queue
<keyboard::_key_proxy
, key
>::do_register(kbd
.key_proxy
, name
, *this);
309 void key::add_listener(event_listener
& listener
, bool analog
) throw(std::bad_alloc
)
312 analog_listeners
.insert(&listener
);
313 digital_listeners
.erase(&listener
);
315 digital_listeners
.insert(&listener
);
316 analog_listeners
.erase(&listener
);
319 void key::remove_listener(event_listener
& listener
) throw()
321 digital_listeners
.erase(&listener
);
322 analog_listeners
.erase(&listener
);
325 void key::set_exclusive(event_listener
* listener
) throw()
327 umutex_class
u(mutex
);
328 exclusive_listener
= listener
;
331 void key::call_listeners(modifier_set
& mods
, event
& event
)
333 kbd
.set_current_key(this);
334 bool digital
= (event
.get_change_mask() & 0xAAAAAAAAUL
) != 0;
336 if(exclusive_listener
) {
338 exclusive_listener
->on_key_event(mods
, *this, event
);
339 kbd
.set_current_key(NULL
);
342 event_listener
* itr
= NULL
;
344 auto itr2
= digital_listeners
.upper_bound(itr
);
345 if(itr2
== digital_listeners
.end())
349 itr
->on_key_event(mods
, *this, event
);
354 auto itr2
= analog_listeners
.upper_bound(itr
);
355 if(itr2
== analog_listeners
.end())
359 itr
->on_key_event(mods
, *this, event
);
363 kbd
.set_current_key(NULL
);
366 key_axis
* key::cast_axis() throw()
368 if(type
!= KBD_KEYTYPE_AXIS
)
370 return dynamic_cast<key_axis
*>(this);
373 key_mouse
* key::cast_mouse() throw()
375 if(type
!= KBD_KEYTYPE_MOUSE
)
377 return dynamic_cast<key_mouse
*>(this);
380 key_key::key_key(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
)
381 throw(std::bad_alloc
)
382 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_KEY
)
387 key_key::~key_key() throw() {}
389 void key_key::set_state(modifier_set mods
, int32_t _state
) throw()
391 uint32_t change
= _state
? 1 : 0;
394 if(state
!= _state
) {
402 call_listeners(mods
, e
);
406 int32_t key_key::get_state() const throw() { return state
; }
407 int32_t key_key::get_state_digital() const throw() { return state
; }
409 std::vector
<std::string
> key_key::get_subkeys() throw(std::bad_alloc
)
411 std::vector
<std::string
> r
;
416 key_hat::key_hat(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
)
417 throw(std::bad_alloc
)
418 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_HAT
)
422 key_hat::~key_hat() throw() {}
424 void key_hat::set_state(modifier_set mods
, int32_t _state
) throw()
430 if(state
!= _state
) {
431 int32_t schange
= state
^ _state
;
433 if(state
& 1) change
|= 1;
434 if(schange
& 1) change
|= 2;
435 if(state
& 2) change
|= 4;
436 if(schange
& 2) change
|= 8;
437 if(state
& 4) change
|= 16;
438 if(schange
& 4) change
|= 32;
439 if(state
& 8) change
|= 64;
440 if(schange
& 8) change
|= 128;
446 call_listeners(mods
, e
);
450 int32_t key_hat::get_state() const throw() { return state
; }
451 int32_t key_hat::get_state_digital() const throw() { return state
; }
453 std::vector
<std::string
> key_hat::get_subkeys() throw(std::bad_alloc
)
455 std::vector
<std::string
> r
;
463 key_axis::key_axis(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
464 int mode
) throw(std::bad_alloc
)
465 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_AXIS
)
469 last_tolerance
= 0.5;
472 key_axis::~key_axis() throw() {}
474 int32_t key_axis::get_state() const throw()
476 umutex_class
u(mutex
);
480 int32_t key_axis::get_state_digital() const throw()
482 umutex_class
u(mutex
);
483 if(rawstate
<= -32768 * last_tolerance
)
485 if(rawstate
>= 32767 * last_tolerance
)
490 int key_axis::get_mode() const throw()
492 umutex_class
u(mutex
);
496 std::vector
<std::string
> key_axis::get_subkeys() throw(std::bad_alloc
)
498 umutex_class
u(mutex
);
499 std::vector
<std::string
> r
;
509 void key_axis::set_state(modifier_set mods
, int32_t _rawstate
) throw()
512 int32_t state
, ostate
;
514 int dold
= 0, dnew
= 0;
516 if(rawstate
!= _rawstate
) {
519 rawstate
= _rawstate
;
521 if(state
<= -32768 * last_tolerance
)
523 if(state
>= 32767 * last_tolerance
)
528 if((dold
> 0 && dnew
<= 0) || (dold
<= 0 && dnew
> 0))
532 if((dold
< 0 && dnew
>= 0) || (dold
>= 0 && dnew
< 0))
538 event_axis
e(state
, change
);
539 call_listeners(mods
, e
);
543 void key_axis::set_mode(int mode
, double tolerance
) throw()
545 umutex_class
u(mutex
);
547 last_tolerance
= tolerance
;
550 key_mouse::key_mouse(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
551 mouse_calibration _cal
) throw(std::bad_alloc
)
552 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_MOUSE
)
558 key_mouse::~key_mouse() throw() {}
559 int32_t key_mouse::get_state_digital() const throw() { return 0; }
561 int32_t key_mouse::get_state() const throw()
563 umutex_class
u(mutex
);
564 return cal
.get_calibrated_value(rawstate
);
567 std::vector
<std::string
> key_mouse::get_subkeys() throw(std::bad_alloc
)
569 return std::vector
<std::string
>();
572 mouse_calibration
key_mouse::get_calibration() const throw()
574 umutex_class
u(mutex
);
575 mouse_calibration tmp
= cal
;
579 void key_mouse::set_state(modifier_set mods
, int32_t _rawstate
) throw()
583 mouse_calibration _cal
;
585 if(rawstate
!= _rawstate
) {
586 rawstate
= _rawstate
;
587 state
= cal
.get_calibrated_value(rawstate
);
593 event_mouse
e(state
, _cal
);
594 call_listeners(mods
, e
);
598 void key_mouse::set_calibration(mouse_calibration _cal
) throw()
602 int32_t state
= cal
.get_calibrated_value(rawstate
);
604 event_mouse
e(state
, _cal
);
606 call_listeners(mods
, e
);