diff --git a/src/hub.js b/src/hub.js
index 93221603b2ed89a4ef85e698d4eee5c842766cd1..edde9177a6142da53f0b701e67e1d605dcd53c7d 100644
--- a/src/hub.js
+++ b/src/hub.js
@@ -77,6 +77,7 @@ import "./systems/personal-space-bubble";
 import "./systems/app-mode";
 import "./systems/exit-on-blur";
 import "./systems/userinput/userinput";
+import "./systems/userinput/userinput-debug";
 
 import "./gltf-component-mappings";
 
diff --git a/src/systems/userinput/bindings/keyboard-mouse-user.js b/src/systems/userinput/bindings/keyboard-mouse-user.js
index b42e5a1654302bc60f175118d915fd941a6b9322..2ff3297c9ae344cfda7dc3e23dd589df13356fe6 100644
--- a/src/systems/userinput/bindings/keyboard-mouse-user.js
+++ b/src/systems/userinput/bindings/keyboard-mouse-user.js
@@ -158,7 +158,8 @@ export const keyboardMouseUserBindings = addSetsToBindings({
       dest: {
         value: paths.actions.stopGazeTeleport
       },
-      xform: xforms.falling
+      xform: xforms.falling,
+      priority: 100
     }
   ],
 
@@ -311,5 +312,19 @@ export const keyboardMouseUserBindings = addSetsToBindings({
       dest: { value: paths.actions.cursor.grab },
       xform: xforms.rising
     }
+  ],
+  [sets.inputFocused]: [
+    {
+      src: { value: "/device/keyboard" },
+      dest: { value: paths.noop },
+      xform: xforms.noop,
+      priority: 1000
+    },
+    {
+      src: { value: "/device/keyboard/l" },
+      dest: { value: paths.actions.logDebugFrame },
+      xform: xforms.rising,
+      priority: 1100
+    }
   ]
 });
diff --git a/src/systems/userinput/resolve-action-sets.js b/src/systems/userinput/resolve-action-sets.js
index 7c1a8c15a3ff0795105cf5f0717ad852c7a38165..39a0d8e50d76380d6791565db074616bc8fde4be 100644
--- a/src/systems/userinput/resolve-action-sets.js
+++ b/src/systems/userinput/resolve-action-sets.js
@@ -162,4 +162,5 @@ export function resolveActionSets() {
   userinput.toggleSet(sets.cursorHoldingPen, cursorHoldingPen);
   userinput.toggleSet(sets.cursorHoldingCamera, cursorHoldingCamera);
   userinput.toggleSet(sets.cursorHoldingInteractable, cursorHoldingInteractable);
+  userinput.toggleSet(sets.inputFocused, document.activeElement.nodeName === "INPUT");
 }
diff --git a/src/systems/userinput/sets.js b/src/systems/userinput/sets.js
index c764b47cfaddd0a0ea635bfff267031a033ee1c5..e29d0489e0d091edf40ec8746d782237b3fa263c 100644
--- a/src/systems/userinput/sets.js
+++ b/src/systems/userinput/sets.js
@@ -1,5 +1,6 @@
 export const sets = {};
 sets.global = "global";
+sets.inputFocused = "inputFocused";
 sets.cursorHoveringOnPen = "cursorHoveringOnPen";
 sets.cursorHoveringOnCamera = "cursorHoveringOnCamera";
 sets.cursorHoveringOnInteractable = "cursorHoveringOnInteractable";
diff --git a/src/systems/userinput/userinput-debug.js b/src/systems/userinput/userinput-debug.js
new file mode 100644
index 0000000000000000000000000000000000000000..9eea8a87a2abdfa0db4dd228f12a3bbcd801cb7e
--- /dev/null
+++ b/src/systems/userinput/userinput-debug.js
@@ -0,0 +1,83 @@
+import { paths } from "./paths";
+const line = "__________________________________________________________________";
+const bindingToString = b => {
+  const sb = [];
+  sb.push("  ");
+  sb.push("src: ");
+  sb.push("\n");
+  for (const s of Object.keys(b.src)) {
+    sb.push("  ");
+    sb.push("  ");
+    sb.push(s);
+    sb.push(" : ");
+    sb.push(b.src[s]);
+    sb.push("\n");
+  }
+  sb.push("  ");
+  sb.push("dest: ");
+  sb.push("\n");
+  for (const s of Object.keys(b.dest)) {
+    sb.push("  ");
+    sb.push("  ");
+    sb.push(s);
+    sb.push(" : ");
+    sb.push(b.dest[s]);
+    sb.push("\n");
+  }
+  sb.push("  ");
+  sb.push("priority");
+  sb.push(" : ");
+  sb.push(b.priority || 0);
+  for (const s of b.sets) {
+    sb.push("\n");
+    sb.push("  ");
+    sb.push("in set");
+    sb.push(" : ");
+    sb.push(s);
+    sb.push("\n");
+  }
+  sb.push(line);
+  sb.push("\n");
+  return sb.join("");
+};
+AFRAME.registerSystem("userinput-debug", {
+  tick() {
+    const userinput = AFRAME.scenes[0].systems.userinput;
+    if (userinput.get(paths.actions.logDebugFrame) || userinput.get(paths.actions.log)) {
+      const sb = [];
+      sb.push("\n");
+      sb.push(line);
+      sb.push("\n");
+      sb.push("actives:");
+      sb.push("\n");
+      sb.push(line);
+      sb.push("\n");
+      for (let i = 0; i < userinput.runners.length; i++) {
+        if (userinput.actives[i]) {
+          sb.push(bindingToString(userinput.runners[i]));
+        }
+      }
+      sb.push("\n");
+      sb.push(line);
+      sb.push("\n");
+      sb.push("inactives:");
+      sb.push("\n");
+      sb.push(line);
+      sb.push("\n");
+      for (let i = 0; i < userinput.runners.length; i++) {
+        if (!userinput.actives[i]) {
+          sb.push(bindingToString(userinput.runners[i]));
+        }
+      }
+      console.log("active and inactive bindings");
+      console.log(sb.join(""));
+      console.log("runners", userinput.runners);
+      console.log("actives", userinput.actives);
+      console.log("xformStates", userinput.xformStates);
+      console.log("devices", userinput.activeDevices);
+      console.log("map", userinput.map);
+      console.log("activeSets", userinput.activeSets);
+      console.log("frame", userinput.frame);
+    }
+  }
+});
diff --git a/src/systems/userinput/userinput.js b/src/systems/userinput/userinput.js
index 1ac910e9e0e98781d3aed71186b595a56fd248ac..fc84e80f7a971ce43dec6ec5b0228557d5968d26 100644
--- a/src/systems/userinput/userinput.js
+++ b/src/systems/userinput/userinput.js
@@ -1,4 +1,3 @@
-import { paths } from "./paths";
 import { sets } from "./sets";
 
 import { MouseDevice } from "./devices/mouse";
