X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fwidgets%2Fmodest-window-mgr.c;h=fb88abf2cb08f3584af8f5e9dbfe7660a67e792b;hp=3cfb17bd3ac6d8ccb919a1151323b9f482b60aed;hb=f6d386ff93e929092ba105385a29d760aeba9ff7;hpb=7b18df5711ee7782411329e8a47d1d573d898136 diff --git a/src/widgets/modest-window-mgr.c b/src/widgets/modest-window-mgr.c index 3cfb17b..fb88abf 100644 --- a/src/widgets/modest-window-mgr.c +++ b/src/widgets/modest-window-mgr.c @@ -52,6 +52,9 @@ static gboolean on_modal_window_close (GtkWidget *widget, GdkEvent *event, gpointer user_data); +static void on_modal_dialog_destroy (GtkObject *object, + gpointer user_data); + static void on_modal_dialog_close (GtkDialog *dialog, gint arg1, gpointer user_data); @@ -246,14 +249,15 @@ modest_window_mgr_finalize (GObject *obj) } modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids); + priv->window_state_uids = NULL; if (priv->window_list) { GList *iter = priv->window_list; /* unregister pending windows */ while (iter) { - modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), - MODEST_WINDOW (iter->data)); + ModestWindow *window = (ModestWindow *) iter->data; iter = g_list_next (iter); + modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window); } g_list_free (priv->window_list); priv->window_list = NULL; @@ -275,6 +279,7 @@ modest_window_mgr_finalize (GObject *obj) } modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids); + priv->modal_handler_uids = NULL; if (priv->modal_windows) { g_mutex_lock (priv->queue_lock); @@ -325,7 +330,7 @@ remove_uid (GSList *list, const gchar *uid) GSList *cursor = list, *start = list; if (!uid) - return FALSE; + return list; while (cursor) { GSList *next = g_slist_next (cursor); @@ -420,37 +425,11 @@ modest_window_mgr_register_help_id (ModestWindowMgr *self, GtkWindow *win, const const gchar* modest_window_mgr_get_help_id (ModestWindowMgr *self, GtkWindow *win) { - const gchar* help_id = NULL; - /* we don't need 'self', but for API consistency... */ - g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL); - + g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR (self), NULL); g_return_val_if_fail (win, NULL); - g_return_val_if_fail (GTK_IS_WINDOW(win), NULL); - - if (MODEST_IS_MAIN_WINDOW (win)) { - GtkWidget *folder_view; - TnyFolderStore *folder_store; - - /* Get selected folder */ - folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), - MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); - folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)); - - /* Switch help_id */ - if (folder_store && TNY_IS_FOLDER (folder_store)) { - help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store)); - if (!help_id) - g_warning ("%s: BUG: did not get a valid help_id", __FUNCTION__); - } - if (folder_store) - g_object_unref (folder_store); - } - if (!help_id) - help_id = g_object_get_data (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM); - - return help_id; + return g_object_get_data (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM); } static gint @@ -567,7 +546,7 @@ get_show_toolbar_key (GType window_type, return key; } -#ifdef MODEST_PLATFORM_MAEMO +#ifndef MODEST_TOOLKIT_GTK static void on_window_is_topmost (GObject *gobject, GParamSpec *arg1, @@ -693,7 +672,7 @@ modest_window_mgr_register_window (ModestWindowMgr *self, /* Listen to window state changes. Unfortunately window-state-event does not properly work for the Maemo version, so we need to use is-topmost and the ifdef */ -#ifdef MODEST_PLATFORM_MAEMO +#ifndef MODEST_TOOLKIT_GTK priv->window_state_uids = modest_signal_mgr_connect (priv->window_state_uids, G_OBJECT (window), @@ -732,12 +711,38 @@ modest_window_mgr_register_window (ModestWindowMgr *self, modest_window_show_toolbar (window, modest_conf_get_bool (modest_runtime_get_conf (), key, NULL)); } +static void +cancel_window_operations (ModestWindow *window) +{ + GSList* pending_ops = NULL; + + /* cancel open and receive operations */ + pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (), + G_OBJECT (window)); + while (pending_ops != NULL) { + ModestMailOperationTypeOperation type; + GSList* tmp_list = NULL; + + type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data)); + if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE || type == MODEST_MAIL_OPERATION_TYPE_OPEN) { + modest_mail_operation_cancel (pending_ops->data); + } + g_object_unref (G_OBJECT (pending_ops->data)); + tmp_list = pending_ops; + pending_ops = g_slist_next (pending_ops); + g_slist_free_1 (tmp_list); + } +} + + + static gboolean on_window_destroy (ModestWindow *window, GdkEvent *event, ModestWindowMgr *self) { gint dialog_response = GTK_RESPONSE_NONE; + gboolean no_propagate = FALSE; /* Specific stuff first */ if (MODEST_IS_MAIN_WINDOW (window)) { @@ -748,8 +753,10 @@ on_window_destroy (ModestWindow *window, if (g_list_length (priv->window_list) > 1) { /* Present the window if it's not visible now */ - if (!gtk_window_has_toplevel_focus (GTK_WINDOW (window))) + if (!gtk_window_has_toplevel_focus (GTK_WINDOW (window))) { gtk_window_present (GTK_WINDOW (window)); + priv->current_top = window; + } /* Create the confirmation dialog MSG-NOT308 */ dialog_response = modest_platform_run_confirmation_dialog ( GTK_WINDOW (window), _("emev_nc_close_windows")); @@ -774,6 +781,18 @@ on_window_destroy (ModestWindow *window, return TRUE; } } + + /* Do not unregister it, just hide */ + gtk_widget_hide_all (GTK_WIDGET (window)); + + /* Cancel pending operations */ + cancel_window_operations (window); + + /* Fake the window system, make it think that there is no window */ + if (modest_window_mgr_num_windows (self) == 0) + g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0); + + no_propagate = TRUE; } else { if (MODEST_IS_MSG_EDIT_WINDOW (window)) { @@ -796,12 +815,12 @@ on_window_destroy (ModestWindow *window, return TRUE; } } + /* Unregister window */ + modest_window_mgr_unregister_window (self, window); + no_propagate = TRUE; } - /* Unregister window */ - modest_window_mgr_unregister_window (self, window); - - return FALSE; + return no_propagate; } static void @@ -823,7 +842,6 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, GList *win; ModestWindowMgrPrivate *priv; gulong *tmp, handler_id; - GSList* pending_ops = NULL; g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); g_return_if_fail (MODEST_IS_WINDOW (window)); @@ -851,7 +869,7 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, } /* Remove the viewer window handler from the hash table. The - HashTable could not exist if the main window was closeed + HashTable could not exist if the main window was closed when there were other windows remaining */ if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) { tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window); @@ -871,35 +889,33 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, priv->window_list = g_list_remove_link (priv->window_list, win); tmp = g_hash_table_lookup (priv->destroy_handlers, window); handler_id = *tmp; + g_hash_table_remove (priv->destroy_handlers, window); /* cancel open and receive operations */ - pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (), - G_OBJECT (window)); - while (pending_ops != NULL) { - ModestMailOperationTypeOperation type; - GSList* tmp_list = NULL; + cancel_window_operations (window); - type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data)); - if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE || type == MODEST_MAIL_OPERATION_TYPE_OPEN) { - modest_mail_operation_cancel (pending_ops->data); - } - g_object_unref (G_OBJECT (pending_ops->data)); - tmp_list = pending_ops; - pending_ops = g_slist_next (pending_ops); - g_slist_free_1 (tmp_list); - } + /* Check if it's the topmost window, and remove the window from the stack. + * This is needed for the cases there's no other topmost window that will + * replace it in topmost handler. + */ + if (window == priv->current_top) + priv->current_top = NULL; /* Disconnect the "window-state-event" handler, we won't need it anymore */ -#ifdef MODEST_PLATFORM_MAEMO - priv->window_state_uids = modest_signal_mgr_disconnect (priv->window_state_uids, - G_OBJECT (window), - "notify::is-topmost"); + if (priv->window_state_uids) { +#ifndef MODEST_TOOLKIT_GTK + priv->window_state_uids = + modest_signal_mgr_disconnect (priv->window_state_uids, + G_OBJECT (window), + "notify::is-topmost"); #else - priv->window_state_uids = modest_signal_mgr_disconnect (priv->window_state_uids, - G_OBJECT (window), - "window-state-event"); + priv->window_state_uids = + modest_signal_mgr_disconnect (priv->window_state_uids, + G_OBJECT (window), + "window-state-event"); #endif + } /* Disconnect the "delete-event" handler, we won't need it anymore */ g_signal_handler_disconnect (window, handler_id); @@ -908,10 +924,12 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, modest_window_disconnect_signals (window); /* Destroy the window */ + g_object_unref (win->data); gtk_widget_destroy (win->data); + g_list_free (win); /* If there are no more windows registered emit the signal */ - if (priv->window_list == NULL && priv->banner_counter == 0) + if (modest_window_mgr_num_windows (self) == 0) g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0); } @@ -1094,7 +1112,7 @@ modest_window_mgr_set_modal (ModestWindowMgr *self, g_queue_push_head (priv->modal_windows, window); g_mutex_unlock (priv->queue_lock); - if (GTK_IS_DIALOG (window)) + if (GTK_IS_DIALOG (window)) { /* Note that response is not always enough because it could be captured and removed easily by dialogs but works for most of situations */ @@ -1104,13 +1122,25 @@ modest_window_mgr_set_modal (ModestWindowMgr *self, "response", G_CALLBACK (on_modal_dialog_close), self); - else + /* We need this as well because dialogs are often + destroyed with gtk_widget_destroy and this one will + prevent response from happening */ + priv->modal_handler_uids = + modest_signal_mgr_connect (priv->modal_handler_uids, + G_OBJECT (window), + "destroy", + G_CALLBACK (on_modal_dialog_destroy), + self); + } else { priv->modal_handler_uids = modest_signal_mgr_connect (priv->modal_handler_uids, G_OBJECT (window), "delete-event", G_CALLBACK (on_modal_window_close), self); + } + /* Destroy width parent */ + gtk_window_set_destroy_with_parent (window, TRUE); } @@ -1207,6 +1237,10 @@ idle_top_modal (gpointer data) if (topmost) { gdk_threads_enter (); gtk_window_present (topmost); + /* It seems that the window looses modality if some + other is shown on top of it after set_transient_for + and set_parent */ + gtk_window_set_modal (topmost, TRUE); gdk_threads_leave (); } @@ -1235,12 +1269,17 @@ remove_modal_from_queue (GtkWidget *widget, g_mutex_unlock (priv->queue_lock); /* Disconnect handler */ - priv->modal_handler_uids = - modest_signal_mgr_disconnect (priv->modal_handler_uids, + priv->modal_handler_uids = + modest_signal_mgr_disconnect (priv->modal_handler_uids, G_OBJECT (widget), - GTK_IS_DIALOG (widget) ? - "response" : - "destroy-event"); + GTK_IS_DIALOG (widget) ? + "response" : + "delete-event"); + if (GTK_IS_DIALOG (widget)) + priv->modal_handler_uids = + modest_signal_mgr_disconnect (priv->modal_handler_uids, + G_OBJECT (widget), + "destroy"); /* Schedule the next one for being shown */ g_idle_add (idle_top_modal, self); @@ -1267,10 +1306,22 @@ on_modal_dialog_close (GtkDialog *dialog, { ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data); - /* Remove modal window from queue */ + /* Remove modal window from queue. Note that if "destroy" + signal was invoked before the response the window could be + already deleted */ remove_modal_from_queue (GTK_WIDGET (dialog), self); } +static void +on_modal_dialog_destroy (GtkObject *object, + gpointer user_data) +{ + ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data); + + /* Remove modal window from queue */ + remove_modal_from_queue (GTK_WIDGET (object), self); +} + gint modest_window_mgr_num_windows (ModestWindowMgr *self) { @@ -1284,6 +1335,10 @@ modest_window_mgr_num_windows (ModestWindowMgr *self) if (priv->window_list) num_windows = g_list_length (priv->window_list); + /* Do not take into account the main window if it was hidden */ + if (priv->main_window && !GTK_WIDGET_VISIBLE (priv->main_window)) + num_windows--; + return num_windows + priv->banner_counter; } @@ -1350,8 +1405,6 @@ modest_window_mgr_unregister_banner (ModestWindowMgr *self) priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); priv->banner_counter--; - if (priv->window_list == NULL && priv->banner_counter == 0) { + if (modest_window_mgr_num_windows (self) == 0) g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0); - } - }