1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#ifndef PHYSICAL_KEYBOARD_HANDLER_HXX
19#define PHYSICAL_KEYBOARD_HANDLER_HXX
20
21#include <map>
22
23class OSystem;
24class EventHandler;
25
26#include "bspf.hxx"
27#include "Event.hxx"
28#include "EventHandlerConstants.hxx"
29#include "KeyMap.hxx"
30
31/**
32 This class handles all physical keyboard-related operations in Stella.
33
34 It is responsible for getting/setting events associated with keyboard
35 actions.
36
37 Essentially, this class is an extension of the EventHandler class, but
38 handling only keyboard-specific functionality.
39
40 @author Stephen Anthony, Thomas Jentzsch
41*/
42class PhysicalKeyboardHandler
43{
44 public:
45
46 PhysicalKeyboardHandler(OSystem& system, EventHandler& handler);
47
48 void setDefaultMapping(Event::Type type, EventMode mode, bool updateDefaults = false);
49
50 /** define mappings for current controllers */
51 void defineControllerMappings(const Controller::Type type, Controller::Jack port);
52 /** enable mappings for emulation mode */
53 void enableEmulationMappings();
54
55 void eraseMapping(Event::Type event, EventMode mode);
56 void saveMapping();
57
58 string getMappingDesc(Event::Type event, EventMode mode) const {
59 return myKeyMap.getEventMappingDesc(event, getEventMode(event, mode));
60 }
61
62 /** Bind a physical keyboard event to a virtual event/action. */
63 bool addMapping(Event::Type event, EventMode mode, StellaKey key, StellaMod mod);
64
65 /** Handle a physical keyboard event. */
66 void handleEvent(StellaKey key, StellaMod mod, bool pressed, bool repeated);
67
68 Event::Type eventForKey(EventMode mode, StellaKey key, StellaMod mod) const {
69 return myKeyMap.get(mode, key, mod);
70 }
71
72 #ifdef BSPF_UNIX
73 /** See comments on 'myAltKeyCounter' for more information. */
74 uInt8& altKeyCount() { return myAltKeyCounter; }
75 #endif
76
77 /** See comments on KeyMap.myModEnabled for more information. */
78 bool& useModKeys() { return myKeyMap.enableMod(); }
79
80 private:
81
82 // Structure used for action menu items
83 struct EventMapping {
84 Event::Type event;
85 StellaKey key;
86 int mod = KBDM_NONE;
87 };
88 using EventMappingArray = std::vector<EventMapping>;
89
90 void setDefaultKey(EventMapping map, Event::Type event = Event::NoType,
91 EventMode mode = EventMode::kEmulationMode, bool updateDefaults = false);
92
93 /** returns the event's controller mode */
94 EventMode getEventMode(const Event::Type event, const EventMode mode) const;
95 /** Checks event type. */
96 bool isJoystickEvent(const Event::Type event) const;
97 bool isPaddleEvent(const Event::Type event) const;
98 bool isKeypadEvent(const Event::Type event) const;
99 bool isCommonEvent(const Event::Type event) const;
100
101 void enableCommonMappings();
102
103 void enableMappings(const Event::EventSet events, EventMode mode);
104 void enableMapping(const Event::Type event, EventMode mode);
105
106 OSystem& myOSystem;
107 EventHandler& myHandler;
108
109 // Hashmap of key events
110 KeyMap myKeyMap;
111
112 EventMode myLeftMode;
113 EventMode myRightMode;
114
115 #ifdef BSPF_UNIX
116 // Sometimes key combos with the Alt key become 'stuck' after the
117 // window changes state, and we want to ignore that event
118 // For example, press Alt-Tab and then upon re-entering the window,
119 // the app receives 'tab'; obviously the 'tab' shouldn't be happening
120 // So we keep track of the cases that matter (for now, Alt-Tab)
121 // and swallow the event afterwards
122 // Basically, the initial event sets the variable to 1, and upon
123 // returning to the app (ie, receiving EVENT_WINDOW_FOCUS_GAINED),
124 // the count is updated to 2, but only if it was already updated to 1
125 // TODO - This may be a bug in SDL, and might be removed in the future
126 // It only seems to be an issue in Linux
127 uInt8 myAltKeyCounter;
128 #endif
129
130 // Controller menu and common emulation mappings
131 static EventMappingArray DefaultMenuMapping;
132 static EventMappingArray DefaultCommonMapping;
133 // Controller specific mappings
134 static EventMappingArray DefaultJoystickMapping;
135 static EventMappingArray DefaultPaddleMapping;
136 static EventMappingArray DefaultKeypadMapping;
137 static EventMappingArray CompuMateMapping;
138};
139
140#endif
141