]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-geometry.c
Updated Spanish Translation
[empathy.git] / libempathy-gtk / empathy-geometry.c
index b807425ea27c5fe95982520d0e4e9a6da6a4ca20..6874cd7966dd6c96c347e141e7beb0770fd7b654 100644 (file)
  */
 
 #include "config.h"
+#include "empathy-geometry.h"
 
 #include <sys/stat.h>
+#include <tp-account-widgets/tpaw-utils.h>
 
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "libempathy/empathy-utils.h"
-#include "empathy-geometry.h"
+#include "empathy-ui-utils.h"
+#include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
-#include <libempathy/empathy-debug.h>
+#include "empathy-debug.h"
 
 #define GEOMETRY_DIR_CREATE_MODE  (S_IRUSR | S_IWUSR | S_IXUSR)
 #define GEOMETRY_FILE_CREATE_MODE (S_IRUSR | S_IWUSR)
 
-#define GEOMETRY_KEY_FILENAME         "geometry.ini"
-#define GEOMETRY_FORMAT               "%d,%d,%d,%d"
-#define GEOMETRY_GROUP_NAME           "geometry"
-#define GEOMETRY_MAXIMIZED_GROUP_NAME "maximized"
+/* geometry.ini file contains 2 groups:
+ *  - one with position and size of each window
+ *  - one with the maximized state of each window
+ * Windows are identified by a name. (e.g. "main-window") */
+#define GEOMETRY_FILENAME             "geometry.ini"
+#define GEOMETRY_POSITION_FORMAT      "%d,%d,%d,%d" /* "x,y,w,h" */
+#define GEOMETRY_POSITION_GROUP       "geometry"
+#define GEOMETRY_MAXIMIZED_GROUP      "maximized"
+
+/* Key used to keep window's name inside the object's qdata */
 #define GEOMETRY_NAME_KEY             "geometry-name-key"
 
 static guint store_id = 0;
@@ -62,7 +67,7 @@ geometry_real_store (GKeyFile *key_file)
     }
 
   filename = g_build_filename (g_get_user_config_dir (),
-    PACKAGE_NAME, GEOMETRY_KEY_FILENAME, NULL);
+    PACKAGE_NAME, GEOMETRY_FILENAME, NULL);
 
   if (!g_file_set_contents (filename, content, length, &error))
     {
@@ -109,7 +114,7 @@ geometry_get_key_file (void)
       g_mkdir_with_parents (dir, GEOMETRY_DIR_CREATE_MODE);
     }
 
-  filename = g_build_filename (dir, GEOMETRY_KEY_FILENAME, NULL);
+  filename = g_build_filename (dir, GEOMETRY_FILENAME, NULL);
   g_free (dir);
 
   key_file = g_key_file_new ();
@@ -120,36 +125,26 @@ geometry_get_key_file (void)
 }
 
 void
