1 #ifndef _library__keyboard__hpp__included__
2 #define _library__keyboard__hpp__included__
4 #include "register-queue.hpp"
5 #include "threadtypes.hpp"
12 class keyboard_modifier
;
14 class keyboard_key_axis
;
15 class keyboard_key_mouse
;
16 class keyboard_event_listener
;
19 * A group of modifiers and keys.
21 * Instances of this class allow registering, unregistering and looking up modifiers and keys.
27 * Create a new instance.
29 keyboard() throw(std::bad_alloc
);
31 * Destroy an instance.
33 * The keys and modifiers in instance are not freed.
37 * Registration proxy for modifiers.
39 * This proxy is intended to be used together with register_queue.
41 * It is safe to use this proxy even in global ctor context.
43 struct _modifier_proxy
45 _modifier_proxy(keyboard
& kbd
) : _kbd(kbd
) {}
46 void do_register(const std::string
& name
, keyboard_modifier
& mod
)
48 _kbd
.do_register_modifier(name
, mod
);
50 void do_unregister(const std::string
& name
)
52 _kbd
.do_unregister_modifier(name
);
58 * Registration proxy for keys.
60 * This proxy is intended to be used together with register_queue.
62 * It is safe to use this proxy even in global ctor context.
66 _key_proxy(keyboard
& kbd
) : _kbd(kbd
) {}
67 void do_register(const std::string
& name
, keyboard_key
& key
)
69 _kbd
.do_register_key(name
, key
);
71 void do_unregister(const std::string
& name
)
73 _kbd
.do_unregister_key(name
);
79 * Lookup modifier by name.
81 * Parameter name: The name of the modifier.
82 * Returns: The modifier.
83 * Throws std::runtime_error: No such modifier.
85 keyboard_modifier
& lookup_modifier(const std::string
& name
) throw(std::runtime_error
);
87 * Try lookup modifier by name.
89 * Parameter name: The name of the modifier.
90 * Returns: The modifier, or NULL if not found.
92 keyboard_modifier
* try_lookup_modifier(const std::string
& name
) throw();
94 * Look up all modifiers.
96 * Returns: The set of modifiers.
98 std::list
<keyboard_modifier
*> all_modifiers() throw(std::bad_alloc
);
100 * Register a modifier.
102 * Parameter name: The name of the modifier.
103 * Parameter mod: The modifier.
105 void do_register_modifier(const std::string
& name
, keyboard_modifier
& mod
) throw(std::bad_alloc
);
107 * Unregister a modifier.
109 * Parameter name: The name of the modifier.
111 void do_unregister_modifier(const std::string
& name
) throw();
113 * Lookup key by name.
115 * Parameter name: The name of the key.
117 * Throws std::runtime_error: No such key.
119 keyboard_key
& lookup_key(const std::string
& name
) throw(std::runtime_error
);
121 * Try lookup key by name.
123 * Parameter name: The name of the key.
124 * Returns: The key, or NULL if not found.
126 keyboard_key
* try_lookup_key(const std::string
& name
) throw();
130 * Returns: The set of keys.
132 std::list
<keyboard_key
*> all_keys() throw(std::bad_alloc
);
136 * Parameter name: The name of the key.
137 * Parameter mod: The key.
139 void do_register_key(const std::string
& name
, keyboard_key
& mod
) throw(std::bad_alloc
);
143 * Parameter name: The name of the key.
145 void do_unregister_key(const std::string
& name
) throw();
147 * Set exclusive listener for all keys at once.
149 void set_exclusive(keyboard_event_listener
* listener
) throw();
153 void set_current_key(keyboard_key
* key
) throw();
157 keyboard_key
* get_current_key() throw();
159 keyboard(const keyboard
&);
160 keyboard
& operator=(const keyboard
&);
161 std::map
<std::string
, keyboard_modifier
*> modifiers
;
162 std::map
<std::string
, keyboard_key
*> keys
;
164 keyboard_key
* current_key
;
168 * A modifier or group of modifiers.
170 class keyboard_modifier
174 * Create a (group of) modifiers.
176 * Parameter keyb: The keyboard these will be on.
177 * Parameter _name: The name of the modifier.
179 keyboard_modifier(keyboard
& keyb
, const std::string
& _name
) throw(std::bad_alloc
)
180 : kbd(keyb
), name(_name
)
182 register_queue
<keyboard::_modifier_proxy
, keyboard_modifier
>::do_register(kbd
.modifier_proxy
, name
,
186 * Create a linked modifier in group.
188 * Parameter keyb: The keyboard these will be on.
189 * Parameter _name: The name of the modifier.
190 * Parameter _link: The name of the modifier group this is in.
192 keyboard_modifier(keyboard
& keyb
, const std::string
& _name
, const std::string
& _link
) throw(std::bad_alloc
)
193 : kbd(keyb
), name(_name
), link(_link
)
195 register_queue
<keyboard::_modifier_proxy
, keyboard_modifier
>::do_register(kbd
.modifier_proxy
, name
,
201 ~keyboard_modifier() throw()
203 register_queue
<keyboard::_modifier_proxy
, keyboard_modifier
>::do_unregister(kbd
.modifier_proxy
, name
);
206 * Get associated keyboard.
208 keyboard
& get_keyboard() const throw() { return kbd
; }
210 * Get name of the modifier.
212 const std::string
& get_name() const throw() { return name
; }
214 * Get linked name of the modifier.
216 * Returns: The linked name, or "" if none.
218 const std::string
& get_link_name() const throw() { return link
; }
220 * Get the linked modifier.
222 * Returns: The linked modifier, or NULL if none (or not initialized yet).
224 keyboard_modifier
* get_link() { return kbd
.try_lookup_modifier(link
); }
232 * A set of modifier keys.
234 class keyboard_modifier_set
238 * Add a modifier into the set.
240 * parameter mod: The modifier to add.
241 * parameter really: If true, actually add the key. If false, do nothing.
242 * throws std::bad_alloc: Not enough memory.
244 void add(keyboard_modifier
& mod
, bool really
= true) throw(std::bad_alloc
);
246 * Remove a modifier from the set.
248 * parameter mod: The modifier to remove.
249 * parameter really: If true, actually remove the key. If false, do nothing.
250 * throws std::bad_alloc: Not enough memory.
252 void remove(keyboard_modifier
& mod
, bool really
= true) throw(std::bad_alloc
);
254 * Construct modifier set from comma-separated string.
256 * parameter kbd: The keyboard to take the modifiers from.
257 * parameter modifiers: The modifiers as string
258 * returns: The constructed modifier set.
259 * throws std::bad_alloc: Not enough memory.
260 * throws std::runtime_error: Illegal modifier or wrong syntax.
262 static keyboard_modifier_set
construct(keyboard
& kbd
, const std::string
& modifiers
) throw(std::bad_alloc
,
265 * Check modifier against its mask for validity.
267 * This method checks that:
268 * - for each modifier in set, either that or its linkage group is in mask.
269 * - Both modifier and its linkage group isn't in either set or mask.
271 * parameter mask: The mask to check against.
272 * returns: True if set is valid, false if not.
273 * throws std::bad_alloc: Not enough memory.
275 bool valid(keyboard_modifier_set
& mask
) throw(std::bad_alloc
);
277 * Check if this modifier set triggers the action.
279 * Modifier set triggers another if for each modifier or linkage group in mask:
280 * - Modifier appears in both set and trigger.
281 * - At least one modifier with this linkage group appears in both set and trigger.
282 * - Modifiers with this linkage group do not appear in either set nor trigger.
285 bool triggers(const keyboard_modifier_set
& trigger
, const keyboard_modifier_set
& mask
) throw(std::bad_alloc
);
289 operator std::string() const throw(std::bad_alloc
);
293 * parameter m: Another set.
294 * returns: True if two sets are equal, false if not.
296 bool operator==(const keyboard_modifier_set
& m
) const throw();
300 bool operator<(const keyboard_modifier_set
& m
) const throw();
302 friend std::ostream
& operator<<(std::ostream
& os
, const keyboard_modifier_set
& m
);
303 std::set
<keyboard_modifier
*> set
;
307 * Debugging print. Prints textual version of set into stream.
309 * parameter os: The stream to print to.
310 * parameter m: The modifier set to print.
311 * returns: reference to os.
313 std::ostream
& operator<<(std::ostream
& os
, const keyboard_modifier_set
& m
);
318 enum keyboard_keytype
321 * A simple key (pressed/released)
325 * A joystick axis (pair of opposite directions or pressure-sensitive button).
329 * A joystick hat (directional control or a dpad).
339 * Joystick axis calibration structure.
341 struct keyboard_axis_calibration
344 * Mode: -1 => Disabled, 0 => Pressure-sentive button, 1 => Axis.
350 * Mouse axis calibration structure.
352 struct keyboard_mouse_calibration
355 * The offset from left of screen area to left of game area.
359 * Translate from screen coordinate to game coordinate.
361 int32_t get_calibrated_value(int32_t x
) const throw();
365 * Superclass of key event data.
371 * Create a new event.
373 * Parameter _chngmask: The change mask.
374 * Parameter _type: Type of the event.
376 keyboard_event(uint32_t _chngmask
, keyboard_keytype _type
) throw()
378 chngmask
= _chngmask
;
384 virtual ~keyboard_event() throw();
386 * Get analog state. The format is dependent on key type.
388 virtual int32_t get_state() const throw() = 0;
390 * Get key change mask.
392 * Returns: A bitmask. Bit 2*n is the state of subkey n. Bit 2*n+1 is set if subkey changed state, else clear.
394 uint32_t get_change_mask() const throw() { return chngmask
; }
398 keyboard_keytype
get_type() const throw() { return type
; }
401 keyboard_keytype type
;
405 * A simple key event.
407 class keyboard_event_key
: public keyboard_event
411 * Construct a new key event.
413 * Parameter chngmask: The change mask.
415 keyboard_event_key(uint32_t chngmask
);
419 ~keyboard_event_key() throw();
423 * Returns: 1 if pressed, 0 if released.
425 int32_t get_state() const throw();
433 class keyboard_event_axis
: public keyboard_event
437 * Construct a new axis event.
439 * Parameter state: The analog state.
440 * Parameter chngmask: The change mask.
441 * Parameter cal: The calibration structure.
443 keyboard_event_axis(int32_t state
, uint32_t chngmask
);
447 ~keyboard_event_axis() throw();
451 * Returns: Analog position of axis, -32768...32767 (0...32767 for pressure-sensitive buttons).
453 int32_t get_state() const throw();
456 keyboard_axis_calibration cal
;
462 class keyboard_event_hat
: public keyboard_event
466 * Construct a new hat event.
468 * Parameter chngmask: The change mask to use.
470 keyboard_event_hat(uint32_t chngmask
);
474 ~keyboard_event_hat() throw();
478 * Returns: Bitmask: 1 => Up, 2 => Right, 4 => Down, 8 => Left.
480 int32_t get_state() const throw();
486 class keyboard_event_mouse
: public keyboard_event
490 * Construct a new mouse event.
492 * Parameter state: The game-relative position to use.
493 * Parameter cal: The calibration structure.
495 keyboard_event_mouse(int32_t state
, const keyboard_mouse_calibration
& cal
);
499 ~keyboard_event_mouse() throw();
503 * Returns: Position of mouse relative to game area (with right/down positive).
505 int32_t get_state() const throw();
507 * Get calibration data.
509 keyboard_mouse_calibration
get_calibration() { return cal
; }
512 keyboard_mouse_calibration cal
;
516 * A keyboard event listener.
518 class keyboard_event_listener
524 virtual ~keyboard_event_listener() throw();
526 * Receive a key event.
528 * Parameter mods: Modifiers currently active.
529 * Parameter key: The key this event is about.
530 * Parameter event: The event.
532 virtual void on_key_event(keyboard_modifier_set
& mods
, keyboard_key
& key
, keyboard_event
& event
) = 0;
536 * A (compound) key on keyboard.
544 * Parameter keyb: The keyboard this is on.
545 * Parameter name: The base name of the key.
546 * Parameter clazz: The class of the key.
547 * Parameter type: The type of key.
549 keyboard_key(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
, keyboard_keytype type
)
550 throw(std::bad_alloc
);
554 virtual ~keyboard_key() throw();
558 const std::string
& get_class() { return clazz
; }
562 const std::string
& get_name() { return name
; }
564 * Get keyboard this is on.
566 keyboard
& get_keyboard() { return kbd
; }
570 keyboard_keytype
get_type() const throw() { return type
; }
574 * Parameter listener: The listener.
575 * Parameter analog: If true, also pass analog events.
577 void add_listener(keyboard_event_listener
& listener
, bool analog
) throw(std::bad_alloc
);
581 * Parameter listener: The listener.
583 void remove_listener(keyboard_event_listener
& listener
) throw();
585 * Set exclusive listener.
587 * Parameter listener: The listener. NULL to ungrab key.
589 void set_exclusive(keyboard_event_listener
* listener
) throw();
593 * Parameter mods: The current modifiers.
594 * Parameter state: The new state. The format is dependent on key type.
596 virtual void set_state(keyboard_modifier_set mods
, int32_t state
) throw() = 0;
598 * Get analog state. The format is dependent on key type.
600 virtual int32_t get_state() const throw() = 0;
602 * Get digital state. The format is dependent on key type.
604 virtual int32_t get_state_digital() const throw() = 0;
606 * Get the subkey suffixes.
608 virtual std::vector
<std::string
> get_subkeys() throw(std::bad_alloc
) = 0;
610 * Dynamic cast to axis type.
612 keyboard_key_axis
* cast_axis() throw();
614 * Dynamic cast to mouse type.
616 keyboard_key_mouse
* cast_mouse() throw();
619 * Call all event listeners on this key.
621 * Parameter mods: The current modifiers.
622 * Parameter event: The event to pass.
624 void call_listeners(keyboard_modifier_set
& mods
, keyboard_event
& event
);
626 * Mutex protecting state.
628 mutable mutex_class mutex
;
630 keyboard_key(keyboard_key
&);
631 keyboard_key
& operator=(keyboard_key
&);
635 std::set
<keyboard_event_listener
*> digital_listeners
;
636 std::set
<keyboard_event_listener
*> analog_listeners
;
637 keyboard_event_listener
* exclusive_listener
;
638 keyboard_keytype type
;
642 * A simple key on keyboard.
644 class keyboard_key_key
: public keyboard_key
650 * Parameter keyb: The keyboard this is on.
651 * Parameter name: The base name of the key.
652 * Parameter clazz: The class of the key.
654 keyboard_key_key(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
) throw(std::bad_alloc
);
658 ~keyboard_key_key() throw();
662 * Parameter mods: The current modifiers.
663 * Parameter state: The new state. 1 for pressed, 0 for released.
665 void set_state(keyboard_modifier_set mods
, int32_t state
) throw();
667 * Get analog state. 1 for pressed, 0 for released.
669 int32_t get_state() const throw();
671 * Get digital state. 1 for pressed, 0 for released.
673 int32_t get_state_digital() const throw();
675 * Get the subkey suffixes.
677 std::vector
<std::string
> get_subkeys() throw(std::bad_alloc
);
679 keyboard_key_key(keyboard_key_key
&);
680 keyboard_key_key
& operator=(keyboard_key_key
&);
687 class keyboard_key_hat
: public keyboard_key
693 * Parameter keyb: The keyboard this is on.
694 * Parameter name: The base name of the key.
695 * Parameter clazz: The class of the key.
697 keyboard_key_hat(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
) throw(std::bad_alloc
);
701 ~keyboard_key_hat() throw();
705 * Parameter mods: The current modifiers.
706 * Parameter state: The new state. 1 => up, 2 => right, 4 => down, 8 => left.
708 void set_state(keyboard_modifier_set mods
, int32_t state
) throw();
710 * Get analog state. 1 => up, 2 => right, 4 => down, 8 => left.
712 int32_t get_state() const throw();
714 * Get digital state. 1 => up, 2 => right, 4 => down, 8 => left.
716 int32_t get_state_digital() const throw();
718 * Get the subkey suffixes.
720 std::vector
<std::string
> get_subkeys() throw(std::bad_alloc
);
722 keyboard_key_hat(keyboard_key_hat
&);
723 keyboard_key_hat
& operator=(keyboard_key_hat
&);
728 * An axis on keyboard.
730 class keyboard_key_axis
: public keyboard_key
736 * Parameter keyb: The keyboard this is on.
737 * Parameter name: The base name of the key.
738 * Parameter clazz: The class of the key.
739 * Parameter mode: Initial mode: -1 => disabled, 0 => axis, 1 => pressure
741 keyboard_key_axis(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
, int mode
)
742 throw(std::bad_alloc
);
746 ~keyboard_key_axis() throw();
750 * Parameter mods: The current modifiers.
751 * Parameter state: The new state. Uncalibrated analog position.
753 void set_state(keyboard_modifier_set mods
, int32_t state
) throw();
755 * Get analog state. -32767...32767 for axes, 0...32767 for pressure-sensitive buttons.
757 int32_t get_state() const throw();
759 * Get digital state. -1 => left, 0 => center/unpressed, 1 => Right/pressed.
761 int32_t get_state_digital() const throw();
763 * Get the subkey suffixes.
765 std::vector
<std::string
> get_subkeys() throw(std::bad_alloc
);
769 int get_mode() const throw();
773 void set_mode(int mode
, double tolerance
) throw();
775 keyboard_key_axis(keyboard_key_axis
&);
776 keyboard_key_axis
& operator=(keyboard_key_axis
&);
779 double last_tolerance
;
784 * A mouse axis on keyboard.
786 class keyboard_key_mouse
: public keyboard_key
792 * Parameter keyb: The keyboard this is on.
793 * Parameter name: The base name of the key.
794 * Parameter clazz: The class of the key.
795 * Parameter cal: Initial calibration.
797 keyboard_key_mouse(keyboard
& keyb
, const std::string
& name
, const std::string
& clazz
,
798 keyboard_mouse_calibration cal
) throw(std::bad_alloc
);
802 ~keyboard_key_mouse() throw();
806 * Parameter mods: The current modifiers.
807 * Parameter state: The new state. Screen-relative analog position.
809 void set_state(keyboard_modifier_set mods
, int32_t state
) throw();
811 * Get analog state. Game-relative analog position.
813 int32_t get_state() const throw();
815 * Get digital state. Always returns 0.
817 int32_t get_state_digital() const throw();
819 * Get the subkey suffixes. Returns empty list.
821 std::vector
<std::string
> get_subkeys() throw(std::bad_alloc
);
825 keyboard_mouse_calibration
get_calibration() const throw();
829 void set_calibration(keyboard_mouse_calibration cal
) throw();
831 keyboard_key_mouse(keyboard_key_mouse
&);
832 keyboard_key_mouse
& operator=(keyboard_key_mouse
&);
834 keyboard_mouse_calibration cal
;