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
)
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
)
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()
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
)
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
)
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()
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());
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
)
151 void modifier_set::remove(modifier
& mod
, bool really
)
157 modifier_set
modifier_set::construct(keyboard
& kbd
, const std::string
& _modifiers
)
160 std::string modifiers
= _modifiers
;
161 while(modifiers
!= "") {
162 std::string mod
= modifiers
;
164 size_t split
= modifiers
.find_first_of(",");
165 if(split
< modifiers
.length()) {
166 mod
= modifiers
.substr(0, split
);
167 rest
= modifiers
.substr(split
+ 1);
169 set
.add(kbd
.lookup_modifier(mod
));
175 bool modifier_set::valid(modifier_set
& mask
)
177 //No element can be together with its linkage group.
179 modifier
* j
= i
->get_link();
180 if(j
&& set
.count(j
))
183 for(auto i
: mask
.set
) {
184 modifier
* j
= i
->get_link();
185 if(j
&& mask
.set
.count(j
))
188 //For every element of set, it or its linkage group must be in mask.
190 modifier
* j
= i
->get_link();
191 if(!mask
.set
.count(i
) && !mask
.set
.count(j
? j
: i
))
197 bool modifier_set::operator==(const modifier_set
& m
) const throw()
208 bool modifier_set::operator<(const modifier_set
& m
) const throw()
210 auto i1
= set
.begin();
211 auto i2
= m
.set
.begin();
212 for(; i1
!= set
.end() && i2
!= m
.set
.end(); i1
++, i2
++) {
213 if((uint64_t)*i1
< (uint64_t)*i2
)
215 if((uint64_t)*i1
> (uint64_t)*i2
)
218 return (i2
!= m
.set
.end());
221 modifier_set::operator std::string() const
225 r
= r
+ ((r
!= "") ? "," : "") + i
->get_name();
229 std::ostream
& operator<<(std::ostream
& os
, const modifier_set
& m
)
233 os
<< i
->get_name() << " ";
238 bool modifier_set::triggers(const modifier_set
& trigger
, const modifier_set
& mask
)
240 for(auto i
: mask
.set
) {
241 bool trigger_exact
= trigger
.set
.count(i
);
242 bool trigger_ingroup
= false;
243 for(auto j
: trigger
.set
)
244 if(j
->get_link() == i
)
245 trigger_ingroup
= true;
246 bool trigger_none
= !trigger_exact
&& !trigger_ingroup
;
248 //If trigger_exact is set, then this key or a key in this group must be pressed.
252 any
= any
|| (j
== i
|| j
->get_link() == i
);
256 //If trigger_ingroup is set, then exactly that set of keys in group must be pressed.
257 if(trigger_ingroup
) {
258 for(auto j
: i
->get_keyboard().all_modifiers()) {
259 if(j
->get_link() != i
)
260 continue; //Not interested.
261 if((set
.count(j
) > 0) != (trigger
.set
.count(j
) > 0))
265 //If trigger_none is set, then this key nor keys in this key group can't be pressed.
269 any
= any
|| (j
== i
|| j
->get_link() == i
);
277 int32_t mouse_calibration::get_calibrated_value(int32_t x
) const throw()
282 event::~event() throw() {}
283 event_key::~event_key() throw() {}
284 event_axis::~event_axis() throw() {}
285 event_hat::~event_hat() throw() {}
286 event_mouse::~event_mouse() throw() {}
287 event_listener::~event_listener() throw() {}
291 kbd
.do_unregister(name
, *this);
294 event_key::event_key(uint32_t chngmask
)
295 : event(chngmask
, keytype::KBD_KEYTYPE_KEY
)
299 event_axis::event_axis(int32_t _state
, uint32_t chngmask
)
300 : event(chngmask
, keytype::KBD_KEYTYPE_AXIS
)
305 event_hat::event_hat(uint32_t chngmask
)
306 : event(chngmask
, keytype::KBD_KEYTYPE_HAT
)
310 event_mouse::event_mouse(int32_t _state
, const mouse_calibration
& _cal
)
311 : event(0, keytype::KBD_KEYTYPE_MOUSE
)
317 int32_t event_key::get_state() const throw() { return (get_change_mask() & 1) != 0; }
318 int32_t event_axis::get_state() const throw() { return state
; }
319 int32_t event_mouse::get_state() const throw() { return state
; }
321 int32_t event_hat::get_state() const throw()
324 uint32_t m
= get_change_mask();
332 key::key(keyboard
& keyb
, const std::string
& _name
, const std::string
& _clazz
,
334 : kbd(keyb
), clazz(_clazz
), name(_name
), type(_type
)
336 exclusive_listener
= NULL
;
337 kbd
.do_register(name
, *this);
340 void key::add_listener(event_listener
& listener
, bool analog
)
343 analog_listeners
.insert(&listener
);
344 digital_listeners
.erase(&listener
);
346 digital_listeners
.insert(&listener
);
347 analog_listeners
.erase(&listener
);
350 void key::remove_listener(event_listener
& listener
) throw()
352 digital_listeners
.erase(&listener
);
353 analog_listeners
.erase(&listener
);
356 void key::set_exclusive(event_listener
* listener
) throw()
358 threads::arlock
u(get_keyboard_lock());
359 exclusive_listener
= listener
;
362 void key::call_listeners(modifier_set
& mods
, event
& event
)
364 kbd
.set_current_key(this);
365 bool digital
= (event
.get_change_mask() & 0xAAAAAAAAUL
) != 0;
366 get_keyboard_lock().lock();
367 if(exclusive_listener
) {
368 get_keyboard_lock().unlock();
369 exclusive_listener
->on_key_event(mods
, *this, event
);
370 kbd
.set_current_key(NULL
);
373 event_listener
* itr
= NULL
;
375 auto itr2
= digital_listeners
.upper_bound(itr
);
376 if(itr2
== digital_listeners
.end())
379 get_keyboard_lock().unlock();
380 itr
->on_key_event(mods
, *this, event
);
381 get_keyboard_lock().lock();
385 auto itr2
= analog_listeners
.upper_bound(itr
);
386 if(itr2
== analog_listeners
.end())
389 get_keyboard_lock().unlock();
390 itr
->on_key_event(mods
, *this, event
);
391 get_keyboard_lock().lock();
393 get_keyboard_lock().unlock();
394 kbd
.set_current_key(NULL
);
397 key_axis
* key::cast_axis() throw()
399 if(type
!= KBD_KEYTYPE_AXIS
)
401 return dynamic_cast<key_axis
*>(this);
404 key_mouse
* key::cast_mouse() throw()
406 if(type
!= KBD_KEYTYPE_MOUSE
)
408 return dynamic_cast<key_mouse
*>(this);
411 key_key::key_key(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
)
412 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_KEY
)
417 key_key::~key_key() throw() {}
419 void key_key::set_state(modifier_set mods
, int32_t _state
) throw()
421 uint32_t change
= _state
? 1 : 0;
423 get_keyboard_lock().lock();
424 if(state
!= _state
) {
429 get_keyboard_lock().unlock();
432 call_listeners(mods
, e
);
436 int32_t key_key::get_state() const throw() { return state
; }
437 int32_t key_key::get_state_digital() const throw() { return state
; }
439 std::vector
<std::string
> key_key::get_subkeys()
441 std::vector
<std::string
> r
;
446 key_hat::key_hat(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
)
447 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_HAT
)
451 key_hat::~key_hat() throw() {}
453 void key_hat::set_state(modifier_set mods
, int32_t _state
) throw()
458 get_keyboard_lock().lock();
459 if(state
!= _state
) {
460 int32_t schange
= state
^ _state
;
462 if(state
& 1) change
|= 1;
463 if(schange
& 1) change
|= 2;
464 if(state
& 2) change
|= 4;
465 if(schange
& 2) change
|= 8;
466 if(state
& 4) change
|= 16;
467 if(schange
& 4) change
|= 32;
468 if(state
& 8) change
|= 64;
469 if(schange
& 8) change
|= 128;
472 get_keyboard_lock().unlock();
475 call_listeners(mods
, e
);
479 int32_t key_hat::get_state() const throw() { return state
; }
480 int32_t key_hat::get_state_digital() const throw() { return state
; }
482 std::vector
<std::string
> key_hat::get_subkeys()
484 std::vector
<std::string
> r
;
492 key_axis::key_axis(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
494 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_AXIS
)
498 last_tolerance
= 0.5;
501 key_axis::~key_axis() throw() {}
503 int32_t key_axis::get_state() const throw()
505 threads::arlock
u(get_keyboard_lock());
509 int32_t key_axis::get_state_digital() const throw()
511 threads::arlock
u(get_keyboard_lock());
512 if(rawstate
<= -32768 * last_tolerance
)
514 if(rawstate
>= 32767 * last_tolerance
)
519 int key_axis::get_mode() const throw()
521 threads::arlock
u(get_keyboard_lock());
525 std::vector
<std::string
> key_axis::get_subkeys()
527 threads::arlock
u(get_keyboard_lock());
528 std::vector
<std::string
> r
;
538 void key_axis::set_state(modifier_set mods
, int32_t _rawstate
) throw()
543 int dold
= 0, dnew
= 0;
544 get_keyboard_lock().lock();
545 if(rawstate
!= _rawstate
) {
547 rawstate
= _rawstate
;
549 if(state
<= -32768 * last_tolerance
)
551 if(state
>= 32767 * last_tolerance
)
556 if((dold
> 0 && dnew
<= 0) || (dold
<= 0 && dnew
> 0))
560 if((dold
< 0 && dnew
>= 0) || (dold
>= 0 && dnew
< 0))
564 get_keyboard_lock().unlock();
566 event_axis
e(state
, change
);
567 call_listeners(mods
, e
);
571 void key_axis::set_mode(int mode
, double tolerance
) throw()
573 threads::arlock
u(get_keyboard_lock());
575 last_tolerance
= tolerance
;
578 key_mouse::key_mouse(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
579 mouse_calibration _cal
)
580 : key(keyb
, name
, clazz
, keytype::KBD_KEYTYPE_MOUSE
)
586 key_mouse::~key_mouse() throw() {}
587 int32_t key_mouse::get_state_digital() const throw() { return 0; }
589 int32_t key_mouse::get_state() const throw()
591 threads::arlock
u(get_keyboard_lock());
592 return cal
.get_calibrated_value(rawstate
);
595 std::vector
<std::string
> key_mouse::get_subkeys()
597 return std::vector
<std::string
>();
600 mouse_calibration
key_mouse::get_calibration() const throw()
602 threads::arlock
u(get_keyboard_lock());
603 mouse_calibration tmp
= cal
;
607 void key_mouse::set_state(modifier_set mods
, int32_t _rawstate
) throw()
611 mouse_calibration _cal
;
612 get_keyboard_lock().lock();
613 if(rawstate
!= _rawstate
) {
614 rawstate
= _rawstate
;
615 state
= cal
.get_calibrated_value(rawstate
);
619 get_keyboard_lock().unlock();
621 event_mouse
e(state
, _cal
);
622 call_listeners(mods
, e
);
626 void key_mouse::set_calibration(mouse_calibration _cal
) throw()
628 get_keyboard_lock().lock();
630 int32_t state
= cal
.get_calibrated_value(rawstate
);
631 get_keyboard_lock().unlock();
632 event_mouse
e(state
, _cal
);
634 call_listeners(mods
, e
);