diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 37341017..b05d16bf 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -30,7 +30,6 @@ target_include_directories(app PRIVATE include)
 target_sources(app PRIVATE src/kscan.c)
 target_sources(app PRIVATE src/matrix_transform.c)
 target_sources(app PRIVATE src/keymap.c)
-target_sources(app PRIVATE src/hid_listener.c)
 target_sources(app PRIVATE src/hid.c)
 target_sources(app PRIVATE src/sensors.c)
 target_sources_ifdef(CONFIG_ZMK_DISPLAY app PRIVATE src/display.c)
@@ -56,5 +55,5 @@ target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c)
 target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c)
 target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
 target_sources(app PRIVATE src/endpoints.c)
+target_sources(app PRIVATE src/hid_listener.c)
 target_sources(app PRIVATE src/main.c)
-
diff --git a/app/Kconfig b/app/Kconfig
index 01384a0f..55c5bae7 100644
--- a/app/Kconfig
+++ b/app/Kconfig
@@ -40,8 +40,8 @@ menuconfig ZMK_BLE
 	select BT_PERIPHERAL
 	select BT_GATT_DIS
 	select BT_GATT_BAS
-	select SETTINGS
-	select BT_SETTINGS
+	# select SETTINGS
+	# select BT_SETTINGS
 
 if ZMK_BLE
 
