GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/input/keyboardconfig.cpp Lines: 10 125 8.0 %
Date: 2021-03-17 Branches: 4 132 3.0 %

Line Branch Exec Source
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
40
1
KeyboardConfig keyboard;
41
42
1
KeyboardConfig::KeyboardConfig() :
43
    mEnabled(true),
44
    mActiveKeys(nullptr),
45
    mActiveKeys2(nullptr),
46
    mRepeatTime(0),
47
    mKeyToAction(),
48
    mKeyToId(),
49
    mKeyTimeMap(),
50
4
    mBlockAltTab(true)
51
{
52
}
53
54
void KeyboardConfig::init()
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
63
215
void KeyboardConfig::deinit()
64
{
65
215
    delete [] mActiveKeys2;
66
215
    mActiveKeys2 = nullptr;
67
215
}
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
75
void KeyboardConfig::refreshActiveKeys()
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
145
KeysVector *KeyboardConfig::getActionVector(const SDL_Event &event)
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
154
KeysVector *KeyboardConfig::getActionVectorByKey(const int i)
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
162
InputActionT KeyboardConfig::getActionId(const SDL_Event &event)
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
171
2
bool KeyboardConfig::isActionActive(const InputActionT index) const
172
{
173

2
    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
198
void KeyboardConfig::update()
199
{
200
    inputManager.updateKeyActionMap(mKeyToAction, mKeyToId,
201
        mKeyTimeMap, InputType::KEYBOARD);
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
214
void KeyboardConfig::handleActivateKey(const int key)
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
233
void KeyboardConfig::handleDeActicateKey(const int key)
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")
245
    FOR_EACH (KeyTimeMapIter, it, mKeyTimeMap)
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)
263
                > CAST_S32(mRepeatTime))
264
            {
265
                keyTime = time;
266
                inputManager.triggerAction(getActionVectorByKey(key));
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

3
}
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
294
        if (settings.inputFocused != KeyboardFocus::Focused2)
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