diff --git a/include/bindings.h b/include/bindings.h
index b78a00fc..648933ff 100644
--- a/include/bindings.h
+++ b/include/bindings.h
@@ -28,7 +28,7 @@ extern const char *DEFAULT_BINDING_MODE;
 Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
                            const char *release, const char *border, const char *whole_window,
                            const char *exclude_titlebar, const char *command, const char *mode,
-                           bool pango_markup);
+                           bool pango_markup, const char *passthrough);
 
 /**
  * Grab the bound keys (tell X to send us keypress events for those keycodes)
diff --git a/include/config_directives.h b/include/config_directives.h
index fd384c0c..849db9ce 100644
--- a/include/config_directives.h
+++ b/include/config_directives.h
@@ -77,7 +77,7 @@ CFGFUN(color_single, const char *colorclass, const char *color);
 CFGFUN(floating_modifier, const char *modifiers);
 CFGFUN(default_border, const char *windowtype, const char *border, const long width);
 CFGFUN(workspace, const char *workspace, const char *output);
-CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command);
+CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *passthrough, const char *command);
 
 CFGFUN(enter_mode, const char *pango_markup, const char *modename);
 CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command);
diff --git a/include/data.h b/include/data.h
index f448d263..4d070330 100644
--- a/include/data.h
+++ b/include/data.h
@@ -357,6 +357,11 @@ struct Binding {
     char *command;
 
     TAILQ_ENTRY(Binding) bindings;
+
+    /** Window class to use for key passthrough. Currently an exact string match. */
+    struct {
+        char *class;
+    } passthrough;
 };
 
 /**
diff --git a/parser-specs/config.spec b/parser-specs/config.spec
index d1528374..4f10fb68 100644
--- a/parser-specs/config.spec
+++ b/parser-specs/config.spec
@@ -448,6 +448,8 @@ state BINDING:
       ->
   '+'
       ->
+  passthrough = '--passthrough'
+      ->
   key = word
       -> BINDCOMMAND
 
@@ -460,8 +462,10 @@ state BINDCOMMAND:
       ->
   exclude_titlebar = '--exclude-titlebar'
       ->
+  passthrough = '--passthrough'
+      ->
   command = string
-      -> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $exclude_titlebar, $command)
+      -> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $exclude_titlebar, $passthrough, $command)
 
 ################################################################################
 # Mode configuration
diff --git a/src/bindings.c b/src/bindings.c
index 909fe2c3..de122e45 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -59,7 +59,7 @@ static struct Mode *mode_from_name(const char *name, bool pango_markup) {
 Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
                            const char *release, const char *border, const char *whole_window,
                            const char *exclude_titlebar, const char *command, const char *modename,
-                           bool pango_markup) {
+                           bool pango_markup, const char *passthrough) {
     Binding *new_binding = scalloc(1, sizeof(Binding));
     DLOG("Binding %p bindtype %s, modifiers %s, input code %s, release %s\n", new_binding, bindtype, modifiers, input_code, release);
     new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS);
@@ -107,6 +107,13 @@ Binding *configure_binding(const char *bindtype, const char *modifiers, const ch
 
     TAILQ_INIT(&(new_binding->keycodes_head));
 
+    // XXX: should change this to be configurable, but I only care about Emacs, so.
+    if (passthrough) {
+        new_binding->passthrough.class = sstrdup("Emacs");
+    } else {
+        new_binding->passthrough.class = NULL;
+    }
+
     return new_binding;
 }
 
@@ -819,6 +826,9 @@ static Binding *binding_copy(Binding *bind) {
     if (bind->command != NULL) {
         ret->command = sstrdup(bind->command);
     }
+    if (bind->passthrough.class != NULL) {
+        ret->passthrough.class = sstrdup(bind->passthrough.class);
+    }
     TAILQ_INIT(&(ret->keycodes_head));
     struct Binding_Keycode *binding_keycode;
     TAILQ_FOREACH (binding_keycode, &(bind->keycodes_head), keycodes) {
@@ -846,6 +856,7 @@ void binding_free(Binding *bind) {
 
     FREE(bind->symbol);
     FREE(bind->command);
+    FREE(bind->passthrough.class);
     FREE(bind);
 }
 
diff --git a/src/config_directives.c b/src/config_directives.c
index 52ab6e14..ad605187 100644
--- a/src/config_directives.c
+++ b/src/config_directives.c
@@ -175,8 +175,8 @@ CFGFUN(font, const char *font) {
     set_font(&config.font);
 }
 
-CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command) {
-    configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, DEFAULT_BINDING_MODE, false);
+CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *passthrough, const char *command) {
+    configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, DEFAULT_BINDING_MODE, false, passthrough);
 }
 
 /*******************************************************************************
@@ -192,7 +192,7 @@ CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *ke
         return;
     }
 
-    configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, current_mode, current_mode_pango_markup);
+    configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, current_mode, current_mode_pango_markup, NULL);
 }
 
 CFGFUN(enter_mode, const char *pango_markup, const char *modename) {
diff --git a/src/key_press.c b/src/key_press.c
index 715ba30a..43a3e40f 100644
--- a/src/key_press.c
+++ b/src/key_press.c
@@ -8,6 +8,7 @@
  *
  */
 #include "all.h"
+#include "xcb/xproto.h"
 
 /*
  * There was a KeyPress or KeyRelease (both events have the same fields). We
@@ -29,6 +30,30 @@ void handle_key_press(xcb_key_press_event_t *event) {
         return;
     }
 
+    DLOG("PATCH: checking if we should pass keypress through\n");
+    if (bind->passthrough.class) {
+        xcb_generic_error_t *focus_error;
+        xcb_get_input_focus_reply_t *input_focus = xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), &focus_error);
+
+        if (focus_error != NULL) {
+            DLOG("PATCH: could not get focused window");
+            free(focus_error);
+        } else {
+            Con *con = con_by_window_id(input_focus->focus);
+            const xcb_window_t focus = input_focus->focus;
+            free(input_focus);
+
+            const bool should_pass = con && con->window->class_class && strcmp(con->window->class_class, bind->passthrough.class) == 0;
+            if (should_pass) {
+                DLOG("PATCH: forwarding keypress (%d %s %s @ %d %d)\n", focus, con->name, con->window->class_class, event->event_x, event->event_y);
+                event->event = focus;
+                xcb_send_event(conn, false, focus, XCB_EVENT_MASK_NO_EVENT, (const char *)event);
+                return;
+            }
+        }
+    }
+
+    DLOG("PATCH: handling keypress normally\n");
     CommandResult *result = run_binding(bind, NULL);
     command_result_free(result);
 }