diff --git a/app/include/zmk/event-manager.h b/app/include/zmk/event-manager.h
index 39381715..43d3f299 100644
--- a/app/include/zmk/event-manager.h
+++ b/app/include/zmk/event-manager.h
@@ -72,8 +72,12 @@ struct zmk_event_subscription {
 #define ZMK_EVENT_RAISE(ev) \
     zmk_event_manager_raise((struct zmk_event_header *)ev);
 
+#define ZMK_EVENT_RAISE_AFTER(ev, mod) \
+    zmk_event_manager_raise_after((struct zmk_event_header *)ev, &zmk_listener_##mod);
+
 #define ZMK_EVENT_RELEASE(ev) \
     zmk_event_manager_release((struct zmk_event_header *)ev);
 
 int zmk_event_manager_raise(struct zmk_event_header *event);
+int zmk_event_manager_raise_after(struct zmk_event_header *event, const struct zmk_listener *listener);
 int zmk_event_manager_release(struct zmk_event_header *event);
diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c
index 34df1c0b..7404c798 100644
--- a/app/src/behaviors/behavior_key_press.c
+++ b/app/src/behaviors/behavior_key_press.c
@@ -28,27 +28,17 @@ static int behavior_key_press_init(struct device *dev)
 static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _)
 {
   const struct behavior_key_press_config *cfg = dev->config_info;
-  struct keycode_state_changed *ev;
   LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
 
-  ev = new_keycode_state_changed();
-  ev->usage_page = cfg->usage_page;
-  ev->keycode = keycode;
-  ev->state = true;
-  return ZMK_EVENT_RAISE(ev);
+  return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true));
 }
 
 static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _)
 {
   const struct behavior_key_press_config *cfg = dev->config_info;
-  struct keycode_state_changed *ev;
   LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
 
-  ev = new_keycode_state_changed();
-  ev->usage_page = cfg->usage_page;
-  ev->keycode = keycode;
-  ev->state = false;
-  return ZMK_EVENT_RAISE(ev);
+  return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false));
 }
 
 static const struct behavior_driver_api behavior_key_press_driver_api = {
diff --git a/app/src/behaviors/behavior_mod_tap.c b/app/src/behaviors/behavior_mod_tap.c
index 62604eba..6151f7e9 100644
--- a/app/src/behaviors/behavior_mod_tap.c
+++ b/app/src/behaviors/behavior_mod_tap.c
@@ -10,25 +10,124 @@
 #include <drivers/behavior.h>
 #include <logging/log.h>
 
+#include <zmk/matrix.h>
+#include <zmk/endpoints.h>
 #include <zmk/event-manager.h>
 #include <zmk/events/keycode-state-changed.h>
 #include <zmk/events/modifiers-state-changed.h>
+#include <zmk/hid.h>
 
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
-struct behavior_mod_tap_config { };
-struct behavior_mod_tap_data {
-  u16_t pending_press_positions;
+#define ZMK_BHV_MOD_TAP_MAX_HELD 4
+#define ZMK_BHV_MOD_TAP_MAX_PENDING_KC 4
+
+struct active_mod_tap_item {
+  u32_t keycode;
+  u8_t mods;
+  bool pending;
+  zmk_mod_flags active_mods;
 };
 
+struct captured_keycode_state_change_item {
+  struct keycode_state_changed* event;
+  zmk_mod_flags active_mods;
+};
+
+struct behavior_mod_tap_config { };
+struct behavior_mod_tap_data {
+  struct active_mod_tap_item active_mod_taps[ZMK_BHV_MOD_TAP_MAX_HELD];
+  struct captured_keycode_state_change_item captured_keycode_events[ZMK_BHV_MOD_TAP_MAX_PENDING_KC];
+};
+
+bool have_pending_mods(char *label) {
+  struct device *dev = device_get_binding(label);
+  struct behavior_mod_tap_data *data = dev->driver_data;
+
+  for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
+    if (data->active_mod_taps[i].mods) {
+      LOG_DBG("Found pending mods for %d and keycode 0x%02X", data->active_mod_taps[i].mods, data->active_mod_taps[i].keycode);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+struct captured_keycode_state_change_item* find_pending_keycode(struct behavior_mod_tap_data *data, u32_t keycode)
+{
+  for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_PENDING_KC; i++) {
+    if (data->captured_keycode_events[i].event == NULL) {
+      continue;
+    }
+
+    if (data->captured_keycode_events[i].event->keycode == keycode) {
+      return &data->captured_keycode_events[i];
+    }
+  }
+
+  return NULL;
+}
+
+zmk_mod_flags behavior_mod_tap_active_mods(struct behavior_mod_tap_data *data)
+{
+  zmk_mod_flags mods = 0;
+
+  for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
+    mods |= data->active_mod_taps[i].mods;
+  }
+
+  return mods;
+}
+
+int behavior_mod_tap_capture_keycode_event(struct behavior_mod_tap_data *data, struct keycode_state_changed *ev)
+{
+  for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_PENDING_KC; i++) {
+    if (data->captured_keycode_events[i].event != NULL) {
+      continue;
+    }
+
+    data->captured_keycode_events[i].event = ev;
+    data->captured_keycode_events[i].active_mods = behavior_mod_tap_active_mods(data);
+    return 0;
+  }
+
+  return -ENOMEM;
+}
+
+void behavior_mod_tap_update_active_mods_state(struct behavior_mod_tap_data *data, zmk_mod_flags used_flags)
+{
+  for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
+    if ((data->active_mod_taps[i].mods & used_flags) == data->active_mod_taps[i].mods) {
+      data->active_mod_taps[i].pending = false;
+    }
+  }
+}
+
+// How to pass context to subscription?!
 int behavior_mod_tap_listener(const struct zmk_event_header *eh)
 {
-  if (is_keycode_state_changed(eh)) {
+  if (is_keycode_state_changed(eh) && have_pending_mods(DT_INST_LABEL(0))) {
     struct device *dev = device_get_binding(DT_INST_LABEL(0));
-    const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
+    struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
+    struct behavior_mod_tap_data *data = dev->driver_data;
+    struct captured_keycode_state_change_item* pending_keycode;
     if (ev->state) {
-      struct behavior_mod_tap_data *data = dev->driver_data;
-      data->pending_press_positions = 0;
+      LOG_DBG("Have pending mods, capturing keycode 0x%02X event to ressend later", ev->keycode);
+      behavior_mod_tap_capture_keycode_event(data, ev);
+      return ZMK_EV_EVENT_CAPTURED;
+    } else if ((pending_keycode = find_pending_keycode(data, ev->keycode)) != NULL) {
+      LOG_DBG("Key released, going to activate mods 0x%02X then send pending key press for keycode 0x%02X",
+              pending_keycode->active_mods, pending_keycode->event->keycode);
+
+      zmk_hid_register_mods(pending_keycode->active_mods);
+      behavior_mod_tap_update_active_mods_state(data, pending_keycode->active_mods);
+
+      ZMK_EVENT_RELEASE(pending_keycode->event);
+      k_msleep(10);
+
+      pending_keycode->event = NULL;
+      pending_keycode->active_mods = 0;
     }
   }
   return 0;
@@ -46,9 +145,25 @@ static int behavior_mod_tap_init(struct device *dev)
 static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t mods, u32_t keycode)
 {
   struct behavior_mod_tap_data *data = dev->driver_data;
-  LOG_DBG("mods: %d, keycode: %d", mods, keycode);
-  WRITE_BIT(data->pending_press_positions, position, true);
-  return ZMK_EVENT_RAISE(create_modifiers_state_changed(mods, true));
+  LOG_DBG("mods: %d, keycode: 0x%02X", mods, keycode);
+  for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
+    if (data->active_mod_taps[i].mods != 0) {
+      continue;
+    }
+
+    zmk_mod_flags active_mods = behavior_mod_tap_active_mods(data);
+
+    data->active_mod_taps[i].active_mods = active_mods;
+    data->active_mod_taps[i].mods = mods;
+    data->active_mod_taps[i].keycode = keycode;
+    data->active_mod_taps[i].pending = true;
+
+    return 0;
+  }
+
+  LOG_WRN("Failed to record mod-tap activation, at maximum concurrent mod-tap activations");
+
+  return -ENOMEM;
 }
 
 static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t mods, u32_t keycode)
@@ -56,12 +171,66 @@ static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t
   struct behavior_mod_tap_data *data = dev->driver_data;
   LOG_DBG("mods: %d, keycode: %d", mods, keycode);
   
