ManaPlus
keyboardconfig.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2007 Joshua Langley <[email protected]>
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "input/keyboardconfig.h"
25 
26 #include "configuration.h"
27 #ifdef USE_SDL2
28 #include "settings.h"
29 #endif // USE_SDL2
30 
31 #include "input/inputmanager.h"
32 
33 #include "utils/foreach.h"
34 #include "utils/gettext.h"
35 
36 #include "debug.h"
37 
38 extern volatile int tick_time;
39 
41 
43  mEnabled(true),
44  mActiveKeys(nullptr),
45  mActiveKeys2(nullptr),
46  mRepeatTime(0),
47  mKeyToAction(),
48  mKeyToId(),
49  mKeyTimeMap(),
50  mBlockAltTab(true)
51 {
52 }
53 
55 {
56  mEnabled = true;
57  delete [] mActiveKeys2;
58  mActiveKeys2 = new uint8_t[500];
59  mRepeatTime = config.getIntValue("repeateInterval2") / 10;
60  mBlockAltTab = config.getBoolValue("blockAltTab");
61 }
62 
64 {
65  delete [] mActiveKeys2;
66  mActiveKeys2 = nullptr;
67 }
68 
69 InputActionT KeyboardConfig::getKeyIndex(const SDL_Event &event, const int grp)
70 {
71  const int keyValue = getKeyValueFromEvent(event);
72  return inputManager.getKeyIndex(keyValue, grp, InputType::KEYBOARD);
73 }
74 
76 {
77  mActiveKeys = SDL_GetKeyState(nullptr);
78 }
79 
80 std::string KeyboardConfig::getKeyName(const int key)
81 {
82  if (key == -1)
83  return "";
84  if (key > -1)
85  {
86 #ifdef USE_SDL2
87  return SDL_GetScancodeName(
88  static_cast<SDL_Scancode>(key));
89 #else // USE_SDL2
90 
91  return SDL_GetKeyName(static_cast<SDLKey>(key));
92 #endif // USE_SDL2
93  }
94 
95  // TRANSLATORS: long key name, should be short
96  return strprintf(_("key_%d"), CAST_S32(key));
97 }
98 
99 std::string KeyboardConfig::getKeyShortString(const std::string &key)
100 {
101  if (key == "backspace")
102  return "bksp";
103  else if (key == "numlock")
104  return "numlock";
105  else if (key == "caps lock")
106  return "caplock";
107  else if (key == "scroll lock")
108  return "scrlock";
109  else if (key == "right shift")
110  return "rshift";
111  else if (key == "left shift")
112  return "lshift";
113  else if (key == "right ctrl")
114  return "rctrl";
115  else if (key == "left ctrl")
116  return "lctrl";
117  else if (key == "right alt")
118  return "ralt";
119  else if (key == "left alt")
120  return "lalt";
121  else if (key == "right meta")
122  return "rmeta";
123  else if (key == "left meta")
124  return "lmeta";
125  else if (key == "right super")
126  return "rsuper";
127  else if (key == "left super")
128  return "lsuper";
129  else if (key == "print screen")
130  return "print screen";
131  else if (key == "page up")
132  return "pg up";
133  else if (key == "page down")
134  return "pg down";
135 
136  if (key == "unknown key")
137  {
138  // TRANSLATORS: Unknown key short string.
139  // TRANSLATORS: This string must be maximum 5 chars
140  return _("u key");
141  }
142  return key;
143 }
144 
146 {
147  const int i = getKeyValueFromEvent(event);
148 // logger->log("key triggerAction: %d", i);
149  if (i != 0 && i < SDLK_LAST && mKeyToAction.find(i) != mKeyToAction.end())
150  return &mKeyToAction[i];
151  return nullptr;
152 }
153 
155 {
156 // logger->log("key triggerAction: %d", i);
157  if (i != 0 && i < SDLK_LAST && mKeyToAction.find(i) != mKeyToAction.end())
158  return &mKeyToAction[i];
159  return nullptr;
160 }
161 
163 {
164  const int i = getKeyValueFromEvent(event);
165 // logger->log("getActionId: %d", i);
166  if (i != 0 && i < SDLK_LAST && mKeyToId.find(i) != mKeyToId.end())
167  return mKeyToId[i];
168  return InputAction::NO_VALUE;
169 }
170 
172 {
173  if ((mActiveKeys == nullptr) || (mActiveKeys2 == nullptr))
174  return false;
175 
176  const InputFunction &key = inputManager.getKey(index);
177  for (size_t i = 0; i < inputFunctionSize; i ++)
178  {
179  const InputItem &val = key.values[i];
180  if (val.type != InputType::KEYBOARD)
181  continue;
182 
183  const int value = val.value;
184  if (value >= 0)
185  {
186  if (mActiveKeys[value] != 0U)
187  return true;
188  }
189  else if (value < -1 && value > -500)
190  {
191  if (mActiveKeys2[-value] != 0U)
192  return true;
193  }
194  }
195  return false;
196 }
197 
199 {
202 }
203 
204 void KeyboardConfig::handleActivateKey(const SDL_Event &event)
205 {
206  if (mActiveKeys2 == nullptr)
207  return;
208  const int key = getKeyValueFromEvent(event);
209  if (key < -1 && key > -500)
210  mActiveKeys2[-key] = 1;
211  resetRepeat(key);
212 }
213 
215 {
216  if (mActiveKeys2 == nullptr)
217  return;
218  if (key < -1 && key > -500)
219  mActiveKeys2[-key] = 1;
220  resetRepeat(key);
221 }
222 
223 void KeyboardConfig::handleDeActicateKey(const SDL_Event &event)
224 {
225  if (mActiveKeys2 == nullptr)
226  return;
227  const int key = getKeyValueFromEvent(event);
228  if (key < -1 && key > -500)
229  mActiveKeys2[-key] = 0;
230  resetRepeat(key);
231 }
232 
234 {
235  if (mActiveKeys2 == nullptr)
236  return;
237  if (key < -1 && key > -500)
238  mActiveKeys2[-key] = 0;
239  resetRepeat(key);
240 }
241 
242 void KeyboardConfig::handleRepeat(const int time)
243 {
244  BLOCK_START("KeyboardConfig::handleRepeat")
246  {
247  bool repeat(false);
248  const int key = (*it).first;
249  if (key >= 0)
250  {
251  if ((mActiveKeys != nullptr) && (mActiveKeys[key] != 0U))
252  repeat = true;
253  }
254  else if (key < -1 && key > -500)
255  {
256  if ((mActiveKeys2 != nullptr) && (mActiveKeys2[-key] != 0U))
257  repeat = true;
258  }
259  if (repeat)
260  {
261  int &keyTime = (*it).second;
262  if (time > keyTime && abs(time - keyTime)
264  {
265  keyTime = time;
267  }
268  }
269  }
270  BLOCK_END("KeyboardConfig::handleRepeat")
271 }
272 
273 void KeyboardConfig::resetRepeat(const int key)
274 {
275  const KeyTimeMapIter it = mKeyTimeMap.find(key);
276  if (it != mKeyTimeMap.end())
277  (*it).second = tick_time;
278 }
279 
280 #ifdef USE_SDL2
281 
282 bool KeyboardConfig::ignoreKey(const SDL_Event &restrict event)
283 {
284  if (!mBlockAltTab ||
285  mActiveKeys == nullptr)
286  {
287  return false;
288  }
289  const int key = event.key.keysym.scancode;
290  if (key == SDL_SCANCODE_TAB)
291  {
292 #if SDL_VERSION_ATLEAST(2, 0, 5)
293  // SDL_WINDOWEVENT_TAKE_FOCUS not triggered after focus restored
295  return true;
296 #endif // SDL_VERSION_ATLEAST(2, 0, 5)
297 
298  if (mActiveKeys[SDL_SCANCODE_LALT] != 0)
299  return true;
300  }
301  else if (key == SDL_SCANCODE_LALT)
302  {
303  if (mActiveKeys[SDL_SCANCODE_TAB] != 0)
304  return true;
305  }
306  return false;
307 }
308 #endif // USE_SDL2
#define CAST_S32
Definition: cast.h:30
bool getBoolValue(const std::string &key) const
int getIntValue(const std::string &key) const
void updateKeyActionMap(KeyToActionMap &actionMap, KeyToIdMap &idMap, KeyTimeMap &keyTimeMap, const InputTypeT type) const
InputActionT getKeyIndex(const int value, const int grp, const InputTypeT type) const
InputFunction & getKey(InputActionT index) A_CONST
bool triggerAction(const KeysVector *const ptrs)
InputActionT getActionId(const SDL_Event &event)
void refreshActiveKeys()
static std::string getKeyShortString(const std::string &key)
KeyToActionMap mKeyToAction
KeyToIdMap mKeyToId
KeyTimeMap mKeyTimeMap
void resetRepeat(const int key)
static InputActionT getKeyIndex(const SDL_Event &event, const int grp)
void handleActivateKey(const SDL_Event &event)
void handleRepeat(const int time)
KeysVector * getActionVector(const SDL_Event &event)
const uint8_t * mActiveKeys
bool isActionActive(const InputActionT index) const
KeysVector * getActionVectorByKey(const int i)
static std::string getKeyName(const int key)
static int getKeyValueFromEvent(const SDL_Event &event)
uint8_t * mActiveKeys2
void handleDeActicateKey(const SDL_Event &event)
unsigned int mRepeatTime
KeyboardFocusT inputFocused
Definition: settings.h:155
Configuration config
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define _(s)
Definition: gettext.h:35
InputAction ::T InputActionT
Definition: inputaction.h:717
KeyTimeMap::iterator KeyTimeMapIter
Definition: inputevent.h:47
std::vector< InputActionT > KeysVector
Definition: inputevent.h:34
const size_t inputFunctionSize
Definition: inputfunction.h:29
InputManager inputManager
volatile int tick_time
Definition: timer.cpp:53
KeyboardConfig keyboard
#define restrict
Definition: localconsts.h:165
#define nullptr
Definition: localconsts.h:45
@ KEYBOARD
Definition: inputtype.h:38
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
Settings settings
Definition: settings.cpp:32
std::string strprintf(const char *const format,...)
InputItem values[inputFunctionSize]
Definition: inputfunction.h:35
int value
Definition: inputitem.h:45
InputTypeT type
Definition: inputitem.h:44