diff --git a/IPython/html/static/notebook/js/widgets/string.js b/IPython/html/static/notebook/js/widgets/string.js
index f221d8d..16af4bb 100644
--- a/IPython/html/static/notebook/js/widgets/string.js
+++ b/IPython/html/static/notebook/js/widgets/string.js
@@ -113,7 +113,7 @@ define(["notebook/js/widget"], function(widget_manager){
         // Handles: Backend -> Frontend Sync
         //          Frontent -> Frontend Sync
         update : function(){
-            if (!this.user_invoked_update) {
+            if (this.$textbox.val() != this.model.get('value')) {
                 this.$textbox.val(this.model.get('value'));
             }
 
@@ -137,19 +137,15 @@ define(["notebook/js/widget"], function(widget_manager){
         
         // Handles and validates user input.
         handleChanging: function(e) { 
-            this.user_invoked_update = true;
             this.model.set('value', e.target.value);
             this.model.update_other_views(this);
-            this.user_invoked_update = false;
         },
         
         // Handles text submition
         handleKeypress: function(e) { 
             if (e.keyCode == 13) { // Return key
-                this.user_invoked_update = true;
                 this.model.set('submits', this.model.get('submits') + 1);
                 this.model.update_other_views(this);
-                this.user_invoked_update = false;
             }
         },
     });
diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py
index 2c540eb..0a2522a 100644
--- a/IPython/html/widgets/widget.py
+++ b/IPython/html/widgets/widget.py
@@ -58,7 +58,7 @@ class Widget(LoggingConfigurable):
                 old._children.remove(self)                
 
     # Private/protected declarations
-    _property_lock = False
+    _property_lock = (None, None) # Last updated (key, value) from the front-end.  Prevents echo.
     _css = Dict() # Internal CSS property dict
     _add_class = List() # Used to add a js class to a DOM element (call#, selector, class_name)
     _remove_class = List() # Used to remove a js class from a DOM element (call#, selector, class_name)
@@ -153,20 +153,21 @@ class Widget(LoggingConfigurable):
     
     def _handle_recieve_state(self, sync_data):
         """Called when a state is recieved from the frontend."""
-        self._property_lock = True
-        try:
-            
-            # Use _keys instead of keys - Don't get retrieve the css from the client side.
-            for name in self._keys:
-                if name in sync_data:
+        # Use _keys instead of keys - Don't get retrieve the css from the client side.
+        for name in self._keys:
+            if name in sync_data:
+                try:
+                    self._property_lock = (name, sync_data[name])
                     setattr(self, name, sync_data[name])
-        finally:
-            self._property_lock = False
+                finally:
+                    self._property_lock = (None, None)
     
     
     def _handle_property_changed(self, name, old, new):
         """Called when a proeprty has been changed."""
-        if not self._property_lock and self._comm is not None:
+        # Make sure this isn't information that the front-end just sent us.
+        if self._property_lock[0] != name and self._property_lock[1] != new \
+        and self._comm is not None:
             # TODO: Validate properties.
             # Send new state to frontend
             self.send_state(key=name)