2010-10-23 04:37:00 +02:00
|
|
|
/* Copyright (C) 2010 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
|
|
|
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "lib/input.h"
|
2004-07-21 18:51:21 +02:00
|
|
|
#include "ConfigDB.h"
|
2004-11-11 08:09:32 +01:00
|
|
|
#include "CLogger.h"
|
2004-07-22 18:18:12 +02:00
|
|
|
#include "CConsole.h"
|
|
|
|
#include "CStr.h"
|
2005-10-17 01:16:08 +02:00
|
|
|
#include "ps/Globals.h"
|
2007-05-02 14:07:08 +02:00
|
|
|
#include "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
|
|
|
|
2012-02-06 23:47:35 +01:00
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
|
|
#define SDLKEY SDL_Keycode
|
|
|
|
#else
|
|
|
|
#define SDLKEY SDLKey
|
|
|
|
#endif
|
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
struct SKey
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2012-02-06 23:47:35 +01:00
|
|
|
SDLKEY code; // keycode or MOUSE_ or UNIFIED_ value
|
2010-10-23 04:37:00 +02:00
|
|
|
bool negated; // whether the key must be pressed (false) or unpressed (true)
|
2004-07-21 18:51:21 +02:00
|
|
|
};
|
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
// Hotkey data associated with an externally-specified 'primary' keycode
|
|
|
|
struct SHotkeyMapping
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
CStr name; // name of the hotkey
|
|
|
|
bool negated; // whether the primary key must be pressed (false) or unpressed (true)
|
|
|
|
std::vector<SKey> requires; // list of non-primary keys that must also be active
|
2004-07-21 18:51:21 +02:00
|
|
|
};
|
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
typedef std::vector<SHotkeyMapping> KeyMapping;
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
// A mapping of keycodes onto the hotkeys that are associated with that key.
|
|
|
|
// (A hotkey triggered by a combination of multiple keys will be in this map
|
|
|
|
// multiple times.)
|
|
|
|
static std::map<int, KeyMapping> g_HotkeyMap;
|
2004-07-22 18:18:12 +02:00
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
// The current pressed status of hotkeys
|
|
|
|
std::map<std::string, bool> g_HotkeyStatus;
|
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.
|
|
|
|
static void LoadConfigBindings()
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2012-04-17 15:14:34 +02:00
|
|
|
std::map<CStr, CConfigValueSet> bindings = g_ConfigDB.GetValuesWithPrefix( CFG_COMMAND, "hotkey." );
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
CParser multikeyParser;
|
|
|
|
multikeyParser.InputTaskType( "multikey", "<[~$arg(_negate)]$value_+_>_[~$arg(_negate)]$value" );
|
2004-07-22 18:18:12 +02:00
|
|
|
|
2012-04-17 15:14:34 +02:00
|
|
|
for( std::map<CStr, CConfigValueSet>::iterator bindingsIt = bindings.begin(); bindingsIt != bindings.end(); ++bindingsIt )
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
std::string hotkeyName = bindingsIt->first.substr(7); // strip the "hotkey." prefix
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
for( CConfigValueSet::iterator it = bindingsIt->second.begin(); it != bindingsIt->second.end(); ++it )
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
|
|
|
std::string hotkey;
|
|
|
|
if( it->GetString( hotkey ) )
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
std::vector<SKey> keyCombination;
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2004-07-22 18:18:12 +02:00
|
|
|
CParserLine multikeyIdentifier;
|
|
|
|
multikeyIdentifier.ParseString( multikeyParser, hotkey );
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2004-07-22 18:18:12 +02:00
|
|
|
// Iterate through multiple-key bindings (e.g. Ctrl+I)
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2004-11-11 08:09:32 +01:00
|
|
|
bool negateNext = false;
|
|
|
|
|
2004-07-22 18:18:12 +02:00
|
|
|
for( size_t t = 0; t < multikeyIdentifier.GetArgCount(); t++ )
|
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
|
2004-07-22 18:18:12 +02:00
|
|
|
if( multikeyIdentifier.GetArgString( (int)t, hotkey ) )
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2004-11-11 08:09:32 +01:00
|
|
|
if( hotkey == "_negate" )
|
|
|
|
{
|
|
|
|
negateNext = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt decode as key name
|
2010-10-23 04:37:00 +02:00
|
|
|
int mapping = FindKeyCode( hotkey );
|
2004-11-11 08:09:32 +01:00
|
|
|
|
|
|
|
// Attempt to decode as a negation of a keyname
|
|
|
|
// Yes, it's going a bit far, perhaps.
|
|
|
|
// Too powerful for most uses, probably.
|
|
|
|
// However, it got some hardcoding out of the engine.
|
|
|
|
// Thus it makes me happy.
|
2010-10-23 04:37:00 +02:00
|
|
|
|
2004-07-22 18:18:12 +02:00
|
|
|
if( !mapping )
|
2010-10-23 04:37:00 +02:00
|
|
|
{
|
|
|
|
LOGWARNING(L"Hotkey mapping used invalid key '%hs'", hotkey.c_str() );
|
|
|
|
continue;
|
|
|
|
}
|
2004-11-11 08:09:32 +01:00
|
|
|
|
2012-02-06 23:47:35 +01:00
|
|
|
SKey key = { (SDLKEY)mapping, negateNext };
|
2010-10-23 04:37:00 +02:00
|
|
|
keyCombination.push_back(key);
|
2004-11-11 08:09:32 +01:00
|
|
|
|
|
|
|
negateNext = false;
|
|
|
|
|
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
|
|
|
std::vector<SKey>::iterator itKey, itKey2;
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2011-12-29 02:17:03 +01:00
|
|
|
for( itKey = keyCombination.begin(); itKey != keyCombination.end(); ++itKey )
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
SHotkeyMapping bindCode;
|
|
|
|
|
|
|
|
bindCode.name = hotkeyName;
|
|
|
|
bindCode.negated = itKey->negated;
|
|
|
|
|
2011-12-29 02:17:03 +01:00
|
|
|
for( itKey2 = keyCombination.begin(); itKey2 != keyCombination.end(); ++itKey2 )
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
|
|
|
// Push any auxiliary keys.
|
|
|
|
if( itKey != itKey2 )
|
2010-10-23 04:37:00 +02:00
|
|
|
bindCode.requires.push_back( *itKey2 );
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2004-08-03 01:14:54 +02:00
|
|
|
|
2010-10-23 04:37:00 +02: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
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
void LoadHotkeys()
|
2004-07-22 18:18:12 +02:00
|
|
|
{
|
2007-05-02 14:07:08 +02:00
|
|
|
InitKeyNameMap();
|
2004-07-22 18:18:12 +02:00
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
LoadConfigBindings();
|
|
|
|
|
2004-11-11 08:09:32 +01:00
|
|
|
// Set up the state of the hotkeys given no key is down.
|
|
|
|
// i.e. find those hotkeys triggered by all negations.
|
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
for( std::map<int, KeyMapping>::iterator mapIt = g_HotkeyMap.begin(); mapIt != g_HotkeyMap.end(); ++mapIt )
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
KeyMapping& hotkeyMap = mapIt->second;
|
|
|
|
|
2011-12-29 02:17:03 +01:00
|
|
|
for( std::vector<SHotkeyMapping>::iterator it = hotkeyMap.begin(); it != hotkeyMap.end(); ++it )
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
if( !it->negated )
|
2004-11-11 08:09:32 +01:00
|
|
|
continue;
|
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
bool allNegated = true;
|
2004-11-11 08:09:32 +01:00
|
|
|
|
2011-12-29 02:17:03 +01:00
|
|
|
for( std::vector<SKey>::iterator j = it->requires.begin(); j != it->requires.end(); ++j )
|
2010-10-23 04:37:00 +02:00
|
|
|
if( !j->negated )
|
2004-11-11 08:09:32 +01:00
|
|
|
allNegated = false;
|
2005-10-21 20:32:16 +02:00
|
|
|
|
2004-11-11 08:09:32 +01:00
|
|
|
if( allNegated )
|
2010-10-23 04:37:00 +02:00
|
|
|
g_HotkeyStatus[it->name] = true;
|
2004-11-11 08:09:32 +01:00
|
|
|
}
|
|
|
|
}
|
2004-07-22 18:18:12 +02:00
|
|
|
}
|
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
InReaction HotkeyInputHandler( const SDL_Event_* ev )
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2005-10-24 23:43:39 +02:00
|
|
|
int keycode = 0;
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2006-08-26 23:52:18 +02:00
|
|
|
switch( ev->ev.type )
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
|
|
|
case SDL_KEYDOWN:
|
|
|
|
case SDL_KEYUP:
|
2006-08-26 23:52:18 +02:00
|
|
|
keycode = (int)ev->ev.key.keysym.sym;
|
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:
|
2012-02-06 23:47:35 +01:00
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
|
|
if ((int)ev->ev.button.button <= SDL_BUTTON_RIGHT)
|
|
|
|
#elif SDL_VERSION_ATLEAST(1, 2, 13)
|
2010-11-13 02:00:54 +01:00
|
|
|
if ((int)ev->ev.button.button <= SDL_BUTTON_X2)
|
2010-12-11 03:25:21 +01:00
|
|
|
#else
|
|
|
|
if ((int)ev->ev.button.button <= SDL_BUTTON_WHEELDOWN)
|
|
|
|
#endif
|
2007-05-26 20:38:38 +02:00
|
|
|
{
|
2012-01-11 23:50:39 +01:00
|
|
|
keycode = CUSTOM_SDL_KEYCODE + (int)ev->ev.button.button;
|
2007-05-26 20:38:38 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-02-06 23:47:35 +01:00
|
|
|
return IN_PASS;
|
|
|
|
|
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
|
|
case SDL_MOUSEWHEEL:
|
|
|
|
if (ev->ev.wheel.y < 0)
|
|
|
|
{
|
|
|
|
keycode = MOUSE_WHEELUP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (ev->ev.wheel.y > 0)
|
|
|
|
{
|
|
|
|
keycode = MOUSE_WHEELDOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return IN_PASS;
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2011-05-29 23:12:09 +02:00
|
|
|
// Rather ugly hack to make the '"' key work better on a MacBook Pro on Windows so it doesn't
|
|
|
|
// always close the console. (Maybe this would be better handled in wsdl or something?)
|
|
|
|
if (keycode == SDLK_BACKQUOTE && (ev->ev.key.keysym.unicode == '\'' || ev->ev.key.keysym.unicode == '"'))
|
|
|
|
keycode = ev->ev.key.keysym.unicode;
|
|
|
|
|
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;
|
|
|
|
phantom.ev.type = ( ( ev->ev.type == SDL_KEYDOWN ) || ( ev->ev.type == SDL_MOUSEBUTTONDOWN ) ) ? SDL_KEYDOWN : SDL_KEYUP;
|
2004-08-03 01:14:54 +02:00
|
|
|
if( ( keycode == SDLK_LSHIFT ) || ( keycode == SDLK_RSHIFT ) )
|
|
|
|
{
|
2012-02-06 23:47:35 +01:00
|
|
|
phantom.ev.key.keysym.sym = (SDLKEY)UNIFIED_SHIFT;
|
2006-08-26 23:52:18 +02:00
|
|
|
unified[0] = ( phantom.ev.type == SDL_KEYDOWN );
|
2007-05-02 14:07:08 +02:00
|
|
|
HotkeyInputHandler( &phantom );
|
2004-08-03 01:14:54 +02:00
|
|
|
}
|
|
|
|
else if( ( keycode == SDLK_LCTRL ) || ( keycode == SDLK_RCTRL ) )
|
|
|
|
{
|
2012-02-06 23:47:35 +01:00
|
|
|
phantom.ev.key.keysym.sym = (SDLKEY)UNIFIED_CTRL;
|
2006-08-26 23:52:18 +02:00
|
|
|
unified[1] = ( phantom.ev.type == SDL_KEYDOWN );
|
2007-05-02 14:07:08 +02:00
|
|
|
HotkeyInputHandler( &phantom );
|
2004-08-03 01:14:54 +02:00
|
|
|
}
|
|
|
|
else if( ( keycode == SDLK_LALT ) || ( keycode == SDLK_RALT ) )
|
|
|
|
{
|
2012-02-06 23:47:35 +01:00
|
|
|
phantom.ev.key.keysym.sym = (SDLKEY)UNIFIED_ALT;
|
2006-08-26 23:52:18 +02:00
|
|
|
unified[2] = ( phantom.ev.type == SDL_KEYDOWN );
|
2007-05-02 14:07:08 +02:00
|
|
|
HotkeyInputHandler( &phantom );
|
2004-08-03 01:14:54 +02:00
|
|
|
}
|
2012-02-06 23:47:35 +01:00
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
|
|
else if( ( keycode == SDLK_LGUI ) || ( keycode == SDLK_RGUI ) )
|
|
|
|
#else
|
2013-02-24 22:42:21 +01:00
|
|
|
else if( ( keycode == SDLK_LSUPER ) || ( keycode == SDLK_RSUPER ) || ( keycode == SDLK_LMETA ) || ( keycode == SDLK_RMETA) )
|
2012-02-06 23:47:35 +01:00
|
|
|
#endif
|
2004-08-03 01:14:54 +02:00
|
|
|
{
|
2012-02-06 23:47:35 +01:00
|
|
|
phantom.ev.key.keysym.sym = (SDLKEY)UNIFIED_SUPER;
|
|
|
|
unified[3] = ( phantom.ev.type == SDL_KEYDOWN );
|
2007-05-02 14:07:08 +02:00
|
|
|
HotkeyInputHandler( &phantom );
|
2004-08-03 01:14:54 +02:00
|
|
|
}
|
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
// Check whether we have any hotkeys registered for this particular keycode
|
|
|
|
if( g_HotkeyMap.find(keycode) == g_HotkeyMap.end() )
|
|
|
|
return( IN_PASS );
|
|
|
|
|
2011-02-20 21:50:26 +01:00
|
|
|
// Inhibit the dispatch of hotkey events caused by real keys (not fake mouse button
|
|
|
|
// events) while the console is up.
|
2004-08-03 01:14:54 +02:00
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
bool consoleCapture = false;
|
2004-07-22 18:18:12 +02:00
|
|
|
|
2012-01-11 23:50:39 +01:00
|
|
|
if( g_Console->IsActive() && keycode < CUSTOM_SDL_KEYCODE )
|
2004-08-03 01:14:54 +02:00
|
|
|
consoleCapture = true;
|
2004-07-22 18:18:12 +02:00
|
|
|
|
2004-07-23 12:56:52 +02:00
|
|
|
// Here's an interesting bit:
|
|
|
|
// If you have an event bound to, say, 'F', and another to, say, 'Ctrl+F', pressing
|
2004-08-03 01:14:54 +02:00
|
|
|
// 'F' while control is down would normally fire off both.
|
2004-07-23 12:56:52 +02:00
|
|
|
|
|
|
|
// To avoid this, set the modifier keys for /all/ events this key would trigger
|
|
|
|
// (Ctrl, for example, is both group-save and bookmark-save)
|
2004-08-03 01:14:54 +02:00
|
|
|
// but only send a HotkeyDown event for the event with bindings most precisely
|
|
|
|
// matching the conditions (i.e. the event with the highest number of auxiliary
|
2004-07-23 12:56:52 +02:00
|
|
|
// keys, providing they're all down)
|
|
|
|
|
2006-08-26 23:52:18 +02:00
|
|
|
bool typeKeyDown = ( ev->ev.type == SDL_KEYDOWN ) || ( ev->ev.type == SDL_MOUSEBUTTONDOWN );
|
2004-11-11 08:09:32 +01:00
|
|
|
|
|
|
|
// -- KEYDOWN SECTION --
|
|
|
|
|
2010-11-07 21:42:52 +01:00
|
|
|
std::vector<const char*> closestMapNames;
|
2004-11-11 08:09:32 +01:00
|
|
|
size_t closestMapMatch = 0;
|
|
|
|
|
2011-12-29 02:17:03 +01:00
|
|
|
for( std::vector<SHotkeyMapping>::iterator it = g_HotkeyMap[keycode].begin(); it < g_HotkeyMap[keycode].end(); ++it )
|
2005-10-21 20:32:16 +02:00
|
|
|
{
|
2010-11-07 21:42:52 +01:00
|
|
|
// If a key has been pressed, and this event triggers on its release, skip it.
|
2004-11-11 08:09:32 +01:00
|
|
|
// Similarly, if the key's been released and the event triggers on a keypress, skip it.
|
2010-10-23 04:37:00 +02:00
|
|
|
if( it->negated == typeKeyDown )
|
2004-11-11 08:09:32 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Check to see if all auxiliary keys are down
|
2004-07-23 12:56:52 +02:00
|
|
|
|
2004-11-11 08:09:32 +01:00
|
|
|
bool accept = true;
|
2004-08-03 01:14:54 +02:00
|
|
|
|
2011-12-29 02:17:03 +01:00
|
|
|
for( std::vector<SKey>::iterator itKey = it->requires.begin(); itKey != it->requires.end(); ++itKey )
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
bool rqdState = !itKey->negated;
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2012-01-11 23:50:39 +01:00
|
|
|
if( (int)itKey->code < CUSTOM_SDL_KEYCODE )
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
if( g_keys[itKey->code] != rqdState ) accept = false;
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2010-10-23 04:37:00 +02:00
|
|
|
else if( (int)itKey->code < UNIFIED_SHIFT )
|
2005-09-30 00:06:20 +02:00
|
|
|
{
|
2012-01-11 23:50:39 +01:00
|
|
|
if( g_mouse_buttons[itKey->code - CUSTOM_SDL_KEYCODE] != rqdState ) accept = false;
|
2005-09-30 00:06:20 +02:00
|
|
|
}
|
2010-10-23 04:37:00 +02:00
|
|
|
else if( (int)itKey->code < UNIFIED_LAST )
|
2005-09-30 00:06:20 +02:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
if( unified[itKey->code - UNIFIED_SHIFT] != rqdState ) accept = false;
|
2005-09-30 00:06:20 +02:00
|
|
|
}
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2004-07-23 12:56:52 +02:00
|
|
|
|
2011-02-20 21:50:26 +01:00
|
|
|
if( accept && !( consoleCapture && it->name != "console.toggle" ) )
|
2004-07-23 12:56:52 +02:00
|
|
|
{
|
2010-11-07 21:42:52 +01:00
|
|
|
// Tentatively set status to un-pressed, since it may be overridden by
|
|
|
|
// a closer match. (The closest matches will be set to pressed later.)
|
|
|
|
g_HotkeyStatus[it->name] = false;
|
|
|
|
|
|
|
|
// Check if this is an equally precise or more precise match
|
|
|
|
if( it->requires.size() + 1 >= closestMapMatch )
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2010-11-07 21:42:52 +01:00
|
|
|
// Check if more precise
|
|
|
|
if( it->requires.size() + 1 > closestMapMatch )
|
|
|
|
{
|
|
|
|
// Throw away the old less-precise matches
|
|
|
|
closestMapNames.clear();
|
|
|
|
closestMapMatch = it->requires.size() + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
closestMapNames.push_back(it->name.c_str());
|
2004-11-11 08:09:32 +01:00
|
|
|
}
|
2004-07-23 12:56:52 +02:00
|
|
|
}
|
2004-11-11 08:09:32 +01:00
|
|
|
}
|
2004-08-03 01:14:54 +02:00
|
|
|
|
2010-11-07 21:42:52 +01:00
|
|
|
for (size_t i = 0; i < closestMapNames.size(); ++i)
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2010-11-07 21:42:52 +01:00
|
|
|
g_HotkeyStatus[closestMapNames[i]] = true;
|
|
|
|
|
2010-10-23 04:37:00 +02:00
|
|
|
SDL_Event hotkeyNotification;
|
2004-11-11 08:09:32 +01:00
|
|
|
hotkeyNotification.type = SDL_HOTKEYDOWN;
|
2010-11-07 21:42:52 +01:00
|
|
|
hotkeyNotification.user.data1 = const_cast<char*>(closestMapNames[i]);
|
|
|
|
SDL_PushEvent(&hotkeyNotification);
|
2004-11-11 08:09:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// -- KEYUP SECTION --
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2011-12-29 02:17:03 +01:00
|
|
|
for( std::vector<SHotkeyMapping>::iterator it = g_HotkeyMap[keycode].begin(); it < g_HotkeyMap[keycode].end(); ++it )
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
|
|
|
// If it's a keydown event, won't cause HotKeyUps in anything that doesn't
|
|
|
|
// use this key negated => skip them
|
|
|
|
// If it's a keyup event, won't cause HotKeyUps in anything that does use
|
|
|
|
// this key negated => skip them too.
|
2010-10-23 04:37:00 +02:00
|
|
|
if( it->negated != typeKeyDown )
|
2004-11-11 08:09:32 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Check to see if all auxiliary keys are down
|
|
|
|
|
|
|
|
bool accept = true;
|
2004-07-21 18:51:21 +02:00
|
|
|
|
2011-12-29 02:17:03 +01:00
|
|
|
for( std::vector<SKey>::iterator itKey = it->requires.begin(); itKey != it->requires.end(); ++itKey )
|
2004-11-11 08:09:32 +01:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
bool rqdState = !itKey->negated;
|
|
|
|
|
2012-01-11 23:50:39 +01:00
|
|
|
if( (int)itKey->code < CUSTOM_SDL_KEYCODE )
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
if( g_keys[itKey->code] != rqdState ) accept = false;
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2010-10-23 04:37:00 +02:00
|
|
|
else if( (int)itKey->code < UNIFIED_SHIFT )
|
2004-07-21 18:51:21 +02:00
|
|
|
{
|
2012-01-11 23:50:39 +01:00
|
|
|
if( g_mouse_buttons[itKey->code - CUSTOM_SDL_KEYCODE] != rqdState ) accept = false;
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2010-10-23 04:37:00 +02:00
|
|
|
else if( (int)itKey->code < UNIFIED_LAST )
|
2006-07-14 02:14:44 +02:00
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
if( unified[itKey->code - UNIFIED_SHIFT] != rqdState ) accept = false;
|
2006-07-14 02:14:44 +02:00
|
|
|
}
|
2004-11-11 08:09:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if( accept )
|
|
|
|
{
|
2010-10-23 04:37:00 +02:00
|
|
|
g_HotkeyStatus[it->name] = false;
|
|
|
|
SDL_Event hotkeyNotification;
|
2004-11-11 08:09:32 +01:00
|
|
|
hotkeyNotification.type = SDL_HOTKEYUP;
|
2010-10-23 04:37:00 +02:00
|
|
|
hotkeyNotification.user.data1 = const_cast<char*>(it->name.c_str());
|
2004-11-11 08:09:32 +01:00
|
|
|
SDL_PushEvent( &hotkeyNotification );
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
|
|
|
}
|
2004-11-11 08:09:32 +01:00
|
|
|
|
2005-10-20 19:44:56 +02:00
|
|
|
return( IN_PASS );
|
2004-07-21 18:51:21 +02:00
|
|
|
}
|
2004-08-09 22:58:32 +02:00
|
|
|
|
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
|
|
|
}
|