X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=shell%2Fev-view.c;h=513ba871bae2407f4dcdd3b23a61e6dc41764e8e;hb=f3707525b60fc63e05c76295b3a1ce50584e156f;hp=13f227e775dac343ca8550e2dbcc6f5039fb55b7;hpb=0a36202909c5b5d6e015b7d3668ae51dfce30e47;p=evince.git diff --git a/shell/ev-view.c b/shell/ev-view.c index 13f227e7..513ba871 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -66,6 +66,7 @@ enum { enum { SIGNAL_BINDING_ACTIVATED, SIGNAL_ZOOM_INVALID, + SIGNAL_HANDLE_LINK, SIGNAL_EXTERNAL_LINK, SIGNAL_POPUP_MENU, N_SIGNALS, @@ -1312,7 +1313,7 @@ goto_dest (EvView *view, EvLinkDest *dest) view->current_page); } -void +static void ev_view_goto_dest (EvView *view, EvLinkDest *dest) { EvLinkDestType type; @@ -1346,13 +1347,15 @@ ev_view_handle_link (EvView *view, EvLink *link) action = ev_link_get_action (link); if (!action) return; - + type = ev_link_action_get_action_type (action); switch (type) { case EV_LINK_ACTION_TYPE_GOTO_DEST: { EvLinkDest *dest; + g_signal_emit (view, signals[SIGNAL_HANDLE_LINK], 0, link); + dest = ev_link_action_get_dest (action); ev_view_goto_dest (view, dest); } @@ -1366,8 +1369,8 @@ ev_view_handle_link (EvView *view, EvLink *link) } } -static gchar * -page_label_from_dest (EvView *view, EvLinkDest *dest) +gchar * +ev_view_page_label_from_dest (EvView *view, EvLinkDest *dest) { EvLinkDestType type; gchar *msg = NULL; @@ -1390,6 +1393,10 @@ page_label_from_dest (EvView *view, EvLinkDest *dest) } break; + case EV_LINK_DEST_TYPE_PAGE_LABEL: { + msg = g_strdup (ev_link_dest_get_page_label (dest)); + } + break; default: msg = ev_page_cache_get_page_label (view->page_cache, ev_link_dest_get_page (dest)); @@ -1439,8 +1446,8 @@ tip_from_link (EvView *view, EvLink *link) switch (type) { case EV_LINK_ACTION_TYPE_GOTO_DEST: - page_label = page_label_from_dest (view, - ev_link_action_get_dest (action)); + page_label = ev_view_page_label_from_dest (view, + ev_link_action_get_dest (action)); msg = g_strdup_printf (_("Go to page %s"), page_label); g_free (page_label); break; @@ -1510,7 +1517,6 @@ handle_link_over_xy (EvView *view, gint x, gint y) view->cursor == EV_VIEW_CURSOR_IBEAM) ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL); } - return; } /*** Images ***/ @@ -1907,7 +1913,7 @@ ev_view_expose_event (GtkWidget *widget, area.width = widget->allocation.width; area.height = widget->allocation.height; - + draw_loading_text (view, &area, &(event->area)); @@ -1975,6 +1981,9 @@ ev_view_button_press_event (GtkWidget *widget, GdkEventButton *event) { EvView *view = EV_VIEW (widget); + + if (!view->document) + return FALSE; if (!GTK_WIDGET_HAS_FOCUS (widget)) { gtk_widget_grab_focus (widget); @@ -1997,7 +2006,8 @@ ev_view_button_press_event (GtkWidget *widget, } gtk_widget_queue_draw (widget); - } else if ((image = ev_view_get_image_at_location (view, event->x, event->y))) { + } else if (!location_in_text (view, event->x + view->scroll_x, event->y + view->scroll_y) && + (image = ev_view_get_image_at_location (view, event->x, event->y))) { if (view->image_dnd_info.image) g_object_unref (view->image_dnd_info.image); view->image_dnd_info.image = g_object_ref (image); @@ -2311,7 +2321,7 @@ ev_view_button_release_event (GtkWidget *widget, ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL); } - if (view->document && view->pressed_button == 1) { + if (view->document && view->pressed_button != 3) { link = ev_view_get_link_at_location (view, event->x, event->y); } else { link = NULL; @@ -2340,7 +2350,23 @@ ev_view_button_release_event (GtkWidget *widget, view->selection_info.in_drag = FALSE; } else if (link) { - ev_view_handle_link (view, link); + if (event->button == 2) { + EvLinkAction *action; + EvLinkActionType type; + + action = ev_link_get_action (link); + if (!action) + return FALSE; + + type = ev_link_action_get_action_type (action); + if (type == EV_LINK_ACTION_TYPE_GOTO_DEST) { + g_signal_emit (view, + signals[SIGNAL_EXTERNAL_LINK], + 0, action); + } + } else { + ev_view_handle_link (view, link); + } } else if (view->presentation) { switch (event->button) { case 1: @@ -2423,6 +2449,8 @@ ev_view_goto_window_key_press_event (GtkWidget *widget, case GDK_Return: case GDK_KP_Enter: case GDK_ISO_Enter: + case GDK_BackSpace: + case GDK_Delete: return FALSE; default: if (!key_is_numeric (event->keyval)) @@ -2560,6 +2588,9 @@ ev_view_key_press_event (GtkWidget *widget, EvView *view = EV_VIEW (widget); EvPresentationState current; + if (!view->document) + return FALSE; + if (!view->presentation || view->presentation_state == EV_PRESENTATION_END) return gtk_bindings_activate_event (GTK_OBJECT (widget), event); @@ -2771,55 +2802,69 @@ draw_loading_text (EvView *view, GdkRectangle *page_area, GdkRectangle *expose_area) { - const char *loading_text; - PangoLayout *layout; - PangoFontDescription *font_desc; - PangoRectangle logical_rect; - double real_scale; - int target_width; - + cairo_t *cr; + gint width, height; + /* Don't annoy users with loading messages during presentations. * FIXME: Temporary "workaround" for * http://bugzilla.gnome.org/show_bug.cgi?id=320352 */ if (view->presentation) return; - loading_text = _("Loading..."); - - ev_document_fc_mutex_lock (); - - layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), loading_text); - - font_desc = pango_font_description_new (); - - - /* We set the font to be 10 points, get the size, and scale appropriately */ - pango_font_description_set_size (font_desc, 10 * PANGO_SCALE); - pango_layout_set_font_description (layout, font_desc); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - /* Make sure we fit the middle of the page */ - target_width = MAX (page_area->width / 2, 1); - real_scale = ((double)target_width / (double) logical_rect.width) * (PANGO_SCALE * 10); - pango_font_description_set_size (font_desc, (int)real_scale); - pango_layout_set_font_description (layout, font_desc); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - gtk_paint_layout (GTK_WIDGET (view)->style, - GTK_WIDGET (view)->window, - GTK_WIDGET_STATE (view), - FALSE, - page_area, - GTK_WIDGET (view), - NULL, - page_area->x + (target_width/2), - page_area->y + (page_area->height - logical_rect.height) / 2, - layout); + if (!view->loading_text) { + const gchar *loading_text; + PangoLayout *layout; + PangoFontDescription *font_desc; + PangoRectangle logical_rect; + gdouble real_scale; + gint target_width; + + loading_text = _("Loading..."); - pango_font_description_free (font_desc); - g_object_unref (layout); + ev_document_fc_mutex_lock (); + + layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), loading_text); + + font_desc = pango_font_description_new (); + + /* We set the font to be 10 points, get the size, and scale appropriately */ + pango_font_description_set_size (font_desc, 10 * PANGO_SCALE); + pango_layout_set_font_description (layout, font_desc); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + /* Make sure we fit the middle of the page */ + target_width = MAX (page_area->width / 2, 1); + real_scale = ((double)target_width / (double) logical_rect.width) * (PANGO_SCALE * 10); + pango_font_description_set_size (font_desc, (int)real_scale); + pango_layout_set_font_description (layout, font_desc); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + view->loading_text = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + logical_rect.width, + logical_rect.height); + cr = cairo_create (view->loading_text); + cairo_set_source_rgb (cr, + 155 / (double)255, + 155 / (double)255, + 155 / (double)255); + pango_cairo_show_layout (cr, layout); + cairo_destroy (cr); + + pango_font_description_free (font_desc); + g_object_unref (layout); + + ev_document_fc_mutex_unlock (); + } - ev_document_fc_mutex_unlock (); + width = (page_area->width - cairo_image_surface_get_width (view->loading_text)) / 2; + height = (page_area->height - cairo_image_surface_get_height (view->loading_text)) / 2; + + cr = gdk_cairo_create (GTK_WIDGET (view)->window); + cairo_set_source_surface (cr, view->loading_text, + page_area->x + width, + page_area->y + height); + cairo_paint (cr); + cairo_destroy (cr); } static void @@ -2990,6 +3035,11 @@ ev_view_destroy (GtkObject *object) view->selection_update_id = 0; } + if (view->loading_text) { + cairo_surface_destroy (view->loading_text); + view->loading_text = NULL; + } + ev_view_presentation_transition_stop (view); ev_view_set_scroll_adjustments (view, NULL, NULL); @@ -3172,6 +3222,14 @@ ev_view_class_init (EvViewClass *class) NULL, NULL, ev_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + signals[SIGNAL_HANDLE_LINK] = g_signal_new ("handle-link", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EvViewClass, handle_link), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); signals[SIGNAL_EXTERNAL_LINK] = g_signal_new ("external-link", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, @@ -3347,10 +3405,17 @@ page_changed_cb (EvPageCache *page_cache, EvView *view) { if (view->current_page != new_page) { + gint x, y; + view->current_page = new_page; view->pending_scroll = SCROLL_TO_PAGE_POSITION; + if (view->presentation) ev_view_presentation_transition_start (view); + + gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y); + handle_link_over_xy (view, x, y); + gtk_widget_queue_resize (GTK_WIDGET (view)); } else { gtk_widget_queue_draw (GTK_WIDGET (view)); @@ -3362,10 +3427,12 @@ page_changed_cb (EvPageCache *page_cache, } } -static void on_adjustment_value_changed (GtkAdjustment *adjustment, - EvView *view) +static void +on_adjustment_value_changed (GtkAdjustment *adjustment, + EvView *view) { int dx = 0, dy = 0; + gint x, y; if (! GTK_WIDGET_REALIZED (view)) return; @@ -3384,13 +3451,14 @@ static void on_adjustment_value_changed (GtkAdjustment *adjustment, view->scroll_y = 0; } - if (view->pending_resize) gtk_widget_queue_draw (GTK_WIDGET (view)); else gdk_window_scroll (GTK_WIDGET (view)->window, dx, dy); - + gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y); + handle_link_over_xy (view, x, y); + if (view->document) view_update_range_and_current_page (view); } @@ -3412,6 +3480,9 @@ setup_caches (EvView *view) g_signal_connect (view->page_cache, "page-changed", G_CALLBACK (page_changed_cb), view); view->pixbuf_cache = ev_pixbuf_cache_new (GTK_WIDGET (view), view->document); g_signal_connect (view->pixbuf_cache, "job-finished", G_CALLBACK (job_finished_cb), view); + page_changed_cb (view->page_cache, + ev_page_cache_get_current_page (view->page_cache), + view); } static void @@ -3494,6 +3565,11 @@ ev_view_set_zoom (EvView *view, if (ABS (view->scale - scale) < EPSILON) return; + if (view->loading_text) { + cairo_surface_destroy (view->loading_text); + view->loading_text = NULL; + } + view->scale = scale; view->pending_resize = TRUE; @@ -3726,6 +3802,9 @@ ev_view_zoom_in (EvView *view) { g_return_if_fail (view->sizing_mode == EV_SIZING_FREE); + if (view->presentation) + return; + view->pending_scroll = SCROLL_TO_CENTER; ev_view_set_zoom (view, ZOOM_IN_FACTOR, TRUE); } @@ -3735,6 +3814,9 @@ ev_view_zoom_out (EvView *view) { g_return_if_fail (view->sizing_mode == EV_SIZING_FREE); + if (view->presentation) + return; + view->pending_scroll = SCROLL_TO_CENTER; ev_view_set_zoom (view, ZOOM_OUT_FACTOR, TRUE); } @@ -4618,6 +4700,7 @@ get_selected_text (EvView *ev_view) { GString *text; GList *l; + gchar *normalized_text; text = g_string_new (NULL); @@ -4636,7 +4719,9 @@ get_selected_text (EvView *ev_view) ev_document_doc_mutex_unlock (); - return g_string_free (text, FALSE); + normalized_text = g_utf8_normalize (text->str, text->len, G_NORMALIZE_NFKC); + g_string_free (text, TRUE); + return normalized_text; } void @@ -4670,8 +4755,10 @@ ev_view_primary_get_cb (GtkClipboard *clipboard, } text = get_selected_text (ev_view); - gtk_selection_data_set_text (selection_data, text, -1); - g_free (text); + if (text) { + gtk_selection_data_set_text (selection_data, text, -1); + g_free (text); + } } static void