diff --git a/externals/footils/knob/knob.c b/externals/footils/knob/knob.c index 78b8ce140f11e5dc1778bd1fd83ce98d8160e4eb..8be5abf64760841f4f5f72a87bce806c5c607e56 100644 --- a/externals/footils/knob/knob.c +++ b/externals/footils/knob/knob.c @@ -528,7 +528,7 @@ static void knob_click(t_knob *x, t_floatarg xpos, t_floatarg ypos, (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); knob_bang(x); glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, (t_glistmotionfn)knob_motion, - 0, 0, xpos, ypos); + 0, 0, xpos, ypos, 0); } static int knob_newclick(t_gobj *z, struct _glist *glist, diff --git a/externals/ggee/gui/w_envgen.h b/externals/ggee/gui/w_envgen.h index 76cd4aa1f52dbc95b508fd103b8db8cc0930bb5e..d30076911b09218378aaa7e054feab095cb9c3ff 100644 --- a/externals/ggee/gui/w_envgen.h +++ b/externals/ggee/gui/w_envgen.h @@ -541,7 +541,7 @@ static int envgen_newclick(t_envgen *x, struct _glist *glist, envgen_next_doodle(x, glist, xpos, ypos); glist_grab(x->w.glist, &x->x_obj.te_g, (t_glistmotionfn) envgen_motion, - (t_glistkeyfn) envgen_key, 0, xpos, ypos); + (t_glistkeyfn) envgen_key, 0, xpos, ypos, 0); x->resizing = 0; if (x->resizeable && (xpos > wxpos + x->w.width) && diff --git a/externals/iem/iemgui/src/cube_sphere.c b/externals/iem/iemgui/src/cube_sphere.c index dea32cbcdf5f3efacac048dbcb4b02ce0506a793..e894ac7d29f73265bffc96ca71f7d900a599842a 100644 --- a/externals/iem/iemgui/src/cube_sphere.c +++ b/externals/iem/iemgui/src/cube_sphere.c @@ -366,7 +366,7 @@ static void cube_sphere_click(t_cube_sphere *x, t_floatarg xpos, t_floatarg ypos x->x_sel_index = sel; x->x_pos_x = x->x_pix_src_x[sel]; x->x_pos_y = x->x_pix_src_y[sel]; - glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, (t_glistmotionfn)cube_sphere_motion, 0, 0, xpos, ypos); + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, (t_glistmotionfn)cube_sphere_motion, 0, 0, xpos, ypos, 0); } } } diff --git a/externals/iem/iemgui/src/iem_event.c b/externals/iem/iemgui/src/iem_event.c index d0a82969004a439d112e51376794b7747a376ee5..5c1b3539d35fca4ed93df8f36ba0c39ef91899bf 100644 --- a/externals/iem/iemgui/src/iem_event.c +++ b/externals/iem/iemgui/src/iem_event.c @@ -232,7 +232,7 @@ static int iem_event_click(t_gobj *z, struct _glist *glist, int xpix, int ypix, if(doit) { glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, - (t_glistmotionfn)iem_event_motion, iem_event_key, 0, (t_float)xpix, (t_float)ypix); + (t_glistmotionfn)iem_event_motion, iem_event_key, 0, (t_float)xpix, (t_float)ypix, 0); outlet_anything(x->x_gui.x_obj.ob_outlet, x->x_dragg_x_y, 2, x->x_at_out); if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) diff --git a/externals/iem/iemgui/src/numberbox_matrix.c b/externals/iem/iemgui/src/numberbox_matrix.c index f6e41b9a46965ba535b7ac0cd44c83bc1b07b8ce..bdd23d83d34bdf10b469f30adc13951deb8b4b62 100644 --- a/externals/iem/iemgui/src/numberbox_matrix.c +++ b/externals/iem/iemgui/src/numberbox_matrix.c @@ -716,7 +716,7 @@ static void numberbox_matrix_click(t_numberbox_matrix *x, t_floatarg xpos, t_flo t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, - (t_glistmotionfn)numberbox_matrix_motion, numberbox_matrix_key, 0, xpos, ypos); + (t_glistmotionfn)numberbox_matrix_motion, numberbox_matrix_key, 0, xpos, ypos, 0); } static int numberbox_matrix_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit) diff --git a/externals/iem/iemgui/src/room_sim_2d.c b/externals/iem/iemgui/src/room_sim_2d.c index 4dc9535b3263113c28d45c5f44b82b05e3d69d73..373409270abae1ae9e643e63d613e17ad2217d8e 100644 --- a/externals/iem/iemgui/src/room_sim_2d.c +++ b/externals/iem/iemgui/src/room_sim_2d.c @@ -440,7 +440,7 @@ static void room_sim_2d_click(t_room_sim_2d *x, t_floatarg xpos, t_floatarg ypos x->x_pos_x = x->x_pix_src_x[sel]; x->x_pos_y = x->x_pix_src_y[sel]; glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, - (t_glistmotionfn)room_sim_2d_motion, 0, 0, xpos, ypos); + (t_glistmotionfn)room_sim_2d_motion, 0, 0, xpos, ypos, 0); } } diff --git a/externals/iem/iemgui/src/room_sim_3d.c b/externals/iem/iemgui/src/room_sim_3d.c index 11d9dad5367cd42cbdc4776d029ad0e6e4c5eb83..d7ca6afd9671f0b7eb17a5ac66321f20c443a819 100644 --- a/externals/iem/iemgui/src/room_sim_3d.c +++ b/externals/iem/iemgui/src/room_sim_3d.c @@ -532,7 +532,7 @@ static void room_sim_3d_click(t_room_sim_3d *x, t_floatarg xpos, t_floatarg ypos x->x_pos_x = x->x_pix_src_x[sel]; x->x_pos_y = x->x_pix_src_y[sel]; x->x_pos_z = x->x_pix_src_z[sel]; - glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, (t_glistmotionfn)room_sim_3d_motion, 0, 0, xpos, ypos); + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, (t_glistmotionfn)room_sim_3d_motion, 0, 0, xpos, ypos, 0); } } diff --git a/externals/miXed/cyclone/hammer/comment.c b/externals/miXed/cyclone/hammer/comment.c index 25a71b7f4431be699d0251f45393cc759bfef83a..562666bbdc9abfbb3dd4d50f2e66ab88fdc3b55e 100644 --- a/externals/miXed/cyclone/hammer/comment.c +++ b/externals/miXed/cyclone/hammer/comment.c @@ -195,7 +195,7 @@ static void comment_dograb(t_comment *x) Here we use it just to prevent backspace from erasing entire text. This has to be done also when we are already active, because after being clicked at we have lost our previous grab. */ - glist_grab(x->x_glist, (t_gobj *)x, 0, comment_grabbedkey, 0, 0, 0); + glist_grab(x->x_glist, (t_gobj *)x, 0, comment_grabbedkey, 0, 0, 0, 0); } static void comment__bboxhook(t_comment *x, t_symbol *bindsym, diff --git a/externals/moonlib/mknob.c b/externals/moonlib/mknob.c index d8430ffd9a82dda7841619e81bb89f9b941560e7..c010e0f6506fa7c630f2900f18d474541916755f 100644 --- a/externals/moonlib/mknob.c +++ b/externals/moonlib/mknob.c @@ -450,13 +450,13 @@ static void mknob_click(t_mknob *x, t_floatarg xpos, t_floatarg ypos, if (x->x_gui.x_h<0) glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, - (t_glistmotionfn)mknob_motion_fullcircular, 0, 0, xpos, ypos); + (t_glistmotionfn)mknob_motion_fullcircular, 0, 0, xpos, ypos, 0); else if (x->x_gui.x_h==0) glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, - (t_glistmotionfn)mknob_motion_circular, 0, 0, xpos, ypos); + (t_glistmotionfn)mknob_motion_circular, 0, 0, xpos, ypos, 0); else glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, - (t_glistmotionfn)mknob_motion, 0, 0, xpos, ypos); + (t_glistmotionfn)mknob_motion, 0, 0, xpos, ypos, 0); } static int mknob_newclick(t_gobj *z, struct _glist *glist, diff --git a/externals/pidip/modules/pdp_colorgrid.c b/externals/pidip/modules/pdp_colorgrid.c index c47b16fb43a514bc96da8a088e74c1964f698aba..c261abdb7f92fa05ba2fab3ec16f9fee84218913 100755 --- a/externals/pidip/modules/pdp_colorgrid.c +++ b/externals/pidip/modules/pdp_colorgrid.c @@ -1481,7 +1481,7 @@ static int pdp_colorgrid_click(t_gobj *z, struct _glist *glist, pdp_colorgrid_output_current(x); pdp_colorgrid_draw_update(x, glist); glist_grab(glist, &x->x_obj.te_g, (t_glistmotionfn)pdp_colorgrid_motion, - 0, 0, xpix, ypix); + 0, 0, xpix, ypix, 0); } return (1); } diff --git a/externals/tof/src/w_breakpoints.h b/externals/tof/src/w_breakpoints.h index 24defdb2b036e566659596b106f9eecd029e2d00..34f052a54532f1e7d4f8563d34123b83759098d4 100644 --- a/externals/tof/src/w_breakpoints.h +++ b/externals/tof/src/w_breakpoints.h @@ -518,7 +518,7 @@ static int breakpoints_newclick(t_breakpoints *x, struct _glist *glist, breakpoints_next_doodle(x,glist,xpos,ypos); glist_grab(x->w.glist, &x->x_obj.te_g, (t_glistmotionfn) breakpoints_motion, - (t_glistkeyfn) breakpoints_key, 0, xpos, ypos); + (t_glistkeyfn) breakpoints_key, 0, xpos, ypos, 0); x->w.shift = shift; breakpoints_followpointer(x,glist); @@ -544,7 +544,7 @@ static int breakpoints_newclick(t_breakpoints *x, struct _glist *glist, breakpoints_next_doodle(x,glist,xpos,ypos); glist_grab(x->w.glist, &x->x_obj.te_g, (t_glistmotionfn) breakpoints_motion, - (t_glistkeyfn) breakpoints_key, 0, xpos, ypos); + (t_glistkeyfn) breakpoints_key, 0, xpos, ypos, 0); x->resizing = 0; if (x->resizeable && (xpos > wxpos + x->w.width) && diff --git a/externals/unauthorized/audience~.c b/externals/unauthorized/audience~.c index 87081724544af13a3fa6611942def8e0cceda186..297d58cd8131ec9459eef76a4875b123fac8a7ec 100644 --- a/externals/unauthorized/audience~.c +++ b/externals/unauthorized/audience~.c @@ -670,7 +670,7 @@ static int audience_click(t_gobj *z, struct _glist *glist, } audience_draw_update(x, glist); glist_grab(glist, &x->x_obj.te_g, (t_glistmotionfn)audience_motion, - 0, 0, xpix, ypix); + 0, 0, xpix, ypix, 0); } return (1); } diff --git a/externals/unauthorized/cooled~.c b/externals/unauthorized/cooled~.c index b234b7c179049938100a75f4d4646fa2baf845fd..057dbd5cf60fa3136373e01034013d4b48f71a1c 100644 --- a/externals/unauthorized/cooled~.c +++ b/externals/unauthorized/cooled~.c @@ -880,7 +880,7 @@ static int cooled_click(t_gobj *z, struct _glist *glist, x->x_alted = alt; // activate motion callback glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)cooled_motion, - 0, 0, xpix, ypix ); + 0, 0, xpix, ypix, 0 ); // draw insertion line if ( glist_isvisible( x->x_glist ) ) diff --git a/externals/unauthorized/grid.c b/externals/unauthorized/grid.c index 9a423dbe070e573cd2895fabf429b394db504cbf..6b3c18cb534612e12b304a6d47fa724117b817fe 100644 --- a/externals/unauthorized/grid.c +++ b/externals/unauthorized/grid.c @@ -510,7 +510,7 @@ static int grid_click(t_gobj *z, struct _glist *glist, grid_output_current(x); grid_draw_update(x, glist); glist_grab(glist, &x->x_obj.te_g, (t_glistmotionfn)grid_motion, - 0, 0, xpix, ypix); + 0, 0, xpix, ypix, 0); } return (1); } diff --git a/externals/unauthorized/playlist.c b/externals/unauthorized/playlist.c index d9e869e7fbadb9886ec27b012dfbe8c41bd5e29c..50c576975456229ac78a6d18ce2c7fcf94bdbf32 100644 --- a/externals/unauthorized/playlist.c +++ b/externals/unauthorized/playlist.c @@ -640,7 +640,7 @@ static int playlist_click(t_gobj *z, struct _glist *glist, } x->x_glist = glist; glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)playlist_motion, - NULL, NULL, xpix, ypix ); + NULL, NULL, xpix, ypix, 0 ); } return (1); } diff --git a/externals/unauthorized/scratcher~.c b/externals/unauthorized/scratcher~.c index 14b5088fb030f9c79fc45da3f5f5656a749e387f..353fe8e3dec48d62795e41c4098b41cf5cecb601 100644 --- a/externals/unauthorized/scratcher~.c +++ b/externals/unauthorized/scratcher~.c @@ -417,7 +417,7 @@ static int scratcher_click(t_gobj *z, struct _glist *glist, { // activate motion callback glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)scratcher_motion, - 0, 0, xpix, ypix ); + 0, 0, xpix, ypix, 0 ); x->x_readspeed=0.; x->x_motioned = 1; if ( x->x_showspeed ) diff --git a/externals/unauthorized/scrolllist.c b/externals/unauthorized/scrolllist.c index 5a85c2fbdb9bd287ee6fe1051e404a0b8fbb3756..0e8afd006842749ee03520612c0137689570872f 100644 --- a/externals/unauthorized/scrolllist.c +++ b/externals/unauthorized/scrolllist.c @@ -426,7 +426,7 @@ static int scrolllist_click(t_gobj *z, struct _glist *glist, } x->x_glist = glist; glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)scrolllist_motion, - NULL, NULL, xpix, ypix ); + NULL, NULL, xpix, ypix, 0 ); } return (1); } diff --git a/externals/unauthorized/sonogram~.c b/externals/unauthorized/sonogram~.c index 30efb5c2acd502cc538994817efc688639dced40..3e9f81f0e549dae2e12e58937c353bd1148014b7 100644 --- a/externals/unauthorized/sonogram~.c +++ b/externals/unauthorized/sonogram~.c @@ -1116,7 +1116,7 @@ static int sonogram_click(t_gobj *z, struct _glist *glist, x->x_alted = alt; // activate motion callback glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)sonogram_motion, - 0, 0, xpix, ypix ); + 0, 0, xpix, ypix, 0 ); if ( shift && alt && (x->x_xstartcapture != x->x_xendcapture ) ) { diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index 800a9c31bbef89a4a90ab079c0a785320c48802c..0d866aeb4c0f43452590de235eae413a21f48aa9 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -1859,7 +1859,7 @@ function canvas_sendkey(cid, state, evt, char_code, repeat) { var shift = evt.shiftKey ? 1 : 0, repeat_number = repeat ? 1 : 0; //post("canvas_sendkey state=" + state + " evt=" + evt + - // " char_code=<" + char_code + "> repeat=" + repeat); + // " char_code=<" + char_code + "> repeat=" + repeat + " shift=" + shift); pdsend(cid, "key", state, char_code, shift, 1, repeat_number); } @@ -2995,13 +2995,10 @@ function gui_text_set (cid, tag, text) { function gui_text_set_mynumbox (cid, tag, text, active) { gui(cid).get_elem(tag + "text", function(e) { - //post("gui_text_set_mynumbox " + tag + " " + text + " " + active); text = text.trim(); e.textContent = ""; text_to_tspans(cid, e, text); - if (active === 2) { - e.classList.remove("activated"); - } else if (active === 1) { + if (active === 1) { e.classList.add("activated"); } else { e.classList.remove("activated"); @@ -3357,17 +3354,24 @@ function gui_numbox_coords(cid, tag, w, h) { }); } -function gui_numbox_draw_text(cid,tag,text,font_size,color,xpos,ypos,basex,basey) { +function gui_numbox_draw_text(cid,tag,text,font_size,color,xpos,ypos,basex,basey,fontmargin) { // kludge alert -- I'm not sure why I need to add half to the ypos // below. But it works for most font sizes. gui(cid).get_gobj(tag) .append(function(frag, w) { - //post("ypos=" + ypos + " int=" + Math.floor(ypos)); - //ypos = Math.floor(ypos); + var trans_y = 0; + // fine-tuning the translate y rule: + if (font_size === 18 && fontmargin === 2) { + trans_y = 16.5; + } else if (font_size === 17 && fontmargin === 2) { + trans_y = 15.5; + } else { + trans_y = (font_size - fontmargin/2); + } var svg_text = create_item(cid, "text", { transform: "translate(" + - (xpos - basex) + "," + - ((ypos - basey + (ypos - basey) * 0.5)|0) + ")", + (xpos - basex) + "," + trans_y + ")", + //((ypos - basey + (ypos - basey) * 0.5)|0) + ")", "font-size": font_size, fill: color, id: tag + "text" @@ -3394,9 +3398,19 @@ function gui_numbox_update(cid, tag, fcolor, bgcolor, num_font_size, font_name, }); } -function gui_numbox_update_text_position(cid, tag, x, y) { +function gui_numbox_update_text_position(cid, tag, x, y, font_size, fontmargin) { + var trans_y = 0; + // fine-tuning the translate y rule: + if (font_size === 18 && fontmargin === 2) { + trans_y = 16.5; + } else if (font_size === 17 && fontmargin === 2) { + trans_y = 15.5; + } else { + trans_y = (font_size - fontmargin/2); + } gui(cid).get_elem(tag + "text", { - transform: "translate( " + x + "," + ((y + y*0.5)|0) + ")" + //transform: "translate(" + x + "," + ((y + y*0.5)|0) + ")" + transform: "translate(" + x + "," + trans_y + ")" }); } diff --git a/pd/src/g_all_guis.h b/pd/src/g_all_guis.h index b7684019fe00dd5815513673e2b6da7a0500924e..cdd34e9b0ccbc7025fba9fcba9f738bc4e0f1e38 100644 --- a/pd/src/g_all_guis.h +++ b/pd/src/g_all_guis.h @@ -86,7 +86,9 @@ typedef struct _iemgui t_scalehandle *x_handle; //24 t_scalehandle *x_lhandle; //19 int x_vis; //bool //64 /* is the object drawn? */ - int x_changed; //bool //30 /* has the value changed so that we need to do graphic update */ + int x_changed; //bool //30 /* has the value changed so that we need to do graphic update + /* in numbox we also use it to signify when the activated value + has been changed and clipped */ // grep -w "$1" *.[ch]|wc -l t_glist *x_selected; // 24 matches @@ -180,7 +182,6 @@ typedef struct _my_numbox { t_iemgui x_gui; t_clock *x_clock_reset; - t_clock *x_clock_wait; double x_val; double x_min; double x_max; @@ -195,9 +196,19 @@ typedef struct _my_numbox int x_num_fontsize;/* font size for the number only that should automatically adjust to the box size */ int x_focused; /* helps us determine when and how we are editing value - 0 no focus, 1 keyboard focus, 2 mouse focus */ + 0 no focus, 1 mouse focus, 2 keyboard focus without + the trailing '>', and, 3 keyboard focus with the + trailing '>' */ int x_log_height; - int x_drawstyle; /* 0 default, 1 just frame, 2, just arrow, 3 number only */ + int x_drawstyle; /* 0 default, 1 just frame, 2, just arrow, 3 number only */ + int x_shiftclick; /* used to keep track how the number was originally focused + so that when it is shift-clicked, it is in append mode, and + when focused without the shift, it is operating in the old + mode */ + int x_dragged; /* used to keep track if the number box was dragged, so that + even if we arrive back at the previous number, it does not + activate with exclusive keyboard focus. This is why old_val + comparison is not a good one */ } t_my_numbox; extern int sys_noloadbang; diff --git a/pd/src/g_array.c b/pd/src/g_array.c index 4b01e03586d82e4cea6b9bbbadc676ffaed745e6..4b361e8f70527bb2b65b8f415a0df272d7c71773 100644 --- a/pd/src/g_array.c +++ b/pd/src/g_array.c @@ -1265,7 +1265,7 @@ int array_doclick(t_array *array, t_glist *glist, t_scalar *sc, t_array *ap, array_motion_ycumulative = 0; } //fprintf(stderr," glist_grab %d %d\n", xpix, ypix); - glist_grab(glist, 0, array_motion, 0, 0, xpix, ypix); + glist_grab(glist, 0, array_motion, 0, 0, xpix, ypix, 0); } if (alt) { diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h index cde9837014ad4a16ab8b7ca2eb8275062a2b1f7f..adf46dcc5b026f8fcd7bca42b51e1fa4cdf1e389 100644 --- a/pd/src/g_canvas.h +++ b/pd/src/g_canvas.h @@ -120,6 +120,7 @@ typedef struct _editor struct _glist *e_glist; /* glist which owns this */ int e_xwas; /* xpos on last mousedown or motion event */ int e_ywas; /* ypos, similarly */ + int exclusive; /* should the glist_grab be exclusive? */ int e_selectline_index1; /* indices for the selected line if any */ int e_selectline_outno; /* (only valid if e_selectedline is set) */ int e_selectline_index2; @@ -487,7 +488,8 @@ EXTERN void glist_delete(t_glist *x, t_gobj *y); EXTERN void glist_retext(t_glist *x, t_text *y); EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn, t_glistkeyfn keyfn, t_glistkeynameafn keynameafn, - int xpos, int ypos); + int xpos, int ypos, int exclusive); +EXTERN int glist_grab_exclusive(t_glist *x, int exclusive); EXTERN int glist_isvisible(t_glist *x); EXTERN int glist_istoplevel(t_glist *x); EXTERN t_glist *glist_findgraph(t_glist *x); diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c index ef71817264cea7a3ee78a7b194252418b37c434b..36d9aa913bbe5d58e9dcf8ee54db04cf9412ac7b 100644 --- a/pd/src/g_editor.c +++ b/pd/src/g_editor.c @@ -2719,6 +2719,7 @@ static t_editor *editor_new(t_glist *owner) x->gl_magic_glass = magicGlass_new(owner); x->canvas_cnct_inlet_tag[0] = 0; x->canvas_cnct_outlet_tag[0] = 0; + x->exclusive = 0; return (x); } @@ -3690,7 +3691,7 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, if (doit && x->gl_editor->e_grab && x->gl_editor->e_keyfn) { (* x->gl_editor->e_keyfn) (x->gl_editor->e_grab, 0); - glist_grab(x, 0, 0, 0, 0, 0, 0); + glist_grab(x, 0, 0, 0, 0, 0, 0, 0); } if (doit && !runmode && xpos == canvas_upx && ypos == canvas_upy && @@ -5345,7 +5346,8 @@ void canvas_mouseup(t_canvas *x, canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); } - if (x->gl_editor->e_onmotion != MA_CONNECT || + if ((x->gl_editor->e_onmotion != MA_CONNECT && + x->gl_editor->e_onmotion != MA_PASSOUT) || x->gl_editor->e_onmotion == MA_CONNECT && !glob_shift) { //fprintf(stderr,"releasing shift during connect without " @@ -5361,10 +5363,23 @@ void canvas_mouseup(t_canvas *x, x->gl_editor->e_onmotion = MA_NONE; } //fprintf(stderr,"canvas_mouseup -> canvas_doclick %d\n", which); - /* this is to ignore scrollbar clicks from within tcl */ - if (canvas_last_glist_mod == -1) - canvas_doclick(x, xpos, ypos, 0, - (glob_shift + glob_ctrl*2 + glob_alt*4), 0); + /* this is to ignore scrollbar clicks from within tcl and is + unused within nw.js 2.x implementation and onward. here, + we use doit = -1 to signify mouseup */ + //if (canvas_last_glist_mod == -1) { + if (x->gl_editor->e_onmotion == MA_PASSOUT) + { + // here we borrow the double-click flag and make it -1 which signifies + // mouse up since otherwise doit (the last argument) value of 0 is + // shared between mouse up and mouse motion, making this unclear + int clickreturned = gobj_click( + x->gl_editor->e_grab, x, xpos, ypos, glob_shift, glob_alt, -1, 0); + x->gl_editor->e_onmotion = MA_NONE; + } + + canvas_doclick(x, xpos, ypos, 0, + (glob_shift + glob_ctrl*2 + glob_alt*4), 0); + //} // now dispatch to any click listeners canvas_dispatch_mouseclick(0., xpos, ypos, which); } @@ -5588,10 +5603,38 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av) // set the shared variable for broadcasting of keypresses to key et al. objects t_atom at[2]; + // 2020-10-04 ico@vt.edu: we are here changing the order of broadcasting + // key presses to grabbed objects first, and only then to all bound objects + // this change should be heavily scrutinized as it may introduce subtle + // and not so subtle regressions. I am here introducing it becuase doing so + // allows us to have some really nice flexibility in respect to grabbed objects. + // For instance, by allowing grabbed events to propagate first, objects like + // iemgui numbox and gatom can grab exclusive hold of key presses in select cases + // before such events propagate to other bound elements. So, here + // we do grabbed keynameafn here for key presses and releases + if (x && x->gl_editor && x->gl_editor->e_grab) + { + // as per vanilla behavior, we first send keynums, then keynames + if (x->gl_editor->e_keyfn && keynum && focus && down) + (* x->gl_editor->e_keyfn) + (x->gl_editor->e_grab, (t_float)keynum); + // this takes care of both keyname presses and releases + // because we don't discriminate between the down states + // as we used to... + if (x->gl_editor->e_keynameafn && gotkeysym && focus) + { + at[0] = av[0]; + SETFLOAT(at, down); + SETSYMBOL(at+1, gotkeysym); + (* x->gl_editor->e_keynameafn) (x->gl_editor->e_grab, 0, 2, at); + } + } + // now broadcast key press to key et al. objects - // ico@vt.edu 20200918: only do so if we do not have an object - // that has grabbed the keyboard, such as gatom or iemgui numbox - if (!x || !x->gl_editor || !x->gl_editor->e_grab) + // 2020-10-05 ico@vt.edu: only do so if we do not have an object + // that has grabbed the keyboard exclusively, such as gatom or iemgui numbox + //post("canvas_key exclusive=%d", (x && x->gl_editor ? x->gl_editor->exclusive : 0)); + if (!x || !x->gl_editor || !x->gl_editor->e_grab || !x->gl_editor->exclusive) { if (!autorepeat) { @@ -5624,28 +5667,16 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av) if (!x || !x->gl_editor) return; + if (x && down) { /* cancel any dragging action */ if (x->gl_editor->e_onmotion == MA_MOVE) x->gl_editor->e_onmotion = MA_NONE; - /* if an object has "grabbed" keys just send them on */ - if (x->gl_editor->e_grab) - { - if (x->gl_editor->e_keyfn && keynum && focus) - (* x->gl_editor->e_keyfn) - (x->gl_editor->e_grab, (t_float)keynum); - if (x->gl_editor->e_keynameafn && gotkeysym && focus) - { - at[0] = av[0]; - SETFLOAT(at, down); - SETSYMBOL(at+1, gotkeysym); - (* x->gl_editor->e_keynameafn) (x->gl_editor->e_grab, 0, 2, at); - } - } + /* if a text editor is open send the key on, as long as it is either "real" (has a key number) or else is an arrow key. */ - else if (x->gl_editor->e_textedfor && focus && (keynum + if (!x->gl_editor->e_grab && x->gl_editor->e_textedfor && focus && (keynum || !strcmp(gotkeysym->s_name, "Up") || !strcmp(gotkeysym->s_name, "Down") || !strcmp(gotkeysym->s_name, "Left") @@ -5758,6 +5789,7 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av) //fprintf(stderr," %d %d %d %s %d %d\n", // glob_shift, glob_ctrl, glob_alt, gotkeysym->s_name, keynum, down); //canvas_motion(x, canvas_last_glist_x, canvas_last_glist_y, canvas_last_glist_mod); + // call canvas_motion, so that we can update modifiers... pd_vmess(&x->gl_pd, gensym("motion"), "fff", (double)canvas_last_glist_x, (double)canvas_last_glist_y, @@ -5791,6 +5823,8 @@ void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos, bug("editor"); return; } + /* the following is not being used since this was used by tcl/tk + with nw.js we never issue a mod lesser than 0 if (canvas_last_glist_mod == -1 && mod != -1) { //fprintf(stderr,"revert the cursor %d\n", x->gl_edit); @@ -5798,7 +5832,7 @@ void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos, canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); else canvas_setcursor(x, CURSOR_RUNMODE_NOTHING); - } + }*/ glist_setlastxymod(x, xpos, ypos, mod); if (x->gl_editor->e_onmotion == MA_MOVE) { diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c index 8691141adfa76d481997ed4d22d23e14731b0050..86821c87ec580646c0fdd247afd98e19cb3f628c 100644 --- a/pd/src/g_graph.c +++ b/pd/src/g_graph.c @@ -368,8 +368,12 @@ void glist_retext(t_glist *glist, t_text *y) } } +// 2020-10-05 ico@vt.edu: +// exclusive flag only applies to keyboard events (keyfn and keynameafn) +// as of right now I cannot think of a scenario where mouse motion should be +// exclusive to a single object. void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn, t_glistkeyfn keyfn, - t_glistkeynameafn keynameafn, int xpos, int ypos) + t_glistkeynameafn keynameafn, int xpos, int ypos, int exclusive) { //fprintf(stderr,"glist_grab\n"); t_glist *x2 = glist_getcanvas(x); @@ -382,6 +386,21 @@ void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn, t_glistkeyfn ke x2->gl_editor->e_keynameafn = keynameafn; x2->gl_editor->e_xwas = xpos; x2->gl_editor->e_ywas = ypos; + x2->gl_editor->exclusive = exclusive; +} + +// change glist_grab exclusive flag separate from the rest +// only do so if e_grab is not null +int glist_grab_exclusive(t_glist *x, int exclusive) +{ + t_glist *x2 = glist_getcanvas(x); + if (x2->gl_editor->e_grab) + { + if (exclusive != 0 && exclusive != 1) return(1); + x2->gl_editor->exclusive = exclusive; + return(0); + } + return(1); } t_canvas *glist_getcanvas(t_glist *x) diff --git a/pd/src/g_numbox.c b/pd/src/g_numbox.c index 9dc258226757ae759fe5e8f0600767b259256b94..ae48b08d8453a6c16ff319354701dfcf26fa77e6 100644 --- a/pd/src/g_numbox.c +++ b/pd/src/g_numbox.c @@ -27,53 +27,43 @@ t_widgetbehavior my_numbox_widgetbehavior; /*static*/ t_class *my_numbox_class; // forward declarations -static void my_numbox_set_change(t_my_numbox *x, t_floatarg f); +static void my_numbox_remove_grab(t_my_numbox *x); +static void my_numbox_motion(t_my_numbox *x, t_floatarg dx, t_floatarg dy); static void my_numbox_ftoa(t_my_numbox *x , int append); static void my_numbox_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av); -static t_symbol *numbox_keyname_sym_a; - static void my_numbox_tick_reset(t_my_numbox *x) { //post("tick_reset\n"); - if(x->x_gui.x_change && x->x_gui.x_glist) - { - //post(" success\n"); - my_numbox_set_change(x, 0); + my_numbox_remove_grab(x); + if(x->x_gui.x_changed) my_numbox_ftoa(x, 0); - sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); - } - glist_grab(x->x_gui.x_glist, 0, 0, 0, 0, 0, 0); - x->x_focused = 0; -} - -static void my_numbox_tick_wait(t_my_numbox *x) -{ - //post("tick_wait\n"); sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); } -// to enable ability to change values using arrow keys (only when focused) -static void my_numbox_set_change(t_my_numbox *x, t_floatarg f) +// change the grab state depending on the current level of focus +// 0 = no focus and therefore no grab +// 1 = only mouse focus +// 2 = exclusive keyboard and mouse focus +static void my_numbox_remove_grab(t_my_numbox *x) { - if (f == 0 && x->x_gui.x_change != 0) - { - x->x_gui.x_change = 0; - pd_unbind(&x->x_gui.x_obj.ob_pd, numbox_keyname_sym_a); - } - else if (f == 1 && x->x_gui.x_change != 1) - { - x->x_gui.x_change = 1; - pd_bind(&x->x_gui.x_obj.ob_pd, numbox_keyname_sym_a); - } + x->x_focused = 0; + glist_grab(x->x_gui.x_glist, 0, 0, 0, 0, 0, 0, 0); } void my_numbox_clip(t_my_numbox *x) { if(x->x_val < x->x_min) + { x->x_val = x->x_min; + x->x_gui.x_changed = 2; + + } if(x->x_val > x->x_max) + { x->x_val = x->x_max; + x->x_gui.x_changed = 2; + } } int my_numbox_calc_fontwidth2(t_my_numbox *x, int w, int h, int fontsize) @@ -92,6 +82,9 @@ int my_numbox_calc_fontwidth(t_my_numbox *x) x->x_num_fontsize); } +// we enable append flag when we want the value to be still displayed as-is +// without it being converted to + or - because it falls outside the numbox size +// boundaries static void my_numbox_ftoa(t_my_numbox *x, int append) { double f=x->x_val; @@ -152,65 +145,106 @@ static void my_numbox_ftoa(t_my_numbox *x, int append) static void my_numbox_draw_update(t_gobj *client, t_glist *glist) { t_my_numbox *x = (t_my_numbox *)client; - + //post("my_numbox_draw_update focused=%d changed=%d emptybuf=%d", + // x->x_focused, x->x_gui.x_changed, x->x_buf[0] ? 0 : 1); // we cannot ignore this call even if there is no change // since that will mess up number highlighting while editing // the code is left here as it is similar to other iemguis // but should not be used for this reason // if (!x->x_gui.x_changed) return; - x->x_gui.x_changed = 0; if (!glist_isvisible(glist)) return; - if(x->x_gui.x_change && x->x_buf[0]) + // if we are activated (focused) + if(x->x_focused && x->x_buf[0]) { - //post("draw_update 1 : focused=%d", x->x_focused); + int cursor_added = 0; + //post("...draw_update 1 : focused=%d <%s> buflen=%d", + // x->x_focused, x->x_buf, strlen(x->x_buf)); char *cp=x->x_buf; int sl = strlen(x->x_buf); - if (x->x_focused == 1) + // if we have been typing (focused == 3) + if (x->x_focused == 3) { x->x_buf[sl] = '>'; x->x_buf[sl+1] = 0; - } else if (x->x_focused == 2) { - // this is triggered when one presses return while retaining the focus of the number - // so, we make sure to subtract the '>' that has disappeared and adjust visible digits - // accordingly below - x->x_buf[sl] = 0; - sl--; + sl++; + cursor_added = 1; } + else if (x->x_focused == 2) { + // the following two options are triggered when one presses return while retaining + // the focus. so, we make sure to subtract the '>' that should dissappear, and adjust + // visible digits accordingly below + if (x->x_gui.x_changed == 2) + { + // if we pressed enter while having a value outside the min/max bounds + // clip the value before displaying it + my_numbox_ftoa(x, 0); + sl = strlen(x->x_buf); + x->x_buf[sl] = 0; + //post("changed and clipped"); + } + else + { + // otherwise, display it as-is + x->x_buf[sl] = 0; + } + } + // lastly, in case the number is longer than the number width, update the text offset + //post("...offset=%d width=%d", sl, x->x_gui.x_w); if(sl >= x->x_gui.x_w) - cp += sl - x->x_gui.x_w + 1; + { + cp += sl - x->x_gui.x_w; + //post("......new offset=%d", cp); + } + // send content to the front-end activated (last argument) gui_vmess("gui_text_set_mynumbox", "xxsi", glist_getcanvas(glist), x, cp, 1); - // here we check that we are not in the focused mode 2 that has this already taken care of above - if (x->x_focused != 2) - x->x_buf[sl] = 0; + // now get rid of the cursor in the x->x_buf after it has been passed to the GUI + // to prevent the corruption of future keyboard input updates (e.g. without this + // pressing 1 and then 2 will otherwise generate "1>2>") + if (cursor_added) + { + x->x_buf[sl-1] = 0; + } } else { - //if (!x->x_focused || x->x_focused == 2) - //post("draw_update 2: x->x_buf=<%s> focused=%d change=%d", x->x_buf, x->x_focused, x->x_gui.x_change); - if (!x->x_buf[0] && x->x_focused == 1 && x->x_gui.x_change == 1) + // here we capture several conditions: + //post("...draw_update 2: x->x_buf=<%s> focused=%d change=%d", \ + x->x_buf, x->x_focused, x->x_gui.x_change); + + if (!x->x_buf[0] && x->x_focused == 3) { + // 1st condition: we are still typing into the number box and have deleted the + // last digit,so we draw only the '>' x->x_buf[0] = '>'; x->x_buf[1] = 0; } else { + // 2nd condition: we replace the x->x_buf with the last stored value + // e.g. when we are timing out and therefore losing focus and the + // value is reverting to its stored one my_numbox_ftoa(x, 0); /* mmm... side-effects */ } + + // then draw the object based on its focus. Here we also check for special case + // where we have been selected in edit mode and are toplevel in which case even + // if we are not activated, our number should be still colored as activated. gui_vmess("gui_text_set_mynumbox", "xxsi", glist_getcanvas(glist), x, x->x_buf, x->x_gui.x_selected == glist_getcanvas(glist) && - !x->x_gui.x_change && x->x_gui.x_glist == glist_getcanvas(glist) ? - 2 : (x->x_gui.x_change ? 1 : 0)); + !x->x_focused && x->x_gui.x_glist == glist_getcanvas(glist) ? + 0 : (x->x_focused ? 1 : 0)); x->x_buf[0] = 0; /* mmm... more side-effects... no clue why we'd need to mutate a struct member in order to draw stuff */ } + x->x_gui.x_changed = 0; } static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist) @@ -219,7 +253,7 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist) char cbuf[8]; sprintf(cbuf, "#%6.6x", x->x_gui.x_bcol); int half=x->x_gui.x_h/2; - t_float d=1+x->x_gui.x_h/34.0; + int d=1+x->x_gui.x_h/34; int x1=text_xpix(&x->x_gui.x_obj, glist), x2=x1+x->x_numwidth; int y1=text_ypix(&x->x_gui.x_obj, glist), y2=y1+x->x_gui.x_h; @@ -236,13 +270,13 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist) my_numbox_ftoa(x, 0); sprintf(cbuf, "#%6.6x", x->x_gui.x_fcol); - gui_vmess("gui_numbox_draw_text", "xxsisifii", + gui_vmess("gui_numbox_draw_text", "xxsisiiiii", canvas, x, x->x_buf, x->x_num_fontsize, cbuf, - x1+half+2, y1+half+d, x1, y1); + x1+half+2, y1+half+d, x1, y1, x->x_gui.x_h - x->x_num_fontsize); } /* Not sure that this is needed anymore */ @@ -270,11 +304,13 @@ static void my_numbox_draw_move(t_my_numbox *x, t_glist *glist) x2 - x1, y2 - y1); - gui_vmess("gui_numbox_update_text_position", "xxii", + gui_vmess("gui_numbox_update_text_position", "xxiiii", canvas, x, half + 2, - half + d); + half + d, + x->x_num_fontsize, + x->x_gui.x_h - x->x_num_fontsize); } static void my_numbox_draw_config(t_my_numbox* x,t_glist* glist) @@ -300,7 +336,7 @@ static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist) int issel = x->x_gui.x_selected == canvas && x->x_gui.x_glist == canvas; if(x->x_gui.x_selected && x->x_gui.x_change) { - my_numbox_set_change(x, 0); + x->x_focused = 0; clock_unset(x->x_clock_reset); x->x_buf[0] = 0; sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); @@ -341,7 +377,7 @@ static void my_numbox__motionhook(t_scalehandle *sh, if (sh->h_scale) { t_my_numbox *x = (t_my_numbox *)(sh->h_master); - x->x_focused = 2; + //x->x_focused = 1; //int dx = (int)mouse_x - sh->h_offset_x; int dy = (sh->h_constrain == CURSOR_EDITMODE_RESIZE_X) ? 0 : (int)mouse_y - sh->h_offset_y; @@ -449,9 +485,9 @@ static void my_numbox_save(t_gobj *z, t_binbuf *b) t_symbol *srl[3]; iemgui_save(&x->x_gui, srl, bflcol); - if(x->x_gui.x_change) + if(x->x_focused) { - my_numbox_set_change(x, 0); + my_numbox_remove_grab(x); clock_unset(x->x_clock_reset); x->x_gui.x_changed = 1; sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); @@ -514,7 +550,7 @@ static void my_numbox_properties(t_gobj *z, t_glist *owner) iemgui_properties(&x->x_gui, srl); if(x->x_gui.x_change) { - my_numbox_set_change(x, 0); + my_numbox_remove_grab(x); clock_unset(x->x_clock_reset); x->x_gui.x_changed = 1; sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); @@ -599,75 +635,137 @@ static void my_numbox_dialog(t_my_numbox *x, t_symbol *s, int argc, static void my_numbox_motion(t_my_numbox *x, t_floatarg dx, t_floatarg dy) { - x->x_focused = 2; - double k2=1.0; - int old = x->x_val; - - if(x->x_gui.x_finemoved) - k2 = 0.01; - if(x->x_lin0_log1) - x->x_val *= pow(x->x_k, -k2*dy); - else - x->x_val -= k2*dy; - my_numbox_clip(x); - if (old != x->x_val) + if (x->x_focused == 1 && dy) { + double k2=1.0; x->x_gui.x_changed = 1; - my_numbox_ftoa(x, 0); + x->x_dragged = 1; + // if we have clicked and have started dragging, this means we want to + // change number by dragging, so here we disable the exclusive nature + // of glist_grab + glist_grab_exclusive(x->x_gui.x_glist, 0); + + if(x->x_gui.x_finemoved) + k2 = 0.01; + if(x->x_lin0_log1) + x->x_val *= pow(x->x_k, -k2*dy); + else + x->x_val -= k2*dy; + my_numbox_clip(x); + my_numbox_ftoa(x, 1); sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); my_numbox_bang(x); + + clock_unset(x->x_clock_reset); + clock_delay(x->x_clock_reset, 3000); } - clock_unset(x->x_clock_reset); - clock_delay(x->x_clock_reset, 3000); } +// this is called whenever there is a mousedown with left mouse button on top of the object +// this DOES NOT get called on mouse up static void my_numbox_click(t_my_numbox *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { + //post("my_numbox_click: is this even being used at all other than below?"); glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, - (t_glistmotionfn)my_numbox_motion, my_numbox_key, my_numbox_list, xpos, ypos); + (t_glistmotionfn)my_numbox_motion, 0, my_numbox_list, + xpos, ypos, 0); } +// this one gets called on both mouse down and mouse up (doit reports the mouse state) +// it is also called when there is motion without dragging, which alos reports doit as 0 static int my_numbox_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit) { t_my_numbox* x = (t_my_numbox *)z; - if(doit) + if (doit) { - //printf("newclick doit\n"); + //post("my_numbox_newclick calling my_numbox_click..."); my_numbox_click( x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt); - if(shift) + + if (shift) { x->x_gui.x_finemoved = 1; + x->x_shiftclick = 1; } else + { x->x_gui.x_finemoved = 0; - if(!x->x_gui.x_change) + x->x_shiftclick = 0; + } + + // if we are clicking on the object for the first time and are + // about to focus onto it + // LATER: reconcile the following if/else statements + if (!x->x_focused) { - clock_delay(x->x_clock_wait, 50); - my_numbox_set_change(x, 1); + //post("|...focusing for the first time"); clock_delay(x->x_clock_reset, 3000); if (shift) my_numbox_ftoa(x, 1); else x->x_buf[0] = 0; - x->x_focused = 2; + x->x_focused = 1; + x->x_dragged = 0; + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); } else { - my_numbox_set_change(x, 0); + //post("|...refocusing"); + // we have already been mouse focused only, and are clicking + // on the object again + // + // OR + // + // we have been keyboard focused and are clicking on the + // object again which should revert the value back to + // whatever was last stored and change focus back to mouse only + // we check for the latter below... clock_unset(x->x_clock_reset); - x->x_buf[0] = 0; - x->x_gui.x_changed = 1; + clock_delay(x->x_clock_reset, 3000); + if (x->x_focused > 1) + my_numbox_ftoa(x, 1); + else + x->x_buf[0] = 0; + x->x_focused = 1; + x->x_dragged = 0; sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); } } - else + // we have to check if we are focused and that dbl (a.k.a. double-click) is -1 + // as that suggests a genuine mouseup among all the mouse motion messages + // in g_editor.c that also have doit = 0 + else if (x->x_focused && dbl == -1) { - //x->x_focused = 1; + // here we check if the user has immediately let go of the mouse button + // which should put us in the exclusive text activated mode. + // we ignore focused = 2 state + if (x->x_focused == 1) + { + //post("|...letting go focused=1"); + if (!x->x_dragged) + { + //post("|...entering exclusive"); + x->x_focused = 3; + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)my_numbox_motion, my_numbox_key, my_numbox_list, + (t_floatarg)xpix, (t_floatarg)ypix, 1); + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } + else + { + x->x_dragged = 0; + //post("|...dragging complete, deactivating"); + // we have dragged the mouse, changed the value, + // and should immediately release focus + clock_unset(x->x_clock_reset); + x->x_gui.x_changed = 1; + my_numbox_tick_reset(x); + } + } } return (1); } @@ -770,15 +868,18 @@ static void my_numbox_loadbang(t_my_numbox *x, t_floatarg action) static void my_numbox_key(void *z, t_floatarg fkey) { t_my_numbox *x = z; + //post("numbox_key %f <%s>", fkey, x->x_buf); if (fkey != 0) - x->x_focused = 1; + { + x->x_focused = 3; + } // this is used for arrow up and down if (fkey == -1) { clock_unset(x->x_clock_reset); x->x_gui.x_changed = 1; - sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + my_numbox_draw_update(x, x->x_gui.x_glist); clock_delay(x->x_clock_reset, 3000); return; } @@ -791,20 +892,40 @@ static void my_numbox_key(void *z, t_floatarg fkey) // and therefore loses focus if (c == 0) { - my_numbox_set_change(x, 0); + x->x_dragged = 0; // do we need this? + //post("...clicking outside the number, deactivating"); + my_numbox_remove_grab(x); clock_unset(x->x_clock_reset); x->x_gui.x_changed = 1; - clock_delay(x->x_clock_reset, 0); - sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + my_numbox_tick_reset(x); + //sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); return; } if(((c>='0')&&(c<='9'))||(c=='.')||(c=='-')|| (c=='e')||(c=='+')||(c=='E')) { + if (x->x_shiftclick == -1) + { + x->x_buf[0] = 0; + x->x_shiftclick = 0; + } if(strlen(x->x_buf) < (IEMGUI_MAX_NUM_LEN-2)) { buf[0] = c; - strcat(x->x_buf, buf); + if (strlen(x->x_buf) == 1 && x->x_buf[0] == '0') + { + // if we have just committed a number by pressing return + // and the numbox is still focused, and we got clipped + // down to 0, make sure that our first digit goes to the + // first, not second place + strcpy(x->x_buf, buf); + //post("->STRCPY <%s>", x->x_buf); + } + else + { + strcat(x->x_buf, buf); + //post("->STRCAT <%s>", x->x_buf); + } x->x_gui.x_changed = 1; sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); } @@ -816,7 +937,6 @@ static void my_numbox_key(void *z, t_floatarg fkey) sl = 0; else sl=strlen(x->x_buf)-1; - if(sl < 0) sl = 0; x->x_buf[sl] = 0; @@ -827,12 +947,16 @@ static void my_numbox_key(void *z, t_floatarg fkey) { x->x_val = atof(x->x_buf); //x->x_buf[0] = 0; - my_numbox_set_change(x, 1); clock_unset(x->x_clock_reset); - my_numbox_clip(x); - my_numbox_bang(x); x->x_gui.x_changed = 1; + my_numbox_clip(x); x->x_focused = 2; + my_numbox_bang(x); + if (x->x_shiftclick == 0) + { + // we do this to make the next valid keypress after return clear the box + x->x_shiftclick = -1; + } sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); } @@ -864,21 +988,29 @@ static void my_numbox_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) my_numbox_set(x, atom_getfloatarg(0, ac, av)); my_numbox_bang(x); } - else if (ac == 2 && x->x_gui.x_change == 1 && IS_A_FLOAT(av,0) && IS_A_SYMBOL(av,1)) + else if (ac == 2 && IS_A_FLOAT(av,0) && IS_A_SYMBOL(av,1)) { - //fprintf(stderr,"got keyname %s while grabbed\n", av[1].a_w.w_symbol->s_name); - if (!strcmp("Shift", av[1].a_w.w_symbol->s_name)) + //if (!x->x_gui.x_changed) + // my_numbox_ftoa(x, 1); + //post("got keyname %s %d while grabbed\n", + // av[1].a_w.w_symbol->s_name, av[0].a_w.w_float); + // we allow shift to propagate in both focused modes 1 and 2 + // so as to enable fine movement that may be used in mode 1 + if (x->x_focused && !strcmp("Shift", av[1].a_w.w_symbol->s_name)) { x->x_gui.x_finemoved = (int)av[0].a_w.w_float; - //post("...Shift %d", x->a_shift); + //post("...Shift %d", x->x_gui.x_finemoved); } - if (av[0].a_w.w_float == 1) + if (x->x_focused > 1 && av[0].a_w.w_float == 1) { + if (!strcmp("Up", av[1].a_w.w_symbol->s_name)) { //fprintf(stderr,"...Up\n"); - if((x->x_buf[0] == 0 || x->x_buf == '>') && x->x_val != 0) - sprintf(x->x_buf, "%g", x->x_val+1); + if(x->x_buf[0] == 0 || x->x_buf[0] == '>') + { + sprintf(x->x_buf, "%g", 1.0); + } else sprintf(x->x_buf, "%g", atof(x->x_buf) + 1); my_numbox_key((void *)x, -1); @@ -886,8 +1018,8 @@ static void my_numbox_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) else if (!strcmp("ShiftUp", av[1].a_w.w_symbol->s_name)) { //fprintf(stderr,"...ShiftUp\n"); - if((x->x_buf[0] == 0 || x->x_buf == '>') && x->x_val != 0) - sprintf(x->x_buf, "%g", x->x_val+0.01); + if(x->x_buf[0] == 0 || x->x_buf[0] == '>') + sprintf(x->x_buf, "%g", 0.01); else sprintf(x->x_buf, "%g", atof(x->x_buf) + 0.01); my_numbox_key((void *)x, -1); @@ -895,8 +1027,8 @@ static void my_numbox_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) else if (!strcmp("Down", av[1].a_w.w_symbol->s_name)) { //fprintf(stderr,"...Down\n"); - if((x->x_buf[0] == 0 || x->x_buf == '>') && x->x_val != 0) - sprintf(x->x_buf, "%g", x->x_val-1); + if(x->x_buf[0] == 0 || x->x_buf[0] == '>') + sprintf(x->x_buf, "%g", -1.0); else sprintf(x->x_buf, "%g", atof(x->x_buf) - 1); my_numbox_key((void *)x, -1); @@ -904,8 +1036,8 @@ static void my_numbox_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) else if (!strcmp("ShiftDown", av[1].a_w.w_symbol->s_name)) { //fprintf(stderr,"...ShiftDown\n"); - if((x->x_buf[0] == 0 || x->x_buf == '>') && x->x_val != 0) - sprintf(x->x_buf, "%g", x->x_val-0.01); + if(x->x_buf[0] == 0 || x->x_buf[0] == '>') + sprintf(x->x_buf, "%g", -0.01); else sprintf(x->x_buf, "%g", atof(x->x_buf) - 0.01); my_numbox_key((void *)x, -1); @@ -977,7 +1109,6 @@ static void *my_numbox_new(t_symbol *s, int argc, t_atom *argv) my_numbox_check_minmax(x, min, max); iemgui_verify_snd_ne_rcv(&x->x_gui); x->x_clock_reset = clock_new(x, (t_method)my_numbox_tick_reset); - x->x_clock_wait = clock_new(x, (t_method)my_numbox_tick_wait); x->x_gui.x_change = 0; outlet_new(&x->x_gui.x_obj, &s_float); @@ -995,6 +1126,8 @@ static void *my_numbox_new(t_symbol *s, int argc, t_atom *argv) x->x_focused = 0; x->x_yresize_x = 0; + x->x_shiftclick = 0; + x->x_dragged = 0; return (x); } @@ -1003,9 +1136,9 @@ static void my_numbox_free(t_my_numbox *x) { if(iemgui_has_rcv(&x->x_gui)) pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); - my_numbox_set_change(x, 0); + x->x_focused = 0; + my_numbox_remove_grab(x); clock_free(x->x_clock_reset); - clock_free(x->x_clock_wait); gfxstub_deleteforkey(x); if (x->x_gui. x_handle) scalehandle_free(x->x_gui. x_handle); @@ -1047,8 +1180,6 @@ void g_numbox_setup(void) class_addmethod(my_numbox_class, (t_method)my_numbox_drawstyle, gensym("drawstyle"), A_FLOAT, 0); - numbox_keyname_sym_a = gensym("#keyname_a"); - wb_init(&my_numbox_widgetbehavior,my_numbox_getrect,my_numbox_newclick); class_setwidget(my_numbox_class, &my_numbox_widgetbehavior); class_sethelpsymbol(my_numbox_class, gensym("numbox2")); diff --git a/pd/src/g_slider.c b/pd/src/g_slider.c index 5caeaad6b75a80641980628d642fde2777bfe4a1..093c424f22c8a2426f4617cd71443d65c49ddc90 100644 --- a/pd/src/g_slider.c +++ b/pd/src/g_slider.c @@ -373,6 +373,20 @@ static void slider_motion(t_slider *x, t_floatarg dx, t_floatarg dy) } } + +// we use this exclusively to dynamically capture shift presses when +// dragging the slider +static void slider_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac == 2 && IS_A_FLOAT(av,0) && IS_A_SYMBOL(av,1)) + { + if (!strcmp("Shift", av[1].a_w.w_symbol->s_name)) + { + x->x_gui.x_finemoved = (int)av[0].a_w.w_float; + } + } +} + static void slider_click(t_slider *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { @@ -392,19 +406,27 @@ static void slider_click(t_slider *x, t_floatarg xpos, t_floatarg ypos, x->x_is_last_float=0; // does anyone know how this works with !steady && rcv==snd ? slider_bang(x); glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, - (t_glistmotionfn)slider_motion, 0, 0, xpos, ypos); + (t_glistmotionfn)slider_motion, 0, slider_list, xpos, ypos, 0); } static int slider_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit) { t_slider *x = (t_slider *)z; + //post("slider_newclick dbl=%d doit=%d grabbed=%d", \ + dbl, doit, x->x_gui.x_glist->gl_editor->e_grab ? 1 : 0); + if(doit) { slider_click(x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt); x->x_gui.x_finemoved = !!shift; } + else if (dbl == -1) + { + // genuine mouseup + glist_grab(x->x_gui.x_glist, 0, 0, 0, 0, 0, 0, 0); + } return (1); } diff --git a/pd/src/g_template.c b/pd/src/g_template.c index a37957dfcce526db87f7c49a3d50ad927b248900..646a85692f1eae4c4e0f6514515afa02487e5d21 100644 --- a/pd/src/g_template.c +++ b/pd/src/g_template.c @@ -4475,7 +4475,7 @@ static int draw_click(t_gobj *z, t_glist *glist, &draw_motion_scalar->sc_gobj); else gpointer_setarray(&draw_motion_gpointer, draw_motion_array, draw_motion_wp); - glist_grab(glist, z, draw_motion, 0, 0, xpix, ypix); + glist_grab(glist, z, draw_motion, 0, 0, xpix, ypix, 0); //outlet_anything(x->x_obj.ob_outlet, gensym("click"), 0, 0); } //draw_notifyforscalar(x, glist, sc, gensym("mousedown"), 5, at); @@ -4693,7 +4693,7 @@ static int draw_click(t_gobj *z, t_glist *glist, &draw_motion_scalar->sc_gobj); else gpointer_setarray(&draw_motion_gpointer, draw_motion_array, draw_motion_wp); - glist_grab(glist, z, draw_motion, 0, 0, xpix, ypix); + glist_grab(glist, z, draw_motion, 0, 0, xpix, ypix, 0); } post("we got clicked"); outlet_anything(x->x_obj.ob_outlet, gensym("click"), 0, 0); @@ -5475,7 +5475,7 @@ static int curve_click(t_gobj *z, t_glist *glist, &curve_motion_scalar->sc_gobj); else gpointer_setarray(&curve_motion_gpointer, curve_motion_array, curve_motion_wp); - glist_grab(glist, z, curve_motion, 0, 0, xpix, ypix); + glist_grab(glist, z, curve_motion, 0, 0, xpix, ypix, 0); } return (1); } @@ -7507,7 +7507,7 @@ static int drawsymbol_click(t_gobj *z, t_glist *glist, drawsymbol_motion_array, drawsymbol_motion_wp); /* ico@vt.edu 20200920: LATER consider also using keyname (currently 0) */ glist_grab(glist, z, drawsymbol_motion, drawsymbol_key, - 0, xpix, ypix); + 0, xpix, ypix, 0); } return (1); } @@ -7938,7 +7938,7 @@ static int drawimage_click(t_gobj *z, t_glist *glist, drawimage_motion_array, drawimage_motion_wp); /* ico@vt.edu 20200920: LATER consider also using keyname (currently 0) */ glist_grab(glist, z, drawimage_motion, drawimage_key, - 0, xpix, ypix); + 0, xpix, ypix, 0); } return (1); } diff --git a/pd/src/g_text.c b/pd/src/g_text.c index 692396032c1b3e9efe293257d912bd5c5fabb2e8..eb936ccee57166f5a978a85367427a68c339e105 100644 --- a/pd/src/g_text.c +++ b/pd/src/g_text.c @@ -877,7 +877,7 @@ typedef struct _gatom t_symbol *a_symfrom; /* "receive" name -- bind ourselvs to this */ t_symbol *a_symto; /* "send" name -- send to this on output */ char a_buf[ATOMBUFSIZE]; /* string buffer for typing */ - char a_shift; /* was shift key down when dragging started? */ + int a_shift; /* was shift key down when dragging started? */ char a_wherelabel; /* 0-3 for left, right, above, below */ t_symbol *a_expanded_to; /* a_symto after $0, $1, ... expansion */ int a_shift_clicked; /* used to keep old text after \n. this is @@ -1112,7 +1112,8 @@ static void gatom_key(void *z, t_floatarg f) { t_gatom *x = (t_gatom *)z; int c = f; - //post("gatom_key %f %d", f, x->a_shift); + //post("gatom_key %f shift=%d strlen=%d <%s>", \ + f, x->a_shift, strlen(x->a_buf), x->a_buf); int len = strlen(x->a_buf); t_atom at; char sbuf[ATOMBUFSIZE + 4]; @@ -1120,7 +1121,7 @@ static void gatom_key(void *z, t_floatarg f) { // we're being notified that no more keys will come for this grab //post("gatom_key end <%s> <%s>", x->a_buf, x->a_atom.a_w.w_symbol->s_name); - pd_unbind(&x->a_text.ob_pd, gensym("#keyname_a")); + //pd_unbind(&x->a_text.ob_pd, gensym("#keyname_a")); //post("unbind <%s>", x->a_buf); if (x->a_atom.a_type == A_FLOAT) { @@ -1195,7 +1196,7 @@ static void gatom_key(void *z, t_floatarg f) x->a_buf[0] = 0; /* We want to keep grabbing the keyboard after hitting "Enter", so we're commenting the following out */ - //glist_grab(x->a_glist, 0, 0, 0, 0, 0, 0); + //glist_grab(x->a_glist, 0, 0, 0, 0, 0, 0, 0); } else if (len < (ATOMBUFSIZE-1)) { @@ -1237,8 +1238,8 @@ static void gatom_click(t_gatom *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { - //post("gatom_click %f %f", ctrl, alt); - pd_bind(&x->a_text.ob_pd, gensym("#keyname_a")); + //post("gatom_click shift=%f ctrl=%f alt=%f", shift, ctrl, alt); + //pd_bind(&x->a_text.ob_pd, gensym("#keyname_a")); //post("bind"); if (x->a_text.te_width == 1) { @@ -1260,7 +1261,8 @@ static void gatom_click(t_gatom *x, return; } x->a_shift = shift; - if (x->a_atom.a_type == A_SYMBOL && !strlen(x->a_atom.a_w.w_symbol->s_name)) + if (x->a_atom.a_type == A_SYMBOL && + !strlen(x->a_atom.a_w.w_symbol->s_name)) { char sbuf[ATOMBUFSIZE + 4]; t_atom at; @@ -1270,14 +1272,23 @@ static void gatom_click(t_gatom *x, binbuf_add(x->a_text.te_binbuf, 1, &at); glist_retext(x->a_glist, &x->a_text); } + // unlike iemgui numbox, here we are unable to distinguish + // between the exclusive and non-exclusive focus because + // the old school "click" message passed to the object does + // not provide additional necessary info, such as doubleclick + // (which we use to differentiate between the genuine mouseup + // events and those generated by the mouse motion), and doit + // (which differentiates the button press or 1 from the aforesaid + // two events). Long story short, we do not seek exclusive focus + // with the vanilla gatom. glist_grab(x->a_glist, &x->a_text.te_g, gatom_motion, gatom_key, - gatom_list, xpos, ypos); + gatom_list, xpos, ypos, 0); //post("a_shift_clicked=%d", x->a_shift_clicked); - x->a_shift_clicked = shift; + x->a_shift_clicked = x->a_shift; // second click wipes prior text if (!x->a_shift_clicked) x->a_buf[0] = 0; - //post("a_shift_clicked=%d", x->a_shift_clicked); + //post("a_shift_clicked=%d <%s>", x->a_shift_clicked, x->a_buf); } }