rpms/gtk2/devel gtk+-2.10.3-fam.patch, NONE, 1.1 gtk2.spec, 1.178, 1.179

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Tue Sep 5 16:02:34 UTC 2006


Author: mclasen

Update of /cvs/dist/rpms/gtk2/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv29257

Modified Files:
	gtk2.spec 
Added Files:
	gtk+-2.10.3-fam.patch 
Log Message:
use fam for recent files


gtk+-2.10.3-fam.patch:
 gtkrecentmanager.c |  353 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 342 insertions(+), 11 deletions(-)

--- NEW FILE gtk+-2.10.3-fam.patch ---
--- gtk+-2.10.3/gtk/gtkrecentmanager.c.fam	2006-08-18 11:30:57.000000000 -0400
+++ gtk+-2.10.3/gtk/gtkrecentmanager.c	2006-09-05 11:33:48.000000000 -0400
@@ -38,6 +38,9 @@
 #include "gtktypebuiltins.h"
 #include "gtkprivate.h"
 #include "gtkmarshalers.h"
+
+#include <fam.h>
+
 #include "gtkalias.h"
 
 #ifdef G_OS_UNIX
@@ -110,6 +113,9 @@
   
   time_t last_mtime;
   guint poll_timeout;
+
+  FAMRequest *fam_request;
+  guint changed_timeout;
 };
 
 enum
@@ -274,6 +280,309 @@
   g_type_class_add_private (klass, sizeof (GtkRecentManagerPrivate));
 }
 
