diff --git a/src/console.c b/src/console.c
index 50ecfec9c28fa11a9395907478dbb93d9d416a24..c38a32b4f88a5df516ed0369e8bbc13afaa3c198 100644
--- a/src/console.c
+++ b/src/console.c
@@ -918,6 +918,22 @@ static void CON_InputDelChar(void)
 // ----
 //
 
+//
+// Same as CON_Responder, but is process before everything else, so it cannot be blocked.
+//
+boolean CON_PreResponder(event_t *ev)
+{
+	if (ev->type == ev_keydown && shiftdown == 1 && ev->key == KEY_ESCAPE)
+	{
+		I_SetTextInputMode(con_destlines == 0); // inverse, since this is changed next tic.
+		consoletoggle = true;
+		return true;
+	}
+
+	return false;
+}
+
+//
 // Handles console key input
 //
 boolean CON_Responder(event_t *ev)
diff --git a/src/console.h b/src/console.h
index 2af01f1a3af8bdd50901eabaa5b301107741e213..664b74a223826ee755078f56a046529c553c15b4 100644
--- a/src/console.h
+++ b/src/console.h
@@ -19,6 +19,7 @@ void CON_Init(void);
 void CON_StartRefresh(void);
 void CON_StopRefresh(void);
 
+boolean CON_PreResponder(event_t *ev);
 boolean CON_Responder(event_t *ev);
 
 #ifdef HAVE_THREADS
diff --git a/src/d_main.c b/src/d_main.c
index a6a9385d29d9529374417aa2f37c8978fe1b3c0b..2ae741c4eb79f6a7666c938581a8df036ee95e1e 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -227,6 +227,9 @@ void D_ProcessEvents(void)
 			}
 		}
 
+		if (CON_PreResponder(ev))
+			continue;
+
 		// Screenshots over everything so that they can be taken anywhere.
 		if (M_ScreenshotResponder(ev))
 			continue; // ate the event