diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js
index a0bfb1a2e49a248c2d19ed3884943002f3f463dd..daaf82b91da5dac0e37229e03dff117ed96a4ad7 100644
--- a/pd/nw/pd_canvas.js
+++ b/pd/nw/pd_canvas.js
@@ -99,6 +99,22 @@ var canvas_events = (function() {
                 return 0;
             }
         },
+        target_is_canvasobj = function(evt) {
+            function is_canvas_obj(target) {
+                return target.classList.contains("obj") &&
+                    target.classList.contains("canvasobj");
+            };
+            // ag: A bit of (maybe over-)defensive programming here: depending
+            // on where exactly the user clicked, the actual object may be the
+            // parent or the grandparent of the clicked target.
+            if (evt.target.classList.contains("border") ||
+                evt.target.classList.contains("box_text"))
+                return is_canvas_obj(evt.target.parentNode);
+            else if (evt.target.parentNode.classList.contains("box_text"))
+                return is_canvas_obj(evt.target.parentNode.parentNode);
+            else
+                return is_canvas_obj(evt.target);
+        },
         text_to_normalized_svg_path = function(text) {
             text = text.slice(4).trim()  // draw
                        .slice(4).trim()  // path
@@ -383,6 +399,11 @@ var canvas_events = (function() {
                     (pointer_y + svg_view.y),
                     b, mod
                 );
+                // If Alt is pressed on a box_text, fake a keyup to prevent
+                // dangling temp runmode in case the click opens a subpatch.
+                if (evt.altKey && target_is_canvasobj(evt)) {
+                    pdgui.canvas_sendkey(name, 0, evt, "Alt", 0);
+                }
                 //evt.stopPropagation();
                 //evt.preventDefault();
             },
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index 7e90a25941a92a63259b6fee7f4e5af48794c3ab..96682242efe36282d5672f7d93ec40f9cba8d334 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -2473,7 +2473,7 @@ exports.gui = gui;
 // In the future, it might make sense to combine the scalar and object
 // creation, in which case a flag to toggle the offset would be appropriate.
 
-function gui_gobj_new(cid, tag, type, xpos, ypos, is_toplevel) {
+function gui_gobj_new(cid, tag, type, xpos, ypos, is_toplevel, is_canvas_obj) {
     var g;
     xpos += 0.5,
     ypos += 0.5,
@@ -2482,7 +2482,7 @@ function gui_gobj_new(cid, tag, type, xpos, ypos, is_toplevel) {
         g = create_item(cid, "g", {
             id: tag + "gobj",
             transform: transform_string,
-            class: type + (is_toplevel !== 0 ? "" : " gop")
+            class: type + (is_toplevel !== 0 ? "" : " gop") + (is_canvas_obj === 0 ? "" : " canvasobj")
         });
         add_gobj_to_svg(svg_elem, g);
     });
diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c
index 1af9841ae27d20a162c37aa3e1c1e726efa38d18..66c575bb62d5c0c70e1e463ce524014c8dc6bca7 100644
--- a/pd/src/g_all_guis.c
+++ b/pd/src/g_all_guis.c
@@ -1393,8 +1393,8 @@ void iemgui_base_draw_new(t_iemgui *x)
     gop_redraw = gr;
     char colorbuf[MAXPDSTRING];
     sprintf(colorbuf, "#%6.6x", x->x_bcol);
-    gui_vmess("gui_gobj_new", "xxsiii", canvas, x,
-        "iemgui", x1, y1, glist_istoplevel(x->x_glist));
+    gui_vmess("gui_gobj_new", "xxsiiii", canvas, x,
+        "iemgui", x1, y1, glist_istoplevel(x->x_glist), 0);
     gui_vmess("gui_text_draw_border", "xxsiii",
         canvas,
         x,
diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c
index d93cd3db6b7c81b2392f78114bb3c87407d9458a..c7556e9bfd8d62c0287729231e3e5820ddc3d9f1 100644
--- a/pd/src/g_graph.c
+++ b/pd/src/g_graph.c
@@ -1058,10 +1058,10 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
         int xpix, ypix;
         xpix = text_xpix(&x->gl_obj, parent_glist);
         ypix = text_ypix(&x->gl_obj, parent_glist);
-        gui_vmess("gui_gobj_new", "xssiii",
+        gui_vmess("gui_gobj_new", "xssiiii",
             glist_getcanvas(x->gl_owner),
             tag, "graph", xpix, ypix,
-            parent_glist == glist_getcanvas(x->gl_owner) ? 1 : 0);
+            parent_glist == glist_getcanvas(x->gl_owner) ? 1 : 0, 0);
         if (canvas_showtext(x))
             rtext_draw(glist_findrtext(parent_glist, &x->gl_obj));
     }
diff --git a/pd/src/g_magicglass.c b/pd/src/g_magicglass.c
index a7edd0bf4f466557078e98956245cec100f6b263..70bfd4b612192a8cee458f155cc47d5b853f20b6 100644
--- a/pd/src/g_magicglass.c
+++ b/pd/src/g_magicglass.c
@@ -108,8 +108,8 @@ void magicGlass_updateText(t_magicGlass *x, int moved)
 
 void magicGlass_drawNew(t_magicGlass *x)
 {
-    gui_vmess("gui_gobj_new", "xssiii",
-        x->x_c, "cord_inspector", "cord_inspector", 0, 0, 0);
+    gui_vmess("gui_gobj_new", "xssiiii",
+        x->x_c, "cord_inspector", "cord_inspector", 0, 0, 0, 0);
     gui_vmess("gui_cord_inspector_new", "xi",
         x->x_c, x->x_display_font);
     magicGlass_updateText(x, 0);
diff --git a/pd/src/g_mycanvas.c b/pd/src/g_mycanvas.c
index 7ee35eaec771b24256174639aa4a332cf9dca1b5..c964be131377c07358bcea125d8493fe35b42910 100644
--- a/pd/src/g_mycanvas.c
+++ b/pd/src/g_mycanvas.c
@@ -27,8 +27,8 @@ void my_canvas_draw_new(t_my_canvas *x, t_glist *glist)
     char cbuf[8];
     sprintf(cbuf, "#%6.6x", x->x_gui.x_bcol);
 
-    gui_vmess("gui_gobj_new", "xxsiii", canvas,
-        x, "iemgui", x1, y1, glist_istoplevel(glist));
+    gui_vmess("gui_gobj_new", "xxsiiii", canvas,
+        x, "iemgui", x1, y1, glist_istoplevel(glist), 0);
     gui_vmess("gui_mycanvas_new", "xxsiiiiii", canvas,
         x, cbuf, x1, y1, x1+x->x_vis_w, y1+x->x_vis_h,
         x1+x->x_gui.x_w, y1+x->x_gui.x_h);
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index b7363b4c3f15c2f4ad2edf607933045be01d25de..29a472aa8ec07601a368b67be86282ac9ef8a529 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -2230,13 +2230,14 @@ static void text_vis(t_gobj *z, t_glist *glist, int vis)
                 t_rtext *y = glist_findrtext(glist, x);
                 // make a group
                 text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2);
-                gui_vmess("gui_gobj_new", "xssiii",
+                gui_vmess("gui_gobj_new", "xssiiii",
                     glist_getcanvas(glist),
                     rtext_gettag(y),
                     type,
                     x1,
                     y1,
-                    glist_istoplevel(glist));
+                    glist_istoplevel(glist),
+                    pd_class(&x->te_pd) == canvas_class);
                 if (x->te_type == T_ATOM)
                     glist_retext(glist, x);
                 text_drawborder(x, glist, rtext_gettag(y),