1 | // SuperTux |
2 | // Copyright (C) 2006 Matthias Braun <matze@braunis.de>, |
3 | // 2007-2014 Ingo Ruhnke <grumbel@gmail.com> |
4 | // |
5 | // This program is free software: you can redistribute it and/or modify |
6 | // it under the terms of the GNU General Public License as published by |
7 | // the Free Software Foundation, either version 3 of the License, or |
8 | // (at your option) any later version. |
9 | // |
10 | // This program is distributed in the hope that it will be useful, |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | // GNU General Public License for more details. |
14 | // |
15 | // You should have received a copy of the GNU General Public License |
16 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | |
18 | #include "control/keyboard_manager.hpp" |
19 | |
20 | #include "control/joystick_manager.hpp" |
21 | #include "control/input_manager.hpp" |
22 | #include "control/keyboard_config.hpp" |
23 | #include "gui/menu_manager.hpp" |
24 | #include "supertux/console.hpp" |
25 | |
26 | KeyboardManager::KeyboardManager(InputManager* parent, |
27 | KeyboardConfig& keyboard_config) : |
28 | m_parent(parent), |
29 | m_keyboard_config(keyboard_config), |
30 | m_wait_for_key(), |
31 | m_lock_text_input(false) |
32 | { |
33 | } |
34 | |
35 | void |
36 | KeyboardManager::process_key_event(const SDL_KeyboardEvent& event) |
37 | { |
38 | auto key_mapping = m_keyboard_config.m_keymap.find(event.keysym.sym); |
39 | |
40 | // if console key was pressed: toggle console |
41 | if (key_mapping != m_keyboard_config.m_keymap.end() && |
42 | key_mapping->second == Control::CONSOLE) |
43 | { |
44 | if (event.type == SDL_KEYDOWN) |
45 | { |
46 | // text input gets locked between the console-key being pressed |
47 | // and released to avoid the console-key getting interpreted as |
48 | // text input and echoed to the console |
49 | m_lock_text_input = true; |
50 | |
51 | Console::current()->toggle(); |
52 | } |
53 | else if (event.type == SDL_KEYUP) |
54 | { |
55 | m_lock_text_input = false; |
56 | } |
57 | } |
58 | else if (Console::current()->hasFocus()) |
59 | { |
60 | // if console is open: send key there |
61 | process_console_key_event(event); |
62 | } |
63 | else if (MenuManager::instance().is_active()) |
64 | { |
65 | // if menu mode: send key there |
66 | process_menu_key_event(event); |
67 | } |
68 | else if (key_mapping == m_keyboard_config.m_keymap.end()) |
69 | { |
70 | // default action: update controls |
71 | //log_debug << "Key " << event.key.SDL_Keycode.sym << " is unbound" << std::endl; |
72 | } |
73 | else |
74 | { |
75 | auto control = key_mapping->second; |
76 | bool value = (event.type == SDL_KEYDOWN); |
77 | |
78 | m_parent->get_controller().set_control(control, value); |
79 | |
80 | if (m_keyboard_config.m_jump_with_up_kbd && control == Control::UP) { |
81 | m_parent->get_controller().set_control(Control::JUMP, value); |
82 | } |
83 | } |
84 | } |
85 | |
86 | void |
87 | KeyboardManager::process_text_input_event(const SDL_TextInputEvent& event) |
88 | { |
89 | if (!m_lock_text_input && Console::current()->hasFocus()) { |
90 | for (int i = 0; event.text[i] != '\0'; ++i) |
91 | { |
92 | Console::current()->input(event.text[i]); |
93 | } |
94 | } |
95 | } |
96 | |
97 | void |
98 | KeyboardManager::process_console_key_event(const SDL_KeyboardEvent& event) |
99 | { |
100 | if (event.type != SDL_KEYDOWN) return; |
101 | auto console = Console::current(); |
102 | |
103 | switch (event.keysym.sym) { |
104 | case SDLK_RETURN: |
105 | console->enter(); |
106 | break; |
107 | case SDLK_BACKSPACE: |
108 | console->backspace(); |
109 | break; |
110 | case SDLK_DELETE: |
111 | console->eraseChar(); |
112 | break; |
113 | case SDLK_TAB: |
114 | console->autocomplete(); |
115 | break; |
116 | case SDLK_PAGEUP: |
117 | console->scroll(-1); |
118 | break; |
119 | case SDLK_PAGEDOWN: |
120 | console->scroll(+1); |
121 | break; |
122 | case SDLK_HOME: |
123 | console->move_cursor(-65535); |
124 | break; |
125 | case SDLK_END: |
126 | console->move_cursor(+65535); |
127 | break; |
128 | case SDLK_a: |
129 | if (event.keysym.mod & KMOD_CTRL) { |
130 | console->move_cursor(-65535); |
131 | } |
132 | break; |
133 | case SDLK_e: |
134 | if (event.keysym.mod & KMOD_CTRL) { |
135 | console->move_cursor(+65535); |
136 | } |
137 | break; |
138 | case SDLK_UP: |
139 | console->show_history(-1); |
140 | break; |
141 | case SDLK_DOWN: |
142 | console->show_history(+1); |
143 | break; |
144 | case SDLK_LEFT: |
145 | console->move_cursor(-1); |
146 | break; |
147 | case SDLK_RIGHT: |
148 | console->move_cursor(+1); |
149 | break; |
150 | default: |
151 | break; |
152 | } |
153 | } |
154 | |
155 | void |
156 | KeyboardManager::(const SDL_KeyboardEvent& event) |
157 | { |
158 | // wait for key mode? |
159 | if (m_wait_for_key) |
160 | { |
161 | if (event.type == SDL_KEYUP) |
162 | return; |
163 | |
164 | if (event.keysym.sym != SDLK_ESCAPE && |
165 | event.keysym.sym != SDLK_PAUSE) |
166 | { |
167 | m_keyboard_config.bind_key(event.keysym.sym, *m_wait_for_key); |
168 | } |
169 | m_parent->reset(); |
170 | MenuManager::instance().refresh(); |
171 | m_wait_for_key = boost::none; |
172 | return; |
173 | } |
174 | |
175 | if (m_parent->joystick_manager->wait_for_joystick >= 0) |
176 | { |
177 | if (event.keysym.sym == SDLK_ESCAPE) |
178 | { |
179 | m_parent->reset(); |
180 | MenuManager::instance().refresh(); |
181 | m_parent->joystick_manager->wait_for_joystick = -1; |
182 | } |
183 | return; |
184 | } |
185 | |
186 | Control control; |
187 | /* we use default keys when the menu is open (to avoid problems when |
188 | * redefining keys to invalid settings |
189 | */ |
190 | switch (event.keysym.sym) { |
191 | case SDLK_UP: |
192 | control = Control::UP; |
193 | break; |
194 | case SDLK_DOWN: |
195 | control = Control::DOWN; |
196 | break; |
197 | case SDLK_LEFT: |
198 | control = Control::LEFT; |
199 | break; |
200 | case SDLK_RIGHT: |
201 | control = Control::RIGHT; |
202 | break; |
203 | case SDLK_SPACE: |
204 | control = Control::MENU_SELECT_SPACE; |
205 | break; |
206 | case SDLK_RETURN: |
207 | case SDLK_KP_ENTER: |
208 | control = Control::MENU_SELECT; |
209 | break; |
210 | case SDLK_ESCAPE: |
211 | control = Control::ESCAPE; |
212 | break; |
213 | case SDLK_PAUSE: |
214 | control = Control::START; |
215 | break; |
216 | case SDLK_BACKSPACE: |
217 | control = Control::REMOVE; |
218 | break; |
219 | default: |
220 | if (m_keyboard_config.m_keymap.count(event.keysym.sym) == 0) |
221 | { |
222 | return; |
223 | } |
224 | control = m_keyboard_config.m_keymap[event.keysym.sym]; |
225 | break; |
226 | } |
227 | |
228 | m_parent->get_controller().set_control(control, (event.type == SDL_KEYDOWN)); |
229 | } |
230 | |
231 | void |
232 | KeyboardManager::bind_next_event_to(Control id) |
233 | { |
234 | m_wait_for_key = id; |
235 | } |
236 | |
237 | /* EOF */ |
238 | |