And faaaaaaaade out agaaaaaain - The return of the log out patch.



Rewrote patch to use Havoc's frame drop plan 
And Federico's linear interpolation idea

Given these changes I got 5 or 6 frames in the 2 second gap
instead of 4 frames the old way.

Then I changed it so that it makes a new window over the desktop
That we use to draw in. This allows us to draw the animation
and display the log out dialog at the same time, so I stretched
the length of time the animation got to 5 seconds.

jrb has sent me a glade dialog for a new much simpler layout
and some code to do pixelation, but I've not used either of them
... yet.

All other ideas welcome.
iain
-- 
Index: logout.c
===================================================================
RCS file: /cvs/gnome/gnome-session/gnome-session/logout.c,v
retrieving revision 1.44
diff -u -p -r1.44 logout.c
--- logout.c	15 Oct 2002 06:05:01 -0000	1.44
+++ logout.c	21 Feb 2003 13:03:40 -0000
@@ -54,68 +54,133 @@ static enum
 action = LOGOUT;
 
 typedef struct {
-	GdkScreen    *screen;
-	int           monitor;
-	GdkRectangle  iris_rect;
-	GdkWindow    *root_window;
-	int           iris_block;
-	GdkGC        *iris_gc;
+  GdkScreen    *screen;
+  int           monitor;
+  GdkRectangle  iris_rect;
+  int           rowstride;
+  GdkWindow    *root_window;
+  GdkWindow    *draw_window;
+  GdkPixbuf    *start_pb, *end_pb, *frame;
+  guchar       *start_p, *end_p, *frame_p;
+  int           iris_block;
+  GTimeVal      start_time;
+  GdkGC        *iris_gc;
 } IrisData;
 
 static int num_iris_timeouts = 0;
+static GList *draw_windows = NULL;
 
