diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index fc814ed0062e18d4bfd207014d18e655832cbcfd..58ff2c21c066a76fe8bf8a217d4edd9b1e945899 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -2218,7 +2218,12 @@ int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos,
     if (!gobj_shouldvis(y, x))
         return (0);
     gobj_getrect(y, x, &x1, &y1, &x2, &y2);
-    if (xpos >= x1 && xpos <= x2 && ypos >= y1 && ypos <= y2)
+    // we also add a check that width is greater than 0 because we use this
+    // to return value from objects that are designed to ignore clicks and
+    // pass them below, e.g. pd-l2ork's version of ggee/image which uses this
+    // feature in runtime mode only (we can use canvas->gl_edit check for this
+    // within an external)
+    if (x2-x1 > 0 && xpos >= x1 && xpos <= x2 && ypos >= y1 && ypos <= y2)
     {
         *x1p = x1;
         *y1p = y1;
@@ -3017,6 +3022,8 @@ static double canvas_upclicktime;
 static int canvas_upx, canvas_upy;
 #define DCLICKINTERVAL 0.25
 
+extern t_class *my_canvas_class; // for ignoring runtime clicks
+
     /* mouse click */
 void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
     int mod, int doit)
@@ -3129,8 +3136,8 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
             if (canvas_hitbox(x, y, xpos, ypos, &x1, &y1, &x2, &y2))
             {
                 ob = pd_checkobject(&y->g_pd);
-                /* do not give clicks to comments during runtime */
-                if (!ob || ob->te_type != T_TEXT) 
+                /* do not give clicks to comments or cnv during runtime */
+                if (!ob || (ob->te_type != T_TEXT && ob->ob_pd != my_canvas_class))
                     yclick = y;
                 //fprintf(stderr,"    MAIN found clickable %d\n",
                 //    clickreturned);
@@ -4760,6 +4767,7 @@ void canvas_displaceselection(t_canvas *x, int dx, int dy)
 void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
 {
     static t_symbol *keynumsym, *keyupsym, *keynamesym;
+    static t_symbol *keynumsym_a, *keyupsym_a, *keynamesym_a;
     int keynum;
     t_symbol *gotkeysym;
         
@@ -4844,6 +4852,10 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
         keynumsym = gensym("#key");
         keyupsym = gensym("#keyup");
         keynamesym = gensym("#keyname");
+
+        keynumsym_a = gensym("#key_a");
+        keyupsym_a = gensym("#keyup_a");
+        keynamesym_a = gensym("#keyname_a");
     }
 #ifdef __APPLE__
         if (keynum == 30)
@@ -4855,6 +4867,10 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
         else if (keynum == 29)
             keynum = 0, gotkeysym = gensym("Right");
 #endif
+    // set the shared variable for broadcasting of keypresses to key et al. objectss
+    t_atom at[2];
+
+    // now broadcast key press to key et al. objects
     if (!autorepeat)
     {
         if (keynumsym->s_thing && down)
@@ -4863,13 +4879,26 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
             pd_float(keyupsym->s_thing, (t_float)keynum);
         if (keynamesym->s_thing)
         {
-            t_atom at[2];
             at[0] = av[0];
             SETFLOAT(at, down);
             SETSYMBOL(at+1, gotkeysym);
             pd_list(keynamesym->s_thing, 0, 2, at);
         }
     }
+
+    // now do the same for autorepeat-enabled objects (key et al. alternative behavior)
+    if (keynumsym_a->s_thing && down)
+        pd_float(keynumsym_a->s_thing, (t_float)keynum);
+    if (keyupsym_a->s_thing && !down)
+        pd_float(keyupsym_a->s_thing, (t_float)keynum);
+    if (keynamesym_a->s_thing)
+    {
+        at[0] = av[0];
+        SETFLOAT(at, down);
+        SETSYMBOL(at+1, gotkeysym);
+        pd_list(keynamesym_a->s_thing, 0, 2, at);
+    }
+
     if (!x->gl_editor)  /* if that 'invis'ed the window, we'd better stop. */
         return;
     if (x && down)
diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c
index 0a62b4c759b92205aac8879de01321faa131bf4d..6c1b05bdf4290d1131845f0baf74df688c3a4040 100644
--- a/pd/src/g_graph.c
+++ b/pd/src/g_graph.c
@@ -1483,6 +1483,8 @@ static void graph_motion(void *z, t_floatarg dx, t_floatarg dy)
     garray_redraw(a);
 }
 