+
+/* fam support */
+#undef DEBUG_FAM
+
+static FAMConnection  fam_connection;
+static gboolean       opened_connection = FALSE;
+static gboolean       failed_to_connect = FALSE;
+static guint          fam_io_watch = 0;
+
+static int (*fam_open)           (FAMConnection    *fc) = NULL;
+static int (*fam_close)          (FAMConnection    *fc) = NULL;
+static int (*fam_pending)        (FAMConnection    *fc) = NULL;
+static int (*fam_next_event)     (FAMConnection    *fc,
+                                  FAMEvent         *fe) = NULL;
+static int (*fam_monitor_file)   (FAMConnection    *fc,
+                                  const char       *filename, 
+                                  FAMRequest       *fr,
+                                  void             *userData) = NULL;
+static int (*fam_cancel_monitor) (FAMConnection    *fc,
+                                  const FAMRequest *fr) = NULL;
+
+
+static struct FamDlMapping 
+{
+  const char *fn_name;
+  gpointer fn_ptr_ref;
+} fam_dl_mapping[] = {
+  { "FAMOpen", &fam_open },
+  { "FAMClose", &fam_close },
+  { "FAMPending", &fam_pending },
+  { "FAMNextEvent", &fam_next_event },
+  { "FAMMonitorFile", &fam_monitor_file },
+  { "FAMCancelMonitor", &fam_cancel_monitor }
+};
+
+static void
+open_libfam (void)
+{
+  static gboolean done = FALSE;
+  
+  if (!done)
+    {
+      int i;
+      GModule *fam;
+      
+      done = TRUE;
+
+      fam = g_module_open ("libfam.so.0", G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+      if (!fam)
+	{
+	  g_warning ("Can't open libfam '%s'\n", g_module_error ());
+	  return;
+	}
+
+      for (i = 0; i < G_N_ELEMENTS (fam_dl_mapping); i++)
+	{
+	  if (!g_module_symbol (fam, fam_dl_mapping[i].fn_name,
+				fam_dl_mapping[i].fn_ptr_ref))
+	    {
+	      g_warning ("Missing symbol '%s' in libfam\n",
+			 fam_dl_mapping[i].fn_name);
+	      g_module_close (fam);
+	      for (i = 0; i < G_N_ELEMENTS (fam_dl_mapping); i++)
+		fam_dl_mapping[i].fn_ptr_ref = NULL;
+
+	      return;
+	    }
+	}
+    }
+}
+
+static gboolean
+changed_timeout (gpointer data)
+{
+  GtkRecentManager *manager;
+  
+  GDK_THREADS_ENTER ();
+
+  manager = (GtkRecentManager *)data;
+  manager->priv->changed_timeout = 0;
+
+  gtk_recent_manager_changed (manager);
+
+  GDK_THREADS_LEAVE ();
+  
+  return FALSE;
+}
+
+static void
+handle_fam_event (GtkRecentManager *manager,
+		  FAMEvent         *event)
+{
+  GtkRecentManagerPrivate *priv = manager->priv;
+
+  /* try to group delete-create pairs */
+  if (event->code == FAMDeleted)
+    {
+      if (priv->changed_timeout == 0)
+	priv->changed_timeout = g_timeout_add (500, changed_timeout, manager);
+    }
+  else
+    {
+      if (priv->changed_timeout != 0)
+	{
+	  g_source_remove (priv->changed_timeout);
+	  priv->changed_timeout = 0;
+	}
+      gtk_recent_manager_changed (manager);
+    }
+}
+
+#ifdef DEBUG_FAM
+static inline void
+debug_event (FAMEvent *event)
+{
+#define PRINT_EVENT(str) g_print ("Got event: %d %s <" str ">\n", event->code, event->filename);
+
+  switch (event->code)
+    {
+    case FAMChanged:
+      PRINT_EVENT ("changed");
+      break;
+    case FAMDeleted:
+      PRINT_EVENT ("deleted");
+      break;
+    case FAMStartExecuting:
+      PRINT_EVENT ("start-executing");
+      break;
+    case FAMStopExecuting:
+      PRINT_EVENT ("stop-executing");
+      break;
+    case FAMCreated:
+      PRINT_EVENT ("created");
+      break;
+    case FAMAcknowledge:
+      PRINT_EVENT ("acknowledge");
+      break;
+    case FAMExists:
+      PRINT_EVENT ("exists");
+      break;
+    case FAMEndExist:
+      PRINT_EVENT ("end-exist");
+      break;
+    case FAMMoved:
+      PRINT_EVENT ("moved");
+      break;
+    default:
+      PRINT_EVENT ("invalid");
+      break;
+    }
+
+#undef PRINT_EVENT
+}
+#else
+#define debug_event(event)
+#endif
+
+static gboolean
+process_fam_events (void)
+{
+  if (failed_to_connect)
+    return FALSE;
+
+  while (fam_pending (&fam_connection))
+    {
+      FAMEvent event;
+
+      if (fam_next_event (&fam_connection, &event) != 1)
+        {
+	  g_warning ("Failed to read next event from FAM");
+	  failed_to_connect = TRUE;
+          fam_close (&fam_connection);
+          return FALSE;
+        }
+
+      debug_event (&event);
+
+      if (event.code != FAMChanged &&
+	  event.code != FAMCreated &&
+	  event.code != FAMDeleted)
+	continue;
+
+      handle_fam_event (event.userdata, &event);
+    }
+
+  return TRUE;
+}
+
+static gboolean
+fam_data_pending (GIOChannel   *source,
+		  GIOCondition  condition)
+{
+  g_assert (condition == G_IO_IN || condition == G_IO_PRI);
+
+  if (!process_fam_events ())
+    {
+      fam_io_watch = 0;
+      return FALSE;
+    }
+
+  return TRUE; /* do come again */
+}
+
+static FAMConnection *
+get_fam_connection (void)
+{
+  if (!opened_connection)
+    {
+      opened_connection = TRUE;
+
+      open_libfam ();
+
+      if (fam_open != NULL &&
+	  fam_open (&fam_connection) == 0)
+	{
+	  GIOChannel *io_channel;
+
+	  io_channel = g_io_channel_unix_new (fam_connection.fd);
+	  fam_io_watch = g_io_add_watch (io_channel,
+					 G_IO_IN|G_IO_PRI,
+					 (GIOFunc) fam_data_pending,
+					 NULL);
+	  g_io_channel_unref (io_channel);
+	}
+      else
+	{
+	  g_warning ("Failed to connect to the FAM server");
+	  failed_to_connect = TRUE;
+	}
+    }
+
+  return failed_to_connect ? NULL : &fam_connection;
+}
+
+static FAMRequest *
+register_fam_monitor (const gchar *path,
+		      gpointer     user_data)
+{
+  FAMConnection *fam_connection;
+  FAMRequest    *request;
+
+  if ((fam_connection = get_fam_connection ()) == NULL)
+    {
+      g_warning ("Not adding file monitor on '%s', "
+		 "failed to connect to FAM server\n",
+		 path);
+      return NULL;
+    }
+  
+  /* Need to process any pending events, otherwise we may block
+   * on write - i.e. the FAM sever is blocked because its write
+   * buffer is full notifying us of events, we need to read those
+   * events before it can process our new request.
+   */
+  if (!process_fam_events ())
+    {
+      g_source_remove (fam_io_watch);
+      fam_io_watch = 0;
+      return NULL;
+    }
+
+  request = g_new0 (FAMRequest, 1);
+
+  if (fam_monitor_file (fam_connection, path, request, user_data) != 0)
+    {
+      g_warning ("Failed to add file monitor on '%s'", path);
+      g_free (request);
+
+      return NULL;
+    }
+
+#ifdef DEBUG_FAM
+  g_print ("registering file monitor for '%s'\n", path);
+#endif
+
+  return request;
+}
+
+static void 
+unregister_fam_monitor (FAMRequest *request)
+{
+  if (failed_to_connect)
+    return;
+
+  if (request != NULL)
+    fam_cancel_monitor (&fam_connection, request);
+
+  /* Need to process any remaining events for this monitor
+   */
+  if (!process_fam_events ())
+    {
+      g_source_remove (fam_io_watch);
+      fam_io_watch = 0;
+    }
+
+#ifdef DEBUG_FAM
+  g_print ("unregistering file monitor\n");
+#endif
+}
+
+/* end of fam support */
+
+
 static void
 gtk_recent_manager_init (GtkRecentManager *manager)
 {
@@ -296,9 +605,12 @@
   priv->filename = g_build_filename (g_get_home_dir (),
 				     GTK_RECENTLY_USED_FILE,
 				     NULL);
-  priv->poll_timeout = g_timeout_add (POLL_DELTA,
-		  		      gtk_recent_manager_poll_timeout,
-				      manager);
+
+  priv->fam_request = register_fam_monitor (priv->filename, manager);
+  if (priv->fam_request == NULL)
+    priv->poll_timeout = g_timeout_add (POLL_DELTA,
+					gtk_recent_manager_poll_timeout,
+					manager);
 
   build_recent_items_list (manager);
 }
@@ -356,10 +668,19 @@
   GtkRecentManager *manager = GTK_RECENT_MANAGER (object);
   GtkRecentManagerPrivate *priv = manager->priv;
 
+  if (priv->fam_request)
+    {
+      unregister_fam_monitor (priv->fam_request);
+      g_free (priv->fam_request);
+      priv->fam_request = NULL;
+    }
+  if (priv->changed_timeout)
+    g_source_remove (priv->changed_timeout);
+
   /* remove the poll timeout */
   if (priv->poll_timeout)
     g_source_remove (priv->poll_timeout);
-  
+
   if (priv->filename)
     g_free (priv->filename);
   
@@ -499,18 +820,28 @@
   if (!filename || filename[0] == '\0')
     return;
   
-  g_free (manager->priv->filename);
+  g_free (priv->filename);
 
-  if (manager->priv->poll_timeout)
+  if (priv->fam_request)
     {
-      g_source_remove (manager->priv->poll_timeout);
-      manager->priv->poll_timeout = 0;
+      unregister_fam_monitor (priv->fam_request);
+      g_free (priv->fam_request);
+      priv->fam_request = NULL;
+    }
+
+  if (priv->poll_timeout)
+    {
+      g_source_remove (priv->poll_timeout);
+      priv->poll_timeout = 0;
     }
 
   priv->filename = g_strdup (filename);
-  priv->poll_timeout = g_timeout_add (POLL_DELTA,
-		  		      gtk_recent_manager_poll_timeout,
-				      manager);
+
+  priv->fam_request = register_fam_monitor (priv->filename, manager);
+  if (priv->fam_request == NULL)
+    priv->poll_timeout = g_timeout_add (POLL_DELTA,
+					gtk_recent_manager_poll_timeout,
+					manager);
 
   /* mark us clean, so that we can re-read the list
    * of recently used resources


Index: gtk2.spec
===================================================================
RCS file: /cvs/dist/rpms/gtk2/devel/gtk2.spec,v
retrieving revision 1.178
retrieving revision 1.179
diff -u -r1.178 -r1.179
--- gtk2.spec	5 Sep 2006 13:49:46 -0000	1.178
+++ gtk2.spec	5 Sep 2006 16:02:32 -0000	1.179
@@ -16,7 +16,7 @@
 Summary: The GIMP ToolKit (GTK+), a library for creating GUIs for X
 Name: gtk2
 Version: %{base_version}
-Release: 1%{?dist}
+Release: 2%{?dist}
 License: LGPL
 Group: System Environment/Libraries
 Source: gtk+-%{version}.tar.bz2
@@ -28,11 +28,14 @@
 Patch1: gtk+-2.8.10-set-invisible-char-to-bullet.patch
 # Filechooser search
 Patch2: gtk+-2.10.3-search.patch
+# use fam for recent-files
+Patch3: gtk+-2.10.3-fam.patch
 
 # backport from HEAD
 Patch7: gtk+-2.10.2-cursor-blink.patch
 Patch8: gtk+-2.10.2-im-reset.patch
 
+
 BuildPrereq: atk-devel >= %{atk_version}
 BuildPrereq: pango-devel >= %{pango_version}
 BuildPrereq: glib2-devel >= %{glib2_version}
@@ -50,6 +53,8 @@
 BuildRequires: libXcursor-devel
 BuildRequires: libXfixes-devel
 BuildRequires: libXinerama-devel
+# for patch 3
+BuildRequires: gamin-devel
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Obsoletes: gtk+-gtkbeta
@@ -112,6 +117,7 @@
 %patch0 -p1 -b .lib64
 %patch1 -p1 -b .set-invisible-char-to-bullet
 %patch2 -p1 -b .search
+%patch3 -p1 -b .fam
 
 %patch7 -p0 -b .cursor-blink
 %patch8 -p1 -b .im-reset
@@ -124,6 +130,8 @@
 libtoolize --force
 
 # Patch3 modifies gdk-pixbuf/Makefile.am
+# Patch9 modifies configure.in
+autoheader
 aclocal-1.7
 automake-1.7
 
@@ -286,6 +294,9 @@
 %doc tmpdocs/examples
 
 %changelog
+* Mon Sep  5 2006 Matthias Clasen <mclasen at redhat.com> - 2.10.3-2.fc6
+- Use fam for recent files
+
 * Tue Sep  5 2006 Matthias Clasen <mclasen at redhat.com> - 2.10.3-1.fc6
 - Update to 2.10.3
 




More information about the fedora-cvs-commits mailing list