# PowerToys Keyboard Manager Remapping Engine Internals: Low-Level Hook Architecture Explained

> Discover how the PowerToys Keyboard Manager uses a low-level keyboard hook to remap keys. Learn about its stateful engine and SendInput synthesis for seamless input redirection.

- Repository: [Microsoft/PowerToys](https://github.com/microsoft/PowerToys)
- Tags: internals
- Published: 2026-02-25

---

**The PowerToys Keyboard Manager intercepts every keystroke via a global `WH_KEYBOARD_LL` hook, processes it through a stateful mapping engine, and synthesizes replacement input events using Windows `SendInput` to execute remappings without modifying registry scan codes.**

The Keyboard Manager remapping engine inside `microsoft/PowerToys` transforms raw hardware keystrokes into user-defined outputs through a sophisticated low-level input processing pipeline. This C++ engine runs inside the PowerToys runner process and handles everything from simple key swaps to complex chord shortcuts and application launches without requiring administrator privileges for most operations.

## Hook Installation and Global Event Interception

The engine begins its lifecycle in `KeyboardManager::StartLowlevelKeyboardHook()` within [`src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManager.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManager.cpp). This method calls `SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, …)` to install a global low-level keyboard hook that receives every keystroke before applications process it.

The static callback `KeyboardManager::HookProc` normalizes the virtual-key code using `Helpers::EncodeKeyNumpadOrigin` to handle numpad variations correctly. It then delegates to the active engine instance via `keyboardManagerObjectPtr->HandleKeyboardHookEvent(&event)`. When remappings are cleared, `KeyboardManager::StopLowlevelKeyboardHook()` removes the hook to eliminate performance overhead. The static members `hookHandle`, `hookHandleCopy`, and `keyboardManagerObjectPtr` bridge the C-style Windows API callback to the C++ object instance holding current state.

## State Management and Configuration Storage

All user remappings reside in the `State` class (defined in [`State.h`](https://github.com/microsoft/PowerToys/blob/main/State.h)), which inherits from `MappingConfiguration` shared with the Settings UI. Key data structures include:

- **`singleKeyReMap`** – `std::unordered_map<DWORD, Remap>` for key-to-key translations
- **`singleKeyToTextReMap`** – Maps source keys to Unicode strings for text injection
- **`osLevelShortcutReMap`** / **`appSpecificShortcutReMap`** – Shortcut-to-target mappings using `std::variant` to hold keys, shortcuts, program paths, URIs, or text blocks
- **`activatedApp`** – Tracks which application triggered an app-specific shortcut

`KeyboardManager::LoadSettings()` parses the JSON configuration that the Settings UI writes to `PTSettingsHelper::get_module_save_folder_location`. The engine hot-reloads configurations without restarting via an `EventWaiter` subscription to `SettingsEventName`, triggering the `changeSettingsCallback` lambda when users modify mappings.

## Event Processing Pipeline

The central dispatcher `KeyboardManager::HandleKeyboardHookEvent` in [`KeyboardManager.cpp`](https://github.com/microsoft/PowerToys/blob/main/KeyboardManager.cpp) implements a priority-ordered pipeline:

1. Ignore synthetic events generated by the engine itself to prevent infinite loops
2. Suspend remapping when the Editor window is active
3. Delegate single-key remaps
4. Check app-specific shortcuts
5. Process single-key-to-text injections
6. Finally evaluate OS-level shortcuts

### Single-Key Remapping Logic

`HandleSingleKeyRemapEvent` (implemented in [`KeyboardEventHandlers.cpp`](https://github.com/microsoft/PowerToys/blob/main/KeyboardEventHandlers.cpp) around lines 94-140) queries `state.GetSingleKeyRemap(vk)` for the source virtual key. If the target is `VK_DISABLED`, the function returns `1` to suppress the keystroke entirely. Otherwise, it constructs a `std::vector<INPUT>` containing the target key events and calls `ii.SendVirtualInput(keyEventList)` through the `KeyboardManagerInput::InputInterface` abstraction, which ultimately invokes `SendInput`. Telemetry fires once daily via `Trace::DailyKeyToKeyRemapInvoked`.

### Shortcut-to-Shortcut Handling

`HandleShortcutRemapEvent` (starting at line 70 in [`KeyboardEventHandlers.cpp`](https://github.com/microsoft/PowerToys/blob/main/KeyboardEventHandlers.cpp)) manages complex chord sequences using `ResetChordsIfNeeded` to handle two-key shortcuts correctly. The engine checks `state.CheckShortcutRemapInvoked` to prevent re-triggering during modifier holds.

When a match occurs, the engine releases original shortcut modifiers and presses the target combination. To avoid "modifier-press-release" glitches where Windows misinterprets modifier up/down events, the code inserts a dummy key event between modifier releases and target key presses. For program launch targets, the engine spawns a detached thread calling `ShellExecute` while suppressing the original shortcut keystrokes.

### Text Injection and Unicode Support

`HandleSingleKeyToTextRemapEvent` retrieves the Unicode string from `singleKeyToTextReMap` and calls `Helpers::SetTextKeyEvents`, which builds `INPUT` structures with the `KEYEVENTF_UNICODE` flag. This allows injecting arbitrary Unicode characters, including those not present on the physical keyboard layout.

### Numpad Normalization

The static helper `UpdateNumpadWithShift` (lines 31-80 in [`KeyboardEventHandlers.cpp`](https://github.com/microsoft/PowerToys/blob/main/KeyboardEventHandlers.cpp)) corrects a Windows quirk where the low-level hook sees the Shift flag before decoding numpad keys. When remapping Shift keys, this ensures the original numpad virtual key code is preserved rather than interpreting the keystroke as a navigation key.

## Synthetic Input Generation and Thread Safety

All synthetic input flows through `KeyboardManagerInput::InputInterface` (defined in [`InputInterface.h`](https://github.com/microsoft/PowerToys/blob/main/InputInterface.h)), enabling unit testing by abstracting `SendInput`. The low-level hook executes on the runner's main thread, and the engine maintains thread safety through single-threaded state mutations confined to the `KeyboardManager` object instance. The only global mutable state, `keyboardManagerObjectPtr`, is set during construction and cleared only at destruction, preventing re-entrancy races.

## Telemetry and Error Resilience

Each remap category sends **once-per-day** telemetry events (e.g., `Trace::DailyShortcutToShortcutRemapInvoked`) using `std::chrono::system_clock` to calculate day indices. Error handling wraps settings loading and telemetry in `try/catch` blocks that log to the PowerToys logger via `show_last_error_message` and `Trace::Error`, ensuring hook exceptions never crash the runner process.

## Configuration Examples

### Simple Key-to-Key Remap

```json
{
  "singleKeyReMap": {
    "0x41": { "target": 0x42, "type": "key" }
  }
}

```

This remaps **A** (0x41) to **B** (0x42). The engine looks up the source in `singleKeyReMap`, builds an `INPUT` structure for `VK_B`, sends it via `SendInput`, and returns `1` to swallow the original keystroke.

### Shortcut-to-Shortcut with Modifier Correction

```json
{
  "osLevelShortcutReMap": {
    "Win+A": {
      "targetShortcut": { "modifiers": ["Ctrl"], "key": "V" },
      "type": "shortcut"
    }
  }
}

```

When `HandleShortcutRemapEvent` detects **Win+A**, it releases the Windows key, injects a dummy key to stabilize the modifier state, then presses **Ctrl+V** before suppressing the original input.

### Program Launch Mapping

```json
{
  "osLevelShortcutReMap": {
    "Ctrl+Alt+P": {
      "targetShortcut": { "runProgram": "notepad.exe" },
      "type": "shortcut"
    }
  }
}

```

The engine matches the chord, starts Notepad in a background thread via `ShellExecute`, and returns `1` to prevent the original keystroke from reaching other applications.

## Summary

- **Global Hook**: Uses `SetWindowsHookEx(WH_KEYBOARD_LL)` in [`KeyboardManager.cpp`](https://github.com/microsoft/PowerToys/blob/main/KeyboardManager.cpp) to intercept all keystrokes system-wide without admin rights
- **Stateful Engine**: Maintains mappings in [`State.h`](https://github.com/microsoft/PowerToys/blob/main/State.h) structures (`singleKeyReMap`, `osLevelShortcutReMap`) that hot-reload via `EventWaiter` callbacks
- **Synthetic Input**: Generates replacement keystrokes through `SendInput` via [`KeyboardEventHandlers.cpp`](https://github.com/microsoft/PowerToys/blob/main/KeyboardEventHandlers.cpp), handling Unicode text, modifier chords, and dummy-key insertion for glitch prevention
- **Safety**: Ignores self-generated events to prevent infinite loops, wraps operations in exception handlers, and uninstalls the hook when idle to minimize overhead

## Frequently Asked Questions

### How does Keyboard Manager intercept keystrokes without administrator privileges?

The engine uses `WH_KEYBOARD_LL` (low-level) hooks rather than kernel-level keyboard filters. Windows allows global low-level hooks for processes running at the same integrity level as the input stream, meaning PowerToys can intercept keystrokes for remapping without elevated rights, unlike `WH_KEYBOARD` hooks which require administration for global scope.

### What prevents remapped keys from triggering infinite loops?

Before processing any event, `HandleKeyboardHookEvent` checks if the input was synthesized by the engine itself and immediately passes it through. Additionally, the `State` class tracks `activatedApp` and `CheckShortcutRemapInvoked` to ensure remapped outputs don't recursively match other remapping rules, creating a deterministic one-way transformation pipeline.

### How are modifier keys handled during complex shortcuts?

The `ResetChordsIfNeeded` helper in [`KeyboardEventHandlers.cpp`](https://github.com/microsoft/PowerToys/blob/main/KeyboardEventHandlers.cpp) manages chord states for two-key shortcuts, while the dummy-key insertion technique (inserting a harmless key event between modifier releases and target presses) prevents Windows from interpreting modifier transitions as unintended key combinations. This ensures **Win+A** → **Ctrl+V** doesn't leave the Windows key logically "stuck" down.

### Can configuration changes apply without restarting PowerToys?

Yes. The `changeSettingsCallback` lambda in [`KeyboardManager.cpp`](https://github.com/microsoft/PowerToys/blob/main/KeyboardManager.cpp) subscribes to file system events via `EventWaiter` monitoring the `SettingsEventName`. When the Settings UI writes new JSON to the module save folder, the engine calls `LoadSettings()` to refresh `singleKeyReMap` and shortcut tables while the hook remains active, applying changes within milliseconds without dropping the low-level hook.