+extern t_class *my_canvas_class; // for ignoring runtime clicks
+
 static int graph_click(t_gobj *z, struct _glist *glist,
     int xpix, int ypix, int shift, int alt, int dbl, int doit)
 {
@@ -1517,8 +1519,8 @@ static int graph_click(t_gobj *z, struct _glist *glist,
                 if (canvas_hitbox(x, y, xpix, ypix, &x1, &y1, &x2, &y2))
                 {
                     ob = pd_checkobject(&y->g_pd);
-                    /* do not give clicks to comments during runtime */
-                    if (!ob || ob->te_type != T_TEXT) 
+                    /* do not give clicks to comments or cnv during runtime */
+                    if (!ob || (ob->te_type != T_TEXT && ob->ob_pd != my_canvas_class)) 
                         clickme = y;
                     //fprintf(stderr,"    found clickable %d\n", clickreturned);
                 }
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index 86f6f2e99249097f6e96fb83fd4d8e15e09566d7..84a72926c28232d8ed693d88c1cbe16b30f03165 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -884,7 +884,12 @@ static void gatom_set(t_gatom *x, t_symbol *s, int argc, t_atom *argv)
         x->a_atom.a_w.w_symbol = atom_getsymbol(argv),
             changed = (x->a_atom.a_w.w_symbol != oldatom.a_w.w_symbol);
     if (changed)
-        gatom_retext(x, 1, 0);
+    {
+        if (x->a_atom.a_type == A_FLOAT && x->a_text.te_width == 1)
+            gatom_retext(x, 1, 1);
+        else
+            gatom_retext(x, 1, 0);
+    }
     x->a_buf[0] = 0;
 }
 
@@ -1017,6 +1022,7 @@ static void gatom_key(void *z, t_floatarg f)
         gatom_bang(x);
         gatom_retext(x, 1, 1);
         x->a_buf[0] = 0;
+        glist_grab(x->a_glist, 0, 0, 0, 0, 0);
     }
     else if (len < (ATOMBUFSIZE-1))
     {
@@ -1072,9 +1078,10 @@ static void gatom_click(t_gatom *x,
             {
                 x->a_toggle = x->a_atom.a_w.w_float;
                 gatom_float(x, 0);
-                return;
             }
             else gatom_float(x, x->a_toggle);
+            gatom_retext(x, 0, 1);
+            return;
         }
         x->a_shift = shift;
         x->a_buf[0] = 0;
@@ -1713,11 +1720,11 @@ static int text_click(t_gobj *z, struct _glist *glist,
         t_rtext *y = glist_findrtext(glist, x);
         if (doit)
         {
-            gatom_click((t_gatom *)x, (t_floatarg)xpix, (t_floatarg)ypix,
-                (t_floatarg)shift, (t_floatarg)0, (t_floatarg)alt);
             //fprintf(stderr,"atom click\n");
             sys_vgui(".x%lx.c itemconfigure %s -fill %s\n", canvas, 
                 rtext_gettag(y), "$pd_colors(selection)");
+            gatom_click((t_gatom *)x, (t_floatarg)xpix, (t_floatarg)ypix,
+                (t_floatarg)shift, (t_floatarg)0, (t_floatarg)alt);
         }
         return (1);
     }
diff --git a/pd/src/x_gui.c b/pd/src/x_gui.c
index 4fa11894f48f2fde784c1cb91d715a01bb4f3cc4..9cb78dec38123c4a4c9367072f38766bec6df275 100644
--- a/pd/src/x_gui.c
+++ b/pd/src/x_gui.c
@@ -311,18 +311,28 @@ static void savepanel_setup(void)
 /* ---------------------- key and its relatives ------------------ */
 
 static t_symbol *key_sym, *keyup_sym, *keyname_sym;
+static t_symbol *key_sym_a, *keyup_sym_a, *keyname_sym_a;
 static t_class *key_class, *keyup_class, *keyname_class;
 
 typedef struct _key
 {
     t_object x_obj;
+    t_symbol *x_keysym;
 } t_key;
 
-static void *key_new( void)
+static void *key_new(t_symbol *s, int argc, t_atom *argv)
 {
     t_key *x = (t_key *)pd_new(key_class);
     outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, key_sym);
+    if (argc > 0 && argv->a_type == A_FLOAT)
+        if (atom_getfloatarg(0, argc, argv) == 0)
+            x->x_keysym = key_sym;
+        else if (atom_getfloatarg(0, argc, argv) == 1)
+            x->x_keysym = key_sym_a;
+
+    if (!x->x_keysym)
+        x->x_keysym = key_sym;
+    pd_bind(&x->x_obj.ob_pd, x->x_keysym);
     return (x);
 }
 
