Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
Hotkey.h File Reference

Hotkey system. More...

#include "CStr.h"
#include "lib/input.h"
#include <unordered_map>
#include <vector>
Include dependency graph for Hotkey.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  SKey
 
struct  SHotkeyMapping
 

Typedefs

using SDL_Scancode_ = int
 
typedef std::vector< SHotkeyMappingKeyMapping
 

Functions

void LoadHotkeys (CConfigDB &configDB)
 
void UnloadHotkeys ()
 
InReaction HotkeyStateChange (const SDL_Event_ *ev)
 Updates g_HotkeyMap. More...
 
InReaction HotkeyInputPrepHandler (const SDL_Event_ *ev)
 Detects hotkeys that should fire. More...
 
InReaction HotkeyInputActualHandler (const SDL_Event_ *ev)
 Actually fires hotkeys. More...
 
bool EventWillFireHotkey (const SDL_Event_ *ev, const CStr &keyname)
 
void ResetActiveHotkeys ()
 Resets all currently active hotkeys (and clears in-flight hotkeys). More...
 
bool HotkeyIsPressed (const CStr &keyname)
 

Variables

const uint SDL_USEREVENT_ = 0x8000
 
const uint SDL_HOTKEYPRESS = SDL_USEREVENT_
 
const uint SDL_HOTKEYDOWN = SDL_USEREVENT_ + 1
 
const uint SDL_HOTKEYUP = SDL_USEREVENT_ + 2
 
const uint SDL_HOTKEYPRESS_SILENT = SDL_USEREVENT_ + 3
 
const uint SDL_HOTKEYUP_SILENT = SDL_USEREVENT_ + 4
 
constexpr SDL_Scancode_ UNUSED_HOTKEY_CODE = 0
 
std::unordered_map< SDL_Scancode_, KeyMappingg_HotkeyMap
 

Detailed Description

Hotkey system.

Hotkeys consist of a name (an arbitrary string), and a key mapping. The names and mappings are loaded from the config system (any config setting with the name prefix "hotkey."). When a hotkey is pressed one SDL_HOTKEYPRESS is triggered. While the key is kept down repeated SDL_HOTKEYDOWN events are triggered at an interval determined by the OS. When a hotkey is released an SDL_HOTKEYUP event is triggered. All with the hotkey name stored in ev.user.data1 as a const char*.

Typedef Documentation

◆ KeyMapping

typedef std::vector<SHotkeyMapping> KeyMapping

◆ SDL_Scancode_

using SDL_Scancode_ = int

Function Documentation

◆ EventWillFireHotkey()

bool EventWillFireHotkey ( const SDL_Event_ ev,
const CStr &  keyname 
)
Returns
whether the event
Parameters
evwill fire the hotkey
keyname.

◆ HotkeyInputActualHandler()

InReaction HotkeyInputActualHandler ( const SDL_Event_ ev)

Actually fires hotkeys.

◆ HotkeyInputPrepHandler()

InReaction HotkeyInputPrepHandler ( const SDL_Event_ ev)

Detects hotkeys that should fire.

This allows using EventWillFireHotkey, (and then possibly preventing those hotkeys from firing by handling the event).

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.
  • 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'. Note that mouse buttons/wheel inputs can fire hotkeys, in combinations with keys. ...Yes, this is all surprisingly complex.

◆ HotkeyIsPressed()

bool HotkeyIsPressed ( const CStr &  keyname)
Returns
whether the hotkey is currently pressed (i.e. active).

◆ HotkeyStateChange()

InReaction HotkeyStateChange ( const SDL_Event_ ev)

Updates g_HotkeyMap.

◆ LoadHotkeys()

void LoadHotkeys ( CConfigDB configDB)

◆ ResetActiveHotkeys()

void ResetActiveHotkeys ( )

Resets all currently active hotkeys (and clears in-flight hotkeys).

You should call this when something grabs key input, e.g. an input box, as those prevent keydown/keyup messages from reaching the hotkey system, and can lead to hotkeys being stuck active. NB: active hotkeys are released immediately and "HotkeyUp" message sent.

◆ UnloadHotkeys()

void UnloadHotkeys ( )

Variable Documentation

◆ g_HotkeyMap

std::unordered_map<SDL_Scancode_, KeyMapping> g_HotkeyMap
extern

◆ SDL_HOTKEYDOWN

const uint SDL_HOTKEYDOWN = SDL_USEREVENT_ + 1

◆ SDL_HOTKEYPRESS

const uint SDL_HOTKEYPRESS = SDL_USEREVENT_

◆ SDL_HOTKEYPRESS_SILENT

const uint SDL_HOTKEYPRESS_SILENT = SDL_USEREVENT_ + 3

◆ SDL_HOTKEYUP

const uint SDL_HOTKEYUP = SDL_USEREVENT_ + 2

◆ SDL_HOTKEYUP_SILENT

const uint SDL_HOTKEYUP_SILENT = SDL_USEREVENT_ + 4

◆ SDL_USEREVENT_

const uint SDL_USEREVENT_ = 0x8000

◆ UNUSED_HOTKEY_CODE

constexpr SDL_Scancode_ UNUSED_HOTKEY_CODE = 0
constexpr