diff options
author | Xavier Claessens <xclaesse@gmail.com> | 2009-11-16 02:45:36 +0800 |
---|---|---|
committer | Xavier Claessens <xclaesse@gmail.com> | 2009-11-16 20:24:22 +0800 |
commit | 441909cbcd7c740f49b714b61e31a5236d808538 (patch) | |
tree | 2d09957cc29d0ad396ce00adddf7ed69105a61cf | |
parent | 9bfe3cdd27190113f8da56cf718c3af7ff9da5d9 (diff) | |
download | gsoc2013-empathy-441909cbcd7c740f49b714b61e31a5236d808538.tar gsoc2013-empathy-441909cbcd7c740f49b714b61e31a5236d808538.tar.gz gsoc2013-empathy-441909cbcd7c740f49b714b61e31a5236d808538.tar.bz2 gsoc2013-empathy-441909cbcd7c740f49b714b61e31a5236d808538.tar.lz gsoc2013-empathy-441909cbcd7c740f49b714b61e31a5236d808538.tar.xz gsoc2013-empathy-441909cbcd7c740f49b714b61e31a5236d808538.tar.zst gsoc2013-empathy-441909cbcd7c740f49b714b61e31a5236d808538.zip |
Correctly store/restore maximized state of windows.
-rw-r--r-- | libempathy-gtk/empathy-geometry.c | 267 | ||||
-rw-r--r-- | libempathy-gtk/empathy-geometry.h | 21 | ||||
-rw-r--r-- | src/empathy-chat-window.c | 85 | ||||
-rw-r--r-- | src/empathy-ft-manager.c | 59 | ||||
-rw-r--r-- | src/empathy-main-window.c | 59 |
5 files changed, 184 insertions, 307 deletions
diff --git a/libempathy-gtk/empathy-geometry.c b/libempathy-gtk/empathy-geometry.c index 14e794c44..a41a52d6c 100644 --- a/libempathy-gtk/empathy-geometry.c +++ b/libempathy-gtk/empathy-geometry.c @@ -29,6 +29,7 @@ #include <glib.h> #include <gdk/gdk.h> +#include "libempathy/empathy-utils.h" #include "empathy-geometry.h" #define DEBUG_FLAG EMPATHY_DEBUG_OTHER @@ -37,156 +38,212 @@ #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_KEY_FILENAME "geometry.ini" +#define GEOMETRY_FORMAT "%d,%d,%d,%d" +#define GEOMETRY_GROUP_NAME "geometry" +#define GEOMETRY_MAXIMIZED_GROUP_NAME "maximized" -static gchar *geometry_get_filename (void); +static guint store_id = 0; -static gchar * -geometry_get_filename (void) +static void +geometry_real_store (GKeyFile *key_file) { - gchar *dir; gchar *filename; + gchar *content; + gsize length; + GError *error = NULL; - dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); - if (!g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { - DEBUG ("Creating directory:'%s'", dir); - g_mkdir_with_parents (dir, GEOMETRY_DIR_CREATE_MODE); + content = g_key_file_to_data (key_file, &length, &error); + if (error != NULL) { + DEBUG ("Error: %s", error->message); + g_error_free (error); + return; } - filename = g_build_filename (dir, GEOMETRY_KEY_FILENAME, NULL); - g_free (dir); + filename = g_build_filename (g_get_user_config_dir (), + PACKAGE_NAME, GEOMETRY_KEY_FILENAME, NULL); - return filename; + if (!g_file_set_contents (filename, content, length, &error)) { + DEBUG ("Error: %s", error->message); + g_error_free (error); + } + + g_free (content); + g_free (filename); } -void -empathy_geometry_save (const gchar *name, - gint x, - gint y, - gint w, - gint h) +static gboolean +geometry_store_cb (gpointer key_file) { - GError *error = NULL; - GKeyFile *key_file; - gchar *filename; - GdkScreen *screen; - gint max_width; - gint max_height; - gchar *content; - gsize length; - gchar *str; - gchar *escaped_name; + geometry_real_store (key_file); + store_id = 0; - /* escape the name so that unwanted characters such as # are removed */ - escaped_name = g_uri_escape_string (name, NULL, TRUE); - - DEBUG ("Saving window geometry: name:%s x:%d, y:%d, w:%d, h:%d\n", - escaped_name, x, y, w, h); + return FALSE; +} - screen = gdk_screen_get_default (); - max_width = gdk_screen_get_width (screen); - max_height = gdk_screen_get_height (screen); +static void +geometry_schedule_store (GKeyFile *key_file) +{ + if (store_id != 0) + g_source_remove (store_id); - w = CLAMP (w, 100, max_width); - h = CLAMP (h, 100, max_height); + store_id = g_timeout_add_seconds (1, geometry_store_cb, key_file); +} - x = CLAMP (x, 0, max_width - w); - y = CLAMP (y, 0, max_height - h); +static GKeyFile * +geometry_get_key_file (void) +{ + static GKeyFile *key_file = NULL; + gchar *dir; + gchar *filename; - str = g_strdup_printf (GEOMETRY_FORMAT, x, y, w, h); + if (key_file != NULL) + return key_file; - key_file = g_key_file_new (); + dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); + if (!g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + DEBUG ("Creating directory:'%s'", dir); + g_mkdir_with_parents (dir, GEOMETRY_DIR_CREATE_MODE); + } - filename = geometry_get_filename (); + filename = g_build_filename (dir, GEOMETRY_KEY_FILENAME, NULL); + g_free (dir); + key_file = g_key_file_new (); g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, NULL); - g_key_file_set_string (key_file, GEOMETRY_GROUP_NAME, escaped_name, str); - - g_free (str); - - content = g_key_file_to_data (key_file, &length, NULL); - if (!g_file_set_contents (filename, content, length, &error)) { - g_warning ("Couldn't save window geometry, error:%d->'%s'", - error->code, error->message); - g_error_free (error); - } - - g_free (content); g_free (filename); - g_free (escaped_name); - g_key_file_free (key_file); + + return key_file; } void -empathy_geometry_load (const gchar *name, - gint *x, - gint *y, - gint *w, - gint *h) +empathy_geometry_save (GtkWindow *window, + const gchar *name) { - GKeyFile *key_file; - gchar *filename; - gchar *str = NULL; - gchar *escaped_name; + GKeyFile *key_file; + GdkWindow *gdk_window; + GdkWindowState window_state; + gchar *escaped_name; + gint x, y, w, h; + gboolean maximized; + + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (!EMP_STR_EMPTY (name)); /* escape the name so that unwanted characters such as # are removed */ escaped_name = g_uri_escape_string (name, NULL, TRUE); - if (x) { - *x = -1; - } + /* 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; - if (y) { - *y = -1; - } + key_file = geometry_get_key_file (); - if (w) { - *w = -1; - } + /* Save window size only if not maximized */ + if (!maximized) { + gchar *str; - if (h) { - *h = -1; + 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); } - key_file = g_key_file_new (); + g_key_file_set_boolean (key_file, GEOMETRY_MAXIMIZED_GROUP_NAME, + escaped_name, maximized); - filename = geometry_get_filename (); + geometry_schedule_store (key_file); +} - if (g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, NULL)) { - str = g_key_file_get_string (key_file, GEOMETRY_GROUP_NAME, escaped_name, NULL); - } +void +empathy_geometry_load (GtkWindow *window, + const gchar *name) +{ + GKeyFile *key_file; + gchar *escaped_name; + gchar *str; + gboolean maximized; + + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (!EMP_STR_EMPTY (name)); + + /* escape the name so that unwanted characters such as # are removed */ + escaped_name = g_uri_escape_string (name, NULL, TRUE); + 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); if (str) { - gint tmp_x, tmp_y, tmp_w, tmp_h; + gint x, y, w, h; - sscanf (str, GEOMETRY_FORMAT, &tmp_x, &tmp_y, &tmp_w, &tmp_h); + sscanf (str, GEOMETRY_FORMAT, &x, &y, &w, &h); + gtk_window_move (window, x, y); + gtk_window_resize (window, w, h); + } - if (x) { - *x = tmp_x; - } + /* restore window maximized state */ + maximized = g_key_file_get_boolean (key_file, + GEOMETRY_MAXIMIZED_GROUP_NAME, + escaped_name, NULL); + if (maximized) + gtk_window_maximize (window); + else + gtk_window_unmaximize (window); - if (y) { - *y = tmp_y; - } + g_free (str); + g_free (escaped_name); +} - if (w) { - *w = tmp_w; - } +static gboolean +geometry_configure_event_cb (GtkWindow *window, + GdkEventConfigure *event, + gchar *name) +{ + empathy_geometry_save (window, name); + return FALSE; +} - if (h) { - *h = tmp_h; - } +static gboolean +geometry_window_state_event_cb (GtkWindow *window, + GdkEventWindowState *event, + gchar *name) +{ + if ((event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0) + empathy_geometry_save (window, name); - g_free (str); - } + return FALSE; +} - DEBUG ("Loading window geometry: x:%d, y:%d, w:%d, h:%d\n", - x ? *x : -1, y ? *y : -1, w ? *w : -1, h ? *h : -1); +void +empathy_geometry_bind (GtkWindow *window, + const gchar *name) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (!EMP_STR_EMPTY (name)); + + /* First load initial geometry */ + empathy_geometry_load (window, name); + + /* Track geometry changes */ + g_signal_connect_data (window, "configure-event", + G_CALLBACK (geometry_configure_event_cb), g_strdup (name), + (GClosureNotify) g_free, 0); + g_signal_connect_data (window, "window-state-event", + G_CALLBACK (geometry_window_state_event_cb), g_strdup (name), + (GClosureNotify) g_free, 0); +} - g_free (filename); - g_free (escaped_name); - g_key_file_free (key_file); +void +empathy_geometry_unbind (GtkWindow *window) +{ + g_signal_handlers_disconnect_matched (window, + G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + geometry_configure_event_cb, NULL); + g_signal_handlers_disconnect_matched (window, + G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + geometry_window_state_event_cb, NULL); } diff --git a/libempathy-gtk/empathy-geometry.h b/libempathy-gtk/empathy-geometry.h index b7bd86bc2..2bb923b6c 100644 --- a/libempathy-gtk/empathy-geometry.h +++ b/libempathy-gtk/empathy-geometry.h @@ -26,19 +26,20 @@ #define __EMPATHY_GEOMETRY_H__ #include <glib.h> +#include <gtk/gtk.h> G_BEGIN_DECLS -void empathy_geometry_save (const gchar *name, - gint x, - gint y, - gint w, - gint h); -void empathy_geometry_load (const gchar *name, - gint *x, - gint *y, - gint *w, - gint *h); +void empathy_geometry_save (GtkWindow *window, + const gchar *name); + +void empathy_geometry_load (GtkWindow *window, + const gchar *name); + +void empathy_geometry_bind (GtkWindow *window, + const gchar *name); + +void empathy_geometry_unbind (GtkWindow *window); G_END_DECLS diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c index 4d99afd31..ca3375306 100644 --- a/src/empathy-chat-window.c +++ b/src/empathy-chat-window.c @@ -73,7 +73,6 @@ typedef struct { GList *chats_composing; gboolean page_added; gboolean dnd_same_window; - guint save_geometry_id; EmpathyChatroomManager *chatroom_manager; EmpathyNotifyManager *notify_mgr; GtkWidget *dialog; @@ -725,63 +724,6 @@ chat_window_contacts_toggled_cb (GtkToggleAction *toggle_action, empathy_chat_set_show_contacts (priv->current_chat, active); } -static const gchar * -chat_get_window_id_for_geometry (EmpathyChat *chat) -{ - const gchar *res = NULL; - gboolean separate_windows; - - empathy_conf_get_bool (empathy_conf_get (), - EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS, - &separate_windows); - - if (separate_windows) { - res = empathy_chat_get_id (chat); - } - - return res ? res : "chat-window"; -} - -static gboolean -chat_window_save_geometry_timeout_cb (EmpathyChatWindow *window) -{ - EmpathyChatWindowPriv *priv; - gint x, y, w, h; - - priv = GET_PRIV (window); - - gtk_window_get_size (GTK_WINDOW (priv->dialog), &w, &h); - gtk_window_get_position (GTK_WINDOW (priv->dialog), &x, &y); - - empathy_geometry_save (chat_get_window_id_for_geometry (priv->current_chat), - x, y, w, h); - - priv->save_geometry_id = 0; - - return FALSE; -} - -static gboolean -chat_window_configure_event_cb (GtkWidget *widget, - GdkEventConfigure *event, - EmpathyChatWindow *window) -{ - EmpathyChatWindowPriv *priv; - - priv = GET_PRIV (window); - - if (priv->save_geometry_id != 0) { - g_source_remove (priv->save_geometry_id); - } - - priv->save_geometry_id = - g_timeout_add_seconds (1, - (GSourceFunc) chat_window_save_geometry_timeout_cb, - window); - - return FALSE; -} - static void chat_window_close_activate_cb (GtkAction *action, EmpathyChatWindow *window) @@ -1511,10 +1453,6 @@ chat_window_finalize (GObject *object) g_object_unref (priv->ui_manager); g_object_unref (priv->chatroom_manager); g_object_unref (priv->notify_mgr); - if (priv->save_geometry_id != 0) { - g_source_remove (priv->save_geometry_id); - chat_window_save_geometry_timeout_cb (window); - } if (priv->notification != NULL) { notify_notification_close (priv->notification, NULL); @@ -1591,7 +1529,6 @@ empathy_chat_window_init (EmpathyChatWindow *window) g_free (filename); empathy_builder_connect (gui, window, - "chat_window", "configure-event", chat_window_configure_event_cb, "menu_conv", "activate", chat_window_conv_activate_cb, "menu_conv_clear", "activate", chat_window_clear_activate_cb, "menu_conv_favorite", "toggled", chat_window_favorite_toggled_cb, @@ -1758,7 +1695,6 @@ empathy_chat_window_add_chat (EmpathyChatWindow *window, GtkWidget *label; GtkWidget *popup_label; GtkWidget *child; - gint x, y, w, h; g_return_if_fail (window != NULL); g_return_if_fail (EMPATHY_IS_CHAT (chat)); @@ -1770,21 +1706,18 @@ empathy_chat_window_add_chat (EmpathyChatWindow *window, /* If this window has just been created, position it */ if (priv->chats == NULL) { - empathy_geometry_load (chat_get_window_id_for_geometry (chat), &x, &y, &w, &h); + const gchar *name = "chat-window"; + gboolean separate_windows; - if (x >= 0 && y >= 0) { - /* Let the window manager position it if we don't have - * good x, y coordinates. - */ - gtk_window_move (GTK_WINDOW (priv->dialog), x, y); - } + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS, + &separate_windows); - if (w > 0 && h > 0) { - /* Use the defaults from the ui file if we don't have - * good w, h geometry. - */ - gtk_window_resize (GTK_WINDOW (priv->dialog), w, h); + if (separate_windows) { + name = empathy_chat_get_id (chat); } + + empathy_geometry_bind (GTK_WINDOW (priv->dialog), name); } child = GTK_WIDGET (chat); diff --git a/src/empathy-ft-manager.c b/src/empathy-ft-manager.c index ff12c9b6b..e681f8441 100644 --- a/src/empathy-ft-manager.c +++ b/src/empathy-ft-manager.c @@ -66,8 +66,6 @@ typedef struct { GtkWidget *open_button; GtkWidget *abort_button; GtkWidget *clear_button; - - guint save_geometry_id; } EmpathyFTManagerPriv; enum @@ -868,38 +866,6 @@ ft_manager_stop (EmpathyFTManager *manager) g_object_unref (handler); } -static gboolean -ft_manager_save_geometry_timeout_cb (EmpathyFTManager *manager) -{ - EmpathyFTManagerPriv *priv = GET_PRIV (manager); - gint x, y, w, h; - - gtk_window_get_size (GTK_WINDOW (priv->window), &w, &h); - gtk_window_get_position (GTK_WINDOW (priv->window), &x, &y); - - empathy_geometry_save ("ft-manager", x, y, w, h); - - priv->save_geometry_id = 0; - - return FALSE; -} - -static gboolean -ft_manager_configure_event_cb (GtkWidget *widget, - GdkEventConfigure *event, - EmpathyFTManager *manager) -{ - EmpathyFTManagerPriv *priv = GET_PRIV (manager); - - if (priv->save_geometry_id != 0) - g_source_remove (priv->save_geometry_id); - - priv->save_geometry_id = g_timeout_add (500, - (GSourceFunc) ft_manager_save_geometry_timeout_cb, manager); - - return FALSE; -} - static void ft_manager_response_cb (GtkWidget *widget, gint response, @@ -970,7 +936,6 @@ static void ft_manager_build_ui (EmpathyFTManager *manager) { GtkBuilder *gui; - gint x, y, w, h; GtkTreeView *view; GtkListStore *liststore; GtkTreeViewColumn *column; @@ -993,28 +958,13 @@ ft_manager_build_ui (EmpathyFTManager *manager) "ft_manager_dialog", "destroy", ft_manager_destroy_cb, "ft_manager_dialog", "response", ft_manager_response_cb, "ft_manager_dialog", "delete-event", ft_manager_delete_event_cb, - "ft_manager_dialog", "configure-event", ft_manager_configure_event_cb, "ft_manager_dialog", "key-press-event", ft_manager_key_press_event_cb, NULL); empathy_builder_unref_and_keep_widget (gui, priv->window); /* Window geometry. */ - empathy_geometry_load ("ft-manager", &x, &y, &w, &h); - - if (x >= 0 && y >= 0) - { - /* Let the window manager position it if we don't have - * good x, y coordinates. */ - gtk_window_move (GTK_WINDOW (priv->window), x, y); - } - - if (w > 0 && h > 0) - { - /* Use the defaults from the ui file if we don't have - * good w, h geometry. */ - gtk_window_resize (GTK_WINDOW (priv->window), w, h); - } + empathy_geometry_bind (GTK_WINDOW (priv->window), "ft-manager"); /* Setup the tree view */ view = GTK_TREE_VIEW (priv->treeview); @@ -1093,19 +1043,12 @@ ft_manager_build_ui (EmpathyFTManager *manager) static void empathy_ft_manager_finalize (GObject *object) { - EmpathyFTManager *self = EMPATHY_FT_MANAGER (object); EmpathyFTManagerPriv *priv = GET_PRIV (object); DEBUG ("FT Manager %p", object); g_hash_table_destroy (priv->ft_handler_to_row_ref); - if (priv->save_geometry_id != 0) - { - g_source_remove (priv->save_geometry_id); - ft_manager_save_geometry_timeout_cb (self); - } - G_OBJECT_CLASS (empathy_ft_manager_parent_class)->finalize (object); } diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c index 473e47706..2a316b99e 100644 --- a/src/empathy-main-window.c +++ b/src/empathy-main-window.c @@ -117,9 +117,6 @@ typedef struct { static EmpathyMainWindow *main_window = NULL; -static gboolean main_window_configure_event_timeout_cb ( - EmpathyMainWindow *window); - static void main_window_flash_stop (EmpathyMainWindow *window) { @@ -659,11 +656,6 @@ main_window_destroy_cb (GtkWidget *widget, /* Save user-defined accelerators. */ main_window_accels_save (); - if (window->size_timeout_id) { - g_source_remove (window->size_timeout_id); - main_window_configure_event_timeout_cb (window); - } - g_list_free (window->actions_connected); g_object_unref (window->account_manager); @@ -1104,37 +1096,6 @@ main_window_throbber_button_press_event_cb (GtkWidget *throbber_ebox, return FALSE; } -static gboolean -main_window_configure_event_timeout_cb (EmpathyMainWindow *window) -{ - gint x, y, w, h; - - gtk_window_get_size (GTK_WINDOW (window->window), &w, &h); - gtk_window_get_position (GTK_WINDOW (window->window), &x, &y); - - empathy_geometry_save (GEOMETRY_NAME, x, y, w, h); - - window->size_timeout_id = 0; - - return FALSE; -} - -static gboolean -main_window_configure_event_cb (GtkWidget *widget, - GdkEventConfigure *event, - EmpathyMainWindow *window) -{ - if (window->size_timeout_id) { - g_source_remove (window->size_timeout_id); - } - - window->size_timeout_id = g_timeout_add_seconds (1, - (GSourceFunc) main_window_configure_event_timeout_cb, - window); - - return FALSE; -} - static void main_window_account_removed_cb (TpAccountManager *manager, TpAccount *account, @@ -1247,7 +1208,6 @@ empathy_main_window_show (void) GtkAction *show_map_widget; GtkToolItem *item; gboolean show_offline; - gint x, y, w, h; gchar *filename; GSList *l; @@ -1282,7 +1242,6 @@ empathy_main_window_show (void) empathy_builder_connect (gui, window, "main_window", "destroy", main_window_destroy_cb, - "main_window", "configure_event", main_window_configure_event_cb, "chat_quit", "activate", main_window_chat_quit_cb, "chat_new_message", "activate", main_window_chat_new_message_cb, "view_history", "activate", main_window_view_history_cb, @@ -1388,23 +1347,7 @@ empathy_main_window_show (void) main_window_accels_load (); /* Set window size. */ - empathy_geometry_load (GEOMETRY_NAME, &x, &y, &w, &h); - - if (w >= 1 && h >= 1) { - /* Use the defaults from the ui file if we - * don't have good w, h geometry. - */ - DEBUG ("Configuring window default size w:%d, h:%d", w, h); - gtk_window_set_default_size (GTK_WINDOW (window->window), w, h); - } - - if (x >= 0 && y >= 0) { - /* Let the window manager position it if we - * don't have good x, y coordinates. - */ - DEBUG ("Configuring window default position x:%d, y:%d", x, y); - gtk_window_move (GTK_WINDOW (window->window), x, y); - } + empathy_geometry_bind (GTK_WINDOW (window->window), GEOMETRY_NAME); /* Enable event handling */ window->event_manager = empathy_event_manager_dup_singleton (); |