Bug 634086 - Simulate the native rendering for indeterminate progress bar in GTK. r=karlt
authorMounir Lamouri <mounir.lamouri@gmail.com>
Thu, 05 May 2011 15:11:35 +0200
changeset 69391 0695497a4b52dd6f93d649c2c986553f592b78e2
parent 69390 00d5a081d5d319014113353f7b1976b7218f3f85
child 69392 94dc6447f1026ba7ce0ebec871969b61e607bf32
push id76
push userbzbarsky@mozilla.com
push dateTue, 05 Jul 2011 17:00:57 +0000
treeherdermozilla-beta@d3a2732c35f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs634086
milestone6.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 634086 - Simulate the native rendering for indeterminate progress bar in GTK. r=karlt
widget/src/gtk2/gtk2drawing.c
widget/src/gtk2/gtkdrawing.h
widget/src/gtk2/nsNativeThemeGTK.cpp
--- a/widget/src/gtk2/gtk2drawing.c
+++ b/widget/src/gtk2/gtk2drawing.c
@@ -43,16 +43,17 @@
  * Adapted from the gtkdrawing.c, and gtk+2.0 source.
  */
 
 #include <gtk/gtk.h>
 #include <gdk/gdkprivate.h>
 #include <string.h>
 #include "gtkdrawing.h"
 #include "nsDebug.h"
+#include "prinrval.h"
 
 #include <math.h>
 
 #define XTHICKNESS(style) (style->xthickness)
 #define YTHICKNESS(style) (style->ythickness)
 #define WINDOW_IS_MAPPED(window) ((window) && GDK_IS_WINDOW(window) && gdk_window_is_visible(window))
 
 static GtkWidget* gProtoWindow;
