1 #include "keyboard.hpp"
2 #include "stateobject.hpp"
9 threads::rlock
* global_lock
;
10 threads::rlock
& get_keyboard_lock()
12 if(!global_lock
) global_lock
= new threads::rlock
;
16 struct keyboard_internal
18 std::map
<std::string
, modifier
*> modifiers
;
19 std::map
<std::string
, key
*> keys
;
21 typedef stateobject::type
<keyboard
, keyboard_internal
> keyboard_internal_t
;
24 void keyboard::do_register(const std::string
& name
, modifier
& mod
) throw(std::bad_alloc
)
26 threads::arlock
u(get_keyboard_lock());
27 auto& state
= keyboard_internal_t::get(this);
28 if(state
.modifiers
.count(name
)) return;
29 state
.modifiers
[name
] = &mod
;
32 void keyboard::do_unregister(const std::string
& name
, modifier
& mod
) throw()
34 threads::arlock
u(get_keyboard_lock());
35 auto state
= keyboard_internal_t::get_soft(this);
36 if(!state
|| !state
->modifiers
.count(name
) || state
->modifiers
[name
] != &mod
) return;
37 state
->modifiers
.erase(name
);
40 modifier
& keyboard::lookup_modifier(const std::string
& name
) throw(std::runtime_error
)
42 modifier
* m
= try_lookup_modifier(name
);
44 throw std::runtime_error("No such modifier");
48 modifier
* keyboard::try_lookup_modifier(const std::string
& name
) throw()
50 threads::arlock
u(get_keyboard_lock());
51 auto state
= keyboard_internal_t::get_soft(this);
52 if(!state
|| !state
->modifiers
.count(name
))
54 return state
->modifiers
[name
];
57 std::list
<modifier
*> keyboard::all_modifiers() throw(std::bad_alloc
)
59 threads::arlock
u(get_keyboard_lock());
60 auto state
= keyboard_internal_t::get_soft(this);
61 std::list
<modifier
*> r
;
63 for(auto i
: state
->modifiers
)
64 r
.push_back(i
.second
);
68 void keyboard::do_register(const std::string
& name
, key
& key
) throw(std::bad_alloc
)
70 threads::arlock
u(get_keyboard_lock());
71 auto& state
= keyboard_internal_t::get(this);
72 if(state
.keys
.count(name
)) return;
73 state
.keys
[name
] = &key
;
76 void keyboard::do_unregister(const std::string
& name
, key
& key
) throw()
78 threads::arlock
u(get_keyboard_lock());
79 auto state
= keyboard_internal_t::get_soft(this);
80 if(!state
|| !state
->keys
.count(name
) || state
->keys
[name
] != &key
) return;
81 state
->keys
.erase(name
);
84 key
& keyboard::lookup_key(const std::string
& name
) throw(std::runtime_error
)
86 key
* m
= try_lookup_key(name
);
88 throw std::runtime_error("No such key");
92 key
* keyboard::try_lookup_key(const std::string
& name
) throw()
94 threads::arlock
u(get_keyboard_lock());
95 auto state
= keyboard_internal_t::get_soft(this);
96 if(!state
|| !state
->keys
.count(name
))
98 return state
->keys
[name
];
101 std::list
<key
*> keyboard::all_keys() throw(std::bad_alloc
)
103 threads::arlock
u(get_keyboard_lock());
104 auto state
= keyboard_internal_t::get_soft(this);
107 for(auto i
: state
->keys
)
108 r
.push_back(i
.second
);
112 void keyboard::set_exclusive(event_listener
* listener
) throw()
114 threads::arlock
u(get_keyboard_lock());
115 auto state
= keyboard_internal_t::get_soft(this);
117 for(auto i
: state
->keys
)
118 i
.second
->set_exclusive(listener
);
121 void keyboard::set_current_key(key
* key
) throw()
123 threads::arlock
u(get_keyboard_lock());
127 key
* keyboard::get_current_key() throw()
129 threads::arlock
u(get_keyboard_lock());
133 keyboard::keyboard() throw(std::bad_alloc
)
137 keyboard::~keyboard() throw()
139 threads::arlock
u(get_keyboard_lock());
140 auto state
= keyboard_internal_t::get_soft(this);
142 keyboard_internal_t::clear(this);
145 void modifier_set::add(modifier
& mod
, bool really
) throw(std::bad_alloc
)
151 void modifier_set::remove(modifier
& mod
, bool really
) throw(std::bad_alloc
)
157 modifier_set
modifier_set::construct(keyboard
& kbd
, const std::string
& _modifiers
)
158 throw(std::bad_alloc
, std::runtime_error
)
161 std::string modifiers
= _modifiers
;
162 while(modifiers
!= "") {
163 std::string mod
= modifiers
;
165 size_t split
= modifiers
.find_first_of(",");
166 if(split
< modifiers
.length()) {
167 mod
= modifiers
.substr(0, split
);
168 rest
= modifiers
.substr(split
+ 1);
170 set
.add(kbd
.lookup_modifier(mod
));
176 bool modifier_set::valid(modifier_set
& mask
) throw(std::bad_alloc
)
178 //No element can be together with its linkage group.
180 modifier
* j
= i
->get_link();
181 if(j
&& set
.count(j
))
184 for(auto i
: mask
.set
) {
185 modifier
* j
= i
->get_link();
186 if(j
&& mask
.set
.count(j
))
189 //For every element of set, it or its linkage group must be in mask.
191 modifier
* j
= i
->get_link();
192 if(!mask
.set
.count(i
) && !mask
.set
.count(j
? j
: i
))
198 bool modifier_set::operator==(const modifier_set
& m
) const throw()
209 bool modifier_set::operator<(const modifier_set
& m
) const throw()
211 auto i1
= set
.begin();
212 auto i2
= m
.set
.begin();
213 for(; i1
!= set
.end() && i2
!= m
.set
.end(); i1
++, i2
++) {
214 if((uint64_t)*i1
< (uint64_t)*i2
)
216 if((uint64_t)*i1
> (uint64_t)*i2
)
219 return (i2
!= m
.set
.end());
222 modifier_set::operator std::string() const throw(std::bad_alloc
)
226 r
= r
+ ((r
!= "") ? "," : "") + i
->get_name();
230 std::ostream
& operator<<(std::ostream
& os
, const modifier_set
& m
)
234 os
<< i
->get_name() << " ";
239 bool modifier_set::triggers(const modifier_set
& trigger
, const modifier_set
& mask
)
240 throw(std::bad_alloc
)
242 for(auto i
: mask
.set
) {
243 bool trigger_exact
= trigger
.set
.count(i
);
244 bool trigger_ingroup
= false;
245 for(auto j
: trigger
.set
)
246 if(j
->get_link() == i
)
247 trigger_ingroup
= true;
248 bool trigger_none
= !trigger_exact
&& !trigger_ingroup
;
250 //If trigger_exact is set, then this key or a key in this group must be pressed.
254 any
= any
|| (j
== i
|| j
->get_link() == i
);
258 //If trigger_ingroup is set, then exactly that set of keys in group must be pressed.
259 if(trigger_ingroup
) {
260 for(auto j
: i
->get_keyboard().all_modifiers()) {
261 if(j
->get_link() != i
)
262 continue; //Not interested.
263 if((set
.count(j
) > 0) != (trigger
.set
.count(j
) > 0))
267 //If trigger_none is set, then this key nor keys in this key group can't be pressed.
271 any
= any
|| (j
== i
|| j
->get_link() == i
);
279 int32_t mouse_calibration::get_calibrated_value(int32_t x
) const throw()
284 event::~event() throw() {}
285 event_key::~event_key() throw() {}
286 event_axis::~event_axis() throw() {}
287 event_hat::~event_hat() throw() {}
288 event_mouse::~event_mouse() throw() {}
289 event_listener::~event_listener() throw() {}
293 kbd
.do_unregister(name
, *this);
296 event_key::event_key(uint32_t chngmask
)
297 : event(chngmask
, keytype::KBD_KEYTYPE_KEY
)
301 event_axis::event_axis(int32_t _state
, uint32_t chngmask
)
302 : event(chngmask
, keytype::KBD_KEYTYPE_AXIS
)
307 event_hat::event_hat(uint32_t chngmask
)
308 : event(chngmask
, keytype::KBD_KEYTYPE_HAT
)
312 event_mouse::event_mouse(int32_t _state
, const mouse_calibration
& _cal
)
313 : event(0, keytype::KBD_KEYTYPE_MOUSE
)
319 int32_t event_key::get_state() const throw() { return (get_change_mask() & 1) != 0; }
320 int32_t event_axis::get_state() const throw() { return state
; }
321 int32_t event_mouse::get_state() const throw() { return state
; }
323 int32_t event_hat::get_state() const throw()
326 uint32_t m
= get_change_mask();
334 key::key(keyboard
& keyb
, const std::string
& _name
, const std::string
& _clazz
,
335 keytype _type
) throw(std::bad_alloc
)
336 : kbd(keyb
), clazz(_clazz
), name(_name
), type(_type
)
338 exclusive_listener
= NULL
;
339 kbd
.do_register(name
, *this);
342 void key::add_listener(event_listener
& listener
, bool analog
) throw(std::bad_alloc
)
345 analog_listeners
.insert(&listener
);
346 digital_listeners
.erase(&listener
);
348 digital_listeners
.insert(&listener
);
349 analog_listeners
.erase(&listener
);
352 void key::remove_listener(event_listener
& listener
) throw()
354 digital_listeners
.erase(&listener
);
355 analog_listeners
.erase(&listener
);
358 void key::set_exclusive(event_listener
* listener
) throw()
360 threads::arlock
u(get_keyboard_lock());
361 exclusive_listener
= listener
;
364 void key::call_listeners(modifier_set
& mods
, event
& event
)
366 kbd
.set_current_key(this);
367 bool digital
= (event
.get_change_mask() & 0xAAAAAAAAUL
) != 0;
368 get_keyboard_lock().lock();
369 if(exclusive_listener
) {
370 get_keyboard_lock().unlock();
371 exclusive_listener
->on_key_event(mods
, *this, event
);
372 kbd
.set_current_key(NULL
);
375 event_listener
* itr
= NULL
;
377 auto itr2
= digital_listeners
.upper_bound(itr
);
378 if(itr2
== digital_listeners
.end())
381 get_keyboard_lock().unlock();
382 itr
->on_key_event(mods
, *this, event
);
383 get_keyboard_lock().lock();
387 auto itr2
= analog_listeners
.upper_bound(itr
);
388 if(itr2
== analog_listeners
.end())
391 get_keyboard_lock().unlock();
392 itr
->on_key_event(mods
, *this, event
);
393 get_keyboard_lock().lock();
395 get_keyboard_lock().unlock();
396 kbd
.set_current_key(NULL
);
399 key_axis
* key::cast_axis() throw()
401 if(type
!= KBD_KEYTYPE_AXIS
)
403 return dynamic_cast<key_axis
*>(this);
406 key_mouse
* key::cast_mouse() throw()
408 if(type
!= KBD_KEYTYPE_MOUSE
)
410 return dynamic_cast<key_mouse
*>(this);
413 key_key::key_key(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
)
414 throw(std::bad_alloc
)
415 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_KEY
)
420 key_key::~key_key() throw() {}
422 void key_key::set_state(modifier_set mods
, int32_t _state
) throw()
424 uint32_t change
= _state
? 1 : 0;
426 get_keyboard_lock().lock();
427 if(state
!= _state
) {
432 get_keyboard_lock().unlock();
435 call_listeners(mods
, e
);
439 int32_t key_key::get_state() const throw() { return state
; }
440 int32_t key_key::get_state_digital() const throw() { return state
; }
442 std::vector
<std::string
> key_key::get_subkeys() throw(std::bad_alloc
)
444 std::vector
<std::string
> r
;
449 key_hat::key_hat(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
)
450 throw(std::bad_alloc
)
451 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_HAT
)
455 key_hat::~key_hat() throw() {}
457 void key_hat::set_state(modifier_set mods
, int32_t _state
) throw()
462 get_keyboard_lock().lock();
463 if(state
!= _state
) {
464 int32_t schange
= state
^ _state
;
466 if(state
& 1) change
|= 1;
467 if(schange
& 1) change
|= 2;
468 if(state
& 2) change
|= 4;
469 if(schange
& 2) change
|= 8;
470 if(state
& 4) change
|= 16;
471 if(schange
& 4) change
|= 32;
472 if(state
& 8) change
|= 64;
473 if(schange
& 8) change
|= 128;
476 get_keyboard_lock().unlock();
479 call_listeners(mods
, e
);
483 int32_t key_hat::get_state() const throw() { return state
; }
484 int32_t key_hat::get_state_digital() const throw() { return state
; }
486 std::vector
<std::string
> key_hat::get_subkeys() throw(std::bad_alloc
)
488 std::vector
<std::string
> r
;
496 key_axis::key_axis(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
497 int mode
) throw(std::bad_alloc
)
498 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_AXIS
)
502 last_tolerance
= 0.5;
505 key_axis::~key_axis() throw() {}
507 int32_t key_axis::get_state() const throw()
509 threads::arlock
u(get_keyboard_lock());
513 int32_t key_axis::get_state_digital() const throw()
515 threads::arlock
u(get_keyboard_lock());
516 if(rawstate
<= -32768 * last_tolerance
)
518 if(rawstate
>= 32767 * last_tolerance
)
523 int key_axis::get_mode() const throw()
525 threads::arlock
u(get_keyboard_lock());
529 std::vector
<std::string
> key_axis::get_subkeys() throw(std::bad_alloc
)
531 threads::arlock
u(get_keyboard_lock());
532 std::vector
<std::string
> r
;
542 void key_axis::set_state(modifier_set mods
, int32_t _rawstate
) throw()
547 int dold
= 0, dnew
= 0;
548 get_keyboard_lock().lock();
549 if(rawstate
!= _rawstate
) {
551 rawstate
= _rawstate
;
553 if(state
<= -32768 * last_tolerance
)
555 if(state
>= 32767 * last_tolerance
)
560 if((dold
> 0 && dnew
<= 0) || (dold
<= 0 && dnew
> 0))
564 if((dold
< 0 && dnew
>= 0) || (dold
>= 0 && dnew
< 0))
568 get_keyboard_lock().unlock();
570 event_axis
e(state
, change
);
571 call_listeners(mods
, e
);
575 void key_axis::set_mode(int mode
, double tolerance
) throw()
577 threads::arlock
u(get_keyboard_lock());
579 last_tolerance
= tolerance
;
582 key_mouse::key_mouse(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
583 mouse_calibration _cal
) throw(std::bad_alloc
)
584 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_MOUSE
)
590 key_mouse::~key_mouse() throw() {}
591 int32_t key_mouse::get_state_digital() const throw() { return 0; }
593 int32_t key_mouse::get_state() const throw()
595 threads::arlock
u(get_keyboard_lock());
596 return cal
.get_calibrated_value(rawstate
);
599 std::vector
<std::string
> key_mouse::get_subkeys() throw(std::bad_alloc
)
601 return std::vector
<std::string
>();
604 mouse_calibration
key_mouse::get_calibration() const throw()
606 threads::arlock
u(get_keyboard_lock());
607 mouse_calibration tmp
= cal
;
611 void key_mouse::set_state(modifier_set mods
, int32_t _rawstate
) throw()
615 mouse_calibration _cal
;
616 get_keyboard_lock().lock();
617 if(rawstate
!= _rawstate
) {
618 rawstate
= _rawstate
;
619 state
= cal
.get_calibrated_value(rawstate
);
623 get_keyboard_lock().unlock();
625 event_mouse
e(state
, _cal
);
626 call_listeners(mods
, e
);
630 void key_mouse::set_calibration(mouse_calibration _cal
) throw()
632 get_keyboard_lock().lock();
634 int32_t state
= cal
.get_calibrated_value(rawstate
);
635 get_keyboard_lock().unlock();
636 event_mouse
e(state
, _cal
);
638 call_listeners(mods
, e
);