[Xfce4-commits] <exo:master> Use an idle function for delayed scrolling.

Jannis Pohlmann jannis at xfce.org
Fri Sep 11 20:22:01 CEST 2009


Updating branch refs/heads/master
         to 0a7be769f07828953d62e86fbc9da755f9aa8ad6 (commit)
       from 790a952f24b6d9ceb5cebec0a97fb11274d905f7 (commit)

commit 0a7be769f07828953d62e86fbc9da755f9aa8ad6
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Fri Sep 11 20:10:04 2009 +0200

    Use an idle function for delayed scrolling.
    
    It looks like modifying the bin_window GdkWindow inside the expose
    event handler of ExoIconView does no longer work with client-side
    windows. This was done for delaying the scrolling to a certain path
    until the widget is realized and layouting is completed.
    
    As a result of using gdk_window_move() inside of the expose event
    handler, the painted icon view was not up to date or mixed up after the
    event handler had finished. Icons moved up a few pixels when hovering
    them and with scroll positions further down the view, the contents were
    painted twice (in the old and new state), resulting in overlapping
    items.
    
    This commit implements delayed scrolling via an idle function, which is
    the only way I see right now to work around this. It may cause the
    automatic scrolling to the previous file to be delayed for a very short
    time, but this shouldn't be critical.
    
    A bug was filed against GDK on
    
      http://bugzilla.gnome.org/show_bug.cgi?id=594880

 exo/exo-icon-view.c |   78 ++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/exo/exo-icon-view.c b/exo/exo-icon-view.c
index 7a64a65..b3b1624 100644
--- a/exo/exo-icon-view.c
+++ b/exo/exo-icon-view.c
@@ -466,6 +466,7 @@ struct _ExoIconViewPrivate
   GtkAdjustment *vadjustment;
 
   gint layout_idle_id;
+  gint scroll_idle_id;
 
   gboolean doing_rubberband;
   gint rubberband_x_1, rubberband_y_1;
@@ -1229,6 +1230,10 @@ exo_icon_view_finalize (GObject *object)
   if (G_UNLIKELY (icon_view->priv->single_click_timeout_id != 0))
     g_source_remove (icon_view->priv->single_click_timeout_id);
 
+  /* kill the scroll idle source */
+  if (G_UNLIKELY (icon_view->priv->scroll_idle_id != 0))
+    g_source_remove (icon_view->priv->scroll_idle_id);
+
   /* kill the layout idle source (it's important to have this last!) */
   if (G_UNLIKELY (icon_view->priv->layout_idle_id != 0))
     g_source_remove (icon_view->priv->layout_idle_id);
@@ -1622,28 +1627,6 @@ exo_icon_view_expose_event (GtkWidget      *widget,
   if (G_UNLIKELY (priv->layout_idle_id != 0))
     return FALSE;
 
-  /* scroll to the previously remembered path (if any) */
-  if (G_UNLIKELY (priv->scroll_to_path != NULL))
-    {
-      /* grab the path from the reference and invalidate the reference */
-      path = gtk_tree_row_reference_get_path (priv->scroll_to_path);
-      gtk_tree_row_reference_free (priv->scroll_to_path);
-      priv->scroll_to_path = NULL;
-
-      /* check if the reference was still valid */
-      if (G_LIKELY (path != NULL))
-        {
-          /* try to scroll again */
-          exo_icon_view_scroll_to_path (icon_view, path,
-                                        priv->scroll_to_use_align,
-                                        priv->scroll_to_row_align,
-                                        priv->scroll_to_col_align);
-
-          /* release the path */
-          gtk_tree_path_free (path);
-        }
-    }
-
   /* check if we need to draw a drag indicator */
   exo_icon_view_get_drag_dest_item (icon_view, &path, &dest_pos);
   if (G_UNLIKELY (path != NULL))
@@ -5417,6 +5400,8 @@ update_text_cell (ExoIconView *icon_view)
     }
 }
 
+
+
 static void
 update_pixbuf_cell (ExoIconView *icon_view)
 {
@@ -5762,6 +5747,46 @@ exo_icon_view_set_cursor (ExoIconView     *icon_view,
 
 
 
+static gboolean
+scroll_delayed (gpointer user_data)
+{
+  ExoIconView *icon_view = user_data;
+  GtkTreePath *path;
+
+  _exo_return_val_if_fail (EXO_IS_ICON_VIEW (icon_view), FALSE);
+  
+  /* schedule the scrolling again if the window still isn't realized or 
+   * the layouting still is not finished */
+  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (icon_view)) || icon_view->priv->layout_idle_id != 0)
+    return TRUE;
+  
+  /* scroll to the previously remembered path (if any) */
+  if (G_UNLIKELY (icon_view->priv->scroll_to_path != NULL))
+    {
+      /* grab the path from the reference and invalidate the reference */
+      path = gtk_tree_row_reference_get_path (icon_view->priv->scroll_to_path);
+      gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
+      icon_view->priv->scroll_to_path = NULL;
+
+      /* check if the reference was still valid */
+      if (G_LIKELY (path != NULL))
+        {
+          /* try to scroll again */
+          exo_icon_view_scroll_to_path (icon_view, path,
+                                        icon_view->priv->scroll_to_use_align,
+                                        icon_view->priv->scroll_to_row_align,
+                                        icon_view->priv->scroll_to_col_align);
+
+          /* release the path */
+          gtk_tree_path_free (path);
+        }
+    }
+
+  return FALSE;
+}
+
+
+
 /**
  * exo_icon_view_scroll_to_path:
  * @icon_view: A #ExoIconView.
@@ -5803,6 +5828,10 @@ exo_icon_view_scroll_to_path (ExoIconView *icon_view,
   /* Delay scrolling if either not realized or pending layout() */
   if (!GTK_WIDGET_REALIZED (icon_view) || icon_view->priv->layout_idle_id != 0)
     {
+      /* drop previous scroll idle handler */
+      if (G_UNLIKELY (icon_view->priv->scroll_idle_id != 0))
+        g_source_remove (icon_view->priv->scroll_idle_id);
+
       /* release the previous scroll_to_path reference */
       if (G_UNLIKELY (icon_view->priv->scroll_to_path != NULL))
         gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
@@ -5812,6 +5841,11 @@ exo_icon_view_scroll_to_path (ExoIconView *icon_view,
       icon_view->priv->scroll_to_use_align = use_align;
       icon_view->priv->scroll_to_row_align = row_align;
       icon_view->priv->scroll_to_col_align = col_align;
+
+      /* schedule an idle handler to scroll to the given path */
+      icon_view->priv->scroll_idle_id = g_idle_add_full (G_PRIORITY_LOW, 
+                                                         scroll_delayed, icon_view, 
+                                                         NULL);
     }
   else
     {



More information about the Xfce4-commits mailing list