Save bitmaps as PNG
[lsnes.git] / include / library / keyboard.hpp
blob76c1f40db28215591b49d04d4572c5fa503c07c8
1 #ifndef _library__keyboard__hpp__included__
2 #define _library__keyboard__hpp__included__
4 #include "register-queue.hpp"
5 #include "threadtypes.hpp"
6 #include <map>
7 #include <set>
8 #include <string>
9 #include <vector>
10 #include <list>
12 class keyboard_modifier;
13 class keyboard_key;
14 class keyboard_key_axis;
15 class keyboard_key_mouse;
16 class keyboard_event_listener;
18 /**
19 * A group of modifiers and keys.
21 * Instances of this class allow registering, unregistering and looking up modifiers and keys.
23 class keyboard
25 public:
26 /**
27 * Create a new instance.
29 keyboard() throw(std::bad_alloc);
30 /**
31 * Destroy an instance.
33 * The keys and modifiers in instance are not freed.
35 ~keyboard() throw();
36 /**
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);
54 private:
55 keyboard& _kbd;
56 } modifier_proxy;
57 /**
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.
64 struct _key_proxy
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);
75 private:
76 keyboard& _kbd;
77 } key_proxy;
78 /**
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);
86 /**
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();
93 /**
94 * Look up all modifiers.
96 * Returns: The set of modifiers.
98 std::list<keyboard_modifier*> all_modifiers() throw(std::bad_alloc);
99 /**
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.
116 * Returns: 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();
128 * Look up all keys.
130 * Returns: The set of keys.
132 std::list<keyboard_key*> all_keys() throw(std::bad_alloc);
134 * Register a key.
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);
141 * Unregister a key.
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();
151 * Set current key.
153 void set_current_key(keyboard_key* key) throw();
155 * Get current key.
157 keyboard_key* get_current_key() throw();
158 private:
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;
163 mutex_class mutex;
164 keyboard_key* current_key;
168 * A modifier or group of modifiers.
170 class keyboard_modifier
172 public:
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,
183 *this);
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,
196 *this);
199 * Destructor.
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); }
225 private:
226 keyboard& kbd;
227 std::string name;
228 std::string link;
232 * A set of modifier keys.
234 class keyboard_modifier_set
236 public:
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,
263 std::runtime_error);
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);
287 * Stringify.
289 operator std::string() const throw(std::bad_alloc);
291 * Equality check.
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();
298 * Less than check.
300 bool operator<(const keyboard_modifier_set& m) const throw();
301 private:
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);
316 * Type of key.
318 enum keyboard_keytype
321 * A simple key (pressed/released)
323 KBD_KEYTYPE_KEY,
325 * A joystick axis (pair of opposite directions or pressure-sensitive button).
327 KBD_KEYTYPE_AXIS,
329 * A joystick hat (directional control or a dpad).
331 KBD_KEYTYPE_HAT,
333 * A mouse axis.
335 KBD_KEYTYPE_MOUSE
339 * Joystick axis calibration structure.
341 struct keyboard_axis_calibration
344 * Mode: -1 => Disabled, 0 => Pressure-sentive button, 1 => Axis.
346 int mode;
350 * Mouse axis calibration structure.
352 struct keyboard_mouse_calibration
355 * The offset from left of screen area to left of game area.
357 int32_t offset;
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.
367 class keyboard_event
369 public:
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;
379 type = _type;
382 * Destructor.
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; }
396 * Get type of event.
398 keyboard_keytype get_type() const throw() { return type; }
399 private:
400 uint32_t chngmask;
401 keyboard_keytype type;
405 * A simple key event.
407 class keyboard_event_key : public keyboard_event
409 public:
411 * Construct a new key event.
413 * Parameter chngmask: The change mask.
415 keyboard_event_key(uint32_t chngmask);
417 * Destructor.
419 ~keyboard_event_key() throw();
421 * Get analog state.
423 * Returns: 1 if pressed, 0 if released.
425 int32_t get_state() const throw();
426 private:
427 int32_t state;
431 * An axis event.
433 class keyboard_event_axis : public keyboard_event
435 public:
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);
445 * Destructor.
447 ~keyboard_event_axis() throw();
449 * Get analog state.
451 * Returns: Analog position of axis, -32768...32767 (0...32767 for pressure-sensitive buttons).
453 int32_t get_state() const throw();
454 private:
455 int32_t state;
456 keyboard_axis_calibration cal;
460 * A hat event.
462 class keyboard_event_hat : public keyboard_event
464 public:
466 * Construct a new hat event.
468 * Parameter chngmask: The change mask to use.
470 keyboard_event_hat(uint32_t chngmask);
472 * Destructor.
474 ~keyboard_event_hat() throw();
476 * Get analog state.
478 * Returns: Bitmask: 1 => Up, 2 => Right, 4 => Down, 8 => Left.
480 int32_t get_state() const throw();
484 * A mouse event.
486 class keyboard_event_mouse : public keyboard_event
488 public:
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);
497 * Destructor.
499 ~keyboard_event_mouse() throw();
501 * Get analog state.
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; }
510 private:
511 int32_t state;
512 keyboard_mouse_calibration cal;
516 * A keyboard event listener.
518 class keyboard_event_listener
520 public:
522 * Destructor.
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.
538 class keyboard_key
540 public:
542 * Constructor.
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);
552 * Destructor.
554 virtual ~keyboard_key() throw();
556 * Get class.
558 const std::string& get_class() { return clazz; }
560 * Get name.
562 const std::string& get_name() { return name; }
564 * Get keyboard this is on.
566 keyboard& get_keyboard() { return kbd; }
568 * Get key type.
570 keyboard_keytype get_type() const throw() { return type; }
572 * Add listener.
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);
579 * Remove listener.
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();
591 * Set analog state.
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();
617 protected:
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;
629 private:
630 keyboard_key(keyboard_key&);
631 keyboard_key& operator=(keyboard_key&);
632 keyboard& kbd;
633 std::string clazz;
634 std::string name;
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
646 public:
648 * Constructor.
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);
656 * Destructor.
658 ~keyboard_key_key() throw();
660 * Set analog state.
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);
678 private:
679 keyboard_key_key(keyboard_key_key&);
680 keyboard_key_key& operator=(keyboard_key_key&);
681 int32_t state;
685 * A hat on keyboard.
687 class keyboard_key_hat : public keyboard_key
689 public:
691 * Constructor.
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);
699 * Destructor.
701 ~keyboard_key_hat() throw();
703 * Set analog state.
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);
721 private:
722 keyboard_key_hat(keyboard_key_hat&);
723 keyboard_key_hat& operator=(keyboard_key_hat&);
724 int32_t state;
728 * An axis on keyboard.
730 class keyboard_key_axis : public keyboard_key
732 public:
734 * Constructor.
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);
744 * Destructor.
746 ~keyboard_key_axis() throw();
748 * Set analog state.
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);
767 * Get mode.
769 int get_mode() const throw();
771 * Set mode.
773 void set_mode(int mode, double tolerance) throw();
774 private:
775 keyboard_key_axis(keyboard_key_axis&);
776 keyboard_key_axis& operator=(keyboard_key_axis&);
777 int32_t rawstate;
778 int digitalstate;
779 double last_tolerance;
780 int _mode;
784 * A mouse axis on keyboard.
786 class keyboard_key_mouse : public keyboard_key
788 public:
790 * Constructor.
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);
800 * Destructor.
802 ~keyboard_key_mouse() throw();
804 * Set analog state.
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);
823 * Get calibration.
825 keyboard_mouse_calibration get_calibration() const throw();
827 * Set calibration.
829 void set_calibration(keyboard_mouse_calibration cal) throw();
830 private:
831 keyboard_key_mouse(keyboard_key_mouse&);
832 keyboard_key_mouse& operator=(keyboard_key_mouse&);
833 int32_t rawstate;
834 keyboard_mouse_calibration cal;
837 #endif