@@ -2230,26 +2231,52 @@ moz_gtk_progressbar_paint(GdkDrawable* d
                   cliprect, gProgressWidget, "trough", rect->x, rect->y,
                   rect->width, rect->height);
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_progress_chunk_paint(GdkDrawable* drawable, GdkRectangle* rect,
-                             GdkRectangle* cliprect, GtkTextDirection direction)
+                             GdkRectangle* cliprect, GtkTextDirection direction,
+                             GtkThemeWidgetType widget)
 {
     GtkStyle* style;
 
     ensure_progress_widget();
     gtk_widget_set_direction(gProgressWidget, direction);
 
     style = gProgressWidget->style;
 
     TSOffsetStyleGCs(style, rect->x, rect->y);
+
+    if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE) {
+      /**
+       * The bar's width and the bar speed are set depending of the progress
+       * bar size. These could also be constant for all progress bars easily.
+       */
+
+      /* The bar is using a fifth of the element size, based on GtkProgressBar
+       * activity-blocks property. */
+      const gint barWidth = MAX(1, rect->width / 5);
+
+      /* Represents the travel that has to be done for a complete cycle. */
+      const gint travel = 2 * (rect->width - barWidth);
+
+      /* period equals to travel / pixelsPerMillisecond
+       * where pixelsPerMillisecond equals rect->width / 1000.0.
+       * This is equivalent to 1600. */
+      const guint period = 1600;
+      const gint t = PR_IntervalToMilliseconds(PR_IntervalNow()) % period;
+      const gint dx = travel * t / period;
+
+      rect->x += (dx < travel / 2) ? dx : travel - dx;
+      rect->width = barWidth;
+    }
+
     gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
                   cliprect, gProgressWidget, "bar", rect->x, rect->y,
                   rect->width, rect->height);
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
@@ -2953,16 +2980,17 @@ moz_gtk_get_widget_border(GtkThemeWidget
     case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
     case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
     case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
     case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
     case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
     case MOZ_GTK_SCALE_THUMB_VERTICAL:
     case MOZ_GTK_GRIPPER:
     case MOZ_GTK_PROGRESS_CHUNK:
+    case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
     case MOZ_GTK_EXPANDER:
     case MOZ_GTK_TREEVIEW_EXPANDER:
     case MOZ_GTK_TOOLBAR_SEPARATOR:
     case MOZ_GTK_MENUSEPARATOR:
     /* These widgets have no borders.*/
     case MOZ_GTK_SPINBUTTON:
     case MOZ_GTK_TOOLTIP:
     case MOZ_GTK_WINDOW:
@@ -3299,18 +3327,19 @@ moz_gtk_widget_paint(GtkThemeWidgetType 
     case MOZ_GTK_RESIZER:
         return moz_gtk_resizer_paint(drawable, rect, cliprect, state,
                                      direction);
         break;
     case MOZ_GTK_PROGRESSBAR:
         return moz_gtk_progressbar_paint(drawable, rect, cliprect, direction);
         break;
     case MOZ_GTK_PROGRESS_CHUNK:
+    case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
         return moz_gtk_progress_chunk_paint(drawable, rect, cliprect,
-                                            direction);
+                                            direction, widget);
         break;
     case MOZ_GTK_TAB:
         return moz_gtk_tab_paint(drawable, rect, cliprect, state,
                                  (GtkTabFlags) flags, direction);
         break;
     case MOZ_GTK_TABPANELS:
         return moz_gtk_tabpanels_paint(drawable, rect, cliprect, direction);
         break;
--- a/widget/src/gtk2/gtkdrawing.h
+++ b/widget/src/gtk2/gtkdrawing.h
@@ -173,16 +173,18 @@ typedef enum {
   /* Paints a GtkFrame (e.g. a status bar panel). */
   MOZ_GTK_FRAME,
   /* Paints a resize grip for a GtkWindow */
   MOZ_GTK_RESIZER,
   /* Paints a GtkProgressBar. */
   MOZ_GTK_PROGRESSBAR,
   /* Paints a progress chunk of a GtkProgressBar. */
   MOZ_GTK_PROGRESS_CHUNK,
+  /* Paints a progress chunk of an indeterminated GtkProgressBar. */
+  MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE,
   /* Paints a tab of a GtkNotebook. flags is a GtkTabFlags, defined above. */
   MOZ_GTK_TAB,
   /* Paints the background and border of a GtkNotebook. */
   MOZ_GTK_TABPANELS,
   /* Paints a GtkArrow for a GtkNotebook. flags is a GtkArrowType. */
   MOZ_GTK_TAB_SCROLLARROW,
   /* Paints the background and border of a GtkTreeView */
   MOZ_GTK_TREEVIEW,
--- a/widget/src/gtk2/nsNativeThemeGTK.cpp
+++ b/widget/src/gtk2/nsNativeThemeGTK.cpp
@@ -561,17 +561,24 @@ nsNativeThemeGTK::GetGtkWidgetAndState(P
     aGtkWidgetType = MOZ_GTK_FRAME;
     break;
   case NS_THEME_PROGRESSBAR:
   case NS_THEME_PROGRESSBAR_VERTICAL:
     aGtkWidgetType = MOZ_GTK_PROGRESSBAR;
     break;
   case NS_THEME_PROGRESSBAR_CHUNK:
   case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
-    aGtkWidgetType = MOZ_GTK_PROGRESS_CHUNK;
+    {
+      nsIFrame* stateFrame = aFrame->GetParent();
+      nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
+
+      aGtkWidgetType = IsIndeterminateProgress(stateFrame, eventStates)
+                         ? MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE
+                         : MOZ_GTK_PROGRESS_CHUNK;
+    }
     break;
   case NS_THEME_TAB_SCROLLARROW_BACK:
   case NS_THEME_TAB_SCROLLARROW_FORWARD:
     if (aWidgetFlags)
       *aWidgetFlags = aWidgetType == NS_THEME_TAB_SCROLLARROW_BACK ?
                         GTK_ARROW_LEFT : GTK_ARROW_RIGHT;
     aGtkWidgetType = MOZ_GTK_TAB_SCROLLARROW;
     break;
@@ -868,16 +875,23 @@ nsNativeThemeGTK::DrawWidgetBackground(n
       // force refresh of the window, because the widget was not
       // successfully drawn it must be redrawn using the default look
       RefreshWidgetWindow(aFrame);
     } else {
       SetWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state);
     }
   }
 
+  // Indeterminate progress bar are animated.
+  if (gtkWidgetType == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE) {
+    if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) {
+      NS_WARNING("unable to animate widget!");
+    }
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
                                   PRUint8 aWidgetType, nsIntMargin* aResult)
 {
   GtkTextDirection direction = GetTextDirection(aFrame);