From 1da8768a0a328717ddc9c0757f9338787434c11d Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Wed, 21 Oct 2009 16:58:41 +0000 Subject: Use always a different process for every document --- diff --git a/shell/Makefile.am b/shell/Makefile.am index 8d86efe..987d215 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -17,6 +17,7 @@ INCLUDES= \ -I$(top_srcdir)/properties \ -DGNOMELOCALEDIR=\"$(datadir)/locale\" \ -DGNOMEICONDIR=\""$(datadir)/pixmaps"\" \ + -DBINDIR=\""$(bindir)"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ -DEVINCE_COMPILATION \ $(SHELL_CFLAGS) \ diff --git a/shell/ev-application.c b/shell/ev-application.c index 24ef1e0..0690cdb 100644 --- a/shell/ev-application.c +++ b/shell/ev-application.c @@ -20,8 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include #include #include @@ -63,6 +63,9 @@ static void ev_application_save_print_settings (EvApplication *application); struct _EvApplication { GObject base_instance; + EvWindow *window; + gchar *uri; + gchar *dot_dir; gchar *data_dir; gchar *accel_map_file; @@ -70,8 +73,7 @@ struct _EvApplication { #ifdef ENABLE_DBUS DBusGConnection *connection; - GHashTable *windows; - guint doc_counter; + EvMediaPlayerKeys *keys; #endif EggToolbarsModel *toolbars_model; @@ -85,10 +87,6 @@ struct _EvApplication { gchar *filechooser_open_uri; gchar *filechooser_save_uri; -#ifdef ENABLE_DBUS - EvMediaPlayerKeys *keys; -#endif /* ENABLE_DBUS */ - GtkPrintSettings *print_settings; GtkPageSetup *page_setup; GKeyFile *print_settings_file; @@ -128,43 +126,12 @@ ev_application_get_instance (void) return instance; } -#if defined (WITH_SMCLIENT) /* Session */ -static void -save_session (EvApplication *application, - GList *windows_list, - GKeyFile *state_file) -{ - GList *l; - gint i; - const gchar **uri_list; - const gchar *empty = "empty-window"; - - uri_list = g_new (const gchar *, g_list_length (windows_list)); - for (l = windows_list, i = 0; l != NULL; l = g_list_next (l), i++) { - EvWindow *window = EV_WINDOW (l->data); - - if (ev_window_is_empty (window)) - uri_list[i] = empty; - else - uri_list[i] = ev_window_get_uri (window); - } - g_key_file_set_string_list (state_file, - "Evince", - "documents", - (const char **)uri_list, - i); - g_free (uri_list); -} - -#endif /* WITH_SMCLIENT */ - gboolean -ev_application_load_session (EvApplication *application, - const gchar **files) +ev_application_load_session (EvApplication *application) { GKeyFile *state_file; - gchar **uri_list; + gchar *uri; #ifdef WITH_SMCLIENT if (egg_sm_client_is_resumed (application->smclient)) { @@ -175,23 +142,15 @@ ev_application_load_session (EvApplication *application, #endif /* WITH_SMCLIENT */ return FALSE; - uri_list = g_key_file_get_string_list (state_file, - "Evince", - "documents", - NULL, NULL); - if (uri_list) { - gint i; - GdkScreen *screen = gdk_screen_get_default (); - - for (i = 0; uri_list[i]; i++) { - if (g_ascii_strcasecmp (uri_list[i], "empty-window") == 0) - ev_application_open_window (application, screen, GDK_CURRENT_TIME); - else - ev_application_open_uri_at_dest (application, uri_list[i], screen, - NULL, 0, NULL, GDK_CURRENT_TIME); - } - g_strfreev (uri_list); - } + uri = g_key_file_get_string (state_file, "Evince", "uri", NULL); + if (!uri) + return FALSE; + + ev_application_open_uri_at_dest (application, uri, + gdk_screen_get_default (), + NULL, 0, NULL, + GDK_CURRENT_TIME); + g_free (uri); g_key_file_free (state_file); return TRUE; @@ -204,13 +163,10 @@ smclient_save_state_cb (EggSMClient *client, GKeyFile *state_file, EvApplication *application) { - GList *windows; + if (!application->uri) + return; - windows = ev_application_get_windows (application); - if (windows) { - save_session (application, windows, state_file); - g_list_free (windows); - } + g_key_file_set_string (state_file, "Evince", "uri", application->uri); } static void @@ -219,7 +175,6 @@ smclient_quit_cb (EggSMClient *client, { ev_application_shutdown (application); } - #endif /* WITH_SMCLIENT */ static void @@ -443,108 +398,63 @@ build_args (GdkScreen *screen, return args; } -/** - * ev_application_open_window: - * @application: The instance of the application. - * @timestamp: Current time value. - * - * Creates a new window - */ -void -ev_application_open_window (EvApplication *application, - GdkScreen *screen, - guint32 timestamp) +static void +ev_spawn (const char *uri, + GdkScreen *screen, + EvLinkDest *dest, + EvWindowRunMode mode, + const gchar *search_string) { - GtkWidget *new_window = ev_window_new (); + gchar *argv[6]; + guint arg = 0; + gint i; + gboolean res; + GError *error = NULL; - if (screen) { - ev_stock_icons_set_screen (screen); - gtk_window_set_screen (GTK_WINDOW (new_window), screen); - } - - if (!GTK_WIDGET_REALIZED (new_window)) - gtk_widget_realize (new_window); - -#ifdef GDK_WINDOWING_X11 - if (timestamp <= 0) - timestamp = gdk_x11_get_server_time (GTK_WIDGET (new_window)->window); - gdk_x11_window_set_user_time (GTK_WIDGET (new_window)->window, timestamp); + argv[arg++] = g_build_filename (BINDIR, "evince", NULL); - gtk_window_present (GTK_WINDOW (new_window)); -#else - gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp); -#endif /* GDK_WINDOWING_X11 */ -} - -/** - * ev_application_get_empty_window: - * @application: The instance of the application. - * @screen: The screen where the empty window will be search. - * - * It does look if there is any empty window in the indicated screen. - * - * Returns: The first empty #EvWindow in the passed #GdkScreen or NULL in other - * case. - */ -static EvWindow * -ev_application_get_empty_window (EvApplication *application, - GdkScreen *screen) -{ - EvWindow *empty_window = NULL; - GList *windows = ev_application_get_windows (application); - GList *l; - - for (l = windows; l != NULL; l = l->next) { - EvWindow *window = EV_WINDOW (l->data); + /* Page label */ + if (dest) { + const gchar *page_label; - if (ev_window_is_empty (window) && - gtk_window_get_screen (GTK_WINDOW (window)) == screen) { - empty_window = window; - break; - } + page_label = ev_link_dest_get_page_label (dest); + if (page_label) + argv[arg++] = g_strdup_printf ("--page-label=%s", page_label); + else + argv[arg++] = g_strdup_printf ("--page-label=%d", + ev_link_dest_get_page (dest)); } - g_list_free (windows); - - return empty_window; -} - -/** - * ev_application_get_uri_window: - * @application: The instance of the application. - * @uri: The uri to be opened. - * - * It looks in the list of the windows for the one with the document represented - * by the passed uri on it. If the window is empty or the document isn't present - * on any window, it will return NULL. - * - * Returns: The #EvWindow where the document represented by the passed uri is - * shown, NULL in other case. - */ -static EvWindow * -ev_application_get_uri_window (EvApplication *application, const char *uri) -{ - EvWindow *uri_window = NULL; - GList *windows = gtk_window_list_toplevels (); - GList *l; + /* Find string */ + if (search_string) { + argv[arg++] = g_strdup_printf ("--find=%s", search_string); + } - g_return_val_if_fail (uri != NULL, NULL); + /* Mode */ + switch (mode) { + case EV_WINDOW_MODE_FULLSCREEN: + argv[arg++] = g_strdup ("-f"); + break; + case EV_WINDOW_MODE_PRESENTATION: + argv[arg++] = g_strdup ("-s"); + break; + default: + break; + } - for (l = windows; l != NULL; l = l->next) { - if (EV_IS_WINDOW (l->data)) { - EvWindow *window = EV_WINDOW (l->data); - const char *window_uri = ev_window_get_uri (window); + argv[arg++] = (gchar *)uri; + argv[arg] = NULL; - if (window_uri && strcmp (window_uri, uri) == 0 && !ev_window_is_empty (window)) { - uri_window = window; - break; - } - } + res = gdk_spawn_on_screen (screen, NULL /* wd */, argv, NULL /* env */, + 0, NULL, NULL, NULL, &error); + if (!res) { + g_warning ("Error launching evince %s: %s\n", uri, error->message); + g_error_free (error); } - g_list_free (windows); - - return uri_window; + for (i = 0; i < arg - 1; i++) { + g_free (argv[i]); + } } #ifdef ENABLE_DBUS @@ -635,28 +545,19 @@ ev_application_unregister_uri (EvApplication *application, g_object_unref (proxy); } - -static void -ev_application_window_destroyed (EvApplication *application, - EvWindow *ev_window) -{ - gchar *uri = g_hash_table_lookup (application->windows, ev_window); - - ev_application_unregister_uri (application, uri); - g_hash_table_remove (application->windows, ev_window); -} #endif /* ENABLE_DBUS */ static void ev_application_open_uri_in_window (EvApplication *application, const char *uri, - EvWindow *ev_window, GdkScreen *screen, EvLinkDest *dest, EvWindowRunMode mode, const gchar *search_string, guint timestamp) { + EvWindow *ev_window = application->window; + if (screen) { ev_stock_icons_set_screen (screen); gtk_window_set_screen (GTK_WINDOW (ev_window), screen); @@ -666,16 +567,6 @@ ev_application_open_uri_in_window (EvApplication *application, we can restore window size without flickering */ ev_window_open_uri (ev_window, uri, dest, mode, search_string); -#ifdef ENABLE_DBUS - if (application->windows != NULL && - !g_hash_table_lookup (application->windows, ev_window)) { - g_hash_table_insert (application->windows, ev_window, g_strdup (uri)); - g_signal_connect_swapped (ev_window, "destroy", - G_CALLBACK (ev_application_window_destroyed), - application); - } -#endif - if (!GTK_WIDGET_REALIZED (GTK_WIDGET (ev_window))) gtk_widget_realize (GTK_WIDGET (ev_window)); @@ -712,13 +603,16 @@ ev_application_open_uri_at_dest (EvApplication *application, const gchar *search_string, guint timestamp) { - EvWindow *ev_window; - g_return_if_fail (uri != NULL); - ev_window = ev_application_get_uri_window (application, uri); + if (application->window && !ev_window_is_empty (application->window)) { + if (application->uri && strcmp (application->uri, uri) != 0) { + /* spawn a new evince process */ + ev_spawn (uri, screen, dest, mode, search_string); + return; + } + } else { #ifdef ENABLE_DBUS - if (!ev_window) { GHashTable *args = build_args (screen, dest, mode, search_string); gboolean ret; @@ -729,23 +623,56 @@ ev_application_open_uri_at_dest (EvApplication *application, g_hash_table_destroy (args); if (!ret) return; - } #endif /* ENABLE_DBUS */ - if (ev_window == NULL) { - ev_window = ev_application_get_empty_window (application, screen); + if (!application->window) + application->window = EV_WINDOW (ev_window_new ()); } - if (ev_window == NULL) { - ev_window = EV_WINDOW (ev_window_new ()); - } + application->uri = g_strdup (uri); - ev_application_open_uri_in_window (application, uri, ev_window, - screen, dest, mode, search_string, + ev_application_open_uri_in_window (application, uri, + screen, dest, mode, + search_string, timestamp); } /** + * ev_application_open_window: + * @application: The instance of the application. + * @timestamp: Current time value. + * + * Creates a new window + */ +void +ev_application_open_window (EvApplication *application, + GdkScreen *screen, + guint32 timestamp) +{ + GtkWidget *new_window = ev_window_new (); + + application->window = EV_WINDOW (new_window); + + if (screen) { + ev_stock_icons_set_screen (screen); + gtk_window_set_screen (GTK_WINDOW (new_window), screen); + } + + if (!GTK_WIDGET_REALIZED (new_window)) + gtk_widget_realize (new_window); + +#ifdef GDK_WINDOWING_X11 + if (timestamp <= 0) + timestamp = gdk_x11_get_server_time (new_window->window); + gdk_x11_window_set_user_time (new_window->window, timestamp); + + gtk_window_present (GTK_WINDOW (new_window)); +#else + gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp); +#endif /* GDK_WINDOWING_X11 */ +} + +/** * ev_application_open_uri: * @application: The instance of the application. * @uri: The uri to be opened @@ -760,14 +687,22 @@ ev_application_open_uri (EvApplication *application, guint timestamp, GError **error) { - EvWindow *ev_window; EvLinkDest *dest = NULL; EvWindowRunMode mode = EV_WINDOW_MODE_NORMAL; const gchar *search_string = NULL; GdkScreen *screen = NULL; - ev_window = ev_application_get_uri_window (application, uri); - g_assert (ev_window != NULL); + g_assert (application->window != NULL); + + /* FIXME: we don't need uri anymore, + * maybe this method should be renamed + * as reload, refresh or something like that + */ + if (!application->uri || strcmp (application->uri, uri)) { + g_warning ("Invalid uri: %s, expected %s\n", + uri, application->uri); + return TRUE; + } if (args) { screen = get_screen_from_args (args); @@ -776,8 +711,9 @@ ev_application_open_uri (EvApplication *application, search_string = get_find_string_from_args (args); } - ev_application_open_uri_in_window (application, uri, ev_window, - screen, dest, mode, search_string, + ev_application_open_uri_in_window (application, uri, + screen, dest, mode, + search_string, timestamp); if (dest) @@ -804,12 +740,14 @@ ev_application_open_uri_list (EvApplication *application, void ev_application_shutdown (EvApplication *application) { + if (application->uri) { #ifdef ENABLE_DBUS - if (application->windows) { - g_hash_table_destroy (application->windows); - application->windows = NULL; - } + ev_application_unregister_uri (application, + application->uri); #endif + g_free (application->uri); + application->uri = NULL; + } if (application->accel_map_file) { gtk_accel_map_save (application->accel_map_file); @@ -955,10 +893,6 @@ ev_application_init (EvApplication *ev_application) dbus_g_connection_register_g_object (ev_application->connection, APPLICATION_DBUS_OBJECT_PATH, G_OBJECT (ev_application)); - ev_application->windows = g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify)g_free); ev_application->scr_saver = totem_scrsaver_new (ev_application->connection); } else { g_warning ("Error connection to DBus: %s\n", error->message); @@ -968,31 +902,16 @@ ev_application_init (EvApplication *ev_application) #endif /* ENABLE_DBUS */ } -/** - * ev_application_get_windows: - * @application: The instance of the application. - * - * It creates a list of the top level windows. - * - * Returns: A #GList of the top level windows. - */ -GList * -ev_application_get_windows (EvApplication *application) +gboolean +ev_application_has_window (EvApplication *application) { - GList *l, *toplevels; - GList *windows = NULL; - - toplevels = gtk_window_list_toplevels (); - - for (l = toplevels; l != NULL; l = l->next) { - if (EV_IS_WINDOW (l->data)) { - windows = g_list_append (windows, l->data); - } - } - - g_list_free (toplevels); + return application->window != NULL; +} - return windows; +const gchar * +ev_application_get_uri (EvApplication *application) +{ + return application->uri; } /** diff --git a/shell/ev-application.h b/shell/ev-application.h index 20a60bb..b012514 100644 --- a/shell/ev-application.h +++ b/shell/ev-application.h @@ -50,11 +50,9 @@ typedef struct _EvApplicationClass EvApplicationClass; GType ev_application_get_type (void) G_GNUC_CONST; EvApplication *ev_application_get_instance (void); -gboolean ev_application_register_service (EvApplication *application); -void ev_application_shutdown (EvApplication *application); -gboolean ev_application_load_session (EvApplication *application, - const gchar **files); +void ev_application_shutdown (EvApplication *application); +gboolean ev_application_load_session (EvApplication *application); void ev_application_open_window (EvApplication *application, GdkScreen *screen, guint32 timestamp); @@ -69,7 +67,8 @@ void ev_application_open_uri_list (EvApplication *application, GSList *uri_list, GdkScreen *screen, guint32 timestamp); -GList *ev_application_get_windows (EvApplication *application); +gboolean ev_application_has_window (EvApplication *application); +const gchar * ev_application_get_uri (EvApplication *application); GObject *ev_application_get_media_keys (EvApplication *application); EggToolbarsModel *ev_application_get_toolbars_model (EvApplication *application); diff --git a/shell/ev-window.c b/shell/ev-window.c index b4133ad..f4974e3 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -310,6 +310,8 @@ static void ev_window_media_player_key_pressed (EvWindow *windo gpointer user_data); static void ev_window_save_print_page_setup (EvWindow *window); +static guint ev_window_n_copies = 0; + G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW) static void @@ -2129,6 +2131,8 @@ ev_window_open_copy_at_dest (EvWindow *window, { EvWindow *new_window = EV_WINDOW (ev_window_new ()); + ev_window_n_copies++; + if (window->priv->metadata) new_window->priv->metadata = g_object_ref (window->priv->metadata); ev_window_open_document (new_window, @@ -4549,14 +4553,12 @@ ev_window_drag_data_received (GtkWidget *widget, static void ev_window_finalize (GObject *object) { - GList *windows = ev_application_get_windows (EV_APP); - - if (windows == NULL) { + if (ev_window_n_copies == 0) { ev_application_shutdown (EV_APP); } else { - g_list_free (windows); + ev_window_n_copies--; } - + G_OBJECT_CLASS (ev_window_parent_class)->finalize (object); } diff --git a/shell/main.c b/shell/main.c index 1de87f6..23872ed 100644 --- a/shell/main.c +++ b/shell/main.c @@ -141,29 +141,17 @@ launch_previewer (void) return retval; } -static gint -find_window_list (EvWindow *window, - const gchar *uri) -{ - return g_ascii_strcasecmp (uri, ev_window_get_uri (window)); -} - static void load_files (const char **files) { GdkScreen *screen = gdk_screen_get_default (); EvWindowRunMode mode = EV_WINDOW_MODE_NORMAL; - GList *windows; gint i; EvLinkDest *global_dest = NULL; - windows = ev_application_get_windows (EV_APP); - if (!files) { - if (!windows) + if (!ev_application_has_window (EV_APP)) ev_application_open_window (EV_APP, screen, GDK_CURRENT_TIME); - else - g_list_free (windows); return; } @@ -176,16 +164,18 @@ load_files (const char **files) mode = EV_WINDOW_MODE_PRESENTATION; for (i = 0; files[i]; i++) { - gchar *uri; - gchar *label; - GFile *file; - EvLinkDest *dest = NULL; + gchar *uri; + gchar *label; + GFile *file; + EvLinkDest *dest = NULL; + const gchar *app_uri; file = g_file_new_for_commandline_arg (files[i]); uri = g_file_get_uri (file); g_object_unref (file); - if (g_list_find_custom (windows, uri, (GCompareFunc) find_window_list)) { + app_uri = ev_application_get_uri (EV_APP); + if (app_uri && strcmp (app_uri, uri) == 0) { g_free (uri); continue; } @@ -207,16 +197,13 @@ load_files (const char **files) g_object_unref (dest); g_free (uri); } - - g_list_free (windows); } int main (int argc, char *argv[]) { GOptionContext *context; - GList *toplevels; - GError *error = NULL; + GError *error = NULL; #ifdef G_OS_WIN32 @@ -265,10 +252,10 @@ main (int argc, char *argv[]) g_option_context_add_group (context, gtk_get_option_group (TRUE)); if (!g_option_context_parse (context, &argc, &argv, &error)) { - g_printerr ("Cannot parse arguments: %s", error->message); + g_printerr ("Cannot parse arguments: %s\n", error->message); g_error_free (error); g_option_context_free (context); - + return 1; } g_option_context_free (context); @@ -294,11 +281,9 @@ main (int argc, char *argv[]) gtk_window_set_default_icon_name ("evince"); #endif /* WITH_SMCLIENT && GDK_WINDOWING_X11 */ - ev_application_load_session (EV_APP, file_arguments); + ev_application_load_session (EV_APP); load_files (file_arguments); - toplevels = gtk_window_list_toplevels (); - if (toplevels) { - g_list_free (toplevels); + if (ev_application_has_window (EV_APP)) { /* Change directory so we don't prevent unmounting in case the initial cwd * is on an external device (see bug #575436) */ -- cgit v0.9.1