-static gint
-iris_callback (IrisData *data)
-{
-  gint i;
-  gint width_step;
-  gint height_step;
-  gint width;
-  gint height;
-
-  width_step = MIN (data->iris_rect.width / 2, data->iris_block);
-  height_step = MIN (data->iris_rect.width / 2, data->iris_block);
+/* Go for five seconds */
+#define FADE_DURATION 1500.0
 
-  for (i = 0; i < MIN (width_step, height_step); i++)
-    {
-      width  = (gint)data->iris_rect.width  - 2 * i;
-      height = (gint)data->iris_rect.height - 2 * i;
+static void
+get_current_frame (IrisData *iris,
+		   double sat)
+{
+  guchar *s, *e, *f;
+  guchar *sp, *ep, *fp;
+  int i, j, width;
+
+  width = iris->iris_rect.width * 3;
+  s = iris->start_p;
+  e = iris->end_p;
+  f = iris->frame_p;
+  
+  for (i = 0; i < iris->iris_rect.height; i++) {
+    
+    s = sp = s + iris->rowstride;
+    e = ep = e + iris->rowstride;
+    f = fp = f + iris->rowstride;
+
+    for (j = 0; j < width; j += 3) {
+      guchar r = abs (*(sp++) - ep[0]);
+      guchar g = abs (*(sp++) - ep[1]);
+      guchar b = abs (*(sp++) - ep[2]);
+
+      *(fp++) = *(ep++) + r * sat;
+      *(fp++) = *(ep++) + g * sat;
+      *(fp++) = *(ep++) + b * sat;
+    }
+  }
+}
 
-      if (width < 0 || height < 0)
-        break;
+#if 0
+static void
+darken_pixbuf (GdkPixbuf *pb)
+{
+  int width, height, rs;
+  int i, j;
+  guchar *p, *pixels;
+  
+  width = gdk_pixbuf_get_width (pb) * 3;
+  height = gdk_pixbuf_get_height (pb);
+  rs = gdk_pixbuf_get_rowstride (pb);
+  pixels = gdk_pixbuf_get_pixels (pb);
+  
+  for (i = 0; i < height; i++) {
+    p = pixels + (i * rs);
+    for (j = 0; j < width; j++) {
+      p[j] >>= 1;
+    }
+  }
+}
+#endif
 
-      gdk_draw_rectangle (data->root_window, data->iris_gc, FALSE,
-                          data->iris_rect.x + i,
-			  data->iris_rect.y + i,
-                          width, height);
+static gboolean
+iris_callback (gpointer data)
+{
+  IrisData *iris = data;
+  double elapsed, percent;
+  GTimeVal current_time;
+
+  g_get_current_time (&current_time);
+  elapsed = ((((double)current_time.tv_sec - iris->start_time.tv_sec) * G_USEC_PER_SEC +
+	      (current_time.tv_usec - iris->start_time.tv_usec))) / 1000.0;
+
+  if (elapsed < 0) {
+    g_warning ("System clock seemed to go backwards?");
+    elapsed = G_MAXDOUBLE;
+  }
+
+  if (elapsed > FADE_DURATION) {
+    gdk_draw_pixbuf (iris->draw_window, iris->iris_gc, iris->end_pb,
+		     0, 0, iris->iris_rect.x, iris->iris_rect.y,
+		     iris->iris_rect.width, iris->iris_rect.height,
+		     GDK_RGB_DITHER_NONE, 0, 0);
+
+    g_object_unref (iris->iris_gc);
+    g_object_unref (iris->start_pb);
+    g_object_unref (iris->end_pb);
+    g_object_unref (iris->frame);
+
+    g_free (iris);
+    
+    if (!--num_iris_timeouts) {
+/*       gtk_main_quit (); */
     }
+    
+    return FALSE;
+  }
+
+  percent = elapsed / FADE_DURATION;
+
+  get_current_frame (iris, 1.0 - percent);
+  gdk_draw_pixbuf (iris->draw_window, iris->iris_gc, iris->frame,
+		   0, 0, iris->iris_rect.x, iris->iris_rect.y,
+		   iris->iris_rect.width, iris->iris_rect.height,
+		   GDK_RGB_DITHER_NONE, 0, 0);
 
   gdk_flush ();
-
-  data->iris_rect.x += width_step;
-  data->iris_rect.y += height_step;
-  data->iris_rect.width -= MIN (data->iris_rect.width, data->iris_block * 2);
-  data->iris_rect.height -= MIN (data->iris_rect.height, data->iris_block * 2);
-
-  if (data->iris_rect.width == 0 || data->iris_rect.height == 0)
-    {
-      g_object_unref (data->iris_gc);
-      g_free (data);
-
-      if (!--num_iris_timeouts)
-        gtk_main_quit ();
-
-      return FALSE;
-    }
-  else
-    return TRUE;
+  
+  return TRUE;
 }
-
+  
 static void
 iris_on_screen (GdkScreen *screen,
 		int        monitor)
 {
-  static char  dash_list [2] = {1, 1};
+  GdkWindowAttr attr;
+  int attr_mask;
   GdkGCValues  values;
   IrisData    *data;
 
@@ -130,21 +195,51 @@ iris_on_screen (GdkScreen *screen,
   data->iris_rect.height = gsm_screen_get_height (screen, monitor);
 
   data->root_window = gdk_screen_get_root_window (screen);
-
-  values.line_style = GDK_LINE_ON_OFF_DASH;
+  attr.window_type = GDK_WINDOW_CHILD;
+  attr.x = data->iris_rect.x;
+  attr.y = data->iris_rect.y;
+  attr.width = data->iris_rect.width;
+  attr.height = data->iris_rect.height;
+  attr.wclass = GDK_INPUT_OUTPUT;
+  attr.visual = gdk_screen_get_system_visual (data->screen);
+  attr.colormap = gdk_screen_get_default_colormap (data->screen);
+  attr.override_redirect = TRUE;
+  attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_NOREDIR;
+
+  data->draw_window = gdk_window_new (NULL, &attr, attr_mask);
+  draw_windows = g_list_prepend (draw_windows, data->draw_window);
+  
+  data->start_pb = gdk_pixbuf_get_from_drawable (NULL, data->root_window,
+						 NULL, data->iris_rect.x,
+						 data->iris_rect.y,
+						 0, 0, data->iris_rect.width,
+						 data->iris_rect.height);
+  
+  data->end_pb = gdk_pixbuf_copy (data->start_pb);
+  gdk_pixbuf_saturate_and_pixelate (data->start_pb, data->end_pb,
+				    0.0, FALSE);
+  
+  data->frame = gdk_pixbuf_copy (data->start_pb);
+  data->rowstride = gdk_pixbuf_get_rowstride (data->start_pb);
+
+  data->start_p = gdk_pixbuf_get_pixels (data->start_pb);
+  data->end_p = gdk_pixbuf_get_pixels (data->end_pb);
+  data->frame_p = gdk_pixbuf_get_pixels (data->frame);
+  
   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
 
   data->iris_gc = gdk_gc_new_with_values (data->root_window,
 					  &values,
-					  GDK_GC_LINE_STYLE | GDK_GC_SUBWINDOW);
-  gdk_gc_set_dashes (data->iris_gc, 0, dash_list, 2);
+					  GDK_GC_SUBWINDOW);
 
-  /* Plan for a time of 0.5 seconds for effect */
-  data->iris_block = data->iris_rect.height / (500 / 20);
-  if (data->iris_block < 8)
-    data->iris_block = 8;
-
-  g_timeout_add (20, (GSourceFunc) iris_callback, data);
+  gdk_window_show (data->draw_window);
+  gdk_draw_pixbuf (data->draw_window, data->iris_gc, data->frame,
+		   0, 0, data->iris_rect.x, data->iris_rect.y,
+		   data->iris_rect.width, data->iris_rect.height,
+		   GDK_RGB_DITHER_NONE, 0, 0);
+  
+  g_get_current_time (&data->start_time);
+  g_idle_add ((GSourceFunc) iris_callback, data);
   num_iris_timeouts++;
 }
 
@@ -155,9 +250,9 @@ iris (void)
 
   gsm_foreach_screen (iris_on_screen);
 
-  gtk_main ();
+/*   gtk_main (); */
 
-  g_assert (num_iris_timeouts == 0);
+/*   g_assert (num_iris_timeouts == 0); */
 }
 
 static void
@@ -213,6 +308,22 @@ force_pango_cache_init ()
 	pango_font_description_free (font_desc);
 }
 