-empathy_geometry_save (GtkWindow *window,
-    const gchar *name)
+empathy_geometry_save_values (GtkWindow *window,
+    gint x,
+    gint y,
+    gint w,
+    gint h,
+    gboolean maximized)
 {
   GKeyFile *key_file;
-  GdkWindow *gdk_window;
-  GdkWindowState window_state;
-  gchar *escaped_name;
-  gint x, y, w, h;
-  gboolean maximized;
+  gchar *position_str = NULL;
+  GHashTable *names;
+  GHashTableIter iter;
+  const gchar *name;
 
-  g_return_if_fail (GTK_IS_WINDOW (window));
-  g_return_if_fail (!EMP_STR_EMPTY (name));
+  names = g_object_get_data (G_OBJECT (window), GEOMETRY_NAME_KEY);
 
-  if (!GTK_WIDGET_VISIBLE (window))
-    return;
-
-  /* escape the name so that unwanted characters such as # are removed */
-  escaped_name = g_uri_escape_string (name, NULL, TRUE);
-
-  /* Get window geometry */
-  gtk_window_get_position (window, &x, &y);
-  gtk_window_get_size (window, &w, &h);
-  gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
-  window_state = gdk_window_get_state (gdk_window);
-  maximized = (window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (names != NULL);
 
   /* Don't save off-screen positioning */
-  if (x + w < 0 || y + h < 0 ||
-      x > gdk_screen_width () ||
-      y > gdk_screen_height ())
+  if (!EMPATHY_RECT_IS_ON_SCREEN (x, y, w, h))
     return;
 
   key_file = geometry_get_key_file ();
@@ -157,20 +152,57 @@ empathy_geometry_save (GtkWindow *window,
   /* Save window size only if not maximized */
   if (!maximized)
     {
-      gchar *str;
+      position_str = g_strdup_printf (GEOMETRY_POSITION_FORMAT, x, y, w, h);
+    }
+
+  g_hash_table_iter_init (&iter, names);
+  while (g_hash_table_iter_next (&iter, (gpointer) &name, NULL))
+    {
+      gchar *escaped_name;
+
+      /* escape the name so that unwanted characters such as # are removed */
+      escaped_name = g_uri_escape_string (name, NULL, TRUE);
+
+      g_key_file_set_boolean (key_file, GEOMETRY_MAXIMIZED_GROUP,
+          escaped_name, maximized);
+
+      if (position_str != NULL)
+        g_key_file_set_string (key_file, GEOMETRY_POSITION_GROUP,
+            escaped_name, position_str);
 
-      str = g_strdup_printf (GEOMETRY_FORMAT, x, y, w, h);
-      g_key_file_set_string (key_file, GEOMETRY_GROUP_NAME, escaped_name, str);
-      g_free (str);
+      g_free (escaped_name);
     }
 
-  g_key_file_set_boolean (key_file, GEOMETRY_MAXIMIZED_GROUP_NAME,
-        escaped_name, maximized);
 
   geometry_schedule_store (key_file);
+  g_free (position_str);
 }
 
-void
+static void
+empathy_geometry_save (GtkWindow *window)
+{
+  GdkWindow *gdk_window;
+  GdkWindowState window_state;
+  gboolean maximized;
+  gint x, y, w, h;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  if (!gtk_widget_get_visible (GTK_WIDGET (window)))
+    return;
+
+  /* Get window geometry */
+  gtk_window_get_position (window, &x, &y);
+  gtk_window_get_size (window, &w, &h);
+
+  gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
+  window_state = gdk_window_get_state (gdk_window);
+  maximized = (window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
+
+  empathy_geometry_save_values (window, x, y, w, h, maximized);
+}
+
+static void
 empathy_geometry_load (GtkWindow *window,
     const gchar *name)
 {
@@ -180,7 +212,7 @@ empathy_geometry_load (GtkWindow *window,
   gboolean  maximized;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
-  g_return_if_fail (!EMP_STR_EMPTY (name));
+  g_return_if_fail (!TPAW_STR_EMPTY (name));
 
   /* escape the name so that unwanted characters such as # are removed */
   escaped_name = g_uri_escape_string (name, NULL, TRUE);
@@ -188,20 +220,19 @@ empathy_geometry_load (GtkWindow *window,
   key_file = geometry_get_key_file ();
 
   /* restore window size and position */
-  str = g_key_file_get_string (key_file, GEOMETRY_GROUP_NAME, escaped_name,
-      NULL);
+  str = g_key_file_get_string (key_file, GEOMETRY_POSITION_GROUP,
+      escaped_name, NULL);
   if (str)
     {
       gint x, y, w, h;
 
-      sscanf (str, GEOMETRY_FORMAT, &x, &y, &w, &h);
+      sscanf (str, GEOMETRY_POSITION_FORMAT, &x, &y, &w, &h);
       gtk_window_move (window, x, y);
       gtk_window_resize (window, w, h);
     }
 
   /* restore window maximized state */
-  maximized = g_key_file_get_boolean (key_file,
-      GEOMETRY_MAXIMIZED_GROUP_NAME,
+  maximized = g_key_file_get_boolean (key_file, GEOMETRY_MAXIMIZED_GROUP,
       escaped_name, NULL);
 
   if (maximized)
@@ -218,10 +249,7 @@ geometry_configure_event_cb (GtkWindow *window,
     GdkEventConfigure *event,
     gpointer user_data)
 {
-  gchar *name;
-
-  name = g_object_get_data (G_OBJECT (window), GEOMETRY_NAME_KEY);
-  empathy_geometry_save (window, name);
+  empathy_geometry_save (window);
 
   return FALSE;
 }
@@ -233,10 +261,7 @@ geometry_window_state_event_cb (GtkWindow *window,
 {
   if ((event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0)
     {
-      gchar *name;
-
-      name = g_object_get_data (G_OBJECT (window), GEOMETRY_NAME_KEY);
-      empathy_geometry_save (window, name);
+      empathy_geometry_save (window);
     }
 
   return FALSE;
@@ -246,10 +271,19 @@ static void
 geometry_map_cb (GtkWindow *window,
     gpointer user_data)
 {
-  gchar *name;
+  GHashTable *names;
+  GHashTableIter iter;
+  const gchar *name;
 
   /* The WM will replace this window, restore its last position */
-  name = g_object_get_data (G_OBJECT (window), GEOMETRY_NAME_KEY);
+  names = g_object_get_data (G_OBJECT (window), GEOMETRY_NAME_KEY);
+
+  g_assert (names != NULL);
+
+  /* Use the first name we get in the hash table */
+  g_hash_table_iter_init (&iter, names);
+  g_assert (g_hash_table_iter_next (&iter, (gpointer) &name, NULL));
+
   empathy_geometry_load (window, name);
 }
 
@@ -257,23 +291,37 @@ void
 empathy_geometry_bind (GtkWindow *window,
     const gchar *name)
 {
-  gchar *str;
+  GHashTable *names;
+  gboolean connect_sigs = FALSE;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
-  g_return_if_fail (!EMP_STR_EMPTY (name));
+  g_return_if_fail (!TPAW_STR_EMPTY (name));
 
   /* Check if this window is already bound */
-  str = g_object_get_data (G_OBJECT (window), GEOMETRY_NAME_KEY);
-  if (str != NULL)
-    return;
+  names = g_object_get_data (G_OBJECT (window), GEOMETRY_NAME_KEY);
+  if (names == NULL)
+    {
+      connect_sigs = TRUE;
+      names = g_hash_table_new_full (g_str_hash, g_str_equal,
+          g_free, NULL);
+
+      g_object_set_data_full (G_OBJECT (window), GEOMETRY_NAME_KEY, names,
+          (GDestroyNotify) g_hash_table_unref);
+    }
+  else if (g_hash_table_lookup (names, name) != NULL)
+    {
+      return;
+    }
 
   /* Store the geometry name in the window's data */
-  str = g_strdup (name);
-  g_object_set_data_full (G_OBJECT (window), GEOMETRY_NAME_KEY, str, g_free);
+  g_hash_table_insert (names, g_strdup (name), GUINT_TO_POINTER (TRUE));
 
   /* Load initial geometry */
   empathy_geometry_load (window, name);
 
+  if (!connect_sigs)
+    return;
+
   /* Track geometry changes */
   g_signal_connect (window, "configure-event",
     G_CALLBACK (geometry_configure_event_cb), NULL);
@@ -284,8 +332,20 @@ empathy_geometry_bind (GtkWindow *window,
 }
 
 void
-empathy_geometry_unbind (GtkWindow *window)
+empathy_geometry_unbind (GtkWindow *window,
+    const gchar *name)
 {
+  GHashTable *names;
+
+  names = g_object_get_data (G_OBJECT (window), GEOMETRY_NAME_KEY);
+  if (names == NULL)
+    return;
+
+  g_hash_table_remove (names, name);
+
+  if (g_hash_table_size (names) > 0)
+    return;
+
   g_signal_handlers_disconnect_by_func (window,
     geometry_configure_event_cb, NULL);
   g_signal_handlers_disconnect_by_func (window,