X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=shell%2Fev-window.c;h=e6b0903f1adea9c8baec2653958490c0bd54f6e8;hb=d7b96b2211ecffd77d9318e1971191f4c4020b47;hp=6849b2406795fc206dafc6323f2a56a1caa35ba3;hpb=7042909ab901b54e952410572b3d724e49094158;p=evince.git diff --git a/shell/ev-window.c b/shell/ev-window.c index 6849b240..e6b0903f 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -28,67 +28,69 @@ #include "config.h" #endif -#include "ev-window.h" -#include "ev-window-title.h" -#include "ev-navigation-action.h" -#include "ev-page-action.h" -#include "ev-open-recent-action.h" -#include "ev-sidebar.h" -#include "ev-sidebar-links.h" -#include "ev-sidebar-attachments.h" -#include "ev-sidebar-thumbnails.h" -#include "ev-view.h" -#include "ev-password.h" -#include "ev-password-view.h" -#include "ev-properties-dialog.h" -#include "ev-file-exporter.h" -#include "ev-document-thumbnails.h" -#include "ev-document-links.h" -#include "ev-document-fonts.h" -#include "ev-document-find.h" -#include "ev-document-images.h" -#include "ev-document-security.h" -#include "ev-document-factory.h" -#include "ev-job-queue.h" -#include "ev-jobs.h" -#include "ev-sidebar-page.h" -#include "eggfindbar.h" -#include "egg-toolbar-editor.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + #include "egg-editable-toolbar.h" +#include "egg-toolbar-editor.h" #include "egg-toolbars-model.h" -#include "ephy-zoom.h" + +#include "eggfindbar.h" + #include "ephy-zoom-action.h" +#include "ephy-zoom.h" + #include "ev-application.h" -#include "ev-stock-icons.h" -#include "ev-metadata-manager.h" +#include "ev-document-factory.h" +#include "ev-document-find.h" +#include "ev-document-fonts.h" +#include "ev-document-images.h" +#include "ev-document-links.h" +#include "ev-document-thumbnails.h" +#include "ev-file-exporter.h" #include "ev-file-helpers.h" -#include "ev-utils.h" +#include "ev-file-monitor.h" #include "ev-history.h" #include "ev-image.h" +#include "ev-job-scheduler.h" +#include "ev-jobs.h" #include "ev-message-area.h" +#include "ev-metadata-manager.h" #include "ev-mount-operation.h" -#include "ev-file-monitor.h" +#include "ev-navigation-action.h" +#include "ev-open-recent-action.h" +#include "ev-page-action.h" +#include "ev-password.h" +#include "ev-password-view.h" +#include "ev-properties-dialog.h" +#include "ev-sidebar-attachments.h" +#include "ev-sidebar.h" +#include "ev-sidebar-links.h" +#include "ev-sidebar-page.h" +#include "ev-sidebar-thumbnails.h" +#include "ev-stock-icons.h" +#include "ev-utils.h" +#include "ev-view.h" +#include "ev-window.h" +#include "ev-window-title.h" + #ifdef ENABLE_DBUS #include "ev-media-player-keys.h" #endif /* ENABLE_DBUS */ -#include - #ifdef ENABLE_PDF #include #endif -#include -#include -#include -#include -#include - -#include -#include -#include -#include - typedef enum { PAGE_MODE_DOCUMENT, PAGE_MODE_PASSWORD @@ -164,6 +166,7 @@ struct _EvWindowPrivate { gboolean unlink_temp_file; gboolean in_reload; EvFileMonitor *monitor; + guint setup_document_idle; EvDocument *document; EvHistory *history; @@ -176,6 +179,7 @@ struct _EvWindowPrivate { EvJob *thumbnail_job; EvJob *save_job; EvJob *print_job; + EvJob *find_job; /* Printing */ gboolean print_preview; @@ -221,16 +225,16 @@ static void ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_si EvWindow *ev_window); static void ev_window_set_page_mode (EvWindow *window, EvWindowPageMode page_mode); -static void ev_window_load_job_cb (EvJobLoad *job, +static void ev_window_load_job_cb (EvJob *job, gpointer data); static void ev_window_reload_document (EvWindow *window); -static void ev_window_reload_job_cb (EvJobLoad *job, +static void ev_window_reload_job_cb (EvJob *job, EvWindow *window); static void ev_window_set_icon_from_thumbnail (EvJobThumbnail *job, EvWindow *ev_window); -static void ev_window_print_job_cb (EvJobPrint *job, +static void ev_window_print_job_cb (EvJob *job, EvWindow *window); -static void ev_window_save_job_cb (EvJobSave *save, +static void ev_window_save_job_cb (EvJob *save, EvWindow *window); static void ev_window_sizing_mode_changed_cb (EvView *view, GParamSpec *pspec, @@ -272,6 +276,7 @@ static void ev_window_cmd_view_page_width (GtkAction *action, static void view_handle_link_cb (EvView *view, EvLink *link, EvWindow *window); +static void ev_window_update_find_status_message (EvWindow *ev_window); static void ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window); static void find_bar_search_changed_cb (EggFindBar *find_bar, @@ -280,6 +285,9 @@ static void find_bar_search_changed_cb (EggFindBar *find_ static void ev_window_do_preview_print (EvWindow *window); static void ev_window_load_file_remote (EvWindow *ev_window, GFile *source_file); +static void ev_window_media_player_key_pressed (EvWindow *window, + const gchar *key, + gpointer user_data); G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW) @@ -393,6 +401,7 @@ ev_window_update_actions (EvWindow *ev_window) int n_pages = 0, page = -1; gboolean has_pages = FALSE; gboolean presentation_mode; + gboolean can_find_in_page = FALSE; if (ev_window->priv->document && ev_window->priv->page_cache) { page = ev_page_cache_get_current_page (ev_window->priv->page_cache); @@ -400,13 +409,16 @@ ev_window_update_actions (EvWindow *ev_window) has_pages = n_pages > 0; } + can_find_in_page = (ev_window->priv->find_job && + ev_job_find_has_results (EV_JOB_FIND (ev_window->priv->find_job))); + ev_window_set_action_sensitive (ev_window, "EditCopy", has_pages && ev_view_get_has_selection (view)); ev_window_set_action_sensitive (ev_window, "EditFindNext", - ev_view_can_find_next (view)); + has_pages && can_find_in_page); ev_window_set_action_sensitive (ev_window, "EditFindPrevious", - ev_view_can_find_previous (view)); + has_pages && can_find_in_page); presentation_mode = ev_view_get_presentation (view); @@ -684,19 +696,15 @@ ev_window_warning_message (GtkWindow *window, const gchar *msg) ev_window_set_message_area (EV_WINDOW (window), area); } -static void -find_changed_cb (EvDocument *document, int page, EvWindow *ev_window) -{ - ev_window_update_actions (ev_window); -} - static void page_changed_cb (EvPageCache *page_cache, gint page, EvWindow *ev_window) { ev_window_update_actions (ev_window); - + + ev_window_update_find_status_message (ev_window); + if (!ev_window_is_empty (ev_window)) ev_metadata_manager_set_int (ev_window->priv->uri, "page", page); } @@ -1080,8 +1088,9 @@ static void ev_window_clear_thumbnail_job (EvWindow *ev_window) { if (ev_window->priv->thumbnail_job != NULL) { - ev_job_queue_remove_job (ev_window->priv->thumbnail_job); - + if (!ev_job_is_finished (ev_window->priv->thumbnail_job)) + ev_job_cancel (ev_window->priv->thumbnail_job); + g_signal_handlers_disconnect_by_func (ev_window->priv->thumbnail_job, ev_window_set_icon_from_thumbnail, ev_window); @@ -1125,7 +1134,7 @@ ev_window_refresh_window_thumbnail (EvWindow *ev_window, int rotation) g_signal_connect (ev_window->priv->thumbnail_job, "finished", G_CALLBACK (ev_window_set_icon_from_thumbnail), ev_window); - ev_job_queue_add_job (EV_JOB (ev_window->priv->thumbnail_job), EV_JOB_PRIORITY_LOW); + ev_job_scheduler_push_job (ev_window->priv->thumbnail_job, EV_JOB_PRIORITY_NONE); } static gboolean @@ -1135,13 +1144,8 @@ ev_window_setup_document (EvWindow *ev_window) EvDocument *document = ev_window->priv->document; EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar); GtkAction *action; - - if (EV_IS_DOCUMENT_FIND (document)) { - g_signal_connect_object (G_OBJECT (document), - "find_changed", - G_CALLBACK (find_changed_cb), - ev_window, 0); - } + + ev_window->priv->setup_document_idle = 0; ev_window_refresh_window_thumbnail (ev_window, 0); @@ -1200,7 +1204,9 @@ ev_window_set_document (EvWindow *ev_window, EvDocument *document) _("The document contains no pages")); } - g_idle_add ((GSourceFunc)ev_window_setup_document, ev_window); + if (ev_window->priv->setup_document_idle > 0) + g_source_remove (ev_window->priv->setup_document_idle); + ev_window->priv->setup_document_idle = g_idle_add ((GSourceFunc)ev_window_setup_document, ev_window); } static void @@ -1215,23 +1221,14 @@ password_dialog_response (GtkWidget *password_dialog, gint response_id, EvWindow *ev_window) { - char *password; - if (response_id == GTK_RESPONSE_OK) { - - password = ev_password_dialog_get_password (EV_PASSWORD_DIALOG (password_dialog)); - if (password) { - ev_document_doc_mutex_lock (); - ev_document_security_set_password (EV_DOCUMENT_SECURITY (ev_window->priv->load_job->document), - password); - ev_document_doc_mutex_unlock (); - } - g_free (password); + ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job), + ev_password_dialog_get_password (EV_PASSWORD_DIALOG (password_dialog))); ev_password_dialog_save_password (EV_PASSWORD_DIALOG (password_dialog)); ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_DOCUMENT); - ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH); + ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE); gtk_widget_destroy (password_dialog); @@ -1277,9 +1274,8 @@ static void ev_window_clear_load_job (EvWindow *ev_window) { if (ev_window->priv->load_job != NULL) { - - if (!ev_window->priv->load_job->finished) - ev_job_queue_remove_job (ev_window->priv->load_job); + if (!ev_job_is_finished (ev_window->priv->load_job)) + ev_job_cancel (ev_window->priv->load_job); g_signal_handlers_disconnect_by_func (ev_window->priv->load_job, ev_window_load_job_cb, ev_window); g_object_unref (ev_window->priv->load_job); @@ -1291,9 +1287,8 @@ static void ev_window_clear_reload_job (EvWindow *ev_window) { if (ev_window->priv->reload_job != NULL) { - - if (!ev_window->priv->reload_job->finished) - ev_job_queue_remove_job (ev_window->priv->reload_job); + if (!ev_job_is_finished (ev_window->priv->reload_job)) + ev_job_cancel (ev_window->priv->reload_job); g_signal_handlers_disconnect_by_func (ev_window->priv->reload_job, ev_window_reload_job_cb, ev_window); g_object_unref (ev_window->priv->reload_job); @@ -1349,21 +1344,22 @@ ev_window_clear_temp_file (EvWindow *ev_window) * function should _not_ necessarily expect those to exist after being * called. */ static void -ev_window_load_job_cb (EvJobLoad *job, - gpointer data) +ev_window_load_job_cb (EvJob *job, + gpointer data) { EvWindow *ev_window = EV_WINDOW (data); EvDocument *document = EV_JOB (job)->document; + EvJobLoad *job_load = EV_JOB_LOAD (job); - g_assert (job->uri); + g_assert (job_load->uri); ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE); /* Success! */ - if (job->error == NULL) { + if (!ev_job_is_failed (job)) { ev_window_set_document (ev_window, document); - if (job->mode != EV_WINDOW_MODE_PREVIEW) { + if (job_load->mode != EV_WINDOW_MODE_PREVIEW) { setup_view_from_metadata (ev_window); } @@ -1371,17 +1367,17 @@ ev_window_load_job_cb (EvJobLoad *job, ev_window_add_recent (ev_window, ev_window->priv->uri); } - if (job->dest) { + if (job_load->dest) { EvLink *link; EvLinkAction *link_action; - link_action = ev_link_action_new_dest (g_object_ref (job->dest)); + link_action = ev_link_action_new_dest (g_object_ref (job_load->dest)); link = ev_link_new (NULL, link_action); ev_view_handle_link (EV_VIEW (ev_window->priv->view), link); g_object_unref (link); } - switch (job->mode) { + switch (job_load->mode) { case EV_WINDOW_MODE_FULLSCREEN: ev_window_run_fullscreen (ev_window); break; @@ -1395,14 +1391,14 @@ ev_window_load_job_cb (EvJobLoad *job, break; } - if (job->search_string && EV_IS_DOCUMENT_FIND (document)) { + if (job_load->search_string && EV_IS_DOCUMENT_FIND (document)) { ev_window_cmd_edit_find (NULL, ev_window); egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar), - job->search_string); + job_load->search_string); } /* Create a monitor for the document */ - ev_window->priv->monitor = ev_file_monitor_new (job->uri); + ev_window->priv->monitor = ev_file_monitor_new (job_load->uri); g_signal_connect_swapped (G_OBJECT (ev_window->priv->monitor), "changed", G_CALLBACK (ev_window_document_changed), ev_window); @@ -1418,7 +1414,7 @@ ev_window_load_job_cb (EvJobLoad *job, setup_view_from_metadata (ev_window); - file = g_file_new_for_uri (job->uri); + file = g_file_new_for_uri (job_load->uri); base_name = g_file_get_basename (file); ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view), base_name); @@ -1436,18 +1432,18 @@ ev_window_load_job_cb (EvJobLoad *job, } static void -ev_window_reload_job_cb (EvJobLoad *job, - EvWindow *ev_window) +ev_window_reload_job_cb (EvJob *job, + EvWindow *ev_window) { GtkWidget *widget; - - if (job->error) { + + if (ev_job_is_failed (job)) { ev_window_clear_reload_job (ev_window); ev_window->priv->in_reload = FALSE; return; } - - ev_window_set_document (ev_window, EV_JOB (job)->document); + + ev_window_set_document (ev_window, job->document); /* Restart the search after reloading */ widget = gtk_window_get_focus (GTK_WINDOW (ev_window)); @@ -1455,7 +1451,7 @@ ev_window_reload_job_cb (EvJobLoad *job, find_bar_search_changed_cb (EGG_FIND_BAR (ev_window->priv->find_bar), NULL, ev_window); } - + ev_window_clear_reload_job (ev_window); ev_window->priv->in_reload = FALSE; } @@ -1539,7 +1535,7 @@ window_open_file_copy_ready_cb (GFile *source, g_file_copy_finish (source, async_result, &error); if (!error) { - ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH); + ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE); g_object_unref (source); return; @@ -1649,7 +1645,7 @@ ev_window_open_uri (EvWindow *ev_window, ev_window_load_file_remote (ev_window, source_file); } else { g_object_unref (source_file); - ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH); + ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE); } } @@ -1666,7 +1662,7 @@ ev_window_reload_document (EvWindow *ev_window) g_signal_connect (ev_window->priv->reload_job, "finished", G_CALLBACK (ev_window_reload_job_cb), ev_window); - ev_job_queue_add_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_LOW); + ev_job_scheduler_push_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_NONE); } static void @@ -2067,8 +2063,8 @@ static void ev_window_clear_save_job (EvWindow *ev_window) { if (ev_window->priv->save_job != NULL) { - if (!ev_window->priv->save_job->finished) - ev_job_queue_remove_job (ev_window->priv->save_job); + if (!ev_job_is_finished (ev_window->priv->save_job)) + ev_job_cancel (ev_window->priv->save_job); g_signal_handlers_disconnect_by_func (ev_window->priv->save_job, ev_window_save_job_cb, @@ -2079,13 +2075,14 @@ ev_window_clear_save_job (EvWindow *ev_window) } static void -ev_window_save_job_cb (EvJobSave *job, +ev_window_save_job_cb (EvJob *job, EvWindow *window) { - if (job->error) { + if (ev_job_is_failed (job)) { gchar *msg; - msg = g_strdup_printf (_("The file could not be saved as “%s”."), job->uri); + msg = g_strdup_printf (_("The file could not be saved as “%s”."), + EV_JOB_SAVE (job)->uri); ev_window_error_message (GTK_WINDOW (window), msg, job->error); g_free (msg); } @@ -2114,10 +2111,9 @@ file_save_dialog_response_cb (GtkWidget *fc, G_CALLBACK (ev_window_save_job_cb), ev_window); /* The priority doesn't matter for this job */ - ev_job_queue_add_job (ev_window->priv->save_job, EV_JOB_PRIORITY_LOW); + ev_job_scheduler_push_job (ev_window->priv->save_job, EV_JOB_PRIORITY_NONE); g_free (uri); - gtk_widget_destroy (fc); } @@ -2187,8 +2183,8 @@ static void ev_window_clear_print_job (EvWindow *window) { if (window->priv->print_job) { - if (!window->priv->print_job->finished) - ev_job_queue_remove_job (window->priv->print_job); + if (!ev_job_is_finished (window->priv->print_job)) + ev_job_cancel (window->priv->print_job); g_signal_handlers_disconnect_by_func (window->priv->print_job, ev_window_print_job_cb, @@ -2349,18 +2345,18 @@ ev_window_print_send (EvWindow *window, } static void -ev_window_print_job_cb (EvJobPrint *job, - EvWindow *window) +ev_window_print_job_cb (EvJob *job, + EvWindow *window) { - if (job->error) { + if (ev_job_is_failed (job)) { g_warning ("%s", job->error->message); ev_window_clear_print_job (window); return; } - g_assert (job->temp_file != NULL); + g_assert (EV_JOB_PRINT (job)->temp_file != NULL); - ev_window_print_send (window, job->temp_file); + ev_window_print_send (window, EV_JOB_PRINT (job)->temp_file); } static gboolean @@ -2494,7 +2490,7 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog, G_CALLBACK (ev_window_print_job_cb), window); /* The priority doesn't matter for this job */ - ev_job_queue_add_job (window->priv->print_job, EV_JOB_PRIORITY_LOW); + ev_job_scheduler_push_job (window->priv->print_job, EV_JOB_PRIORITY_NONE); gtk_widget_destroy (GTK_WIDGET (dialog)); window->priv->print_dialog = NULL; @@ -2628,13 +2624,13 @@ ev_window_cmd_focus_page_selector (GtkAction *act, EvWindow *window) static void ev_window_cmd_scroll_forward (GtkAction *action, EvWindow *window) { - ev_view_scroll (EV_VIEW (window->priv->view), EV_SCROLL_PAGE_FORWARD, FALSE); + ev_view_scroll (EV_VIEW (window->priv->view), GTK_SCROLL_PAGE_FORWARD, FALSE); } static void ev_window_cmd_scroll_backward (GtkAction *action, EvWindow *window) { - ev_view_scroll (EV_VIEW (window->priv->view), EV_SCROLL_PAGE_BACKWARD, FALSE); + ev_view_scroll (EV_VIEW (window->priv->view), GTK_SCROLL_PAGE_BACKWARD, FALSE); } static void @@ -3118,6 +3114,35 @@ ev_window_screen_changed (GtkWidget *widget, } } +static gboolean +ev_window_state_event (GtkWidget *widget, + GdkEventWindowState *event) +{ + EvWindow *window = EV_WINDOW (widget); + EvView *view = EV_VIEW (window->priv->view); + + if (GTK_WIDGET_CLASS (ev_window_parent_class)->window_state_event) { + GTK_WIDGET_CLASS (ev_window_parent_class)->window_state_event (widget, event); + } + + if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) == 0) + return FALSE; + + if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) { + if (ev_view_get_fullscreen (view) || ev_view_get_presentation (view)) + return FALSE; + + ev_window_run_fullscreen (window); + } else { + if (ev_view_get_fullscreen (view)) + ev_window_stop_fullscreen (window, FALSE); + else if (ev_view_get_presentation (view)) + ev_window_stop_presentation (window, FALSE); + } + + return FALSE; +} + static void ev_window_set_page_mode (EvWindow *window, EvWindowPageMode page_mode) @@ -3234,12 +3259,6 @@ ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window) ev_view_previous_page (EV_VIEW (ev_window->priv->view)); } -void -ev_window_go_previous_page (EvWindow *ev_window) -{ - ev_window_cmd_go_previous_page (NULL, ev_window); -} - static void ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window) { @@ -3248,12 +3267,6 @@ ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window) ev_view_next_page (EV_VIEW (ev_window->priv->view)); } -void -ev_window_go_next_page (EvWindow *ev_window) -{ - ev_window_cmd_go_next_page (NULL, ev_window); -} - static void ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window) { @@ -3262,12 +3275,6 @@ ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window) ev_page_cache_set_current_page (ev_window->priv->page_cache, 0); } -void -ev_window_go_first_page (EvWindow *ev_window) -{ - ev_window_cmd_go_first_page (NULL, ev_window); -} - static void ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window) { @@ -3279,12 +3286,6 @@ ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window) ev_page_cache_set_current_page (ev_window->priv->page_cache, n_pages - 1); } -void -ev_window_go_last_page (EvWindow *ev_window) -{ - ev_window_cmd_go_last_page (NULL, ev_window); -} - static void ev_window_cmd_go_forward (GtkAction *action, EvWindow *ev_window) { @@ -3385,12 +3386,6 @@ ev_window_cmd_start_presentation (GtkAction *action, EvWindow *window) ev_window_run_presentation (window); } -void -ev_window_start_presentation (EvWindow *ev_window) -{ - ev_window_run_presentation (ev_window); -} - static gboolean ev_window_enumerate_printer_cb (GtkPrinter *printer, EvWindow *window) @@ -3992,15 +3987,73 @@ attachment_bar_menu_popup_cb (EvSidebarAttachments *attachbar, } static void -view_find_status_changed_cb (EvView *view, - GParamSpec *pspec, - EvWindow *ev_window) +ev_window_update_find_status_message (EvWindow *ev_window) +{ + gchar *message; + + if (!ev_window->priv->find_job) + return; + + if (ev_job_is_finished (ev_window->priv->find_job)) { + gint n_results; + + n_results = ev_job_find_get_n_results (EV_JOB_FIND (ev_window->priv->find_job), + ev_page_cache_get_current_page (ev_window->priv->page_cache)); + /* TRANS: Sometimes this could be better translated as + "%d hit(s) on this page". Therefore this string + contains plural cases. */ + message = g_strdup_printf (ngettext ("%d found on this page", + "%d found on this page", + n_results), + n_results); + } else { + gdouble percent; + + percent = ev_job_find_get_progress (EV_JOB_FIND (ev_window->priv->find_job)); + message = g_strdup_printf (_("%3d%% remaining to search"), + (gint) ((1.0 - percent) * 100)); + } + + egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), message); + g_free (message); +} + +static void +ev_window_find_job_finished_cb (EvJobFind *job, + EvWindow *ev_window) { - const char *text; + ev_window_update_find_status_message (ev_window); +} - text = ev_view_get_find_status (view); - egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), - text); +static void +ev_window_find_job_updated_cb (EvJobFind *job, + gint page, + EvWindow *ev_window) +{ + ev_window_update_actions (ev_window); + + ev_view_find_changed (EV_VIEW (ev_window->priv->view), + ev_job_find_get_results (job), + page); + ev_window_update_find_status_message (ev_window); +} + +static void +ev_window_clear_find_job (EvWindow *ev_window) +{ + if (ev_window->priv->find_job != NULL) { + if (!ev_job_is_finished (ev_window->priv->find_job)) + ev_job_cancel (ev_window->priv->find_job); + + g_signal_handlers_disconnect_by_func (ev_window->priv->find_job, + ev_window_find_job_finished_cb, + ev_window); + g_signal_handlers_disconnect_by_func (ev_window->priv->find_job, + ev_window_find_job_updated_cb, + ev_window); + g_object_unref (ev_window->priv->find_job); + ev_window->priv->find_job = NULL; + } } static void @@ -4022,6 +4075,7 @@ find_bar_close_cb (EggFindBar *find_bar, EvWindow *ev_window) { ev_view_find_cancel (EV_VIEW (ev_window->priv->view)); + ev_window_clear_find_job (ev_window); update_chrome_flag (ev_window, EV_CHROME_FINDBAR, FALSE); update_chrome_visibility (ev_window); } @@ -4034,39 +4088,42 @@ find_bar_search_changed_cb (EggFindBar *find_bar, gboolean case_sensitive; const char *search_string; + if (!ev_window->priv->document || !EV_IS_DOCUMENT_FIND (ev_window->priv->document)) + return; + /* Either the string or case sensitivity could have changed. */ - case_sensitive = egg_find_bar_get_case_sensitive (find_bar); search_string = egg_find_bar_get_search_string (find_bar); - ev_view_search_changed (EV_VIEW(ev_window->priv->view)); + ev_view_find_search_changed (EV_VIEW (ev_window->priv->view)); - if (ev_window->priv->document && - EV_IS_DOCUMENT_FIND (ev_window->priv->document)) { - if (search_string && search_string[0]) { - ev_document_doc_mutex_lock (); - ev_document_find_begin (EV_DOCUMENT_FIND (ev_window->priv->document), - ev_page_cache_get_current_page (ev_window->priv->page_cache), - search_string, - case_sensitive); - ev_document_doc_mutex_unlock (); - } else { - ev_document_doc_mutex_lock (); - ev_document_find_cancel (EV_DOCUMENT_FIND (ev_window->priv->document)); - ev_document_doc_mutex_unlock (); - - ev_window_update_actions (ev_window); - egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), - NULL); - gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view)); - } + ev_window_clear_find_job (ev_window); + + if (search_string && search_string[0]) { + ev_window->priv->find_job = ev_job_find_new (ev_window->priv->document, + ev_page_cache_get_current_page (ev_window->priv->page_cache), + ev_page_cache_get_n_pages (ev_window->priv->page_cache), + search_string, + case_sensitive); + g_signal_connect (ev_window->priv->find_job, "finished", + G_CALLBACK (ev_window_find_job_finished_cb), + ev_window); + g_signal_connect (ev_window->priv->find_job, "updated", + G_CALLBACK (ev_window_find_job_updated_cb), + ev_window); + ev_job_scheduler_push_job (ev_window->priv->find_job, EV_JOB_PRIORITY_NONE); + } else { + ev_window_update_actions (ev_window); + egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), + NULL); + gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view)); } } static void find_bar_visibility_changed_cb (EggFindBar *find_bar, - GParamSpec *param, - EvWindow *ev_window) + GParamSpec *param, + EvWindow *ev_window) { gboolean visible; @@ -4074,19 +4131,23 @@ find_bar_visibility_changed_cb (EggFindBar *find_bar, if (ev_window->priv->document && EV_IS_DOCUMENT_FIND (ev_window->priv->document)) { - ev_view_set_highlight_search (EV_VIEW(ev_window->priv->view), visible); - ev_view_search_changed (EV_VIEW(ev_window->priv->view)); + ev_view_find_set_highlight_search (EV_VIEW (ev_window->priv->view), visible); + ev_view_find_search_changed (EV_VIEW (ev_window->priv->view)); ev_window_update_actions (ev_window); - if (!visible) + if (visible) + find_bar_search_changed_cb (find_bar, NULL, ev_window); + else egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), NULL); } } static void -find_bar_scroll(EggFindBar *find_bar, GtkScrollType scroll, EvWindow* ev_window) +find_bar_scroll (EggFindBar *find_bar, + GtkScrollType scroll, + EvWindow *ev_window) { - ev_view_scroll(EV_VIEW(ev_window->priv->view), scroll, FALSE); + ev_view_scroll (EV_VIEW (ev_window->priv->view), scroll, FALSE); } static void @@ -4134,16 +4195,19 @@ ev_window_dispose (GObject *object) { EvWindow *window = EV_WINDOW (object); EvWindowPrivate *priv = window->priv; -#ifdef ENABLE_DBUS - GObject *keys; + GObject *mpkeys = ev_application_get_media_keys (EV_APP); - keys = ev_application_get_media_keys (EV_APP); - if (keys) { - ev_media_player_keys_focused (EV_MEDIA_PLAYER_KEYS (keys), NULL); - g_object_unref (keys); + if (mpkeys) { + g_signal_handlers_disconnect_by_func (mpkeys, + ev_window_media_player_key_pressed, + window); } -#endif /* ENABLE_DBUS */ - + + if (priv->setup_document_idle > 0) { + g_source_remove (priv->setup_document_idle); + priv->setup_document_idle = 0; + } + if (priv->monitor) { g_object_unref (priv->monitor); priv->monitor = NULL; @@ -4223,12 +4287,16 @@ ev_window_dispose (GObject *object) if (priv->thumbnail_job) { ev_window_clear_thumbnail_job (window); } + + if (priv->find_job) { + ev_window_clear_find_job (window); + } if (priv->local_uri) { ev_window_clear_local_uri (window); priv->local_uri = NULL; } - + ev_window_close_dialogs (window); ev_window_clear_print_job (window); @@ -4318,6 +4386,7 @@ ev_window_class_init (EvWindowClass *ev_window_class) g_object_class->finalize = ev_window_finalize; widget_class->screen_changed = ev_window_screen_changed; + widget_class->window_state_event = ev_window_state_event; g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate)); } @@ -4365,9 +4434,9 @@ static const GtkActionEntry entries[] = { G_CALLBACK (ev_window_cmd_edit_find_previous) }, { "EditToolbar", NULL, N_("T_oolbar"), NULL, NULL, G_CALLBACK (ev_window_cmd_edit_toolbar) }, - { "EditRotateLeft", EV_STOCK_ROTATE_LEFT, N_("Rotate _Left"), NULL, NULL, + { "EditRotateLeft", EV_STOCK_ROTATE_LEFT, N_("Rotate _Left"), "Left", NULL, G_CALLBACK (ev_window_cmd_edit_rotate_left) }, - { "EditRotateRight", EV_STOCK_ROTATE_RIGHT, N_("Rotate _Right"), NULL, NULL, + { "EditRotateRight", EV_STOCK_ROTATE_RIGHT, N_("Rotate _Right"), "Right", NULL, G_CALLBACK (ev_window_cmd_edit_rotate_right) }, /* View menu */ @@ -4670,10 +4739,7 @@ view_actions_focus_in_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *win GObject *keys; keys = ev_application_get_media_keys (EV_APP); - if (keys) { - ev_media_player_keys_focused (EV_MEDIA_PLAYER_KEYS (keys), window); - g_object_unref (keys); - } + ev_media_player_keys_focused (EV_MEDIA_PLAYER_KEYS (keys)); #endif /* ENABLE_DBUS */ update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, FALSE); @@ -4820,8 +4886,18 @@ launch_external_uri (EvWindow *window, EvLinkAction *action) const gchar *uri = ev_link_action_get_uri (action); GError *error = NULL; gboolean ret; + + if (!g_strstr_len (uri, strlen (uri), "://")) { + gchar *http; + + /* Not a valid uri, assuming it's http */ + http = g_strdup_printf ("http://%s", uri); + ret = g_app_info_launch_default_for_uri (http, NULL, &error); + g_free (http); + } else { + ret = g_app_info_launch_default_for_uri (uri, NULL, &error); + } - ret = g_app_info_launch_default_for_uri (uri, NULL, &error); if (ret == FALSE) { GtkWidget *dialog; @@ -4999,7 +5075,7 @@ image_save_dialog_response_cb (GtkWidget *fc, } extensions = gdk_pixbuf_format_get_extensions (format); - if (g_str_has_suffix(uri, extensions[0])) { + if (!g_str_has_suffix (uri, extensions[0])) { gchar *uri_extension; uri_extension = g_strconcat (uri, ".", extensions[0], NULL); @@ -5008,7 +5084,7 @@ image_save_dialog_response_cb (GtkWidget *fc, } else { target_file = g_file_new_for_uri (uri); } - g_strfreev(extensions); + g_strfreev (extensions); g_free (uri); is_native = g_file_is_native (target_file); @@ -5106,18 +5182,21 @@ ev_view_popup_cmd_copy_image (GtkAction *action, EvWindow *window) static void ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window) { - GList *l; + GList *l; + GdkScreen *screen; if (!window->priv->attach_list) return; + screen = gtk_window_get_screen (GTK_WINDOW (window)); + for (l = window->priv->attach_list; l && l->data; l = g_list_next (l)) { EvAttachment *attachment; GError *error = NULL; attachment = (EvAttachment *) l->data; - ev_attachment_open (attachment, &error); + ev_attachment_open (attachment, screen, GDK_CURRENT_TIME, &error); if (error) { ev_window_error_message (GTK_WINDOW (window), @@ -5241,6 +5320,35 @@ ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window) gtk_widget_show (fc); } +static void +ev_window_media_player_key_pressed (EvWindow *window, + const gchar *key, + gpointer user_data) +{ + if (!gtk_window_is_active (GTK_WINDOW (window))) + return; + + /* Note how Previous/Next only go to the + * next/previous page despite their icon telling you + * they should go to the beginning/end. + * + * There's very few keyboards with FFW/RWD though, + * so we stick the most useful keybinding on the most + * often seen keys + */ + if (strcmp (key, "Play") == 0) { + ev_window_run_presentation (window); + } else if (strcmp (key, "Previous") == 0) { + ev_window_cmd_go_previous_page (NULL, window); + } else if (strcmp (key, "Next") == 0) { + ev_window_cmd_go_next_page (NULL, window); + } else if (strcmp (key, "FastForward") == 0) { + ev_window_cmd_go_last_page (NULL, window); + } else if (strcmp (key, "Rewind") == 0) { + ev_window_cmd_go_first_page (NULL, window); + } +} + static void ev_window_init (EvWindow *ev_window) { @@ -5248,6 +5356,7 @@ ev_window_init (EvWindow *ev_window) GtkAccelGroup *accel_group; GError *error = NULL; GtkWidget *sidebar_widget; + GObject *mpkeys; g_signal_connect (ev_window, "configure_event", G_CALLBACK (window_configure_event_cb), NULL); @@ -5454,10 +5563,6 @@ ev_window_init (EvWindow *ev_window) gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window), ev_window->priv->view); - g_signal_connect (ev_window->priv->view, - "notify::find-status", - G_CALLBACK (view_find_status_changed_cb), - ev_window); g_signal_connect (ev_window->priv->view, "notify::sizing-mode", G_CALLBACK (ev_window_sizing_mode_changed_cb), @@ -5532,6 +5637,14 @@ ev_window_init (EvWindow *ev_window) "/AttachmentPopup"); ev_window->priv->attach_list = NULL; + /* Media player keys */ + mpkeys = ev_application_get_media_keys (EV_APP); + if (mpkeys) { + g_signal_connect_swapped (mpkeys, "key_pressed", + G_CALLBACK (ev_window_media_player_key_pressed), + ev_window); + } + /* Give focus to the document view */ gtk_widget_grab_focus (ev_window->priv->view);