Hackish proof of concept patch to fix the flashing on dnd. The flashing is due to the fact that we get the expose event between the two modifications caused by the dnd: that causes update_highlighting_cb to be called, which in turn calls ensure_hilight. My idea is to synchrounously process all the pending modifications in the queue which affect the exposed area. The sync process should not be that bad since the exposed area is small and at least we avoid redrawing for each modification. If the sync process turns out to be a problem we should probably do it for a timeslice and if it doesn't suffice for all the modifications in the area, live with a bit of flickering. The implementation is hackish because: a) I hate async_modify and even more I hate running it in a while(). My hate will increase even more if we introduce yet another timeslice timer. b) Instead of 'peeking' at the head of the queue I simply pop and process one extra modification. Seems to work though. diff -r 41940e78acc6 gtksourceview/gtksourcecontextengine.c --- a/gtksourceview/gtksourcecontextengine.c Tue May 30 13:34:31 2006 +++ b/gtksourceview/gtksourcecontextengine.c Wed May 31 11:42:14 2006 @@ -436,7 +436,8 @@ static void text_modified (GtkSourceContextEngine *ce, gint offset, gint delta); -static gboolean async_modify (GtkSourceContextEngine *ce); +static gboolean async_modify (GtkSourceContextEngine *ce, + gint until); static void update_syntax (GtkSourceContextEngine *ce, const GtkTextIter *needed_end, Modify *modify); @@ -589,6 +590,8 @@ const GtkTextIter *end, gboolean synchronous) { + gint end_offset; + g_return_if_fail (GTK_IS_SOURCE_CONTEXT_ENGINE (ce)); g_return_if_fail (start != NULL); g_return_if_fail (end != NULL); @@ -596,9 +599,13 @@ if (!ce->priv->highlight) return; + end_offset = gtk_text_iter_get_offset (end); if (ce->priv->worker_last_offset < 0 || - ce->priv->worker_last_offset >= gtk_text_iter_get_offset (end)) - { + ce->priv->worker_last_offset >= end_offset) + { + /* try to process synchronously all the pending + modifications in this area to avoid fliker */ + while (async_modify (ce, end_offset)) ; ensure_highlighted (ce, start, end); } else @@ -606,7 +613,7 @@ if (synchronous) { /* Do pending asynchronous modifications. */ - while (async_modify (ce)) ; + while (async_modify (ce, -1)) ; update_syntax (ce, end, NULL); ensure_highlighted (ce, start, end); } @@ -1725,7 +1732,7 @@ { GTimer *timer = g_timer_new (); - while (async_modify (ce)) + while (async_modify (ce, -1)) { if (g_timer_elapsed (timer, NULL) * 1000. > WORKER_TIME_SLICE) break; @@ -2314,14 +2321,19 @@ * queue is empty. */ static gboolean -async_modify (GtkSourceContextEngine *ce) +async_modify (GtkSourceContextEngine *ce, gint until) { Modify *modify; + gboolean ret = TRUE; modify = modify_queue_pop (ce->priv->modifications); if (modify == NULL) return FALSE; + + /* (hack) for now process this mod anyway since we popped it */ + if (until != -1 && modify->offset > until) + ret = FALSE; update_syntax (ce, NULL, modify); @@ -2331,7 +2343,7 @@ modify_queue_clear_by_offset (ce->priv->modifications, ce->priv->worker_last_offset); - return TRUE; + return ret; } /**