+static GtkWidget *
+make_title_label (const char *text)
+{
+  GtkWidget *label;
+  char *full;
+
+  full = g_strdup_printf ("<span weight=\"bold\">%s</span>", text);
+  label = gtk_label_new (full);
+  g_free (full);
+
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+
+  return label;
+}
+
 static gboolean
 display_gui (void)
 {
@@ -231,6 +342,7 @@ display_gui (void)
   GError *error = NULL;
   GdkScreen *screen;
   int monitor;
+  GList *dw;
 
   gsm_verbose ("display_gui: showing logout dialog\n");
 
@@ -268,7 +380,7 @@ display_gui (void)
 				GTK_MESSAGE_QUESTION,
 				GTK_BUTTONS_NONE,
 				_("Are you sure you want to log out?"));
-
+  
   a11y_enabled = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (box));
 
   /* Grabbing the Xserver when accessibility is enabled will cause
@@ -290,6 +402,7 @@ display_gui (void)
   gtk_window_set_screen (GTK_WINDOW (box), screen);
   gtk_window_set_policy (GTK_WINDOW (box), FALSE, FALSE, TRUE);
 
+  gtk_container_set_border_width (GTK_CONTAINER (box), 6);
   gtk_container_set_border_width (
 		GTK_CONTAINER (GTK_DIALOG (box)->vbox), GNOME_PAD);
 
@@ -311,18 +424,23 @@ display_gui (void)
   if (((geteuid () == 0) || g_file_exists (t) || g_file_exists(s)) &&
       access (halt_command[0], X_OK) == 0)
     {
-      GtkWidget *frame;
-      GtkWidget *action_vbox;
+      GtkWidget *title, *spacer;
+      GtkWidget *action_vbox, *hbox;
       GtkWidget *r;
-
-      frame = gtk_frame_new (_("Action"));
+      
+      title = make_title_label (_("Action"));
       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (box)->vbox),
-			  frame,
-			  FALSE, TRUE, GNOME_PAD_SMALL);
+			  title, FALSE, FALSE, GNOME_PAD_SMALL);
 
-      action_vbox = gtk_vbox_new (FALSE, 0);
-      gtk_container_add (GTK_CONTAINER (frame), action_vbox);
+      hbox = gtk_hbox_new (FALSE, 6);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (box)->vbox), hbox, TRUE, TRUE, 0);
 
+      spacer = gtk_label_new ("    ");
+      gtk_box_pack_start (GTK_BOX (hbox), spacer, FALSE, FALSE, 0);
+
+      action_vbox = gtk_vbox_new (FALSE, 0);
+      gtk_box_pack_start (GTK_BOX (hbox), action_vbox, TRUE, TRUE, 0);
+      
       r = gtk_radio_button_new_with_mnemonic (NULL, _("_Log Out"));
       gtk_box_pack_start (GTK_BOX (action_vbox), r, FALSE, FALSE, 0);
 
@@ -386,9 +504,19 @@ display_gui (void)
       break;
     default:
     case GTK_RESPONSE_CANCEL:
-      retval= FALSE;
+      retval = FALSE;
+      for (dw = draw_windows; dw; dw = dw->next) {
+	gdk_window_hide (GDK_WINDOW (dw->data));
+	g_object_unref (G_OBJECT (dw->data));
+      }
+      
       break;
     case GTK_RESPONSE_HELP:
+      for (dw = draw_windows; dw; dw = dw->next) {
+	gdk_window_hide (GDK_WINDOW (dw->data));
+	g_object_unref (G_OBJECT (dw->data));
+      }
+      
       gnome_help_display_desktop (NULL, "user-guide", "wgosstartsession.xml",
 				  "gosgetstarted-73", &error);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]