1 #include "keyboard.hpp"
4 void keyboard::do_register_modifier(const std::string
& name
, keyboard_modifier
& mod
) throw(std::bad_alloc
)
7 modifiers
[name
] = &mod
;
10 void keyboard::do_unregister_modifier(const std::string
& name
) throw()
12 umutex_class
u(mutex
);
13 modifiers
.erase(name
);
16 keyboard_modifier
& keyboard::lookup_modifier(const std::string
& name
) throw(std::runtime_error
)
18 keyboard_modifier
* m
= try_lookup_modifier(name
);
20 throw std::runtime_error("No such modifier");
24 keyboard_modifier
* keyboard::try_lookup_modifier(const std::string
& name
) throw()
26 umutex_class
u(mutex
);
27 if(!modifiers
.count(name
))
29 return modifiers
[name
];
32 std::list
<keyboard_modifier
*> keyboard::all_modifiers() throw(std::bad_alloc
)
34 umutex_class
u(mutex
);
35 std::list
<keyboard_modifier
*> r
;
36 for(auto i
: modifiers
)
37 r
.push_back(i
.second
);
41 void keyboard::do_register_key(const std::string
& name
, keyboard_key
& key
) throw(std::bad_alloc
)
43 umutex_class
u(mutex
);
47 void keyboard::do_unregister_key(const std::string
& name
) throw()
49 umutex_class
u(mutex
);
53 keyboard_key
& keyboard::lookup_key(const std::string
& name
) throw(std::runtime_error
)
55 keyboard_key
* m
= try_lookup_key(name
);
57 throw std::runtime_error("No such key");
61 keyboard_key
* keyboard::try_lookup_key(const std::string
& name
) throw()
63 umutex_class
u(mutex
);
69 std::list
<keyboard_key
*> keyboard::all_keys() throw(std::bad_alloc
)
71 umutex_class
u(mutex
);
72 std::list
<keyboard_key
*> r
;
74 r
.push_back(i
.second
);
78 void keyboard::set_exclusive(keyboard_event_listener
* listener
) throw()
80 umutex_class
u(mutex
);
82 i
.second
->set_exclusive(listener
);
85 void keyboard::set_current_key(keyboard_key
* key
) throw()
87 umutex_class
u(mutex
);
91 keyboard_key
* keyboard::get_current_key() throw()
93 umutex_class
u(mutex
);
97 keyboard::keyboard() throw(std::bad_alloc
)
98 : modifier_proxy(*this), key_proxy(*this)
100 register_queue
<keyboard::_modifier_proxy
, keyboard_modifier
>::do_ready(modifier_proxy
, true);
101 register_queue
<keyboard::_key_proxy
, keyboard_key
>::do_ready(key_proxy
, true);
104 keyboard::~keyboard() throw()
106 register_queue
<keyboard::_modifier_proxy
, keyboard_modifier
>::do_ready(modifier_proxy
, false);
107 register_queue
<keyboard::_key_proxy
, keyboard_key
>::do_ready(key_proxy
, false);
110 void keyboard_modifier_set::add(keyboard_modifier
& mod
, bool really
) throw(std::bad_alloc
)
116 void keyboard_modifier_set::remove(keyboard_modifier
& mod
, bool really
) throw(std::bad_alloc
)
122 keyboard_modifier_set
keyboard_modifier_set::construct(keyboard
& kbd
, const std::string
& _modifiers
)
123 throw(std::bad_alloc
, std::runtime_error
)
125 keyboard_modifier_set set
;
126 std::string modifiers
= _modifiers
;
127 while(modifiers
!= "") {
128 std::string mod
= modifiers
;
130 size_t split
= modifiers
.find_first_of(",");
131 if(split
< modifiers
.length()) {
132 mod
= modifiers
.substr(0, split
);
133 rest
= modifiers
.substr(split
+ 1);
135 set
.add(kbd
.lookup_modifier(mod
));
141 bool keyboard_modifier_set::valid(keyboard_modifier_set
& mask
) throw(std::bad_alloc
)
143 //No element can be together with its linkage group.
145 keyboard_modifier
* j
= i
->get_link();
146 if(j
&& set
.count(j
))
149 for(auto i
: mask
.set
) {
150 keyboard_modifier
* j
= i
->get_link();
151 if(j
&& mask
.set
.count(j
))
154 //For every element of set, it or its linkage group must be in mask.
156 keyboard_modifier
* j
= i
->get_link();
157 if(!mask
.set
.count(i
) && !mask
.set
.count(j
? j
: i
))
163 bool keyboard_modifier_set::operator==(const keyboard_modifier_set
& m
) const throw()
174 bool keyboard_modifier_set::operator<(const keyboard_modifier_set
& m
) const throw()
176 auto i1
= set
.begin();
177 auto i2
= m
.set
.begin();
178 for(; i1
!= set
.end() && i2
!= m
.set
.end(); i1
++, i2
++) {
179 if((uint64_t)*i1
< (uint64_t)*i2
)
181 if((uint64_t)*i1
> (uint64_t)*i2
)
184 return (i2
!= m
.set
.end());
187 keyboard_modifier_set::operator std::string() const throw(std::bad_alloc
)
191 r
= r
+ ((r
!= "") ? "," : "") + i
->get_name();
195 std::ostream
& operator<<(std::ostream
& os
, const keyboard_modifier_set
& m
)
199 os
<< i
->get_name() << " ";
204 bool keyboard_modifier_set::triggers(const keyboard_modifier_set
& trigger
, const keyboard_modifier_set
& mask
)
205 throw(std::bad_alloc
)
207 for(auto i
: mask
.set
) {
208 bool trigger_exact
= trigger
.set
.count(i
);
209 bool trigger_ingroup
= false;
210 for(auto j
: trigger
.set
)
211 if(j
->get_link() == i
)
212 trigger_ingroup
= true;
213 bool trigger_none
= !trigger_exact
&& !trigger_ingroup
;
215 //If trigger_exact is set, then this key or a key in this group must be pressed.
219 any
= any
|| (j
== i
|| j
->get_link() == i
);
223 //If trigger_ingroup is set, then exactly that set of keys in group must be pressed.
224 if(trigger_ingroup
) {
225 for(auto j
: i
->get_keyboard().all_modifiers()) {
226 if(j
->get_link() != i
)
227 continue; //Not interested.
228 if((set
.count(j
) > 0) != (trigger
.set
.count(j
) > 0))
232 //If trigger_none is set, then this key nor keys in this key group can't be pressed.
236 any
= any
|| (j
== i
|| j
->get_link() == i
);
244 int32_t keyboard_axis_calibration::get_calibrated_value(int32_t x
) const throw()
254 width
= center
- (double)left
;
256 width
= (double)right
- center
;
257 return 32767.0 * (x
- (double)center
) / width
;
260 int keyboard_axis_calibration::get_digital_state(int32_t x
) const throw()
265 int m
= (esign_a
+ 1) * 3 + esign_b
+ 1;
270 case 0: case 4: case 8: break; //These are not legal.
271 case 1: dwidth
= false; negative
= false; shift
=32767; break; //- to 0.
272 case 2: dwidth
= true; negative
= false; shift
=32767; break; //- to +.
273 case 3: dwidth
= false; negative
= true; shift
=0; break; //0 to -.
274 case 5: dwidth
= false; negative
= false; shift
=0; break; //0 to +.
275 case 6: dwidth
= true; negative
= true; shift
=32767; break; //+ to -.
276 case 7: dwidth
= false; negative
= true; shift
=32767; break; //+ to 0.
281 int32_t threshold
= (int32_t)((dwidth
? 65535 : 32767) * nullwidth
);
282 return (x
> threshold
) ? 1 : 0;
285 int32_t tolerance
= (int32_t)(32767 * nullwidth
);
295 int32_t keyboard_mouse_calibration::get_calibrated_value(int32_t x
) const throw()
300 keyboard_event::~keyboard_event() throw() {}
301 keyboard_event_key::~keyboard_event_key() throw() {}
302 keyboard_event_axis::~keyboard_event_axis() throw() {}
303 keyboard_event_hat::~keyboard_event_hat() throw() {}
304 keyboard_event_mouse::~keyboard_event_mouse() throw() {}
305 keyboard_event_listener::~keyboard_event_listener() throw() {}
307 keyboard_key::~keyboard_key() throw()
309 register_queue
<keyboard::_key_proxy
, keyboard_key
>::do_unregister(kbd
.key_proxy
, name
);
312 keyboard_event_key::keyboard_event_key(uint32_t chngmask
)
313 : keyboard_event(chngmask
, keyboard_keytype::KBD_KEYTYPE_KEY
)
317 keyboard_event_axis::keyboard_event_axis(int32_t _state
, uint32_t chngmask
, const keyboard_axis_calibration
& _cal
)
318 : keyboard_event(chngmask
, keyboard_keytype::KBD_KEYTYPE_AXIS
)
324 keyboard_event_hat::keyboard_event_hat(uint32_t chngmask
)
325 : keyboard_event(chngmask
, keyboard_keytype::KBD_KEYTYPE_HAT
)
329 keyboard_event_mouse::keyboard_event_mouse(int32_t _state
, const keyboard_mouse_calibration
& _cal
)
330 : keyboard_event(0, keyboard_keytype::KBD_KEYTYPE_MOUSE
)
336 int32_t keyboard_event_key::get_state() const throw() { return (get_change_mask() & 1) != 0; }
337 int32_t keyboard_event_axis::get_state() const throw() { return state
; }
338 int32_t keyboard_event_mouse::get_state() const throw() { return state
; }
340 int32_t keyboard_event_hat::get_state() const throw()
343 uint32_t m
= get_change_mask();
351 keyboard_key::keyboard_key(keyboard
& keyb
, const std::string
& _name
, const std::string
& _clazz
,
352 keyboard_keytype _type
) throw(std::bad_alloc
)
353 : kbd(keyb
), clazz(_clazz
), name(_name
), type(_type
)
355 exclusive_listener
= NULL
;
356 register_queue
<keyboard::_key_proxy
, keyboard_key
>::do_register(kbd
.key_proxy
, name
, *this);
359 void keyboard_key::add_listener(keyboard_event_listener
& listener
, bool analog
) throw(std::bad_alloc
)
362 analog_listeners
.insert(&listener
);
363 digital_listeners
.erase(&listener
);
365 digital_listeners
.insert(&listener
);
366 analog_listeners
.erase(&listener
);
369 void keyboard_key::remove_listener(keyboard_event_listener
& listener
) throw()
371 digital_listeners
.erase(&listener
);
372 analog_listeners
.erase(&listener
);
375 void keyboard_key::set_exclusive(keyboard_event_listener
* listener
) throw()
377 umutex_class
u(mutex
);
378 exclusive_listener
= listener
;
381 void keyboard_key::call_listeners(keyboard_modifier_set
& mods
, keyboard_event
& event
)
383 kbd
.set_current_key(this);
384 bool digital
= (event
.get_change_mask() & 0xAAAAAAAAUL
) != 0;
386 if(exclusive_listener
) {
388 exclusive_listener
->on_key_event(mods
, *this, event
);
389 kbd
.set_current_key(NULL
);
392 keyboard_event_listener
* itr
= NULL
;
394 auto itr2
= digital_listeners
.upper_bound(itr
);
395 if(itr2
== digital_listeners
.end())
399 itr
->on_key_event(mods
, *this, event
);
404 auto itr2
= analog_listeners
.upper_bound(itr
);
405 if(itr2
== analog_listeners
.end())
409 itr
->on_key_event(mods
, *this, event
);
413 kbd
.set_current_key(NULL
);
416 keyboard_key_axis
* keyboard_key::cast_axis() throw()
418 if(type
!= KBD_KEYTYPE_AXIS
)
420 return dynamic_cast<keyboard_key_axis
*>(this);
423 keyboard_key_mouse
* keyboard_key::cast_mouse() throw()
425 if(type
!= KBD_KEYTYPE_MOUSE
)
427 return dynamic_cast<keyboard_key_mouse
*>(this);
430 keyboard_key_key::keyboard_key_key(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
)
431 throw(std::bad_alloc
)
432 : keyboard_key(keyb
, name
, clazz
, keyboard_keytype::KBD_KEYTYPE_KEY
)
437 keyboard_key_key::~keyboard_key_key() throw() {}
439 void keyboard_key_key::set_state(keyboard_modifier_set mods
, int32_t _state
) throw()
441 uint32_t change
= _state
? 1 : 0;
444 if(state
!= _state
) {
451 keyboard_event_key
e(change
);
452 call_listeners(mods
, e
);
456 int32_t keyboard_key_key::get_state() const throw() { return state
; }
457 int32_t keyboard_key_key::get_state_digital() const throw() { return state
; }
459 std::vector
<std::string
> keyboard_key_key::get_subkeys() throw(std::bad_alloc
)
461 std::vector
<std::string
> r
;
466 keyboard_key_hat::keyboard_key_hat(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
)
467 throw(std::bad_alloc
)
468 : keyboard_key(keyb
, name
, clazz
, keyboard_keytype::KBD_KEYTYPE_HAT
)
472 keyboard_key_hat::~keyboard_key_hat() throw() {}
474 void keyboard_key_hat::set_state(keyboard_modifier_set mods
, int32_t _state
) throw()
480 if(state
!= _state
) {
481 int32_t schange
= state
^ _state
;
483 if(state
& 1) change
|= 1;
484 if(schange
& 1) change
|= 2;
485 if(state
& 2) change
|= 4;
486 if(schange
& 2) change
|= 8;
487 if(state
& 4) change
|= 16;
488 if(schange
& 4) change
|= 32;
489 if(state
& 8) change
|= 64;
490 if(schange
& 8) change
|= 128;
495 keyboard_event_hat
e(change
);
496 call_listeners(mods
, e
);
500 int32_t keyboard_key_hat::get_state() const throw() { return state
; }
501 int32_t keyboard_key_hat::get_state_digital() const throw() { return state
; }
503 std::vector
<std::string
> keyboard_key_hat::get_subkeys() throw(std::bad_alloc
)
505 std::vector
<std::string
> r
;
513 keyboard_key_axis::keyboard_key_axis(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
514 keyboard_axis_calibration _cal
) throw(std::bad_alloc
)
515 : keyboard_key(keyb
, name
, clazz
, keyboard_keytype::KBD_KEYTYPE_AXIS
)
520 keyboard_key_axis::~keyboard_key_axis() throw() {}
522 int32_t keyboard_key_axis::get_state() const throw()
524 umutex_class
u(mutex
);
525 return cal
.get_calibrated_value(rawstate
);
528 int32_t keyboard_key_axis::get_state_digital() const throw()
530 umutex_class
u(mutex
);
531 int32_t tmp
= cal
.get_calibrated_value(rawstate
);
532 return cal
.get_digital_state(tmp
);
535 keyboard_axis_calibration
keyboard_key_axis::get_calibration() const throw()
537 umutex_class
u(mutex
);
538 keyboard_axis_calibration tmp
= cal
;
542 std::vector
<std::string
> keyboard_key_axis::get_subkeys() throw(std::bad_alloc
)
544 umutex_class
u(mutex
);
545 std::vector
<std::string
> r
;
548 else if(cal
.mode
> 0) {
555 void keyboard_key_axis::set_state(keyboard_modifier_set mods
, int32_t _rawstate
) throw()
558 int32_t state
, ostate
;
560 int dold
= 0, dnew
= 0;
561 keyboard_axis_calibration _cal
;
563 if(rawstate
!= _rawstate
) {
564 ostate
= cal
.get_calibrated_value(rawstate
);
565 dold
= cal
.get_digital_state(ostate
);
566 rawstate
= _rawstate
;
567 state
= cal
.get_calibrated_value(rawstate
);
568 dnew
= cal
.get_digital_state(state
);
571 if((dold
> 0 && dnew
<= 0) || (dold
<= 0 && dnew
> 0))
575 if((dold
< 0 && dnew
>= 0) || (dold
>= 0 && dnew
< 0))
582 keyboard_event_axis
e(state
, change
, _cal
);
583 call_listeners(mods
, e
);
587 void keyboard_key_axis::set_calibration(keyboard_axis_calibration _cal
) throw()
590 int dold
= 0, dnew
= 0;
592 int32_t ostate
= cal
.get_calibrated_value(rawstate
);
593 dold
= cal
.get_digital_state(ostate
);
595 int32_t state
= cal
.get_calibrated_value(rawstate
);
596 dnew
= cal
.get_digital_state(state
);
599 if((dold
< 0 && dnew
>= 0) || (dold
>= 0 && dnew
< 0))
603 if((dold
> 0 && dnew
<= 0) || (dold
<= 0 && dnew
> 0))
606 keyboard_event_axis
e(change
, state
, _cal
);
607 keyboard_modifier_set mods
;
608 call_listeners(mods
, e
);
611 keyboard_key_mouse::keyboard_key_mouse(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
612 keyboard_mouse_calibration _cal
) throw(std::bad_alloc
)
613 : keyboard_key(keyb
, name
, clazz
, keyboard_keytype::KBD_KEYTYPE_MOUSE
)
619 keyboard_key_mouse::~keyboard_key_mouse() throw() {}
620 int32_t keyboard_key_mouse::get_state_digital() const throw() { return 0; }
622 int32_t keyboard_key_mouse::get_state() const throw()
624 umutex_class
u(mutex
);
625 return cal
.get_calibrated_value(rawstate
);
628 std::vector
<std::string
> keyboard_key_mouse::get_subkeys() throw(std::bad_alloc
)
630 return std::vector
<std::string
>();
633 keyboard_mouse_calibration
keyboard_key_mouse::get_calibration() const throw()
635 umutex_class
u(mutex
);
636 keyboard_mouse_calibration tmp
= cal
;
640 void keyboard_key_mouse::set_state(keyboard_modifier_set mods
, int32_t _rawstate
) throw()
644 keyboard_mouse_calibration _cal
;
646 if(rawstate
!= _rawstate
) {
647 rawstate
= _rawstate
;
648 state
= cal
.get_calibrated_value(rawstate
);
654 keyboard_event_mouse
e(state
, _cal
);
655 call_listeners(mods
, e
);
659 void keyboard_key_mouse::set_calibration(keyboard_mouse_calibration _cal
) throw()
663 int32_t state
= cal
.get_calibrated_value(rawstate
);
665 keyboard_event_mouse
e(state
, _cal
);
666 keyboard_modifier_set mods
;
667 call_listeners(mods
, e
);