Lost input in quickfill cells due to race

Christian Stimming christian at cstimming.de
Tue May 24 16:36:16 EDT 2011


Am Dienstag, 24. Mai 2011 schrieb Jim Paris:
> > As an intermediate solution, I think it would be fine if you add some
> > intermediate data that ensures the timeout callback does not drop any
> > characters that appeared in the meantime. Like, can the callback data
> > also store the current position and verify it hasn't changed when it is
> > run? If it had changed (i.e. additional characters have been received),
> > the callback should just do nothing.
> 
> I've been looking at it some more and came up with the below fix,
> which seems to work.

Thanks a lot! I've committed this to SVN and we'll see whether anyone sees new 
problems, but the code looks very good to me. Thanks again!

Christian


> The keyboard input ends up in the commit_cb
> which calls gtk_editable_insert_text then gtk_editable_set_position.
> It's the call to _set_position that clears the selection!
> 
> I think this might be a bug in GTK+, because gtk_entry_real_set_position
> does this:
> 
>   if (position != priv->current_pos ||
>       position != priv->selection_bound)
>     {
>       _gtk_entry_reset_im_context (entry);
>       gtk_entry_set_positions (entry, position, position);
>     }
> 
> The test is basically always true.  I don't think that || was
> intended: priv->current_pos is the start of the selection,
> priv->selection_bound is the end of it.  If the test were &&, then
> an attempt to position the cursor at either end of the selection
> wouldn't have cleared it.
> 
> But either way, the below patch seems to work fine on gnucash for now.
> You can also pull it from branch 'master' at
> https://git.jim.sh/jim/gnucash.git
> 
> A side note: I've just realized that this use of selection for
> autocompletion is one of the big causes of input lag when running
> gnucash over X11-forwarding.  I guess it's the setting of the X
> primary selection causing a flurry of roundtrips every time you hit a
> key.  But at least now that won't translate into lost input anymore.
> 
> -jim
> 
> From: Jim Paris <jim at jtan.com>
> Date: Tue, 24 May 2011 14:45:06 -0400
> Subject: [PATCH] Preserve selection around the call to
> gtk_editable_set_position.
> 
> This lets us drop the racy gnucash_sheet_select_data_cb, which fixes
> problems with lost input.
> ---
>  src/register/register-gnome/gnucash-sheet.c |   35
> ++++++-------------------- 1 files changed, 8 insertions(+), 27
> deletions(-)
> 
> diff --git a/src/register/register-gnome/gnucash-sheet.c
> b/src/register/register-gnome/gnucash-sheet.c index 2d7142f..f5e8671
> 100644
> --- a/src/register/register-gnome/gnucash-sheet.c
> +++ b/src/register/register-gnome/gnucash-sheet.c
> @@ -844,22 +844,6 @@ typedef struct
> 
>  } select_info;
> 
> -/*
> - * This function is needed because gtk_entry_insert_text() sets the
> - * cursor position after emitting the "insert+text" signal.  This
> - * means that the gtk_editable_select_region() call cannot be in the
> - * insert_cb function because it will just be cancelled out after
> - * the function finishes running.
> - */
> -static gboolean
> -gnucash_sheet_select_data_cb (select_info *info)
> -{
> -    gtk_editable_select_region (info->editable,
> -                                info->start_sel, info->end_sel);
> -    g_free(info);
> -    return FALSE; /* This is a one shot function */
> -}
> -
>  static void
>  gnucash_sheet_insert_cb (GtkWidget *widget,
>                           const gchar *insert_text,
> @@ -999,17 +983,7 @@ gnucash_sheet_insert_cb (GtkWidget *widget,
>          *position = g_utf8_strlen(retval, -1);
> 
>      if (start_sel != end_sel)
> -    {
> -        select_info *info;
> -
> -        info = g_malloc(sizeof(*info));
> -        info->editable = editable;
> -        info->start_sel = start_sel;
> -        info->end_sel = end_sel;
> -        g_timeout_add(/*ASAP*/ 1,
> -                               (GSourceFunc)gnucash_sheet_select_data_cb,
> -                               info);
> -    }
> +	gtk_editable_select_region(editable, start_sel, end_sel);
> 
>      g_string_free (new_text_gs, TRUE);
>      g_string_free (change_text_gs, TRUE);
> @@ -2030,7 +2004,14 @@ gnucash_sheet_commit_cb (GtkIMContext *context,
> const gchar *str, gtk_editable_get_position (editable)
> 
>                : sheet->preedit_start_position;
> 
>      gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos);
> +
> +    /* insert_cb may have changed the selection, but
> gtk_editable_set_position +       (erroneously?) clears it.  If a
> selection is set, preserve it. */ +    gtk_editable_get_selection_bounds
> (editable, &sel_start, &sel_end); gtk_editable_set_position (editable,
> tmp_pos);
> +    if (sel_start != sel_end)
> +	gtk_editable_select_region (editable, sel_start, sel_end);
> +
>      gnucash_sheet_im_context_reset_flags(sheet);
>  }



More information about the gnucash-devel mailing list