diff --git a/src/Infiltration/ui/BackwardGame.tsx b/src/Infiltration/ui/BackwardGame.tsx
index b7f82b553..0bea8d51f 100644
--- a/src/Infiltration/ui/BackwardGame.tsx
+++ b/src/Infiltration/ui/BackwardGame.tsx
@@ -33,7 +33,7 @@ export function BackwardGame(props: IMinigameProps): React.ReactElement {
   const [answer] = useState(makeAnswer(difficulty));
   const [guess, setGuess] = useState("");
 
-  function press(event: React.KeyboardEvent<HTMLElement>): void {
+  function press(this: Document, event: KeyboardEvent): void {
     event.preventDefault();
     if (event.keyCode === 16) return;
     const nextGuess = guess + event.key.toUpperCase();
diff --git a/src/Infiltration/ui/BracketGame.tsx b/src/Infiltration/ui/BracketGame.tsx
index 1c8189ae8..a78cd58b1 100644
--- a/src/Infiltration/ui/BracketGame.tsx
+++ b/src/Infiltration/ui/BracketGame.tsx
@@ -36,7 +36,7 @@ function generateLeftSide(difficulty: Difficulty): string {
   return str;
 }
 
-function getChar(event: React.KeyboardEvent<HTMLElement>): string {
+function getChar(event: KeyboardEvent): string {
   if (event.keyCode == 48 && event.shiftKey) return ")";
   if (event.keyCode == 221 && !event.shiftKey) return "]";
   if (event.keyCode == 221 && event.shiftKey) return "}";
@@ -60,7 +60,7 @@ export function BracketGame(props: IMinigameProps): React.ReactElement {
   const [right, setRight] = useState("");
   const [left] = useState(generateLeftSide(difficulty));
 
-  function press(event: React.KeyboardEvent<HTMLElement>): void {
+  function press(this: Document, event: KeyboardEvent): void {
     event.preventDefault();
     const char = getChar(event);
     if (!char) return;
diff --git a/src/Infiltration/ui/BribeGame.tsx b/src/Infiltration/ui/BribeGame.tsx
index bae3a1b79..17841959b 100644
--- a/src/Infiltration/ui/BribeGame.tsx
+++ b/src/Infiltration/ui/BribeGame.tsx
@@ -30,7 +30,7 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
   const [choices] = useState(makeChoices(difficulty));
   const [index, setIndex] = useState(0);
 
-  function press(event: React.KeyboardEvent<HTMLElement>): void {
+  function press(this: Document, event: KeyboardEvent): void {
     event.preventDefault();
     const k = event.keyCode;
     if (k === 32) {
diff --git a/src/Infiltration/ui/CheatCodeGame.tsx b/src/Infiltration/ui/CheatCodeGame.tsx
index d7cc192cc..eb6dcccc6 100644
--- a/src/Infiltration/ui/CheatCodeGame.tsx
+++ b/src/Infiltration/ui/CheatCodeGame.tsx
@@ -32,7 +32,7 @@ export function CheatCodeGame(props: IMinigameProps): React.ReactElement {
   const [code] = useState(generateCode(difficulty));
   const [index, setIndex] = useState(0);
 
-  function press(event: React.KeyboardEvent<HTMLElement>): void {
+  function press(this: Document, event: KeyboardEvent): void {
     event.preventDefault();
     if (code[index] !== getArrow(event)) {
       props.onFailure();
diff --git a/src/Infiltration/ui/Cyberpunk2077Game.tsx b/src/Infiltration/ui/Cyberpunk2077Game.tsx
index 0305ab6a6..b4cdaee7d 100644
--- a/src/Infiltration/ui/Cyberpunk2077Game.tsx
+++ b/src/Infiltration/ui/Cyberpunk2077Game.tsx
@@ -35,7 +35,7 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
   const [index, setIndex] = useState(0);
   const [pos, setPos] = useState([0, 0]);
 
-  function press(event: React.KeyboardEvent<HTMLElement>): void {
+  function press(this: Document, event: KeyboardEvent): void {
     event.preventDefault();
     const move = [0, 0];
     const arrow = getArrow(event);
diff --git a/src/Infiltration/ui/KeyHandler.tsx b/src/Infiltration/ui/KeyHandler.tsx
index 9706e2bf3..3294a2f41 100644
--- a/src/Infiltration/ui/KeyHandler.tsx
+++ b/src/Infiltration/ui/KeyHandler.tsx
@@ -1,22 +1,22 @@
 import React, { useEffect } from "react";
 
 interface IProps {
-  onKeyDown: (event: React.KeyboardEvent<HTMLElement>) => void;
+  onKeyDown: (this: Document, event: KeyboardEvent) => void;
   onFailure: (options?: { automated: boolean }) => void;
 }
 
 export function KeyHandler(props: IProps): React.ReactElement {
-  let elem: any;
-  useEffect(() => elem.focus());
-
-  function onKeyDown(event: React.KeyboardEvent<HTMLElement>): void {
-    if (!event.isTrusted) {
-      props.onFailure({ automated: true });
-      return;
+  useEffect(() => {
+    console.log("binding");
+    function press(this: Document, event: KeyboardEvent): void {
+      console.log("press!");
+      const f = props.onKeyDown.bind(this);
+      f(event);
     }
-    props.onKeyDown(event);
-  }
+    document.addEventListener("keydown", press);
+    return () => document.removeEventListener("keydown", press);
+  });
 
   // invisible autofocused element that eats all the keypress for the minigames.
-  return <div tabIndex={1} ref={(c) => (elem = c)} onKeyDown={onKeyDown} />;
+  return <></>;
 }
diff --git a/src/Infiltration/ui/MinesweeperGame.tsx b/src/Infiltration/ui/MinesweeperGame.tsx
index f30f76474..58cf19b67 100644
--- a/src/Infiltration/ui/MinesweeperGame.tsx
+++ b/src/Infiltration/ui/MinesweeperGame.tsx
@@ -35,7 +35,7 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
   const [pos, setPos] = useState([0, 0]);
   const [memoryPhase, setMemoryPhase] = useState(true);
 
-  function press(event: React.KeyboardEvent<HTMLElement>): void {
+  function press(this: Document, event: KeyboardEvent): void {
     event.preventDefault();
     if (memoryPhase) return;
     const move = [0, 0];
diff --git a/src/Infiltration/ui/SlashGame.tsx b/src/Infiltration/ui/SlashGame.tsx
index 1ab474a89..0db257ab0 100644
--- a/src/Infiltration/ui/SlashGame.tsx
+++ b/src/Infiltration/ui/SlashGame.tsx
@@ -27,7 +27,7 @@ export function SlashGame(props: IMinigameProps): React.ReactElement {
   interpolate(difficulties, props.difficulty, difficulty);
   const [guarding, setGuarding] = useState(true);
 
-  function press(event: React.KeyboardEvent<HTMLElement>): void {
+  function press(this: Document, event: KeyboardEvent): void {
     event.preventDefault();
     if (event.keyCode !== 32) return;
     if (guarding) {
diff --git a/src/Infiltration/ui/WireCuttingGame.tsx b/src/Infiltration/ui/WireCuttingGame.tsx
index 70fe80db2..78709bc0f 100644
--- a/src/Infiltration/ui/WireCuttingGame.tsx
+++ b/src/Infiltration/ui/WireCuttingGame.tsx
@@ -60,7 +60,7 @@ export function WireCuttingGame(props: IMinigameProps): React.ReactElement {
   const [cutWires, setCutWires] = useState(new Array(wires.length).fill(false));
   const [questions] = useState(generateQuestion(wires, difficulty));
 
-  function press(event: React.KeyboardEvent<HTMLElement>): void {
+  function press(this: Document, event: KeyboardEvent): void {
     event.preventDefault();
     const wireNum = parseInt(event.key);
 
diff --git a/src/Infiltration/utils.ts b/src/Infiltration/utils.ts
index 81fbe2223..bd7d7a65d 100644
--- a/src/Infiltration/utils.ts
+++ b/src/Infiltration/utils.ts
@@ -4,7 +4,7 @@ export function random(min: number, max: number): number {
   return Math.random() * (max - min) + min;
 }
 
-export function getArrow(event: React.KeyboardEvent<HTMLElement>): string {
+export function getArrow(event: KeyboardEvent): string {
   switch (event.keyCode) {
     case 38:
     case 87: