changeset 15068:d08d7b7375c7

[gaim-migrate @ 17851] Remember the positions of the windows depending on the titles. Moving all the chat windows to places was getting really really annoying. If you don't want it, turn it off by setting "remember_position" to 0 in .gntrc committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Thu, 30 Nov 2006 05:52:21 +0000
parents 0f950428ef41
children c8228e154e24
files console/libgnt/gntstyle.c console/libgnt/gntstyle.h console/libgnt/gntwm.c console/libgnt/gntwm.h console/libgnt/wms/s.c
diffstat 5 files changed, 169 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/console/libgnt/gntstyle.c	Thu Nov 30 02:01:49 2006 +0000
+++ b/console/libgnt/gntstyle.c	Thu Nov 30 05:52:21 2006 +0000
@@ -282,6 +282,7 @@
 	              {"customcolor", GNT_STYLE_COLOR},
 	              {"mouse", GNT_STYLE_MOUSE},
 	              {"wm", GNT_STYLE_WM},
+	              {"remember_position", GNT_STYLE_REMPOS},
 	              {NULL, 0}};
 
 	if (error)
--- a/console/libgnt/gntstyle.h	Thu Nov 30 02:01:49 2006 +0000
+++ b/console/libgnt/gntstyle.h	Thu Nov 30 05:52:21 2006 +0000
@@ -6,6 +6,7 @@
 	GNT_STYLE_COLOR = 1,
 	GNT_STYLE_MOUSE = 2,
 	GNT_STYLE_WM = 3,
+	GNT_STYLE_REMPOS = 4,
 	GNT_STYLES
 } GntStyle;
 
--- a/console/libgnt/gntwm.c	Thu Nov 30 02:01:49 2006 +0000
+++ b/console/libgnt/gntwm.c	Thu Nov 30 05:52:21 2006 +0000
@@ -42,6 +42,9 @@
 static void gnt_wm_give_focus(GntWM *wm, GntWidget *widget);
 static void update_window_in_list(GntWM *wm, GntWidget *wid);
 
+static gboolean write_already(gpointer data);
+static int write_timeout;
+
 static GList *
 g_list_bring_to_front(GList *list, gpointer data)
 {
@@ -124,31 +127,105 @@
 	doupdate();
 	return TRUE;
 }
+
+static gboolean
+sanitize_position(GntWidget *widget, int *x, int *y)
+{
+	int X_MAX = getmaxx(stdscr);
+	int Y_MAX = getmaxy(stdscr) - 1;
+	int w, h;
+	int nx, ny;
+	gboolean changed = FALSE;
+
+	gnt_widget_get_size(widget, &w, &h);
+	if (x) {
+		if (*x + w > X_MAX) {
+			nx = MAX(0, X_MAX - w);
+			if (nx != *x) {
+				*x = nx;
+				changed = TRUE;
+			}
+		}
+	}
+	if (y) {
+		if (*y + h > Y_MAX) {
+			ny = MAX(0, Y_MAX - h);
+			if (ny != *y) {
+				*y = ny;
+				changed = TRUE;
+			}
+		}
+	}
+	return changed;
+}
+
 static void
 refresh_node(GntWidget *widget, GntNode *node, gpointer null)
 {
 	int x, y, w, h;
-	int nw, nh, nx, ny;
+	int nw, nh;
 
 	int X_MAX = getmaxx(stdscr);
 	int Y_MAX = getmaxy(stdscr) - 1;
 
 	gnt_widget_get_position(widget, &x, &y);
 	gnt_widget_get_size(widget, &w, &h);
-	nx = x; ny = y;
 
-	if (x + w >= X_MAX)
-		nx = MAX(0, X_MAX - w);
-	if (y + h >= Y_MAX)
-		ny = MAX(0, Y_MAX - h);
-	if (x != nx || y != ny)
-		gnt_screen_move_widget(widget, nx, ny);
+	if (sanitize_position(widget, &x, &y))
+		gnt_screen_move_widget(widget, x, y);
 
 	nw = MIN(w, X_MAX);
 	nh = MIN(h, Y_MAX);
 	if (nw != w || nh != h)
 		gnt_screen_resize_widget(widget, nw, nh);
 }
+
+static void
+read_window_positions(GntWM *wm)
+{
+#if GLIB_CHECK_VERSION(2,6,0)
+	GKeyFile *gfile = g_key_file_new();
+	char *filename = g_build_filename(g_get_home_dir(), ".gntpositions", NULL);
+	GError *error = NULL;
+	char **keys;
+	int nk;
+
+	if (!g_key_file_load_from_file(gfile, filename, G_KEY_FILE_NONE, &error)) {
+		g_printerr("GntWM: %s\n", error->message);
+		g_error_free(error);
+		g_free(filename);
+		return;
+	}
+
+	keys = g_key_file_get_keys(gfile, "positions", &nk, &error);
+	if (error) {
+		g_printerr("GntWM: %s\n", error->message);
+		g_error_free(error);
+		error = NULL;
+	} else {
+		while (nk--) {
+			char *title = keys[nk];
+			int l;
+			char **coords = g_key_file_get_string_list(gfile, "positions", title, &l, NULL);
+			if (l == 2) {
+				int x = atoi(coords[0]);
+				int y = atoi(coords[1]);
+				GntPosition *p = g_new0(GntPosition, 1);
+				p->x = x;
+				p->y = y;
+				g_hash_table_replace(wm->positions, g_strdup(title + 1), p);
+			} else {
+				g_printerr("GntWM: Invalid number of arguments for positioing a window.\n");
+			}
+			g_strfreev(coords);
+		}
+		g_strfreev(keys);
+	}
+
+	g_free(filename);
+#endif
+}
+
 static void
 gnt_wm_init(GTypeInstance *instance, gpointer class)
 {
@@ -159,6 +236,9 @@
 	wm->windows = NULL;
 	wm->actions = NULL;
 	wm->nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node);