-  ZMK_EVENT_RAISE(create_modifiers_state_changed(mods, false));
-  k_msleep(10); // TODO: Better approach than k_msleep to avoid USB send failures? Retries in the USB endpoint layer?
-  if (data->pending_press_positions & BIT(position)) {
-    ZMK_EVENT_RAISE(create_keycode_state_changed(USAGE_KEYPAD, keycode, true));
-    k_msleep(10);
-    ZMK_EVENT_RAISE(create_keycode_state_changed(USAGE_KEYPAD, keycode, false));
+  for (int i = 0; i < ZMK_BHV_MOD_TAP_MAX_HELD; i++) {
+    struct active_mod_tap_item *item = &data->active_mod_taps[i];
+    if (item->mods == mods && item->keycode == keycode) {
+      if (item->pending) {
+        LOG_DBG("Sending un-triggered mod-tap for keycode: 0x%02X", keycode);
+
+        if (item->active_mods) {
+          LOG_DBG("Registering recorded active mods captured when mod-tap initially activated: 0x%02X", item->active_mods);
+          behavior_mod_tap_update_active_mods_state(data, item->active_mods);
+          zmk_hid_register_mods(item->active_mods);
+        }
+
+        struct keycode_state_changed *key_press = create_keycode_state_changed(USAGE_KEYPAD, item->keycode, true);
+        ZMK_EVENT_RAISE_AFTER(key_press, behavior_mod_tap);
+        k_msleep(10);
+
+        for (int j = 0; j < ZMK_BHV_MOD_TAP_MAX_PENDING_KC; j++) {
+          if (data->captured_keycode_events[j].event == NULL) {
+            continue;
+          }
+
+          struct keycode_state_changed *ev = data->captured_keycode_events[j].event;
+          data->captured_keycode_events[i].event = NULL;
+          data->captured_keycode_events[i].active_mods = 0;
+          LOG_DBG("Re-sending latched key press for usage page 0x%02X keycode 0x%02X state %s", ev->usage_page, ev->keycode, (ev->state ? "pressed" : "released"));
+          ZMK_EVENT_RELEASE(ev);
+          k_msleep(10);
+        }
+
+        struct keycode_state_changed *key_release = create_keycode_state_changed(USAGE_KEYPAD, keycode, false);
+        LOG_DBG("Sending un-triggered mod-tap release for keycode: 0x%02X", keycode);
+        ZMK_EVENT_RAISE_AFTER(key_release, behavior_mod_tap);
+        k_msleep(10);
+
+        if (item->active_mods) {
+          LOG_DBG("Unregistering recorded active mods captured when mod-tap initially activated: 0x%02X", item->active_mods);
+          zmk_hid_unregister_mods(item->active_mods);
+          zmk_endpoints_send_report(USAGE_KEYPAD);
+        }
+
+        
+      } else {
+        LOG_DBG("Releasing triggered mods: %d", mods);
+        zmk_hid_unregister_mods(mods);
+        zmk_endpoints_send_report(USAGE_KEYPAD);
+      }
+
+      item->mods = 0;
+      item->keycode = 0;
+      item->active_mods = 0;
+
+      LOG_DBG("Removing mods %d from active_mods for other held mod-taps", mods);
+      for (int j = 0; j < ZMK_BHV_MOD_TAP_MAX_HELD; j++) {
+        if (data->active_mod_taps[j].active_mods & mods) {
+          LOG_DBG("Removing 0x%02X from active mod tap mods 0x%02X keycode 0x%02X", mods, data->active_mod_taps[j].mods, data->active_mod_taps[j].keycode);
+          data->active_mod_taps[j].active_mods &= ~mods;
+        }
+      }
+      break;
+    }
   }
 
   return 0;
diff --git a/app/src/event_manager.c b/app/src/event_manager.c
index 3edba10a..5d2e9ed5 100644
--- a/app/src/event_manager.c
+++ b/app/src/event_manager.c
@@ -55,6 +55,22 @@ int zmk_event_manager_raise(struct zmk_event_header *event)
     return zmk_event_manager_handle_from(event, 0);
 }
 
+int zmk_event_manager_raise_after(struct zmk_event_header *event, const struct zmk_listener *listener)
+{
+    u8_t len = __event_subscriptions_end - __event_subscriptions_start;
+    for (int i = 0; i < len; i++) {
+        struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
+
+        if (ev_sub->event_type == event->event && ev_sub->listener == listener) {
+            return zmk_event_manager_handle_from(event, i+1);
+        }
+    }
+
+    LOG_WRN("Unable to find where to raise this after event");
+
+    return -EINVAL;
+}
+
 int zmk_event_manager_release(struct zmk_event_header *event)
 {
     return zmk_event_manager_handle_from(event, event->last_listener_index + 1);
diff --git a/app/src/events/keycode_state_changed.c b/app/src/events/keycode_state_changed.c
index 964b24aa..73508e16 100644
--- a/app/src/events/keycode_state_changed.c
+++ b/app/src/events/keycode_state_changed.c
@@ -7,4 +7,4 @@
 #include <kernel.h>
 #include <zmk/events/keycode-state-changed.h>
 
-ZMK_EVENT_IMPL(keycode_state_changed);
\ No newline at end of file
+ZMK_EVENT_IMPL(keycode_state_changed);