@@ -154,7 +153,7 @@ AFRAME.registerSystem("userinput", {
     for (const { set, value } of this.pendingSetChanges) {
       this.activeSets[value ? "add" : "delete"](set);
     }
-    let runners = this.pendingSetChanges.length ? [] : this.runners;
+    const runners = this.pendingSetChanges.length ? [] : this.runners;
     if (this.pendingSetChanges.length) {
       this.pendingSetChanges.length = 0;
       this.actives = [];
@@ -200,15 +199,15 @@ AFRAME.registerSystem("userinput", {
         let active = true;
         for (const p in binding.src) {
           const path = binding.src[p];
-          let subpaths = String.split(path, "/");
-          while (binding.priority && subpaths.length) {
-            if (binding.priority < maxAmongActive(Array.join(subpaths, "/"), this.map, this.activeSets)) {
+          const subpaths = String.split(path, "/");
+          while (subpaths.length > 1) {
+            if ((binding.priority || 0) < maxAmongActive(Array.join(subpaths, "/"), this.map, this.activeSets)) {
               active = false;
             }
             subpaths.pop();
           }
-          this.actives[i] = active;
         }
+        this.actives[i] = active;
       }
     }
 
@@ -233,83 +232,5 @@ AFRAME.registerSystem("userinput", {
     }
 
     this.runners = runners;
-
-    if (this.frame[paths.actions.logDebugFrame] || this.frame[paths.actions.log]) {
-      const line = "__________________________________________________________________";
-      const bindingToString = b => {
-        let sb = [];
-        sb.push("  ");
-        sb.push("src: ");
-        sb.push("\n");
-        for (const s of Object.keys(b.src)) {
-          sb.push("  ");
-          sb.push("  ");
-          sb.push(s);
-          sb.push(" : ");
-          sb.push(b.src[s]);
-          sb.push("\n");
-        }
-        sb.push("  ");
-        sb.push("dest: ");
-        sb.push("\n");
-        for (const s of Object.keys(b.dest)) {
-          sb.push("  ");
-          sb.push("  ");
-          sb.push(s);
-          sb.push(" : ");
-          sb.push(b.dest[s]);
-          sb.push("\n");
-        }
-        sb.push("  ");
-        sb.push("priority");
-        sb.push(" : ");
-        sb.push(b.priority || 0);
-        for (const s of b.sets) {
-          sb.push("\n");
-          sb.push("  ");
-          sb.push("in set");
-          sb.push(" : ");
-          sb.push(s);
-          sb.push("\n");
-        }
-        sb.push(line);
-        sb.push("\n");
-        return sb.join("");
-      };
-      let sb = [];
-      sb.push("\n");
-      sb.push(line);
-      sb.push("\n");
-      sb.push("actives:");
-      sb.push("\n");
-      sb.push(line);
-      sb.push("\n");
-      for (let i = 0; i < this.runners.length; i++) {
-        if (this.actives[i]) {
-          sb.push(bindingToString(this.runners[i]));
-        }
-      }
-      sb.push("\n");
-      sb.push(line);
-      sb.push("\n");
-      sb.push("inactives:");
-      sb.push("\n");
-      sb.push(line);
-      sb.push("\n");
-      for (let i = 0; i < this.runners.length; i++) {
-        if (!this.actives[i]) {
-          sb.push(bindingToString(this.runners[i]));
-        }
-      }
-      console.log("active and inactive bindings");
-      console.log(sb.join(""));
-      console.log("runners", this.runners);
-      console.log("actives", this.actives);
-      console.log("xformStates", this.xformStates);
-      console.log("devices", this.activeDevices);
-      console.log("map", this.map);
-      console.log("activeSets", this.activeSets);
-      console.log("frame", this.frame);
-    }
   }
 });