Mercurial > pidgin
diff console/libgnt/gntwm.c @ 15067: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 | c9c1ce4a70b6 |
children | 2409a2508650 |
line wrap: on
line diff
--- 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); }