2021-01-15 09:05:10 +01:00
|
|
|
/* Copyright (C) 2021 Wildfire Games.
|
2009-04-18 19:00:33 +02:00
|
|
|
* This file is part of 0 A.D.
|
|
|
|
*
|
|
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2004-07-21 18:51:21 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
#include "Hotkey.h"
|
2007-05-02 14:07:08 +02:00
|
|
|
|
2014-11-17 02:03:59 +01:00
|
|
|
#include <boost/tokenizer.hpp>
|
|
|
|
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
#include "lib/external_libraries/libsdl.h"
|
2015-07-29 03:07:23 +02:00
|
|
|
#include "ps/CConsole.h"
|
|
|
|
#include "ps/CLogger.h"
|
|
|
|
#include "ps/CStr.h"
|
|
|
|
#include "ps/ConfigDB.h"
|
2005-10-17 01:16:08 +02:00
|
|
|
#include "ps/Globals.h"
|
2015-07-29 03:07:23 +02:00
|
|
|
#include "ps/KeyName.h"
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
static bool unified[UNIFIED_LAST - UNIFIED_SHIFT];
|
2005-10-17 01:16:08 +02:00
|
|
|
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
std::unordered_map<int, KeyMapping> g_HotkeyMap;
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2021-01-18 11:58:16 +01:00
|
|
|
namespace {
|
2021-03-31 17:50:25 +02:00
|
|
|
std::unordered_map<std::string, bool> g_HotkeyStatus;
|
|
|
|
|
|
|
|
struct PressedHotkey
|
|
|
|
{
|
|
|
|
PressedHotkey(const SHotkeyMapping* m, bool t) : mapping(m), retriggered(t) {};
|
|
|
|
// NB: this points to one of g_HotkeyMap's mappings. It works because that std::unordered_map is stable once constructed.
|
|
|
|
const SHotkeyMapping* mapping;
|
|
|
|
// Whether the hotkey was triggered by a key release (silences "press" and "up" events).
|
|
|
|
bool retriggered;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ReleasedHotkey
|
|
|
|
{
|
|
|
|
ReleasedHotkey(const char* n, bool t) : name(n), wasRetriggered(t) {};
|
|
|
|
const char* name;
|
|
|
|
bool wasRetriggered;
|
|
|
|
};
|
|
|
|
|
2021-04-02 16:18:20 +02:00
|
|
|
// 'In-flight' state used because the hotkey triggering process is split in two phase.
|
|
|
|
// These hotkeys may still be stopped if the event responsible for triggering them is handled
|
|
|
|
// before it can be used to generate the hotkeys.
|
|
|
|
std::vector<PressedHotkey> newPressedHotkeys;
|
|
|
|
// Stores the 'specificity' of the newly pressed hotkeys.
|
|
|
|
size_t closestMapMatch = 0;
|
|
|
|
// This is merely used to ensure consistency in EventWillFireHotkey.
|
|
|
|
const SDL_Event_* currentEvent;
|
|
|
|
|
2021-03-31 17:50:25 +02:00
|
|
|
// List of currently pressed hotkeys. This is used to quickly reset hotkeys.
|
|
|
|
// This is an unsorted vector because there will generally be very few elements,
|
|
|
|
// so it's presumably faster than std::set.
|
|
|
|
std::vector<PressedHotkey> pressedHotkeys;
|
|
|
|
|
|
|
|
// List of active keys relevant for hotkeys.
|
|
|
|
std::vector<SDL_Scancode_> activeScancodes;
|
2021-01-18 11:58:16 +01:00
|
|
|
}
|
|
|
|
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
static_assert(std::is_integral<std::underlying_type<SDL_Scancode>::type>::value, "SDL_Scancode is not an integral enum.");
|
|
|
|
static_assert(SDL_USEREVENT_ == SDL_USEREVENT, "SDL_USEREVENT_ is not the same type as the real SDL_USEREVENT");
|
2021-01-15 09:05:10 +01:00
|
|
|
static_assert(UNUSED_HOTKEY_CODE == SDL_SCANCODE_UNKNOWN);
|
2004-07-22 18:18:12 +02:00
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
// Look up each key binding in the config file and set the mappings for
|
|
|
|
// all key combinations that trigger it.
|
2021-01-18 11:58:16 +01:00
|
|
|
static void LoadConfigBindings(CConfigDB& configDB)
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2021-01-18 11:58:16 +01:00
|
|
|
for (const std::pair<const CStr, CConfigValueSet>& configPair : configDB.GetValuesWithPrefix(CFG_COMMAND, "hotkey."))
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
2015-07-29 03:07:23 +02:00
|
|
|
std::string hotkeyName = configPair.first.substr(7); // strip the "hotkey." prefix
|
2021-01-15 09:05:10 +01:00
|
|
|
|
2021-01-18 11:58:16 +01:00
|
|
|
// "unused" is kept or the A23->24 migration, this can likely be removed in A25.
|
|
|
|
if (configPair.second.empty() || (configPair.second.size() == 1 && configPair.second.front() == "unused"))
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
2021-01-15 09:05:10 +01:00
|
|
|
// Unused hotkeys must still be registered in the map to appear in the hotkey editor.
|
|
|
|
SHotkeyMapping unusedCode;
|
|
|
|
unusedCode.name = hotkeyName;
|
2021-01-18 11:58:16 +01:00
|
|
|
unusedCode.primary = SKey{ UNUSED_HOTKEY_CODE };
|
2021-01-15 09:05:10 +01:00
|
|
|
g_HotkeyMap[UNUSED_HOTKEY_CODE].push_back(unusedCode);
|
|
|
|
continue;
|
|
|
|
}
|
2016-07-27 14:29:31 +02:00
|
|
|
|
2021-01-15 09:05:10 +01:00
|
|
|
for (const CStr& hotkey : configPair.second)
|
|
|
|
{
|
2014-11-17 02:03:59 +01:00
|
|
|
std::vector<SKey> keyCombination;
|
|
|
|
|
|
|
|
// Iterate through multiple-key bindings (e.g. Ctrl+I)
|
|
|
|
boost::char_separator<char> sep("+");
|
|
|
|
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
|
|
|
tokenizer tok(hotkey, sep);
|
|
|
|
for (tokenizer::iterator it = tok.begin(); it != tok.end(); ++it)
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2014-11-17 02:03:59 +01:00
|
|
|
// Attempt decode as key name
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
SDL_Scancode scancode = FindScancode(it->c_str());
|
|
|
|
if (!scancode)
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
2015-01-22 21:36:24 +01:00
|
|
|
LOGWARNING("Hotkey mapping used invalid key '%s'", hotkey.c_str());
|
2014-11-17 02:03:59 +01:00
|
|
|
continue;
|
2004-07-22 18:18:12 +02:00
|
|
|
}
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2021-01-16 16:24:58 +01:00
|
|
|
SKey key = { scancode };
|
2014-11-17 02:03:59 +01:00
|
|
|
keyCombination.push_back(key);
|
|
|
|
}
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2014-11-17 02:03:59 +01:00
|
|
|
std::vector<SKey>::iterator itKey, itKey2;
|
|
|
|
for (itKey = keyCombination.begin(); itKey != keyCombination.end(); ++itKey)
|
|
|
|
{
|
|
|
|
SHotkeyMapping bindCode;
|
2010-10-23 04:37:00 +02:00
|
|
|
|
2014-11-17 02:03:59 +01:00
|
|
|
bindCode.name = hotkeyName;
|
2021-01-18 11:58:16 +01:00
|
|
|
bindCode.primary = SKey{ itKey->code };
|
2010-10-23 04:37:00 +02:00
|
|
|
|
2014-11-17 02:03:59 +01:00
|
|
|
for (itKey2 = keyCombination.begin(); itKey2 != keyCombination.end(); ++itKey2)
|
|
|
|
if (itKey != itKey2) // Push any auxiliary keys
|
|
|
|
bindCode.requires.push_back(*itKey2);
|
2004-08-03 01:14:54 +02:00
|
|
|
|
2014-11-17 02:03:59 +01:00
|
|
|
g_HotkeyMap[itKey->code].push_back(bindCode);
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
|
|
|
}
|
2004-07-22 18:18:12 +02:00
|
|
|
}
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2010-10-23 04:37:00 +02:00
|
|
|
|
2021-01-18 11:58:16 +01:00
|
|
|
void LoadHotkeys(CConfigDB& configDB)
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
2021-01-18 11:58:16 +01:00
|
|
|
pressedHotkeys.clear();
|
|
|
|
LoadConfigBindings(configDB);
|
2004-07-22 18:18:12 +02:00
|
|
|
}
|
|
|
|
|
2014-09-15 03:27:06 +02:00
|
|
|
void UnloadHotkeys()
|
|
|
|
{
|
2021-01-18 11:58:16 +01:00
|
|
|
pressedHotkeys.clear();
|
2014-09-15 03:27:06 +02:00
|
|
|
g_HotkeyMap.clear();
|
|
|
|
g_HotkeyStatus.clear();
|
|
|
|
}
|
|
|
|
|
2021-01-16 16:24:58 +01:00
|
|
|
bool isPressed(const SKey& key)
|
2014-08-04 18:48:54 +02:00
|
|
|
{
|
|
|
|
// Normal keycodes are below EXTRA_KEYS_BASE
|
2021-01-16 16:24:58 +01:00
|
|
|
if ((int)key.code < EXTRA_KEYS_BASE)
|
|
|
|
return g_scancodes[key.code];
|
2014-08-04 18:48:54 +02:00
|
|
|
// Mouse 'keycodes' are after the modifier keys
|
2021-01-16 16:24:58 +01:00
|
|
|
else if ((int)key.code < MOUSE_LAST && (int)key.code > MOUSE_BASE)
|
|
|
|
return g_mouse_buttons[key.code - MOUSE_BASE];
|
2014-08-04 18:48:54 +02:00
|
|
|
// Modifier keycodes are between the normal keys and the mouse 'keys'
|
2021-01-16 16:24:58 +01:00
|
|
|
else if ((int)key.code < UNIFIED_LAST && (int)key.code > SDL_NUM_SCANCODES)
|
|
|
|
return unified[key.code - UNIFIED_SHIFT];
|
2021-01-16 18:16:02 +01:00
|
|
|
// This codepath shouldn't be taken, but not having it triggers warnings.
|
|
|
|
else
|
|
|
|
return false;
|
2014-08-04 18:48:54 +02:00
|
|
|
}
|
|
|
|
|
2019-09-15 14:16:28 +02:00
|
|
|
InReaction HotkeyStateChange(const SDL_Event_* ev)
|
|
|
|
{
|
2021-03-31 17:50:25 +02:00
|
|
|
if (ev->ev.type == SDL_HOTKEYPRESS || ev->ev.type == SDL_HOTKEYPRESS_SILENT)
|
2019-09-15 14:16:28 +02:00
|
|
|
g_HotkeyStatus[static_cast<const char*>(ev->ev.user.data1)] = true;
|
2021-03-31 17:50:25 +02:00
|
|
|
else if (ev->ev.type == SDL_HOTKEYUP || ev->ev.type == SDL_HOTKEYUP_SILENT)
|
2019-09-15 14:16:28 +02:00
|
|
|
g_HotkeyStatus[static_cast<const char*>(ev->ev.user.data1)] = false;
|
|
|
|
return IN_PASS;
|
|
|
|
}
|
|
|
|
|
2021-04-02 16:18:20 +02:00
|
|
|
InReaction HotkeyInputPrepHandler(const SDL_Event_* ev)
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
int scancode = SDL_SCANCODE_UNKNOWN;
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2021-04-02 16:18:20 +02:00
|
|
|
// Restore default state.
|
|
|
|
newPressedHotkeys.clear();
|
|
|
|
currentEvent = nullptr;
|
|
|
|
|
2015-07-29 03:07:23 +02:00
|
|
|
switch(ev->ev.type)
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
|
|
|
case SDL_KEYDOWN:
|
|
|
|
case SDL_KEYUP:
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
scancode = ev->ev.key.keysym.scancode;
|
2004-07-21 18:51:21 +02:00
|
|
|
break;
|
2012-02-06 23:47:35 +01:00
|
|
|
|
2004-07-21 18:51:21 +02:00
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
|
|
case SDL_MOUSEBUTTONUP:
|
2014-09-20 14:12:35 +02:00
|
|
|
// Mousewheel events are no longer buttons, but we want to maintain the order
|
|
|
|
// expected by g_mouse_buttons for compatibility
|
|
|
|
if (ev->ev.button.button >= SDL_BUTTON_X1)
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
scancode = MOUSE_BASE + (int)ev->ev.button.button + 2;
|
2014-09-20 14:12:35 +02:00
|
|
|
else
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
scancode = MOUSE_BASE + (int)ev->ev.button.button;
|
2014-08-04 03:06:36 +02:00
|
|
|
break;
|
2014-09-20 14:12:35 +02:00
|
|
|
|
2012-02-06 23:47:35 +01:00
|
|
|
case SDL_MOUSEWHEEL:
|
2013-04-05 04:39:30 +02:00
|
|
|
if (ev->ev.wheel.y > 0)
|
2012-02-06 23:47:35 +01:00
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
scancode = MOUSE_WHEELUP;
|
2012-02-06 23:47:35 +01:00
|
|
|
break;
|
|
|
|
}
|
2013-04-05 04:39:30 +02:00
|
|
|
else if (ev->ev.wheel.y < 0)
|
2012-02-06 23:47:35 +01:00
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
scancode = MOUSE_WHEELDOWN;
|
2012-02-06 23:47:35 +01:00
|
|
|
break;
|
|
|
|
}
|
2014-09-20 14:12:35 +02:00
|
|
|
else if (ev->ev.wheel.x > 0)
|
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
scancode = MOUSE_X2;
|
2014-09-20 14:12:35 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (ev->ev.wheel.x < 0)
|
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
scancode = MOUSE_X1;
|
2014-09-20 14:12:35 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-02-06 23:47:35 +01:00
|
|
|
return IN_PASS;
|
|
|
|
|
Improve correctness of hotkeys at low framerates.
SDL queues up all the input events received in a frame. When the hotkey
system saw a key up/down event, it immediately updated its
HotkeyIsPressed state and then pushed a hotkey event onto the end of the
queue.
If the initial queue was e.g. [key-down shift, key-press Z, key-up
shift], the hotkey event triggered by Z would be processed after the
key-up shift had updated the HotkeyIsPressed state, so the handler of
the Z hotkey would not think the shift hotkey was pressed.
If the initial queue was e.g. [key-press Z, mouse-click], the hotkey
triggered by Z would be processed after the mouse-click event, so it
could apply to the wrong building selection.
Fix by pushing the hotkey events onto a special queue that gets
processed before any subsequent SDL input events.
Also update the HotkeyIsPressed status when the HOTKEYDOWN/HOTKEYUP
events are processed, not when they are generated, to guarantee they are
consistent with the DOWN/UP events.
Fixes #1869.
This was SVN commit r14057.
2013-10-30 02:38:32 +01:00
|
|
|
|
2004-07-21 18:51:21 +02:00
|
|
|
default:
|
2007-05-26 20:38:38 +02:00
|
|
|
return IN_PASS;
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
|
|
|
|
2004-08-03 01:14:54 +02:00
|
|
|
// Somewhat hackish:
|
|
|
|
// Create phantom 'unified-modifier' events when left- or right- modifier keys are pressed
|
|
|
|
// Just send them to this handler; don't let the imaginary event codes leak back to real SDL.
|
|
|
|
|
2006-08-26 23:52:18 +02:00
|
|
|
SDL_Event_ phantom;
|
2015-07-29 03:07:23 +02:00
|
|
|
phantom.ev.type = ((ev->ev.type == SDL_KEYDOWN) || (ev->ev.type == SDL_MOUSEBUTTONDOWN)) ? SDL_KEYDOWN : SDL_KEYUP;
|
2020-05-26 23:47:03 +02:00
|
|
|
if (phantom.ev.type == SDL_KEYDOWN)
|
|
|
|
phantom.ev.key.repeat = ev->ev.type == SDL_KEYDOWN ? ev->ev.key.repeat : 0;
|
|
|
|
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
if (scancode == SDL_SCANCODE_LSHIFT || scancode == SDL_SCANCODE_RSHIFT)
|
2004-08-03 01:14:54 +02:00
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
phantom.ev.key.keysym.scancode = static_cast<SDL_Scancode>(UNIFIED_SHIFT);
|
2015-07-29 03:07:23 +02:00
|
|
|
unified[0] = (phantom.ev.type == SDL_KEYDOWN);
|
2021-04-02 16:18:20 +02:00
|
|
|
return HotkeyInputPrepHandler(&phantom);
|
2004-08-03 01:14:54 +02:00
|
|
|
}
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
else if (scancode == SDL_SCANCODE_LCTRL || scancode == SDL_SCANCODE_RCTRL)
|
2004-08-03 01:14:54 +02:00
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
phantom.ev.key.keysym.scancode = static_cast<SDL_Scancode>(UNIFIED_CTRL);
|
2015-07-29 03:07:23 +02:00
|
|
|
unified[1] = (phantom.ev.type == SDL_KEYDOWN);
|
2021-04-02 16:18:20 +02:00
|
|
|
return HotkeyInputPrepHandler(&phantom);
|
2004-08-03 01:14:54 +02:00
|
|
|
}
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
else if (scancode == SDL_SCANCODE_LALT || scancode == SDL_SCANCODE_RALT)
|
2004-08-03 01:14:54 +02:00
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
phantom.ev.key.keysym.scancode = static_cast<SDL_Scancode>(UNIFIED_ALT);
|
2015-07-29 03:07:23 +02:00
|
|
|
unified[2] = (phantom.ev.type == SDL_KEYDOWN);
|
2021-04-02 16:18:20 +02:00
|
|
|
return HotkeyInputPrepHandler(&phantom);
|
2004-08-03 01:14:54 +02:00
|
|
|
}
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
else if (scancode == SDL_SCANCODE_LGUI || scancode == SDL_SCANCODE_RGUI)
|
2004-08-03 01:14:54 +02:00
|
|
|
{
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
phantom.ev.key.keysym.scancode = static_cast<SDL_Scancode>(UNIFIED_SUPER);
|
2015-07-29 03:07:23 +02:00
|
|
|
unified[3] = (phantom.ev.type == SDL_KEYDOWN);
|
2021-04-02 16:18:20 +02:00
|
|
|
return HotkeyInputPrepHandler(&phantom);
|
2004-08-03 01:14:54 +02:00
|
|
|
}
|
|
|
|
|
2021-04-01 16:51:22 +02:00
|
|
|
// Check whether we have any hotkeys registered that include this scancode.
|
Let players remap hotkeys in-game, fix default hotkeys being qwerty-specific.
- Provide a "Hotkey" screen to let players remap hotkeys in-game using a
convenient setup.
- Make all .cfg hotkeys refer to scancodes (i.e. position on the
keyboard), so that default hotkeys now translate correctly for AZERTY,
QWERTZ and other layouts.
- 'BackSpace' is now an alias for 'Delete', and works for killing units.
This fixes #1917, as macs don't have a proper delete key and would need
to use Fn+Del otherwise. This shifts "timewarp" to Shift+BackSpace.
Functionally, this switches hotkeys to scancodes, as that makes more
sense (they are combinations of key positions, not actual text output).
SDL includes are cleaned and key names are reused.
Fixes #2850, Fixes #2604, Refs #1810, Fixes #1917.
Follows work in 3d7784d2af.
Various diffs tested by: Angen, Stan, Freagarach
Comments by: Nescio
Differential Revision: https://code.wildfiregames.com/D2814
This was SVN commit r24215.
2020-11-19 10:27:26 +01:00
|
|
|
if (g_HotkeyMap.find(scancode) == g_HotkeyMap.end())
|
2021-04-02 16:18:20 +02:00
|
|
|
return IN_PASS;
|
|
|
|
|
|
|
|
currentEvent = ev;
|
2010-10-23 04:37:00 +02:00
|
|
|
|
2021-03-31 17:50:25 +02:00
|
|
|
/**
|
|
|
|
* Hotkey behaviour spec (see also tests):
|
|
|
|
* - If both 'F' and 'Ctrl+F' are hotkeys, and Ctrl & F keys are down, then the more specific one only is fired ('Ctrl+F' here).
|
|
|
|
* - If 'Ctrl+F' and 'Ctrl+A' are both hotkeys, both may fire simulatenously (respectively without Ctrl).
|
|
|
|
* - However, per the first point, 'Ctrl+Shift+F' would fire alone in that situation.
|
|
|
|
* - "Press" is sent once, when the hotkey is initially triggered.
|
|
|
|
* - "Up" is sent once, when the hotkey is released or superseded by a more specific hotkey.
|
|
|
|
* - "Down" is sent repeatedly, and is also sent alongside the inital "Press".
|
|
|
|
* - As a special case (see below), "Down" is not sent alongside "PressSilent".
|
|
|
|
* - If 'Ctrl+F' is active, and 'Ctrl' is released, 'F' must become active again.
|
|
|
|
* - However, the "Press" event is _not_ fired. Instead, "PressSilent" is.
|
|
|
|
* - Likewise, once 'F' is released, the "Up" event will be a "UpSilent".
|
|
|
|
* (the reason is that it is unexpected to trigger a press on key release).
|
|
|
|
* - Hotkeys are allowed to fire with extra keys (e.g. Ctrl+F+A still triggers 'Ctrl+F').
|
|
|
|
* - If 'F' and 'Ctrl+F' trigger the same hotkey, adding 'Ctrl' _and_ releasing 'Ctrl' will trigger new 'Press' events.
|
|
|
|
* The "Up" event is only sent when both Ctrl & F are released.
|
|
|
|
* - This is somewhat unexpected/buggy, but it makes the implementation easier and is easily avoidable for players.
|
2021-04-01 16:51:22 +02:00
|
|
|
* - Wheel scrolling is 'instantaneous' behaviour and is essentially entirely separate from the above.
|
|
|
|
* - It won't untrigger other hotkeys, and fires/releases on the same 'key event'.
|
2021-03-31 17:50:25 +02:00
|
|
|
* Note that mouse buttons/wheel inputs can fire hotkeys, in combinations with keys.
|
|
|
|
* ...Yes, this is all surprisingly complex.
|
|
|
|
*/
|
|
|
|
|
2021-04-01 16:51:22 +02:00
|
|
|
bool isReleasedKey = ev->ev.type == SDL_KEYUP || ev->ev.type == SDL_MOUSEBUTTONUP;
|
|
|
|
// Wheel events are pressed & released in the same go.
|
|
|
|
bool isInstantaneous = ev->ev.type == SDL_MOUSEWHEEL;
|
|
|
|
|
|
|
|
if (!isInstantaneous)
|
|
|
|
{
|
|
|
|
std::vector<SDL_Scancode_>::iterator it = std::find(activeScancodes.begin(), activeScancodes.end(), scancode);
|
|
|
|
// This prevents duplicates, assuming we might end up in a weird state - feels safer with input.
|
|
|
|
if (isReleasedKey && it != activeScancodes.end())
|
|
|
|
activeScancodes.erase(it);
|
|
|
|
else if (!isReleasedKey && it == activeScancodes.end())
|
|
|
|
activeScancodes.emplace_back(scancode);
|
|
|
|
}
|
|
|
|
|
2021-04-06 14:26:34 +02:00
|
|
|
std::vector<SDL_Scancode_> triggers;
|
2021-04-01 16:51:22 +02:00
|
|
|
if (!isReleasedKey || isInstantaneous)
|
2021-04-06 14:26:34 +02:00
|
|
|
triggers.push_back(scancode);
|
2021-03-31 17:50:25 +02:00
|
|
|
else
|
|
|
|
// If the key is released, we need to check all less precise hotkeys again, to see if we should retrigger some.
|
|
|
|
for (SDL_Scancode_ code : activeScancodes)
|
2021-04-06 14:26:34 +02:00
|
|
|
triggers.push_back(code);
|
2014-08-04 18:48:54 +02:00
|
|
|
|
2021-03-31 17:50:25 +02:00
|
|
|
// Now check if we need to trigger new hotkeys / retrigger hotkeys.
|
|
|
|
// We'll need the match-level and the keys in play to release currently pressed hotkeys.
|
2021-04-02 16:18:20 +02:00
|
|
|
closestMapMatch = 0;
|
2021-03-31 17:50:25 +02:00
|
|
|
for (SDL_Scancode_ code : triggers)
|
|
|
|
for (const SHotkeyMapping& hotkey : g_HotkeyMap[code])
|
2021-01-18 11:58:16 +01:00
|
|
|
{
|
2021-03-31 17:50:25 +02:00
|
|
|
// Ensure no duplications in the new list.
|
|
|
|
if (std::find_if(newPressedHotkeys.begin(), newPressedHotkeys.end(),
|
|
|
|
[&hotkey](const PressedHotkey& v){ return v.mapping->name == hotkey.name; }) != newPressedHotkeys.end())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bool accept = true;
|
|
|
|
for (const SKey& k : hotkey.requires)
|
2021-01-18 11:58:16 +01:00
|
|
|
{
|
2021-03-31 17:50:25 +02:00
|
|
|
accept = isPressed(k);
|
|
|
|
if (!accept)
|
|
|
|
break;
|
2021-01-18 11:58:16 +01:00
|
|
|
}
|
2015-10-10 09:22:07 +02:00
|
|
|
if (!accept)
|
2021-03-31 17:50:25 +02:00
|
|
|
continue;
|
2004-08-03 01:14:54 +02:00
|
|
|
|
2010-11-07 21:42:52 +01:00
|
|
|
// Check if this is an equally precise or more precise match
|
2015-07-29 03:07:23 +02:00
|
|
|
if (hotkey.requires.size() + 1 >= closestMapMatch)
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2010-11-07 21:42:52 +01:00
|
|
|
// Check if more precise
|
2015-07-29 03:07:23 +02:00
|
|
|
if (hotkey.requires.size() + 1 > closestMapMatch)
|
2010-11-07 21:42:52 +01:00
|
|
|
{
|
|
|
|
// Throw away the old less-precise matches
|
2021-01-18 11:58:16 +01:00
|
|
|
newPressedHotkeys.clear();
|
2015-07-29 03:07:23 +02:00
|
|
|
closestMapMatch = hotkey.requires.size() + 1;
|
2010-11-07 21:42:52 +01:00
|
|
|
}
|
2021-03-31 17:50:25 +02:00
|
|
|
newPressedHotkeys.emplace_back(&hotkey, isReleasedKey);
|
2004-11-11 08:09:32 +01:00
|
|
|
}
|
2004-07-23 12:56:52 +02:00
|
|
|
}
|
2004-08-03 01:14:54 +02:00
|
|
|
|
2021-04-02 16:18:20 +02:00
|
|
|
return IN_PASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
InReaction HotkeyInputActualHandler(const SDL_Event_* ev)
|
|
|
|
{
|
|
|
|
if (!currentEvent)
|
|
|
|
return IN_PASS;
|
|
|
|
|
|
|
|
bool isInstantaneous = ev->ev.type == SDL_MOUSEWHEEL;
|
|
|
|
|
|
|
|
// TODO: it's probably possible to break hotkeys somewhat if the "Up" event that would release a hotkey is handled
|
|
|
|
// by a priori handler - it might be safer to do that in the 'Prep' phase.
|
|
|
|
std::vector<ReleasedHotkey> releasedHotkeys;
|
|
|
|
|
2021-04-01 16:51:22 +02:00
|
|
|
// For instantaneous events, we don't update the pressedHotkeys (i.e. currently active hotkeys),
|
|
|
|
// we just fire/release the triggered hotkeys transiently.
|
|
|
|
// Therefore, skip the whole 'check pressedHotkeys & swap with newPressedHotkeys' logic.
|
|
|
|
if (!isInstantaneous)
|
2021-03-31 17:50:25 +02:00
|
|
|
{
|
2021-04-01 16:51:22 +02:00
|
|
|
for (PressedHotkey& hotkey : pressedHotkeys)
|
2021-01-18 11:58:16 +01:00
|
|
|
{
|
2021-04-01 16:51:22 +02:00
|
|
|
bool addingAnew = std::find_if(newPressedHotkeys.begin(), newPressedHotkeys.end(),
|
|
|
|
[&hotkey](const PressedHotkey& v){ return v.mapping->name == hotkey.mapping->name; }) != newPressedHotkeys.end();
|
|
|
|
|
|
|
|
// Update the triggered status to match our current state.
|
|
|
|
if (addingAnew)
|
|
|
|
std::find_if(newPressedHotkeys.begin(), newPressedHotkeys.end(),
|
|
|
|
[&hotkey](const PressedHotkey& v){ return v.mapping->name == hotkey.mapping->name; })->retriggered = hotkey.retriggered;
|
|
|
|
// If the already-pressed hotkey has a lower specificity than the new hotkey(s), de-activate it.
|
|
|
|
else if (hotkey.mapping->requires.size() + 1 < closestMapMatch)
|
2021-01-18 11:58:16 +01:00
|
|
|
{
|
2021-04-01 16:51:22 +02:00
|
|
|
releasedHotkeys.emplace_back(hotkey.mapping->name.c_str(), hotkey.retriggered);
|
|
|
|
continue;
|
2021-01-18 11:58:16 +01:00
|
|
|
}
|
2021-04-01 16:51:22 +02:00
|
|
|
|
|
|
|
// Check that the hotkey still matches all active keys.
|
|
|
|
bool accept = isPressed(hotkey.mapping->primary);
|
|
|
|
if (accept)
|
|
|
|
for (const SKey& k : hotkey.mapping->requires)
|
|
|
|
{
|
|
|
|
accept = isPressed(k);
|
|
|
|
if (!accept)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!accept && !addingAnew)
|
|
|
|
releasedHotkeys.emplace_back(hotkey.mapping->name.c_str(), hotkey.retriggered);
|
|
|
|
else if (accept)
|
2021-03-31 17:50:25 +02:00
|
|
|
{
|
2021-04-01 16:51:22 +02:00
|
|
|
// If this hotkey has higher specificity than the new hotkeys we wanted to trigger/retrigger,
|
|
|
|
// then discard this new addition(s). This works because at any given time, all hotkeys
|
|
|
|
// active must have the same specificity.
|
|
|
|
if (hotkey.mapping->requires.size() + 1 > closestMapMatch)
|
|
|
|
{
|
|
|
|
closestMapMatch = hotkey.mapping->requires.size() + 1;
|
|
|
|
newPressedHotkeys.clear();
|
|
|
|
newPressedHotkeys.emplace_back(hotkey.mapping, hotkey.retriggered);
|
|
|
|
}
|
|
|
|
else if (!addingAnew)
|
|
|
|
newPressedHotkeys.emplace_back(hotkey.mapping, hotkey.retriggered);
|
2021-03-31 17:50:25 +02:00
|
|
|
}
|
2021-01-18 11:58:16 +01:00
|
|
|
}
|
|
|
|
|
2021-04-01 16:51:22 +02:00
|
|
|
pressedHotkeys.swap(newPressedHotkeys);
|
|
|
|
}
|
2021-01-18 11:58:16 +01:00
|
|
|
|
2021-04-01 16:51:22 +02:00
|
|
|
for (const PressedHotkey& hotkey : isInstantaneous ? newPressedHotkeys : pressedHotkeys)
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2021-01-16 16:24:58 +01:00
|
|
|
// Send a KeyPress event when a hotkey is pressed initially and on mouseButton and mouseWheel events.
|
2020-05-26 23:47:03 +02:00
|
|
|
if (ev->ev.type != SDL_KEYDOWN || ev->ev.key.repeat == 0)
|
|
|
|
{
|
|
|
|
SDL_Event_ hotkeyPressNotification;
|
2021-03-31 17:50:25 +02:00
|
|
|
hotkeyPressNotification.ev.type = hotkey.retriggered ? SDL_HOTKEYPRESS_SILENT : SDL_HOTKEYPRESS;
|
|
|
|
hotkeyPressNotification.ev.user.data1 = const_cast<char*>(hotkey.mapping->name.c_str());
|
2020-05-26 23:47:03 +02:00
|
|
|
in_push_priority_event(&hotkeyPressNotification);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send a HotkeyDown event on every key, mouseButton and mouseWheel event.
|
2021-03-31 17:50:25 +02:00
|
|
|
// The exception is on the first retriggering: hotkeys may fire transiently
|
|
|
|
// while a user lifts fingers off multi-key hotkeys, and listeners to "hotkeydown"
|
|
|
|
// generally don't expect that to trigger then.
|
|
|
|
// (It might be better to check for HotkeyIsPressed, however).
|
2020-05-26 23:47:03 +02:00
|
|
|
// For keys the event is repeated depending on hardware and OS configured interval.
|
|
|
|
// On linux, modifier keys (shift, alt, ctrl) are not repeated, see https://github.com/SFML/SFML/issues/122.
|
2021-03-31 17:50:25 +02:00
|
|
|
if (ev->ev.key.repeat == 0 && hotkey.retriggered)
|
|
|
|
continue;
|
2020-05-26 23:47:03 +02:00
|
|
|
SDL_Event_ hotkeyDownNotification;
|
|
|
|
hotkeyDownNotification.ev.type = SDL_HOTKEYDOWN;
|
2021-03-31 17:50:25 +02:00
|
|
|
hotkeyDownNotification.ev.user.data1 = const_cast<char*>(hotkey.mapping->name.c_str());
|
2020-05-26 23:47:03 +02:00
|
|
|
in_push_priority_event(&hotkeyDownNotification);
|
2004-11-11 08:09:32 +01:00
|
|
|
}
|
|
|
|
|
2021-04-01 16:51:22 +02:00
|
|
|
// Release instantaneous events (e.g. mouse wheel) right away.
|
|
|
|
if (isInstantaneous)
|
|
|
|
for (const PressedHotkey& hotkey : newPressedHotkeys)
|
|
|
|
releasedHotkeys.emplace_back(hotkey.mapping->name.c_str(), false);
|
|
|
|
|
2021-03-31 17:50:25 +02:00
|
|
|
for (const ReleasedHotkey& hotkey : releasedHotkeys)
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2021-01-16 16:24:58 +01:00
|
|
|
SDL_Event_ hotkeyNotification;
|
2021-03-31 17:50:25 +02:00
|
|
|
hotkeyNotification.ev.type = hotkey.wasRetriggered ? SDL_HOTKEYUP_SILENT : SDL_HOTKEYUP;
|
|
|
|
hotkeyNotification.ev.user.data1 = const_cast<char*>(hotkey.name);
|
2021-01-16 16:24:58 +01:00
|
|
|
in_push_priority_event(&hotkeyNotification);
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2004-11-11 08:09:32 +01:00
|
|
|
|
2014-08-04 18:48:54 +02:00
|
|
|
return IN_PASS;
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2004-08-09 22:58:32 +02:00
|
|
|
|
2021-04-02 16:18:20 +02:00
|
|
|
bool EventWillFireHotkey(const SDL_Event_* ev, const CStr& keyname)
|
|
|
|
{
|
|
|
|
// Sanity check of sort. This parameter mostly exists because it looks right from the caller's perspective.
|
|
|
|
if (ev != currentEvent || !currentEvent)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return std::find_if(newPressedHotkeys.begin(), newPressedHotkeys.end(),
|
|
|
|
[&keyname](const PressedHotkey& v){ return v.mapping->name == keyname; }) != newPressedHotkeys.end();
|
|
|
|
}
|
|
|
|
|
2021-04-03 22:12:40 +02:00
|
|
|
void ResetActiveHotkeys()
|
|
|
|
{
|
|
|
|
newPressedHotkeys.clear();
|
|
|
|
for (const PressedHotkey& hotkey : pressedHotkeys)
|
|
|
|
{
|
|
|
|
SDL_Event_ hotkeyNotification;
|
|
|
|
hotkeyNotification.ev.type = hotkey.retriggered ? SDL_HOTKEYUP_SILENT : SDL_HOTKEYUP;
|
|
|
|
hotkeyNotification.ev.user.data1 = const_cast<char*>(hotkey.mapping->name.c_str());
|
|
|
|
in_push_priority_event(&hotkeyNotification);
|
|
|
|
}
|
|
|
|
pressedHotkeys.clear();
|
|
|
|
activeScancodes.clear();
|
|
|
|
currentEvent = nullptr;
|
|
|
|
}
|
|
|
|
|
2010-01-09 20:20:14 +01:00
|
|
|
bool HotkeyIsPressed(const CStr& keyname)
|
2006-08-25 06:24:06 +02:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
return g_HotkeyStatus[keyname];
|
2006-08-25 06:24:06 +02:00
|
|
|
}
|