diff --git a/src/console.c b/src/console.c
index 2eb5b26c3afeae0459a9d4b06aa79274185628f8..4533dfca47864165e9c67391f48767355fef0f4e 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 d75a4d5013d9a92e7abccad7211721b3fa1f00b5..2b8d4326a0868fe2cbced6bc40274b96d2598c95 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