diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js
index 0015d849b5dcaa5f3568beb6809d1d1b19636c90..6f984859e2fbc266ec2d4ee360f11c18dbe16041 100644
--- a/pd/nw/pd_canvas.js
+++ b/pd/nw/pd_canvas.js
@@ -106,6 +106,11 @@ function nw_window_focus_callback() {
     }
 }
 
+function nw_window_blur_callback(name) {
+    // Fake a mouseup event
+    pdgui.pdsend(name, "mouseup_fake");
+}
+
 // These three functions need to be inside canvas_events closure
 function canvas_find_whole_word(elem) {
     canvas_events.match_words(elem.checked);
@@ -416,18 +421,11 @@ var canvas_events = (function() {
             },
             text_mousedown: function(evt) {
                 if (textbox() !== evt.target && !target_is_scrollbar(evt)) {
-                    // Yes: I _really_ want .innerText and NOT .textContent
-                    // here.  I want those newlines: although that isn't
-                    // standard in Pd-Vanilla, Pd-l2ork uses and preserves
-                    // them inside comments
                     utils.create_obj();
-                    //var fudi_msg = text_to_fudi(textbox().innerText);
-                    //pdgui.pdsend(name, "createobj", fudi_msg);
-                    //pdgui.post("formatted content is " + fudi_msg);
                     // send a mousedown and mouseup event to Pd to instantiate
                     // the object
                     events.mousedown(evt);
-                    events.mouseup(evt);
+                    //events.mouseup(evt);
                     canvas_events.normal();
                 }
                 evt.stopPropagation();
@@ -559,6 +557,10 @@ var canvas_events = (function() {
         },
         utils = {
             create_obj: function() {
+                // Yes: I _really_ want .innerText and NOT .textContent
+                // here.  I want those newlines: although that isn't
+                // standard in Pd-Vanilla, Pd-l2ork uses and preserves
+                // them inside comments
                 var fudi_msg = text_to_fudi(textbox().innerText),
                     fudi_array = string_to_array_of_chunks(fudi_msg),
                     i;
@@ -769,6 +771,9 @@ var canvas_events = (function() {
     gui.Window.get().on("focus", function() {
         nw_window_focus_callback();
     });
+    gui.Window.get().on("blur", function() {
+        nw_window_blur_callback(name);
+    });
     // set minimum window size
     gui.Window.get().setMinimumSize(150, 100);
 
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index 53208d43da0008ff7d915b69200fa6afa2dd6b0f..940c834b06d64ce24f3a881c77001fd887b4df62 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -4741,6 +4741,15 @@ void canvas_mouseup(t_canvas *x,
             (glob_shift + glob_ctrl*2 + glob_alt*4), 0);
 }
 
+/* Cheap hack to simulate mouseup at the last x/y coord. We use this in
+   the GUI in case the window gets a blur event before a mouseup */
+void canvas_mouseup_fake(t_canvas *x)
+{
+    if (x->gl_editor && x->gl_edit)
+        canvas_mouseup(x, x->gl_editor->e_xwas, x->gl_editor->e_ywas, 0);
+}
+
+
 /* This entire function is made superfluous in the GUI port-- we get middle-
    click pasting for free by default. */
 void canvas_mousedown_middle(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
@@ -7459,6 +7468,8 @@ void g_editor_setup(void)
         A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_mouseup, gensym("mouseup"),
         A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_mouseup_fake,
+        gensym("mouseup_fake"), A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_mousedown_middle, gensym("mouse-2"),
         A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_key, gensym("key"),