GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/input/keyboardconfig.cpp Lines: 10 122 8.2 %
Date: 2017-11-29 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-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "input/keyboardconfig.h"
24
25
#include "configuration.h"
26
#ifdef USE_SDL2
27
#include "settings.h"
28
#endif  // USE_SDL2
29
30
#include "input/inputmanager.h"
31
32
#include "utils/foreach.h"
33
#include "utils/gettext.h"
34
35
#include "debug.h"
36
37
extern volatile int tick_time;
38
39
2
KeyboardConfig keyboard;
40
41
2
KeyboardConfig::KeyboardConfig() :
42
    mEnabled(true),
43
    mActiveKeys(nullptr),
44
    mActiveKeys2(nullptr),
45
    mRepeatTime(0),
46
    mKeyToAction(),
47
    mKeyToId(),
48
    mKeyTimeMap(),
49
8
    mBlockAltTab(true)
50
{
51
}
52
53
void KeyboardConfig::init()
54
{
55
    mEnabled = true;
56
    delete [] mActiveKeys2;
57
    mActiveKeys2 = new uint8_t[500];
58
    mRepeatTime = config.getIntValue("repeateInterval2") / 10;
59
    mBlockAltTab = config.getBoolValue("blockAltTab");
60
}
61
62
384
void KeyboardConfig::deinit()
63
{
64
384
    delete [] mActiveKeys2;
65
384
    mActiveKeys2 = nullptr;
66
384
}
67
68
InputActionT KeyboardConfig::getKeyIndex(const SDL_Event &event, const int grp)
69
{
70
    const int keyValue = getKeyValueFromEvent(event);
71
    return inputManager.getKeyIndex(keyValue, grp, InputType::KEYBOARD);
72
}
73
74
void KeyboardConfig::refreshActiveKeys()
75
{
76
    mActiveKeys = SDL_GetKeyState(nullptr);
77
}
78
79
std::string KeyboardConfig::getKeyName(const int key)
80
{
81
    if (key == -1)
82
        return "";
83
    if (key > -1)
84
    {
85
#ifdef USE_SDL2
86
        return SDL_GetScancodeName(
87
            static_cast<SDL_Scancode>(key));
88
#else  // USE_SDL2
89
90
        return SDL_GetKeyName(static_cast<SDLKey>(key));
91
#endif  // USE_SDL2
92
    }
93
94
    // TRANSLATORS: long key name, should be short
95
    return strprintf(_("key_%d"), CAST_S32(key));
96
}
97
98
std::string KeyboardConfig::getKeyShortString(const std::string &key)
99
{
100
    if (key == "backspace")
101
        return "bksp";
102
    else if (key == "numlock")
103
        return "numlock";
104
    else if (key == "caps lock")
105
        return "caplock";
106
    else if (key == "scroll lock")
107
        return "scrlock";
108
    else if (key == "right shift")
109
        return "rshift";
110
    else if (key == "left shift")
111
        return "lshift";
112
    else if (key == "right ctrl")
113
        return "rctrl";
114
    else if (key == "left ctrl")
115
        return "lctrl";
116
    else if (key == "right alt")
117
        return "ralt";
118
    else if (key == "left alt")
119
        return "lalt";
120
    else if (key == "right meta")
121
        return "rmeta";
122
    else if (key == "left meta")
123
        return "lmeta";
124
    else if (key == "right super")
125
        return "rsuper";
126
    else if (key == "left super")
127
        return "lsuper";
128
    else if (key == "print screen")
129
        return "print screen";
130
    else if (key == "page up")
131
        return "pg up";
132
    else if (key == "page down")
133
        return "pg down";
134
135
    if (key == "unknown key")
136
    {
137
        // TRANSLATORS: Unknown key short string.
138
        // TRANSLATORS: This string must be maximum 5 chars
139
        return _("u key");
140
    }
141
    return key;
142
}
143
144
KeysVector *KeyboardConfig::getActionVector(const SDL_Event &event)
145
{
146
    const int i = getKeyValueFromEvent(event);
147
//    logger->log("key triggerAction: %d", i);
148
    if (i != 0 && i < SDLK_LAST && mKeyToAction.find(i) != mKeyToAction.end())
149
        return &mKeyToAction[i];
150
    return nullptr;
151
}
152
153
KeysVector *KeyboardConfig::getActionVectorByKey(const int i)
154
{
155
//    logger->log("key triggerAction: %d", i);
156
    if (i != 0 && i < SDLK_LAST && mKeyToAction.find(i) != mKeyToAction.end())
157
        return &mKeyToAction[i];
158
    return nullptr;
159
}
160
161
InputActionT KeyboardConfig::getActionId(const SDL_Event &event)
162
{
163
    const int i = getKeyValueFromEvent(event);
164
//    logger->log("getActionId: %d", i);
165
    if (i != 0 && i < SDLK_LAST && mKeyToId.find(i) != mKeyToId.end())
166
        return mKeyToId[i];
167
    return InputAction::NO_VALUE;
168
}
169
170
4
bool KeyboardConfig::isActionActive(const InputActionT index) const
171
{
172

4
    if ((mActiveKeys == nullptr) || (mActiveKeys2 == nullptr))
173
        return false;
174
175
    const InputFunction &key = inputManager.getKey(index);
176
    for (size_t i = 0; i < inputFunctionSize; i ++)
177
    {
178
        const InputItem &val = key.values[i];
179
        if (val.type != InputType::KEYBOARD)
180
            continue;
181
182
        const int value = val.value;
183
        if (value >= 0)
184
        {
185
            if (mActiveKeys[value] != 0u)
186
                return true;
187
        }
188
        else if (value < -1 && value > -500)
189
        {
190
            if (mActiveKeys2[-value] != 0u)
191
                return true;
192
        }
193
    }
194
    return false;
195
}
196
197
void KeyboardConfig::update()
198
{
199
    inputManager.updateKeyActionMap(mKeyToAction, mKeyToId,
200
        mKeyTimeMap, InputType::KEYBOARD);
201
}
202
203
void KeyboardConfig::handleActivateKey(const SDL_Event &event)
204
{
205
    if (mActiveKeys2 == nullptr)
206
        return;
207
    const int key = getKeyValueFromEvent(event);
208
    if (key < -1 && key > -500)
209
        mActiveKeys2[-key] = 1;
210
    resetRepeat(key);
211
}
212
213
void KeyboardConfig::handleActivateKey(const int key)
214
{
215
    if (mActiveKeys2 == nullptr)
216
        return;
217
    if (key < -1 && key > -500)
218
        mActiveKeys2[-key] = 1;
219
    resetRepeat(key);
220
}
221
222
void KeyboardConfig::handleDeActicateKey(const SDL_Event &event)
223
{
224
    if (mActiveKeys2 == nullptr)
225
        return;
226
    const int key = getKeyValueFromEvent(event);
227
    if (key < -1 && key > -500)
228
        mActiveKeys2[-key] = 0;
229
    resetRepeat(key);
230
}
231
232
void KeyboardConfig::handleDeActicateKey(const int key)
233
{
234
    if (mActiveKeys2 == nullptr)
235
        return;
236
    if (key < -1 && key > -500)
237
        mActiveKeys2[-key] = 0;
238
    resetRepeat(key);
239
}
240
241
void KeyboardConfig::handleRepeat(const int time)
242
{
243
    BLOCK_START("KeyboardConfig::handleRepeat")
244
    FOR_EACH (KeyTimeMapIter, it, mKeyTimeMap)
245
    {
246
        bool repeat(false);
247
        const int key = (*it).first;
248
        if (key >= 0)
249
        {
250
            if ((mActiveKeys != nullptr) && (mActiveKeys[key] != 0u))
251
                repeat = true;
252
        }
253
        else if (key < -1 && key > -500)
254
        {
255
            if ((mActiveKeys2 != nullptr) && (mActiveKeys2[-key] != 0u))
256
                repeat = true;
257
        }
258
        if (repeat)
259
        {
260
            int &keyTime = (*it).second;
261
            if (time > keyTime && abs(time - keyTime)
262
                > CAST_S32(mRepeatTime))
263
            {
264
                keyTime = time;
265
                inputManager.triggerAction(getActionVectorByKey(key));
266
            }
267
        }
268
    }
269
    BLOCK_END("KeyboardConfig::handleRepeat")
270
}
271
272
void KeyboardConfig::resetRepeat(const int key)
273
{
274
    const KeyTimeMapIter it = mKeyTimeMap.find(key);
275
    if (it != mKeyTimeMap.end())
276
        (*it).second = tick_time;
277

6
}
278
279
#ifdef USE_SDL2
280
281
bool KeyboardConfig::ignoreKey(const SDL_Event &restrict event)
282
{
283
    if (!mBlockAltTab ||
284
        mActiveKeys == nullptr)
285
    {
286
        return false;
287
    }
288
    const int key = event.key.keysym.scancode;
289
    if (key == SDL_SCANCODE_TAB)
290
    {
291
#if SDL_VERSION_ATLEAST(2, 0, 5)
292
        // SDL_WINDOWEVENT_TAKE_FOCUS not triggered after focus restored
293
        if (settings.inputFocused != KeyboardFocus::Focused2)
294
            return true;
295
#endif  // SDL_VERSION_ATLEAST(2, 0, 5)
296
297
        if (mActiveKeys[SDL_SCANCODE_LALT] != 0)
298
            return true;
299
    }
300
    else if (key == SDL_SCANCODE_LALT)
301
    {
302
        if (mActiveKeys[SDL_SCANCODE_TAB] != 0)
303
            return true;
304
    }
305
    return false;
306
}
307
#endif  // USE_SDL2