X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=shell%2Fev-view.c;h=e8bcf0bd1d1146a43386bbc7241346fbcc49a10d;hb=67f80b85d70a6d577e36c9578b854003a7d910ca;hp=e9a74d056ab81ad53ef00b5b512bf888c74417ac;hpb=201abe79e893ec212afe7bf990fa73587983b01f;p=evince.git diff --git a/shell/ev-view.c b/shell/ev-view.c index e9a74d05..e8bcf0bd 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -386,6 +386,7 @@ view_set_adjustment_values (EvView *view, factor = 1.0; switch (view->pending_scroll) { case SCROLL_TO_KEEP_POSITION: + case SCROLL_TO_FIND_LOCATION: factor = (adjustment->value) / adjustment->upper; break; case SCROLL_TO_PAGE_POSITION: @@ -406,6 +407,7 @@ view_set_adjustment_values (EvView *view, */ switch (view->pending_scroll) { case SCROLL_TO_KEEP_POSITION: + case SCROLL_TO_FIND_LOCATION: new_value = CLAMP (adjustment->upper * factor + 0.5, 0, adjustment->upper - adjustment->page_size); gtk_adjustment_set_value (adjustment, (int)new_value); break; @@ -428,9 +430,6 @@ view_update_range_and_current_page (EvView *view) gint current_page; gint best_current_page = -1; - if (view->pending_scroll != SCROLL_TO_KEEP_POSITION) - return; - /* Presentation trumps all other modes */ if (view->presentation) { view->start_page = view->current_page; @@ -496,7 +495,7 @@ view_update_range_and_current_page (EvView *view) best_current_page = MAX (best_current_page, view->start_page); current_page = ev_page_cache_get_current_page (view->page_cache); - if (current_page != best_current_page) { + if ((current_page != best_current_page) && (view->pending_scroll == SCROLL_TO_KEEP_POSITION)) { view->current_page = best_current_page; ev_page_cache_set_current_page (view->page_cache, best_current_page); } @@ -582,7 +581,7 @@ ev_view_scroll (EvView *view, view->jump_to_find_result = FALSE; - if (view->presentation) { + if (view->presentation || view->sizing_mode == EV_SIZING_BEST_FIT) { switch (scroll) { case EV_SCROLL_PAGE_BACKWARD: case EV_SCROLL_STEP_BACKWARD: @@ -667,7 +666,7 @@ ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect) GtkAdjustment *adjustment; int value; - view->pending_scroll = SCROLL_TO_KEEP_POSITION; + view->pending_scroll = SCROLL_TO_FIND_LOCATION; adjustment = view->vadjustment; @@ -692,6 +691,8 @@ ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect) widget->allocation.width + MARGIN); gtk_adjustment_set_value (view->hadjustment, value); } + + gtk_widget_queue_resize (GTK_WIDGET (view)); } /*** Geometry computations ***/ @@ -1050,6 +1051,47 @@ location_in_selected_text (EvView *view, return FALSE; } +static gboolean +get_doc_point_from_offset (EvView *view, + gint page, + gint x_offset, + gint y_offset, + gint *x_new, + gint *y_new) +{ + int width, height; + double x, y; + + ev_page_cache_get_size (view->page_cache, page, + view->rotation, + 1.0, + &width, &height); + + x_offset = x_offset / view->scale; + y_offset = y_offset / view->scale; + + if (view->rotation == 0) { + x = x_offset; + y = y_offset; + } else if (view->rotation == 90) { + x = y_offset; + y = width - x_offset; + } else if (view->rotation == 180) { + x = width - x_offset; + y = height - y_offset; + } else if (view->rotation == 270) { + x = height - y_offset; + y = x_offset; + } else { + g_assert_not_reached (); + } + + *x_new = x; + *y_new = y; + + return TRUE; +} + /*** Hyperref ***/ static EvLink * ev_view_get_link_at_location (EvView *view, @@ -1058,6 +1100,7 @@ ev_view_get_link_at_location (EvView *view, { gint page = -1; gint x_offset = 0, y_offset = 0; + gint x_new = 0, y_new = 0; GList *link_mapping; x += view->scroll_x; @@ -1068,10 +1111,15 @@ ev_view_get_link_at_location (EvView *view, if (page == -1) return NULL; + + if (get_doc_point_from_offset (view, page, x_offset, + y_offset, &x_new, &y_new) == FALSE) + return NULL; + link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page); if (link_mapping) - return ev_link_mapping_find (link_mapping, x_offset / view->scale, y_offset / view->scale); + return ev_link_mapping_find (link_mapping, x_new, y_new); else return NULL; } @@ -1080,22 +1128,20 @@ static void goto_fitr_dest (EvView *view, EvLinkDest *dest) { EvPoint doc_point; - int page; double zoom; zoom = zoom_for_size_best_fit (ev_link_dest_get_right (dest) - ev_link_dest_get_left (dest), - ev_link_dest_get_top (dest) - ev_link_dest_get_bottom (dest), + ev_link_dest_get_bottom (dest) - ev_link_dest_get_top (dest), ev_view_get_width (view), ev_view_get_height (view), 0, 0); ev_view_set_sizing_mode (view, EV_SIZING_FREE); ev_view_set_zoom (view, zoom, FALSE); - page = ev_link_dest_get_page (dest); doc_point.x = ev_link_dest_get_left (dest); doc_point.y = ev_link_dest_get_top (dest); - view->current_page = page; + view->current_page = ev_link_dest_get_page (dest); view->pending_point = doc_point; view->pending_scroll = SCROLL_TO_PAGE_POSITION; @@ -1140,13 +1186,13 @@ goto_fith_dest (EvView *view, EvLinkDest *dest) ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height); doc_point.x = 0; - doc_point.y = doc_height - ev_link_dest_get_top (dest); + doc_point.y = ev_link_dest_get_top (dest); zoom = zoom_for_size_fit_width (doc_width, ev_link_dest_get_top (dest), ev_view_get_width (view), ev_view_get_height (view), 0); - ev_view_set_sizing_mode (view, EV_SIZING_FREE); + ev_view_set_sizing_mode (view, EV_SIZING_FIT_WIDTH); ev_view_set_zoom (view, zoom, FALSE); view->current_page = page; @@ -1169,7 +1215,7 @@ goto_fit_dest (EvView *view, EvLinkDest *dest) zoom = zoom_for_size_best_fit (doc_width, doc_height, ev_view_get_width (view), ev_view_get_height (view), 0, 0); - ev_view_set_sizing_mode (view, EV_SIZING_FREE); + ev_view_set_sizing_mode (view, EV_SIZING_BEST_FIT); ev_view_set_zoom (view, zoom, FALSE); view->current_page = page; @@ -1182,20 +1228,19 @@ static void goto_xyz_dest (EvView *view, EvLinkDest *dest) { EvPoint doc_point; - int height, page; + gint page; double zoom; zoom = ev_link_dest_get_zoom (dest); page = ev_link_dest_get_page (dest); - ev_page_cache_get_size (view->page_cache, page, 0, 1.0, NULL, &height); - if (zoom != 0) { + if (zoom > 1) { ev_view_set_sizing_mode (view, EV_SIZING_FREE); ev_view_set_zoom (view, zoom, FALSE); } doc_point.x = ev_link_dest_get_left (dest); - doc_point.y = height - ev_link_dest_get_top (dest); + doc_point.y = ev_link_dest_get_top (dest); view->current_page = page; view->pending_point = doc_point; @@ -1237,6 +1282,9 @@ goto_dest (EvView *view, EvLinkDest *dest) case EV_LINK_DEST_TYPE_XYZ: goto_xyz_dest (view, dest); break; + case EV_LINK_DEST_TYPE_PAGE_LABEL: + ev_page_cache_set_page_label (view->page_cache, ev_link_dest_get_page_label (dest)); + break; default: g_assert_not_reached (); } @@ -1376,10 +1424,10 @@ tip_from_link (EvView *view, EvLink *link) break; case EV_LINK_ACTION_TYPE_GOTO_REMOTE: if (title) { - msg = g_strdup_printf (_("Go to %s on file %s"), title, + msg = g_strdup_printf (_("Go to %s on file “%s”"), title, ev_link_action_get_filename (action)); } else { - msg = g_strdup_printf (_("Go to file %s"), + msg = g_strdup_printf (_("Go to file “%s”"), ev_link_action_get_filename (action)); } @@ -1610,12 +1658,12 @@ ev_view_size_allocate (GtkWidget *widget, view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL); view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL); - view->pending_scroll = SCROLL_TO_KEEP_POSITION; - view->pending_resize = FALSE; - if (view->document) view_update_range_and_current_page (view); + view->pending_scroll = SCROLL_TO_KEEP_POSITION; + view->pending_resize = FALSE; + GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation); } @@ -1738,6 +1786,42 @@ find_selection_for_page (EvView *view, return NULL; } +static void +draw_end_presentation_page (EvView *view, + GdkRectangle *page_area) +{ + PangoLayout *layout; + PangoFontDescription *font_desc; + gchar *markup; + const gchar *text = _("End of presentation. Press Escape to exit."); + + if (view->presentation_state != EV_PRESENTATION_END) + return; + + layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), NULL); + markup = g_strdup_printf ("%s", text); + pango_layout_set_markup (layout, markup, -1); + g_free (markup); + + font_desc = pango_font_description_new (); + pango_font_description_set_size (font_desc, 16 * PANGO_SCALE); + pango_layout_set_font_description (layout, font_desc); + + 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 + 15, + page_area->y + 15, + layout); + + pango_font_description_free (font_desc); + g_object_unref (layout); +} + static gboolean ev_view_expose_event (GtkWidget *widget, GdkEventExpose *event) @@ -1745,6 +1829,26 @@ ev_view_expose_event (GtkWidget *widget, EvView *view = EV_VIEW (widget); int i; + if (view->presentation) { + switch (view->presentation_state) { + case EV_PRESENTATION_END: { + GdkRectangle area = {0}; + + area.width = widget->allocation.width; + area.height = widget->allocation.height; + + draw_end_presentation_page (view, &area); + } + return FALSE; + case EV_PRESENTATION_BLACK: + case EV_PRESENTATION_WHITE: + return FALSE; + case EV_PRESENTATION_NORMAL: + default: + break; + } + } + if (view->loading) { GdkRectangle area = {0}; @@ -1762,7 +1866,7 @@ ev_view_expose_event (GtkWidget *widget, for (i = view->start_page; i <= view->end_page; i++) { GdkRectangle page_area; GtkBorder border; - gboolean page_ready; + gboolean page_ready = TRUE; if (!get_page_extents (view, i, &page_area, &border)) continue; @@ -2010,11 +2114,7 @@ ev_view_motion_notify_event (GtkWidget *widget, return TRUE; } - /* For the Evince 0.4.x release, we limit links to un-rotated documents - * only. - */ - } else if (view->pressed_button <= 0 && - view->rotation == 0) { + } else if (view->pressed_button <= 0) { handle_link_over_xy (view, x, y); return TRUE; } @@ -2033,7 +2133,7 @@ ev_view_button_release_event (GtkWidget *widget, ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL); } - if (view->document) { + if (view->document && view->pressed_button == 1) { link = ev_view_get_link_at_location (view, event->x, event->y); } else { link = NULL; @@ -2076,6 +2176,61 @@ ev_view_button_release_event (GtkWidget *widget, return FALSE; } +static gboolean +ev_view_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + EvView *view = EV_VIEW (widget); + EvPresentationState current; + + if (!view->presentation || + view->presentation_state == EV_PRESENTATION_END) + return gtk_bindings_activate_event (GTK_OBJECT (widget), event); + + + current = view->presentation_state; + + switch (event->keyval) { + case GDK_b: + case GDK_B: + view->presentation_state = + (view->presentation_state == EV_PRESENTATION_BLACK) ? + EV_PRESENTATION_NORMAL : EV_PRESENTATION_BLACK; + break; + case GDK_w: + case GDK_W: + view->presentation_state = + (view->presentation_state == EV_PRESENTATION_WHITE) ? + EV_PRESENTATION_NORMAL : EV_PRESENTATION_WHITE; + break; + default: + if (view->presentation_state == EV_PRESENTATION_BLACK || + view->presentation_state == EV_PRESENTATION_WHITE) { + view->presentation_state = EV_PRESENTATION_NORMAL; + } + } + + if (current == view->presentation_state) + return gtk_bindings_activate_event (GTK_OBJECT (widget), event); + + switch (view->presentation_state) { + case EV_PRESENTATION_NORMAL: + case EV_PRESENTATION_BLACK: + gdk_window_set_background (widget->window, + &widget->style->black); + break; + case EV_PRESENTATION_WHITE: + gdk_window_set_background (widget->window, + &widget->style->white); + break; + default: + return gtk_bindings_activate_event (GTK_OBJECT (widget), event); + } + + gtk_widget_queue_draw (widget); + return TRUE; +} + static gint ev_view_focus_in (GtkWidget *widget, GdkEventFocus *event) @@ -2227,8 +2382,16 @@ draw_loading_text (EvView *view, double real_scale; int target_width; + /* 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; + const char *loading_text = _("Loading..."); + ev_document_doc_mutex_lock (); + layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), loading_text); font_desc = pango_font_description_new (); @@ -2259,6 +2422,8 @@ draw_loading_text (EvView *view, pango_font_description_free (font_desc); g_object_unref (layout); + + ev_document_doc_mutex_unlock (); } static void @@ -2277,7 +2442,7 @@ draw_one_page (EvView *view, gint current_page; g_assert (view->document); - + if (! gdk_rectangle_intersect (page_area, expose_area, &overlap)) return; @@ -2294,6 +2459,7 @@ draw_one_page (EvView *view, real_page_area.y += border->top; real_page_area.width -= (border->left + border->right); real_page_area.height -= (border->top + border->bottom); + *page_ready = TRUE; ev_document_misc_paint_one_page (GTK_WIDGET(view)->window, GTK_WIDGET (view), @@ -2349,7 +2515,6 @@ draw_one_page (EvView *view, GDK_RGB_DITHER_NORMAL, 0, 0); g_object_unref (scaled_image); - *page_ready = TRUE; } else { draw_loading_text (view, &real_page_area, @@ -2406,6 +2571,7 @@ ev_view_destroy (GtkObject *object) if (view->link_tooltip) { gtk_widget_destroy (view->link_tooltip); + view->link_tooltip = NULL; } if (view->selection_scroll_id) { @@ -2550,6 +2716,7 @@ ev_view_class_init (EvViewClass *class) widget_class->button_press_event = ev_view_button_press_event; widget_class->motion_notify_event = ev_view_motion_notify_event; widget_class->button_release_event = ev_view_button_release_event; + widget_class->key_press_event = ev_view_key_press_event; widget_class->focus_in_event = ev_view_focus_in; widget_class->focus_out_event = ev_view_focus_out; widget_class->get_accessible = ev_view_get_accessible; @@ -2723,6 +2890,7 @@ ev_view_init (EvView *view) view->continuous = TRUE; view->dual_page = FALSE; view->presentation = FALSE; + view->presentation_state = EV_PRESENTATION_NORMAL; view->fullscreen = FALSE; view->sizing_mode = EV_SIZING_FIT_WIDTH; view->pending_scroll = SCROLL_TO_KEEP_POSITION; @@ -3012,6 +3180,9 @@ ev_view_set_presentation (EvView *view, if (view->presentation == presentation) return; + if (!presentation) + view->presentation_state = EV_PRESENTATION_NORMAL; + view->presentation = presentation; view->pending_scroll = SCROLL_TO_PAGE_POSITION; gtk_widget_queue_resize (GTK_WIDGET (view)); @@ -3025,7 +3196,6 @@ ev_view_set_presentation (EvView *view, >K_WIDGET (view)->style->mid [GTK_STATE_NORMAL]); } - g_object_notify (G_OBJECT (view), "presentation"); } @@ -4123,27 +4293,47 @@ ev_view_show_cursor (EvView *view) ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL); } +static void +ev_view_reset_presentation_state (EvView *view) +{ + if (!view->presentation || + view->presentation_state == EV_PRESENTATION_NORMAL) + return; + + view->presentation_state = EV_PRESENTATION_NORMAL; + gdk_window_set_background (GTK_WIDGET (view)->window, + >K_WIDGET (view)->style->black); + gtk_widget_queue_draw (GTK_WIDGET (view)); +} + gboolean ev_view_next_page (EvView *view) { - int page; + int page, n_pages; g_return_val_if_fail (EV_IS_VIEW (view), FALSE); if (!view->page_cache) return FALSE; + ev_view_reset_presentation_state (view); + page = ev_page_cache_get_current_page (view->page_cache); + n_pages = ev_page_cache_get_n_pages (view->page_cache); if (view->dual_page && !view->presentation) page = page + 2; else page = page + 1; - if (page < ev_page_cache_get_n_pages (view->page_cache)) { + if (page < n_pages) { ev_page_cache_set_current_page (view->page_cache, page); return TRUE; - } else if (ev_view_get_dual_page (view) && page == ev_page_cache_get_n_pages (view->page_cache)) { + } else if (view->presentation && page == n_pages) { + view->presentation_state = EV_PRESENTATION_END; + gtk_widget_queue_draw (GTK_WIDGET (view)); + return TRUE; + } else if (view->dual_page && page == n_pages) { ev_page_cache_set_current_page (view->page_cache, page - 1); return TRUE; } else { @@ -4161,6 +4351,14 @@ ev_view_previous_page (EvView *view) if (!view->page_cache) return FALSE; + if (view->presentation && + view->presentation_state == EV_PRESENTATION_END) { + ev_view_reset_presentation_state (view); + return TRUE; + } + + ev_view_reset_presentation_state (view); + page = ev_page_cache_get_current_page (view->page_cache); if (view->dual_page && !view->presentation)