X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fwidgets%2Fmodest-window-mgr.c;h=3cfb17bd3ac6d8ccb919a1151323b9f482b60aed;hp=80731e738ccc9080cafeb02311e0663a33d1a237;hb=7b18df5711ee7782411329e8a47d1d573d898136;hpb=f19d5b6e2df7fb9cea5db37287802d1245a7b796 diff --git a/src/widgets/modest-window-mgr.c b/src/widgets/modest-window-mgr.c index 80731e7..3cfb17b 100644 --- a/src/widgets/modest-window-mgr.c +++ b/src/widgets/modest-window-mgr.c @@ -68,6 +68,7 @@ enum { typedef struct _ModestWindowMgrPrivate ModestWindowMgrPrivate; struct _ModestWindowMgrPrivate { GList *window_list; + guint banner_counter; ModestWindow *main_window; @@ -80,6 +81,7 @@ struct _ModestWindowMgrPrivate { GSList *preregistered_uids; GHashTable *destroy_handlers; GHashTable *viewer_handlers; + GSList *window_state_uids; guint closing_time; @@ -88,6 +90,8 @@ struct _ModestWindowMgrPrivate { GtkWidget *cached_editor; guint idle_load_view_id; guint idle_load_editor_id; + + ModestWindow *current_top; }; #define MODEST_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_WINDOW_MGR, \ @@ -194,8 +198,11 @@ modest_window_mgr_init (ModestWindowMgr *obj) priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj); priv->window_list = NULL; + priv->banner_counter = 0; priv->main_window = NULL; priv->fullscreen_mode = FALSE; + priv->current_top = NULL; + priv->window_state_uids = NULL; priv->modal_windows = g_queue_new (); priv->queue_lock = g_mutex_new (); @@ -238,6 +245,8 @@ modest_window_mgr_finalize (GObject *obj) priv->cached_editor = NULL; } + modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids); + if (priv->window_list) { GList *iter = priv->window_list; /* unregister pending windows */ @@ -472,19 +481,25 @@ void modest_window_mgr_close_all_windows (ModestWindowMgr *self) { ModestWindowMgrPrivate *priv = NULL; - GList *wins = NULL; gboolean ret_value = FALSE; g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - /* delete-event handler already removes window_list item, */ - /* so no next its required on this loop */ - wins = priv->window_list; - while (wins) { - g_signal_emit_by_name (G_OBJECT (wins->data), "delete-event", NULL, &ret_value); + /* If there is a main window then try to close it, and it will + close the others if needed */ + if (priv->main_window) { + g_signal_emit_by_name (priv->main_window, "delete-event", NULL, &ret_value); + } else { + GList *wins = NULL, *next = NULL; + /* delete-event handler actually removes window_list item, */ wins = priv->window_list; + while (wins) { + next = g_list_next (wins); + g_signal_emit_by_name (G_OBJECT (wins->data), "delete-event", NULL, &ret_value); + wins = next; + } } } @@ -552,6 +567,64 @@ get_show_toolbar_key (GType window_type, return key; } +#ifdef MODEST_PLATFORM_MAEMO +static void +on_window_is_topmost (GObject *gobject, + GParamSpec *arg1, + gpointer user_data) +{ + ModestWindowMgr *self; + ModestWindowMgrPrivate *priv; + ModestWindow *win = (ModestWindow *) gobject; + + g_return_if_fail (MODEST_IS_WINDOW_MGR (user_data)); + + self = MODEST_WINDOW_MGR (user_data); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + if (hildon_window_get_is_topmost (HILDON_WINDOW (win))) + priv->current_top = win; +} + +#else +static gboolean +on_window_state_event (GtkWidget *widget, + GdkEventWindowState *event, + gpointer user_data) +{ + ModestWindowMgr *self; + ModestWindowMgrPrivate *priv; + + g_return_val_if_fail (MODEST_IS_WINDOW_MGR (user_data), FALSE); + + self = MODEST_WINDOW_MGR (user_data); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + MODEST_DEBUG_BLOCK ( + if (event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) + g_print ("GDK_WINDOW_STATE_WITHDRAWN\n"); + if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) + g_print ("GDK_WINDOW_STATE_ICONIFIED\n"); + if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) + g_print ("GDK_WINDOW_STATE_MAXIMIZED\n"); + if (event->changed_mask & GDK_WINDOW_STATE_STICKY) + g_print ("GDK_WINDOW_STATE_STICKY\n"); + if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) + g_print ("GDK_WINDOW_STATE_FULLSCREEN\n"); + if (event->changed_mask & GDK_WINDOW_STATE_ABOVE) + g_print ("GDK_WINDOW_STATE_ABOVE\n"); + if (event->changed_mask & GDK_WINDOW_STATE_BELOW) + g_print ("GDK_WINDOW_STATE_BELOW\n"); + ); + if (event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN || + event->changed_mask & GDK_WINDOW_STATE_ABOVE) { + priv->current_top = MODEST_WINDOW (widget); + } + + return FALSE; +} +#endif + void modest_window_mgr_register_window (ModestWindowMgr *self, ModestWindow *window) @@ -617,6 +690,24 @@ modest_window_mgr_register_window (ModestWindowMgr *self, g_object_ref (window); priv->window_list = g_list_prepend (priv->window_list, window); + /* 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 + priv->window_state_uids = + modest_signal_mgr_connect (priv->window_state_uids, + G_OBJECT (window), + "notify::is-topmost", + G_CALLBACK (on_window_is_topmost), + self); +#else + priv->window_state_uids = + modest_signal_mgr_connect (priv->window_state_uids, + G_OBJECT (window), + "window-state-event", + G_CALLBACK (on_window_state_event), + self); +#endif /* Listen to object destruction */ handler_id = g_malloc0 (sizeof (gint)); *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self); @@ -665,9 +756,8 @@ on_window_destroy (ModestWindow *window, /* If the user wants to close all the windows */ if ((dialog_response == GTK_RESPONSE_OK) - || (dialog_response == GTK_RESPONSE_ACCEPT) - || (dialog_response == GTK_RESPONSE_YES)) - { + || (dialog_response == GTK_RESPONSE_ACCEPT) + || (dialog_response == GTK_RESPONSE_YES)) { GList *iter = priv->window_list; do { if (iter->data != window) { @@ -680,11 +770,9 @@ on_window_destroy (ModestWindow *window, iter = g_list_next (iter); } } while (iter); - } - else - { - return TRUE; - } + } else { + return TRUE; + } } } else { @@ -703,8 +791,9 @@ on_window_destroy (ModestWindow *window, modest_platform_run_confirmation_dialog (GTK_WINDOW (window), _("mcen_nc_no_email_message_modified_save_changes")); /* Save to drafts */ - if (response != GTK_RESPONSE_CANCEL) - modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)); + if (response == GTK_RESPONSE_OK) + if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window))) + return TRUE; } } } @@ -734,6 +823,7 @@ 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)); @@ -784,23 +874,32 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, g_hash_table_remove (priv->destroy_handlers, window); /* cancel open and receive operations */ - if (MODEST_IS_MSG_VIEW_WINDOW (window)) { + 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* pending_ops = NULL; GSList* tmp_list = NULL; - pending_ops = modest_mail_operation_queue_get_by_source ( - modest_runtime_get_mail_operation_queue (), - G_OBJECT (window)); - while (pending_ops != 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); - } - tmp_list = pending_ops; - pending_ops = g_slist_next (pending_ops); - g_slist_free_1 (tmp_list); + + 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); } + + /* 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"); +#else + 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); @@ -812,7 +911,7 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, gtk_widget_destroy (win->data); /* If there are no more windows registered emit the signal */ - if (priv->window_list == NULL) + if (priv->window_list == NULL && priv->banner_counter == 0) g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0); } @@ -974,6 +1073,14 @@ modest_window_mgr_set_modal (ModestWindowMgr *self, g_mutex_unlock (priv->queue_lock); if (!old_modal) { + /* make us transient wrt the main window then */ + if (priv->current_top && ((GtkWindow *) priv->current_top != window)) { + gtk_window_set_transient_for (window, GTK_WINDOW(priv->current_top)); + } else { + ModestWindow *main_win = modest_window_mgr_get_main_window (self, FALSE); + if (GTK_WINDOW(main_win) != window) /* they should not be the same */ + gtk_window_set_transient_for (window, GTK_WINDOW(main_win)); + } gtk_window_set_modal (window, TRUE); } else { /* un-modalize the old one; the one on top should be the @@ -1097,8 +1204,11 @@ idle_top_modal (gpointer data) g_mutex_unlock (priv->queue_lock); /* Show it */ - if (topmost) + if (topmost) { + gdk_threads_enter (); gtk_window_present (topmost); + gdk_threads_leave (); + } return FALSE; } @@ -1164,21 +1274,29 @@ on_modal_dialog_close (GtkDialog *dialog, gint modest_window_mgr_num_windows (ModestWindowMgr *self) { - ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE(self); + ModestWindowMgrPrivate *priv; gint num_windows = 0; + g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), -1); + + priv = MODEST_WINDOW_MGR_GET_PRIVATE(self); + if (priv->window_list) num_windows = g_list_length (priv->window_list); - return num_windows; + return num_windows + priv->banner_counter; } GtkWidget * modest_window_mgr_get_msg_edit_window (ModestWindowMgr *self) { GtkWidget *result; - ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE(self); + ModestWindowMgrPrivate *priv; + g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL); + + priv = MODEST_WINDOW_MGR_GET_PRIVATE(self); + if (priv->cached_editor) { result = priv->cached_editor; priv->cached_editor = NULL; @@ -1194,7 +1312,11 @@ GtkWidget * modest_window_mgr_get_msg_view_window (ModestWindowMgr *self) { GtkWidget *result; - ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE(self); + ModestWindowMgrPrivate *priv; + + g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL); + + priv = MODEST_WINDOW_MGR_GET_PRIVATE(self); if (priv->cached_view) { result = priv->cached_view; @@ -1206,3 +1328,30 @@ modest_window_mgr_get_msg_view_window (ModestWindowMgr *self) return result; } + +void +modest_window_mgr_register_banner (ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv; + + g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + priv->banner_counter++; + +} + +void +modest_window_mgr_unregister_banner (ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv; + + g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + priv->banner_counter--; + if (priv->window_list == NULL && priv->banner_counter == 0) { + g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0); + } + +}