diff --git a/src/systems/userinput/bindings/vive-user.js b/src/systems/userinput/bindings/vive-user.js
index 7237ed7d82fa9c72d3924ec2b32b6453124218d2..16772c1bce3b995cae157477393e23eed0320d73 100644
--- a/src/systems/userinput/bindings/vive-user.js
+++ b/src/systems/userinput/bindings/vive-user.js
@@ -948,5 +948,13 @@ export const viveUserBindings = addSetsToBindings({
       xform: xforms.falling,
       priority: 3
     }
+  ],
+  [sets.inputFocused]: [
+    {
+      src: { value: "/device/keyboard" },
+      dest: { value: paths.noop },
+      xform: xforms.noop,
+      priority: 1000
+    }
   ]
 });
diff --git a/src/systems/userinput/userinput.js b/src/systems/userinput/userinput.js
index 35398ce7a2471defd2460acf75a8a2b8ff97df99..f380ad216afc6d909ec59f719654210e7baab833 100644
--- a/src/systems/userinput/userinput.js
+++ b/src/systems/userinput/userinput.js
@@ -25,6 +25,16 @@ import { resolveActionSets } from "./resolve-action-sets";
 import { GamepadDevice } from "./devices/gamepad";
 import { gamepadBindings } from "./bindings/generic-gamepad";
 
+function intersection(setA, setB) {
+  var _intersection = new Set();
+  for (var elem of setB) {
+    if (setA.has(elem)) {
+      _intersection.add(elem);
+    }
+  }
+  return _intersection;
+}
+
 const satisfiesPath = (binding, path) => {
   return Object.values(binding.dest) && Object.values(binding.dest).indexOf(path) !== -1;
 };
@@ -142,6 +152,7 @@ AFRAME.registerSystem("userinput", {
   init() {
     this.frame = {};
 
+    this.prevActiveSets = new Set();
     this.activeSets = new Set([sets.global]);
     this.pendingSetChanges = [];
     this.xformStates = new Map();
@@ -256,11 +267,17 @@ AFRAME.registerSystem("userinput", {
       this.masks = computeMasks(this.sortedBindings);
     }
 
+    this.prevActiveSets.clear();
+    for (const item of this.activeSets) {
+      this.prevActiveSets.add(item);
+    }
     resolveActionSets();
     for (const { set, value } of this.pendingSetChanges) {
       this.activeSets[value ? "add" : "delete"](set);
     }
-    const activeSetsChanged = this.pendingSetChanges.length; // TODO: correct this
+    const activeSetsChanged =
+      this.prevActiveSets.size !== this.activeSets.size ||
+      intersection(this.prevActiveSets, this.activeSets).size !== this.activeSets.size;
     this.pendingSetChanges.length = 0;
     if (registeredMappingsChanged || activeSetsChanged || (!this.actives && !this.masked)) {
       this.prevActives = this.actives;