+	wm->positions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+	if (gnt_style_get_bool(GNT_STYLE_REMPOS, TRUE))
+		read_window_positions(wm);
 }
 
 static void
@@ -645,6 +725,8 @@
 wm_quit(GntBindable *bindable, GList *list)
 {
 	GntWM *wm = GNT_WM(bindable);
+	if (write_timeout)
+		write_already(wm);
 	g_main_loop_quit(wm->loop);
 	return TRUE;
 }
@@ -905,6 +987,16 @@
 		return;
 	}
 
+	if (GNT_IS_BOX(widget)) {
+		const char *title = GNT_BOX(widget)->title;
+		GntPosition *p = NULL;
+		if (title && (p = g_hash_table_lookup(wm->positions, title)) != NULL) {
+			sanitize_position(widget, &p->x, &p->y);
+			gnt_widget_set_position(widget, p->x, p->y);
+			mvwin(widget->window, p->y, p->x);
+		}
+	}
+
 	g_signal_emit(wm, signals[SIG_NEW_WIN], 0, widget);
 	g_signal_emit(wm, signals[SIG_DECORATE_WIN], 0, widget);
 
@@ -1088,6 +1180,46 @@
 	update_screen(wm);
 }
 
+static void
+write_gdi(gpointer key, gpointer value, gpointer data)
+{
+	GntPosition *p = value;
+	fprintf(data, ".%s = %d;%d\n", key, p->x, p->y);
+}
+
+static gboolean
+write_already(gpointer data)
+{
+	GntWM *wm = data;
+	FILE *file;
+	char *filename;
+
+	filename = g_build_filename(g_get_home_dir(), ".gntpositions", NULL);
+
+	file = fopen(filename, "wb");
+	if (file == NULL) {
+		g_printerr("GntWM: error opening file to save positions\n");
+	} else {
+		fprintf(file, "[positions]\n");
+		g_hash_table_foreach(wm->positions, write_gdi, file);
+		fclose(file);
+	}
+
+	g_free(filename);
+	g_source_remove(write_timeout);
+	write_timeout = 0;
+	return FALSE;
+}
+
+static void
+write_positions_to_file(GntWM *wm)
+{
+	if (write_timeout) {
+		g_source_remove(write_timeout);
+	}
+	write_timeout = g_timeout_add(10000, write_already, wm);
+}
+
 void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y)
 {
 	gboolean ret = TRUE;
@@ -1107,6 +1239,17 @@
 	move_panel(node->panel, y, x);
 
 	g_signal_emit(wm, signals[SIG_MOVED], 0, node);
+	if (gnt_style_get_bool(GNT_STYLE_REMPOS, TRUE) && GNT_IS_BOX(widget)) {
+		const char *title = GNT_BOX(widget)->title;
+		if (title) {
+			GntPosition *p = g_new0(GntPosition, 1);
+			GntWidget *wid = node->me;
+			p->x = wid->priv.x;
+			p->y = wid->priv.y;
+			g_hash_table_replace(wm->positions, g_strdup(title), p);
+			write_positions_to_file(wm);
+		}
+	}
 
 	update_screen(wm);
 }
--- a/console/libgnt/gntwm.h	Thu Nov 30 02:01:49 2006 +0000
+++ b/console/libgnt/gntwm.h	Thu Nov 30 05:52:21 2006 +0000
@@ -27,6 +27,12 @@
 
 typedef struct _GntWM GntWM;
 
+typedef struct _GnPosition
+{
+	int x;
+	int y;
+} GntPosition;
+
 /**
  * An application can register actions which will show up in a 'start-menu' like popup
  */
@@ -73,6 +79,8 @@
 	
 	GntKeyPressMode mode;
 
+	GHashTable *positions;
+
 	void *res1;
 	void *res2;
 	void *res3;
--- a/console/libgnt/wms/s.c	Thu Nov 30 02:01:49 2006 +0000
+++ b/console/libgnt/wms/s.c	Thu Nov 30 05:52:21 2006 +0000
@@ -97,19 +97,16 @@
 			mvwin(win->window, y, x);
 
 			gnt_widget_set_size(win, -1, h + 2);  /* XXX: Why is the +2 needed here? -- sadrul */
-		} else if (name && strcmp(name, "conversation-window") == 0) {
-			/* Put the conversation windows to the far-right */
-			x = maxx - w;
-			y = 0;
-			gnt_widget_set_position(win, x, y);
-			mvwin(win->window, y, x);
 		} else if (!GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) {
-			/* In the middle of the screen */
-			x = (maxx - w) / 2;
-			y = (maxy - h) / 2;
+			const char *title = GNT_BOX(win)->title;
+			if (title == NULL || !g_hash_table_lookup(wm->positions, title)) {
+				/* In the middle of the screen */
+				x = (maxx - w) / 2;
+				y = (maxy - h) / 2;
 
-			gnt_widget_set_position(win, x, y);
-			mvwin(win->window, y, x);
+				gnt_widget_set_position(win, x, y);
+				mvwin(win->window, y, x);
+			}
 		}
 	}
 	org_new_window(wm, win);