X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=shell%2Fev-view.c;h=1685aee823eb8c8070111dcda836083913ed187e;hb=14def5e0c1c11cee1523e10c72df74f4cf5e451d;hp=0fd2834aeb6b03f89004eaf6d90259012be76709;hpb=1624d8ca4f26f53dcae3e2f122285d75fa003384;p=evince.git diff --git a/shell/ev-view.c b/shell/ev-view.c index 0fd2834a..1685aee8 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -18,44 +18,40 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include "config.h" + #include #include #include -#include + #include -#include -#include -#include +#include #include -#include "ev-marshal.h" -#include "ev-view.h" -#include "ev-view-private.h" -#include "ev-utils.h" -#include "ev-document-links.h" -#include "ev-document-images.h" -#include "ev-document-find.h" -#include "ev-document-transition.h" +#include "ev-application.h" #include "ev-document-forms.h" +#include "ev-document-images.h" +#include "ev-document-links.h" #include "ev-document-misc.h" -#include "ev-job-queue.h" +#include "ev-document-transition.h" +#include "ev-marshal.h" #include "ev-page-cache.h" #include "ev-pixbuf-cache.h" #include "ev-transition-animation.h" +#include "ev-utils.h" +#include "ev-view.h" +#include "ev-view-private.h" + #if !GTK_CHECK_VERSION (2, 11, 7) #include "ev-tooltip.h" #endif -#include "ev-application.h" #define EV_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass)) #define EV_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_VIEW)) #define EV_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_VIEW, EvViewClass)) - enum { PROP_0, - PROP_FIND_STATUS, PROP_CONTINUOUS, PROP_DUAL_PAGE, PROP_FULLSCREEN, @@ -128,7 +124,7 @@ static void set_scroll_adjustment (EvView static void add_scroll_binding_keypad (GtkBindingSet *binding_set, guint keyval, GdkModifierType modifiers, - EvScrollType scroll, + GtkScrollType scroll, gboolean horizontal); static void ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect); @@ -230,9 +226,6 @@ static void draw_loading_text (EvView *view, GdkRectangle *expose_area); /*** Callbacks ***/ -static void find_changed_cb (EvDocument *document, - int page, - EvView *view); static void job_finished_cb (EvPixbufCache *pixbuf_cache, GdkRegion *region, EvView *view); @@ -305,10 +298,11 @@ static void ev_view_handle_cursor_over_xy (EvView *view, gint y); /*** Find ***/ -static void update_find_status_message (EvView *view, - gboolean this_page); -static void ev_view_set_find_status (EvView *view, - const char *message); +static gint ev_view_find_get_n_results (EvView *view, + gint page); +static EvRectangle *ev_view_find_get_result (EvView *view, + gint page, + gint result); static void jump_to_find_result (EvView *view); static void jump_to_find_page (EvView *view, EvViewFindDirection direction, @@ -320,6 +314,7 @@ static void compute_selections (EvView GdkPoint *start, GdkPoint *stop); static void clear_selection (EvView *view); +static void clear_link_selected (EvView *view); static void selection_free (EvViewSelection *selection); static char* get_selected_text (EvView *ev_view); static void ev_view_primary_get_cb (GtkClipboard *clipboard, @@ -579,25 +574,25 @@ static void add_scroll_binding_keypad (GtkBindingSet *binding_set, guint keyval, GdkModifierType modifiers, - EvScrollType scroll, + GtkScrollType scroll, gboolean horizontal) { guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left; gtk_binding_entry_add_signal (binding_set, keyval, modifiers, "binding_activated", 2, - EV_TYPE_SCROLL_TYPE, scroll, + GTK_TYPE_SCROLL_TYPE, scroll, G_TYPE_BOOLEAN, horizontal); gtk_binding_entry_add_signal (binding_set, keypad_keyval, modifiers, "binding_activated", 2, - EV_TYPE_SCROLL_TYPE, scroll, + GTK_TYPE_SCROLL_TYPE, scroll, G_TYPE_BOOLEAN, horizontal); } void ev_view_scroll (EvView *view, - EvScrollType scroll, - gboolean horizontal) + GtkScrollType scroll, + gboolean horizontal) { GtkAdjustment *adjustment; double value, increment; @@ -608,12 +603,12 @@ ev_view_scroll (EvView *view, if (view->presentation || view->sizing_mode == EV_SIZING_BEST_FIT) { switch (scroll) { - case EV_SCROLL_PAGE_BACKWARD: - case EV_SCROLL_STEP_BACKWARD: + case GTK_SCROLL_PAGE_BACKWARD: + case GTK_SCROLL_STEP_BACKWARD: ev_view_previous_page (view); break; - case EV_SCROLL_PAGE_FORWARD: - case EV_SCROLL_STEP_FORWARD: + case GTK_SCROLL_PAGE_FORWARD: + case GTK_SCROLL_STEP_FORWARD: ev_view_next_page (view); break; default: @@ -634,7 +629,7 @@ ev_view_scroll (EvView *view, last_page = TRUE; switch (scroll) { - case EV_SCROLL_PAGE_BACKWARD: + case GTK_SCROLL_PAGE_BACKWARD: /* Do not jump backwards if at the first page */ if (value == (adjustment->lower) && first_page) { /* Do nothing */ @@ -647,7 +642,7 @@ ev_view_scroll (EvView *view, value = MAX (value - increment, adjustment->lower); } break; - case EV_SCROLL_PAGE_FORWARD: + case GTK_SCROLL_PAGE_FORWARD: /* Do not jump forward if at the last page */ if (value == (adjustment->upper - adjustment->page_size) && last_page) { /* Do nothing */ @@ -660,16 +655,16 @@ ev_view_scroll (EvView *view, value = MIN (value + increment, adjustment->upper - adjustment->page_size); } break; - case EV_SCROLL_STEP_BACKWARD: + case GTK_SCROLL_STEP_BACKWARD: value -= adjustment->step_increment; break; - case EV_SCROLL_STEP_FORWARD: + case GTK_SCROLL_STEP_FORWARD: value += adjustment->step_increment; break; - case EV_SCROLL_STEP_DOWN: + case GTK_SCROLL_STEP_DOWN: value -= adjustment->step_increment / 10; break; - case EV_SCROLL_STEP_UP: + case GTK_SCROLL_STEP_UP: value += adjustment->step_increment / 10; break; default: @@ -1575,7 +1570,8 @@ ev_view_handle_cursor_over_xy (EvView *view, gint x, gint y) } else { if (view->cursor == EV_VIEW_CURSOR_LINK || view->cursor == EV_VIEW_CURSOR_IBEAM || - view->cursor == EV_VIEW_CURSOR_DRAG) + view->cursor == EV_VIEW_CURSOR_DRAG || + view->cursor == EV_VIEW_CURSOR_AUTOSCROLL) ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL); } } @@ -1657,9 +1653,9 @@ ev_view_form_field_get_region (EvView *view, GList *forms_mapping; forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, - field->page); + field->page->index); ev_form_field_mapping_get_area (forms_mapping, field, &field_area); - doc_rect_to_view_rect (view, field->page, &field_area, &view_area); + doc_rect_to_view_rect (view, field->page->index, &field_area, &view_area); view_area.x -= view->scroll_x; view_area.y -= view->scroll_y; @@ -1710,7 +1706,7 @@ ev_view_form_field_button_create_widget (EvView *view, * we need to update also the region for the current selected item */ forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, - field->page); + field->page->index); for (l = forms_mapping; l; l = g_list_next (l)) { EvFormField *button = ((EvFormFieldMapping *)(l->data))->field; GdkRegion *button_region; @@ -1738,7 +1734,7 @@ ev_view_form_field_button_create_widget (EvView *view, ev_pixbuf_cache_reload_page (view->pixbuf_cache, field_region, - field->page, + field->page->index, view->rotation, view->scale); gdk_region_destroy (field_region); @@ -1768,7 +1764,7 @@ ev_view_form_field_text_save (EvView *view, field->changed = FALSE; ev_pixbuf_cache_reload_page (view->pixbuf_cache, field_region, - field->page, + field->page->index, view->rotation, view->scale); gdk_region_destroy (field_region); @@ -1889,7 +1885,7 @@ ev_view_form_field_choice_save (EvView *view, field->changed = FALSE; ev_pixbuf_cache_reload_page (view->pixbuf_cache, field_region, - field->page, + field->page->index, view->rotation, view->scale); gdk_region_destroy (field_region); @@ -1906,7 +1902,8 @@ ev_view_form_field_choice_changed (GtkWidget *widget, gint item; item = gtk_combo_box_get_active (GTK_COMBO_BOX (widget)); - if (GPOINTER_TO_INT (field_choice->selected_items->data) != item) { + if (!field_choice->selected_items || + GPOINTER_TO_INT (field_choice->selected_items->data) != item) { g_list_free (field_choice->selected_items); field_choice->selected_items = NULL; field_choice->selected_items = g_list_prepend (field_choice->selected_items, @@ -2105,10 +2102,10 @@ ev_view_handle_form_field (EvView *view, g_object_ref (field), (GDestroyNotify)g_object_unref); - form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, field->page); + form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, field->page->index); ev_form_field_mapping_get_area (form_field_mapping, field, &field_area); - doc_rect_to_view_rect (view, field->page, &field_area, &view_area); + doc_rect_to_view_rect (view, field->page->index, &field_area, &view_area); view_area.x -= view->scroll_x; view_area.y -= view->scroll_y; @@ -2308,10 +2305,10 @@ ev_view_size_allocate (GtkWidget *widget, continue; form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, - field->page); + field->page->index); ev_form_field_mapping_get_area (form_field_mapping, field, &field_area); - doc_rect_to_view_rect (view, field->page, &field_area, &view_area); + doc_rect_to_view_rect (view, field->page->index, &field_area, &view_area); view_area.x -= view->scroll_x; view_area.y -= view->scroll_y; @@ -2385,15 +2382,16 @@ ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) } view->jump_to_find_result = FALSE; + /* Shift+Wheel scrolls the in the perpendicular direction */ if (state & GDK_SHIFT_MASK) { if (event->direction == GDK_SCROLL_UP) event->direction = GDK_SCROLL_LEFT; - if (event->direction == GDK_SCROLL_LEFT) + else if (event->direction == GDK_SCROLL_LEFT) event->direction = GDK_SCROLL_UP; - if (event->direction == GDK_SCROLL_DOWN) + else if (event->direction == GDK_SCROLL_DOWN) event->direction = GDK_SCROLL_RIGHT; - if (event->direction == GDK_SCROLL_RIGHT) + else if (event->direction == GDK_SCROLL_RIGHT) event->direction = GDK_SCROLL_DOWN; event->state &= ~GDK_SHIFT_MASK; @@ -2480,7 +2478,7 @@ ev_view_expose_event (GtkWidget *widget, cairo_t *cr; gint i; - if (view->animation) { + if (view->animation && ev_transition_animation_ready (view->animation)) { GdkRectangle page_area; GtkBorder border; @@ -2545,7 +2543,7 @@ ev_view_expose_event (GtkWidget *widget, draw_one_page (view, i, cr, &page_area, &border, &(event->area), &page_ready); - if (page_ready && EV_IS_DOCUMENT_FIND (view->document) && view->highlight_find_results) + if (page_ready && view->find_pages && view->highlight_find_results) highlight_find_results (view, i); } @@ -2686,15 +2684,12 @@ ev_view_button_press_event (GtkWidget *widget, view->pressed_button = event->button; view->selection_info.in_drag = FALSE; + + if (view->scroll_info.autoscrolling) + return TRUE; switch (event->button) { case 1: { - - if (view->scroll_info.autoscrolling == TRUE) { - view->scroll_info.autoscrolling = FALSE; - return TRUE; - } - EvImage *image; EvFormField *field; @@ -2733,10 +2728,6 @@ ev_view_button_press_event (GtkWidget *widget, case 2: /* use root coordinates as reference point because * scrolling changes window relative coordinates */ - if (view->scroll_info.autoscrolling == TRUE) { - view->scroll_info.autoscrolling = FALSE; - return TRUE; - } view->drag_info.start.x = event->x_root; view->drag_info.start.y = event->y_root; view->drag_info.hadj = gtk_adjustment_get_value (view->hadjustment); @@ -2746,8 +2737,7 @@ ev_view_button_press_event (GtkWidget *widget, return TRUE; case 3: - if (!view->scroll_info.autoscrolling) - view->scroll_info.start_y = event->y; + view->scroll_info.start_y = event->y; return ev_view_do_popup_menu (view, event->x, event->y); } @@ -2794,16 +2784,28 @@ ev_view_drag_data_get (GtkWidget *widget, if (view->image_dnd_info.image) { GdkPixbuf *pixbuf; - pixbuf = ev_image_get_pixbuf (view->image_dnd_info.image); + ev_document_doc_mutex_lock (); + pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (view->document), + view->image_dnd_info.image); + ev_document_doc_mutex_unlock (); + gtk_selection_data_set_pixbuf (selection_data, pixbuf); + g_object_unref (pixbuf); } break; case TARGET_DND_URI: if (view->image_dnd_info.image) { + GdkPixbuf *pixbuf; const gchar *tmp_uri; gchar **uris; - tmp_uri = ev_image_save_tmp (view->image_dnd_info.image); + ev_document_doc_mutex_lock (); + pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (view->document), + view->image_dnd_info.image); + ev_document_doc_mutex_unlock (); + + tmp_uri = ev_image_save_tmp (view->image_dnd_info.image, pixbuf); + g_object_unref (pixbuf); uris = g_new0 (gchar *, 2); uris[0] = (gchar *)tmp_uri; @@ -2992,6 +2994,7 @@ ev_view_motion_notify_event (GtkWidget *widget, if (view->scroll_info.autoscrolling) { view->scroll_info.last_y = y; + return TRUE; } if (view->selection_info.in_drag) { @@ -3035,15 +3038,20 @@ ev_view_motion_notify_event (GtkWidget *widget, } } - /* For the Evince 0.4.x release, we limit selection to un-rotated - * documents only. - */ - if (view->pressed_button == 1 && view->rotation == 0) { + switch (view->pressed_button) { + case 1: + /* For the Evince 0.4.x release, we limit selection to un-rotated + * documents only. + */ + if (view->rotation != 0) + return FALSE; /* Schedule timeout to scroll during selection and additionally * scroll once to allow arbitrary speed. */ if (!view->selection_scroll_id) - view->selection_scroll_id = g_timeout_add (SCROLL_TIME, (GSourceFunc)selection_scroll_timeout_cb, view); + view->selection_scroll_id = g_timeout_add (SCROLL_TIME, + (GSourceFunc)selection_scroll_timeout_cb, + view); else selection_scroll_timeout_cb (view); @@ -3060,7 +3068,7 @@ ev_view_motion_notify_event (GtkWidget *widget, view->selection_update_id = g_idle_add ((GSourceFunc)selection_update_idle_cb, view); return TRUE; - } else if (view->pressed_button == 2) { + case 2: if (!view->drag_info.in_drag) { gboolean start; int i; @@ -3110,10 +3118,11 @@ ev_view_motion_notify_event (GtkWidget *widget, return TRUE; } - } else if (view->pressed_button <= 0) { + + break; + default: ev_view_handle_cursor_over_xy (view, x, y); - return TRUE; - } + } return FALSE; } @@ -3125,19 +3134,30 @@ ev_view_button_release_event (GtkWidget *widget, EvView *view = EV_VIEW (widget); EvLink *link = NULL; - view->drag_info.in_drag = FALSE; view->image_dnd_info.in_drag = FALSE; - - view->drag_info.release_timeout_id = g_timeout_add (20, - (GSourceFunc)ev_view_scroll_drag_release, view); - if (view->pressed_button == 2) { - ev_view_handle_cursor_over_xy (view, event->x, event->y); + if (view->scroll_info.autoscrolling) { + ev_view_autoscroll_stop (view); + view->pressed_button = -1; + + return TRUE; + } + + if (view->drag_info.in_drag) { + view->drag_info.release_timeout_id = + g_timeout_add (20, + (GSourceFunc)ev_view_scroll_drag_release, view); } - if (view->document && view->pressed_button != 3) { + if (view->document && !view->drag_info.in_drag && view->pressed_button != 3) { link = ev_view_get_link_at_location (view, event->x, event->y); } + + view->drag_info.in_drag = FALSE; + + if (view->pressed_button == 2) { + ev_view_handle_cursor_over_xy (view, event->x, event->y); + } view->pressed_button = -1; @@ -3159,6 +3179,7 @@ ev_view_button_release_event (GtkWidget *widget, } if (view->selection_info.selections) { + clear_link_selected (view); ev_view_update_primary_selection (view); if (view->selection_info.in_drag) { @@ -3359,7 +3380,7 @@ ev_view_goto_window_create (EvView *view) g_signal_connect (view->goto_entry, "activate", G_CALLBACK (ev_view_goto_entry_activate), view); - gtk_box_pack_start_defaults (GTK_BOX (hbox), view->goto_entry); + gtk_box_pack_start (GTK_BOX (hbox), view->goto_entry, TRUE, TRUE, 0); gtk_widget_show (view->goto_entry); gtk_widget_realize (view->goto_entry); } @@ -3419,6 +3440,8 @@ ev_view_key_press_event (GtkWidget *widget, switch (event->keyval) { case GDK_b: case GDK_B: + case GDK_period: + case GDK_KP_Decimal: view->presentation_state = (view->presentation_state == EV_PRESENTATION_BLACK) ? EV_PRESENTATION_NORMAL : EV_PRESENTATION_BLACK; @@ -3587,15 +3610,12 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window, static void highlight_find_results (EvView *view, int page) { - EvDocumentFind *find; - int i, results = 0; + gint i, n_results = 0; - find = EV_DOCUMENT_FIND (view->document); + n_results = ev_view_find_get_n_results (view, page); - results = ev_document_find_get_n_results (find, page); - - for (i = 0; i < results; i++) { - EvRectangle rectangle; + for (i = 0; i < n_results; i++) { + EvRectangle *rectangle; GdkRectangle view_rectangle; guchar alpha; @@ -3605,8 +3625,8 @@ highlight_find_results (EvView *view, int page) alpha = 0x20; } - ev_document_find_get_result (find, page, i, &rectangle); - doc_rect_to_view_rect (view, page, &rectangle, &view_rectangle); + rectangle = ev_view_find_get_result (view, page, i); + doc_rect_to_view_rect (view, page, rectangle, &view_rectangle); draw_rubberband (GTK_WIDGET (view), view->layout.bin_window, &view_rectangle, alpha); } @@ -3720,9 +3740,12 @@ draw_one_page (EvView *view, page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page); if (!page_surface) { - draw_loading_text (view, - &real_page_area, - expose_area); + if (!view->presentation) { + draw_loading_text (view, + &real_page_area, + expose_area); + } + *page_ready = FALSE; return; @@ -3798,9 +3821,8 @@ ev_view_finalize (GObject *object) { EvView *view = EV_VIEW (object); - g_free (view->find_status); - clear_selection (view); + clear_link_selected (view); if (view->image_dnd_info.image) g_object_unref (view->image_dnd_info.image); @@ -3948,9 +3970,6 @@ ev_view_get_property (GObject *object, EvView *view = EV_VIEW (object); switch (prop_id) { - case PROP_FIND_STATUS: - g_value_set_string (value, view->find_status); - break; case PROP_CONTINUOUS: g_value_set_boolean (value, view->continuous); break; @@ -4066,14 +4085,6 @@ ev_view_class_init (EvViewClass *class) G_TYPE_OBJECT); - g_object_class_install_property (object_class, - PROP_FIND_STATUS, - g_param_spec_string ("find-status", - "Find Status Message", - "The find status message", - NULL, - G_PARAM_READABLE)); - g_object_class_install_property (object_class, PROP_CONTINUOUS, g_param_spec_boolean ("continuous", @@ -4141,22 +4152,22 @@ ev_view_class_init (EvViewClass *class) binding_set = gtk_binding_set_by_class (class); - add_scroll_binding_keypad (binding_set, GDK_Left, 0, EV_SCROLL_STEP_BACKWARD, TRUE); - add_scroll_binding_keypad (binding_set, GDK_Right, 0, EV_SCROLL_STEP_FORWARD, TRUE); - add_scroll_binding_keypad (binding_set, GDK_Left, GDK_MOD1_MASK, EV_SCROLL_STEP_DOWN, TRUE); - add_scroll_binding_keypad (binding_set, GDK_Right, GDK_MOD1_MASK, EV_SCROLL_STEP_UP, TRUE); - add_scroll_binding_keypad (binding_set, GDK_Up, 0, EV_SCROLL_STEP_BACKWARD, FALSE); - add_scroll_binding_keypad (binding_set, GDK_Down, 0, EV_SCROLL_STEP_FORWARD, FALSE); - add_scroll_binding_keypad (binding_set, GDK_Up, GDK_MOD1_MASK, EV_SCROLL_STEP_DOWN, FALSE); - add_scroll_binding_keypad (binding_set, GDK_Down, GDK_MOD1_MASK, EV_SCROLL_STEP_UP, FALSE); - gtk_binding_entry_add_signal (binding_set, GDK_H, 0, "binding_activated", 2, EV_TYPE_SCROLL_TYPE, - EV_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_J, 0, "binding_activated", 2, EV_TYPE_SCROLL_TYPE, - EV_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, FALSE); - gtk_binding_entry_add_signal (binding_set, GDK_K, 0, "binding_activated", 2, EV_TYPE_SCROLL_TYPE, - EV_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, FALSE); - gtk_binding_entry_add_signal (binding_set, GDK_L, 0, "binding_activated", 2, EV_TYPE_SCROLL_TYPE, - EV_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, TRUE); + add_scroll_binding_keypad (binding_set, GDK_Left, 0, GTK_SCROLL_STEP_BACKWARD, TRUE); + add_scroll_binding_keypad (binding_set, GDK_Right, 0, GTK_SCROLL_STEP_FORWARD, TRUE); + add_scroll_binding_keypad (binding_set, GDK_Left, GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, TRUE); + add_scroll_binding_keypad (binding_set, GDK_Right, GDK_MOD1_MASK, GTK_SCROLL_STEP_UP, TRUE); + add_scroll_binding_keypad (binding_set, GDK_Up, 0, GTK_SCROLL_STEP_BACKWARD, FALSE); + add_scroll_binding_keypad (binding_set, GDK_Down, 0, GTK_SCROLL_STEP_FORWARD, FALSE); + add_scroll_binding_keypad (binding_set, GDK_Up, GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, FALSE); + add_scroll_binding_keypad (binding_set, GDK_Down, GDK_MOD1_MASK, GTK_SCROLL_STEP_UP, FALSE); + gtk_binding_entry_add_signal (binding_set, GDK_H, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE, + GTK_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, TRUE); + gtk_binding_entry_add_signal (binding_set, GDK_J, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE, + GTK_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal (binding_set, GDK_K, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE, + GTK_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal (binding_set, GDK_L, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE, + GTK_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, TRUE); } @@ -4198,25 +4209,6 @@ ev_view_init (EvView *view) /*** Callbacks ***/ -static void -find_changed_cb (EvDocument *document, int page, EvView *view) -{ - double percent; - int n_pages; - - percent = ev_document_find_get_progress - (EV_DOCUMENT_FIND (view->document)); - n_pages = ev_page_cache_get_n_pages (view->page_cache); - - if (view->jump_to_find_result == TRUE) { - jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0); - jump_to_find_result (view); - } - update_find_status_message (view, percent * n_pages >= n_pages - 1 ); - if (view->current_page == page) - gtk_widget_queue_draw (GTK_WIDGET (view)); -} - static void ev_view_change_page (EvView *view, gint new_page) @@ -4309,10 +4301,7 @@ page_changed_cb (EvPageCache *page_cache, gtk_widget_queue_draw (GTK_WIDGET (view)); } - if (EV_IS_DOCUMENT_FIND (view->document)) { - view->find_result = 0; - update_find_status_message (view, TRUE); - } + view->find_result = 0; } static void @@ -4409,7 +4398,8 @@ ev_view_set_loading (EvView *view, gtk_widget_queue_draw (GTK_WIDGET (view)); } -static gboolean ev_view_autoscroll_cb (EvView *view) +static gboolean +ev_view_autoscroll_cb (EvView *view) { gdouble speed, value; @@ -4442,10 +4432,43 @@ static gboolean ev_view_autoscroll_cb (EvView *view) } -void ev_view_autoscroll(EvView *view) +void +ev_view_autoscroll_start (EvView *view) { + gint x, y; + + g_return_if_fail (EV_IS_VIEW (view)); + + if (view->scroll_info.autoscrolling) + return; + view->scroll_info.autoscrolling = TRUE; - view->scroll_info.timeout_id = g_timeout_add (20, (GSourceFunc)(ev_view_autoscroll_cb), view); + view->scroll_info.timeout_id = + g_timeout_add (20, (GSourceFunc)ev_view_autoscroll_cb, + view); + + gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y); + ev_view_handle_cursor_over_xy (view, x, y); +} + +void +ev_view_autoscroll_stop (EvView *view) +{ + gint x, y; + + g_return_if_fail (EV_IS_VIEW (view)); + + if (!view->scroll_info.autoscrolling) + return; + + view->scroll_info.autoscrolling = FALSE; + if (view->scroll_info.timeout_id) { + g_source_remove (view->scroll_info.timeout_id); + view->scroll_info.timeout_id = 0; + } + + gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y); + ev_view_handle_cursor_over_xy (view, x, y); } void @@ -4460,12 +4483,8 @@ ev_view_set_document (EvView *view, clear_caches (view); if (view->document) { - g_signal_handlers_disconnect_by_func (view->document, - find_changed_cb, - view); g_object_unref (view->document); view->page_cache = NULL; - } view->document = document; @@ -4473,13 +4492,6 @@ ev_view_set_document (EvView *view, if (view->document) { g_object_ref (view->document); - if (EV_IS_DOCUMENT_FIND (view->document)) { - g_signal_connect (view->document, - "find_changed", - G_CALLBACK (find_changed_cb), - view); - } - setup_caches (view); } @@ -4707,17 +4719,10 @@ ev_view_presentation_transition_start (EvView *view) duration = ev_document_transition_get_page_duration (EV_DOCUMENT_TRANSITION (view->document), view->current_page); if (duration > 0) { -#if GLIB_CHECK_VERSION (2, 13, 0) view->trans_timeout_id = g_timeout_add_seconds (duration, (GSourceFunc) transition_next_page, view); -#else - view->trans_timeout_id = - g_timeout_add (duration * 1000, - (GSourceFunc) transition_next_page, - view); -#endif } } @@ -5087,71 +5092,32 @@ ev_view_set_zoom_for_size (EvView *view, } /*** Find ***/ -static void -update_find_status_message (EvView *view, gboolean this_page) -{ - char *message; - - if (this_page) { - int results; - - results = ev_document_find_get_n_results - (EV_DOCUMENT_FIND (view->document), - view->current_page); - /* 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", - results), - results); - } else { - double percent; - - percent = ev_document_find_get_progress - (EV_DOCUMENT_FIND (view->document)); - message = g_strdup_printf (_("%3d%% remaining to search"), - (int) ((1.0 - percent) * 100)); - - } - ev_view_set_find_status (view, message); - g_free (message); -} - -const char * -ev_view_get_find_status (EvView *view) +static gint +ev_view_find_get_n_results (EvView *view, gint page) { - g_return_val_if_fail (EV_IS_VIEW (view), NULL); - - return view->find_status; + return view->find_pages ? g_list_length (view->find_pages[page]) : 0; } -static void -ev_view_set_find_status (EvView *view, const char *message) +static EvRectangle * +ev_view_find_get_result (EvView *view, gint page, gint result) { - g_return_if_fail (EV_IS_VIEW (view)); - - g_free (view->find_status); - view->find_status = g_strdup (message); - g_object_notify (G_OBJECT (view), "find-status"); + return view->find_pages ? (EvRectangle *) g_list_nth_data (view->find_pages[page], result) : NULL; } static void jump_to_find_result (EvView *view) { - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - EvRectangle rect; - GdkRectangle view_rect; - int n_results; - int page = view->current_page; + gint n_results; + gint page = view->current_page; - n_results = ev_document_find_get_n_results (find, page); + n_results = ev_view_find_get_n_results (view, page); - if (n_results > 0 && view->find_result < n_results) { - ev_document_find_get_result - (find, page, view->find_result, &rect); + if (n_results > 0 && view->find_result < n_results) { + EvRectangle *rect; + GdkRectangle view_rect; - doc_rect_to_view_rect (view, page, &rect, &view_rect); + rect = ev_view_find_get_result (view, page, view->find_result); + doc_rect_to_view_rect (view, page, rect, &view_rect); ensure_rectangle_is_visible (view, &view_rect); } } @@ -5174,7 +5140,6 @@ jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift) n_pages = ev_page_cache_get_n_pages (view->page_cache); for (i = 0; i < n_pages; i++) { - int has_results; int page; if (direction == EV_VIEW_FIND_NEXT) @@ -5185,53 +5150,39 @@ jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift) if (page >= n_pages) { page = page - n_pages; - } - if (page < 0) + } else if (page < 0) page = page + n_pages; - - has_results = ev_document_find_page_has_results - (EV_DOCUMENT_FIND (view->document), page); - if (has_results == -1) { - break; - } else if (has_results == 1) { + + if (ev_view_find_get_n_results (view, page) > 0) { ev_page_cache_set_current_page (view->page_cache, page); break; } } } -gboolean -ev_view_can_find_next (EvView *view) +void +ev_view_find_changed (EvView *view, GList **results, gint page) { - if (EV_IS_DOCUMENT_FIND (view->document)) { - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - int i, n_pages; - - n_pages = ev_page_cache_get_n_pages (view->page_cache); - for (i = 0; i < n_pages; i++) { - if (ev_document_find_get_n_results (find, i) > 0) { - return TRUE; - } - } + view->find_pages = results; + + if (view->jump_to_find_result == TRUE) { + jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0); + jump_to_find_result (view); } - return FALSE; + if (view->current_page == page) + gtk_widget_queue_draw (GTK_WIDGET (view)); } void ev_view_find_next (EvView *view) { - int n_results, n_pages; - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - - n_results = ev_document_find_get_n_results (find, view->current_page); - - n_pages = ev_page_cache_get_n_pages (view->page_cache); + gint n_results; + n_results = ev_view_find_get_n_results (view, view->current_page); view->find_result++; if (view->find_result >= n_results) { - view->find_result = 0; jump_to_find_page (view, EV_VIEW_FIND_NEXT, 1); jump_to_find_result (view); @@ -5241,42 +5192,14 @@ ev_view_find_next (EvView *view) } } -gboolean -ev_view_can_find_previous (EvView *view) -{ - if (EV_IS_DOCUMENT_FIND (view->document)) { - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - int i, n_pages; - - n_pages = ev_page_cache_get_n_pages (view->page_cache); - for (i = n_pages - 1; i >= 0; i--) { - if (ev_document_find_get_n_results (find, i) > 0) { - return TRUE; - } - } - } - - return FALSE; -} void ev_view_find_previous (EvView *view) { - int n_results, n_pages; - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - EvPageCache *page_cache; - - page_cache = ev_page_cache_get (view->document); - - n_results = ev_document_find_get_n_results (find, view->current_page); - - n_pages = ev_page_cache_get_n_pages (page_cache); - view->find_result--; if (view->find_result < 0) { - jump_to_find_page (view, EV_VIEW_FIND_PREV, -1); - view->find_result = ev_document_find_get_n_results (find, view->current_page) - 1; + view->find_result = ev_view_find_get_n_results (view, view->current_page) - 1; jump_to_find_result (view); } else { jump_to_find_result (view); @@ -5284,18 +5207,27 @@ ev_view_find_previous (EvView *view) } } -void ev_view_search_changed (EvView *view) +void +ev_view_find_search_changed (EvView *view) { /* search string has changed, focus on new search result */ view->jump_to_find_result = TRUE; + view->find_pages = NULL; } -void ev_view_set_highlight_search (EvView *view, gboolean value) +void +ev_view_find_set_highlight_search (EvView *view, gboolean value) { view->highlight_find_results = value; gtk_widget_queue_draw (GTK_WIDGET (view)); } +void +ev_view_find_cancel (EvView *view) +{ + view->find_pages = NULL; +} + /*** Selections ***/ /* compute_new_selection_rect/text calculates the area currently selected by @@ -5655,15 +5587,19 @@ get_selected_text (EvView *view) EvRenderContext *rc; text = g_string_new (NULL); - rc = ev_render_context_new (view->rotation, 1, view->scale); + rc = ev_render_context_new (NULL, view->rotation, view->scale); ev_document_doc_mutex_lock (); for (l = view->selection_info.selections; l != NULL; l = l->next) { EvViewSelection *selection = (EvViewSelection *)l->data; + EvPage *page; gchar *tmp; - ev_render_context_set_page (rc, selection->page); + page = ev_document_get_page (view->document, selection->page); + ev_render_context_set_page (rc, page); + g_object_unref (page); + tmp = ev_selection_get_selected_text (EV_SELECTION (view->document), rc, selection->style, &(selection->rect)); @@ -5672,28 +5608,36 @@ get_selected_text (EvView *view) g_free (tmp); } - ev_document_doc_mutex_unlock (); - g_object_unref (rc); + ev_document_doc_mutex_unlock (); + normalized_text = g_utf8_normalize (text->str, text->len, G_NORMALIZE_NFKC); g_string_free (text, TRUE); return normalized_text; } +static void +ev_view_clipboard_copy (EvView *view, + const gchar *text) +{ + GtkClipboard *clipboard; + + clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view), + GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text (clipboard, text, -1); +} + void ev_view_copy (EvView *ev_view) { - GtkClipboard *clipboard; char *text; if (!EV_IS_SELECTION (ev_view->document)) return; text = get_selected_text (ev_view); - clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view), - GDK_SELECTION_CLIPBOARD); - gtk_clipboard_set_text (clipboard, text, -1); + ev_view_clipboard_copy (ev_view, text); g_free (text); } @@ -5704,15 +5648,20 @@ ev_view_primary_get_cb (GtkClipboard *clipboard, gpointer data) { EvView *ev_view = EV_VIEW (data); - char *text; - if (!EV_IS_SELECTION (ev_view->document)) - return; - - text = get_selected_text (ev_view); - if (text) { - gtk_selection_data_set_text (selection_data, text, -1); - g_free (text); + if (ev_view->link_selected) { + gtk_selection_data_set_text (selection_data, + ev_link_action_get_uri (ev_view->link_selected), + -1); + } else if (EV_IS_SELECTION (ev_view->document) && + ev_view->selection_info.selections) { + gchar *text; + + text = get_selected_text (ev_view); + if (text) { + gtk_selection_data_set_text (selection_data, text, -1); + g_free (text); + } } } @@ -5723,6 +5672,7 @@ ev_view_primary_clear_cb (GtkClipboard *clipboard, EvView *view = EV_VIEW (data); clear_selection (view); + clear_link_selected (view); } static void @@ -5733,7 +5683,7 @@ ev_view_update_primary_selection (EvView *ev_view) clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view), GDK_SELECTION_PRIMARY); - if (ev_view->selection_info.selections) { + if (ev_view->selection_info.selections || ev_view->link_selected) { if (!gtk_clipboard_set_with_owner (clipboard, clipboard_targets, G_N_ELEMENTS (clipboard_targets), @@ -5747,6 +5697,27 @@ ev_view_update_primary_selection (EvView *ev_view) } } +static void +clear_link_selected (EvView *view) +{ + if (view->link_selected) { + g_object_unref (view->link_selected); + view->link_selected = NULL; + } +} + +void +ev_view_copy_link_address (EvView *view, + EvLinkAction *action) +{ + clear_link_selected (view); + + ev_view_clipboard_copy (view, ev_link_action_get_uri (action)); + + view->link_selected = g_object_ref (action); + ev_view_update_primary_selection (view); +} + /*** Cursor operations ***/ static GdkCursor * @@ -5946,25 +5917,6 @@ ev_sizing_mode_get_type (void) return etype; } -GType -ev_scroll_type_get_type (void) -{ - static GType etype = 0; - if (etype == 0) { - static const GEnumValue values[] = { - { EV_SCROLL_PAGE_FORWARD, "EV_SCROLL_PAGE_FORWARD", "scroll-page-forward" }, - { EV_SCROLL_PAGE_BACKWARD, "EV_SCROLL_PAGE_BACKWARD", "scroll-page-backward" }, - { EV_SCROLL_STEP_FORWARD, "EV_SCROLL_STEP_FORWARD", "scroll-step-forward" }, - { EV_SCROLL_STEP_FORWARD, "EV_SCROLL_STEP_FORWARD", "scroll-step-forward" }, - { EV_SCROLL_STEP_UP, "EV_SCROLL_STEP_UP", "scroll-step-up" }, - { EV_SCROLL_STEP_DOWN, "EV_SCROLL_STEP_DOWN", "scroll-step-down" }, - { 0, NULL, NULL } - }; - etype = g_enum_register_static ("EvScrollType", values); - } - return etype; -} - void ev_view_update_view_size (EvView *view, GtkScrolledWindow * scrolled_window) {