@@ -333,19 +343,28 @@ static void key_float(t_key *x, t_floatarg f)
 
 static void key_free(t_key *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, key_sym);
+    pd_unbind(&x->x_obj.ob_pd, x->x_keysym);
 }
 
 typedef struct _keyup
 {
     t_object x_obj;
+    t_symbol *x_keysym;
 } t_keyup;
 
-static void *keyup_new( void)
+static void *keyup_new(t_symbol *s, int argc, t_atom *argv)
 {
     t_keyup *x = (t_keyup *)pd_new(keyup_class);
     outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, keyup_sym);
+    if (argc > 0 && argv->a_type == A_FLOAT)
+        if (atom_getfloatarg(0, argc, argv) == 0)
+            x->x_keysym = keyup_sym;
+        else if (atom_getfloatarg(0, argc, argv) == 1)
+            x->x_keysym = keyup_sym_a;
+
+    if (!x->x_keysym)
+        x->x_keysym = keyup_sym;
+    pd_bind(&x->x_obj.ob_pd, x->x_keysym);
     return (x);
 }
 
@@ -356,22 +375,31 @@ static void keyup_float(t_keyup *x, t_floatarg f)
 
 static void keyup_free(t_keyup *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, keyup_sym);
+    pd_unbind(&x->x_obj.ob_pd, x->x_keysym);
 }
 
 typedef struct _keyname
 {
     t_object x_obj;
+    t_symbol *x_keysym;
     t_outlet *x_outlet1;
     t_outlet *x_outlet2;
 } t_keyname;
 
-static void *keyname_new( void)
+static void *keyname_new(t_symbol *s, int argc, t_atom *argv)
 {
     t_keyname *x = (t_keyname *)pd_new(keyname_class);
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     x->x_outlet2 = outlet_new(&x->x_obj, &s_symbol);
-    pd_bind(&x->x_obj.ob_pd, keyname_sym);
+    if (argc > 0 && argv->a_type == A_FLOAT)
+        if (atom_getfloatarg(0, argc, argv) == 0)
+            x->x_keysym = keyname_sym;
+        else if (atom_getfloatarg(0, argc, argv) == 1)
+            x->x_keysym = keyname_sym_a;
+
+    if (!x->x_keysym)
+        x->x_keysym = keyname_sym;
+    pd_bind(&x->x_obj.ob_pd, x->x_keysym);
     return (x);
 }
 
@@ -383,29 +411,32 @@ static void keyname_list(t_keyname *x, t_symbol *s, int ac, t_atom *av)
 
 static void keyname_free(t_keyname *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, keyname_sym);
+    pd_unbind(&x->x_obj.ob_pd, x->x_keysym);
 }
 
 static void key_setup(void)
 {
     key_class = class_new(gensym("key"),
         (t_newmethod)key_new, (t_method)key_free,
-        sizeof(t_key), CLASS_NOINLET, 0);
+        sizeof(t_key), 0, A_GIMME, 0);
     class_addfloat(key_class, key_float);
     key_sym = gensym("#key");
+    key_sym_a = gensym("#key_a");
 
     keyup_class = class_new(gensym("keyup"),
         (t_newmethod)keyup_new, (t_method)keyup_free,
-        sizeof(t_keyup), CLASS_NOINLET, 0);
+        sizeof(t_keyup), 0, A_GIMME, 0);
     class_addfloat(keyup_class, keyup_float);
     keyup_sym = gensym("#keyup");
+    keyup_sym_a = gensym("#keyup_a");
     //class_sethelpsymbol(keyup_class, gensym("key"));
     
     keyname_class = class_new(gensym("keyname"),
         (t_newmethod)keyname_new, (t_method)keyname_free,
-        sizeof(t_keyname), CLASS_NOINLET, 0);
+        sizeof(t_keyname), 0, A_GIMME, 0);
     class_addlist(keyname_class, keyname_list);
     keyname_sym = gensym("#keyname");
+    keyname_sym_a = gensym("#keyname_a");
     //class_sethelpsymbol(keyname_class, gensym("key"));
 }