]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-view.c
Icons for a new sizes.
[evince.git] / shell / ev-view.c
index 468a8946acd72e84f6efe5429320872f80e90691..4fda98c155989e76c65369fa5d000bbcd973e5fc 100644 (file)
@@ -42,7 +42,9 @@
 #include "ev-job-queue.h"
 #include "ev-page-cache.h"
 #include "ev-pixbuf-cache.h"
 #include "ev-job-queue.h"
 #include "ev-page-cache.h"
 #include "ev-pixbuf-cache.h"
+#if !GTK_CHECK_VERSION (2, 11, 7)
 #include "ev-tooltip.h"
 #include "ev-tooltip.h"
+#endif
 #include "ev-application.h"
 
 #define EV_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass))
 #include "ev-application.h"
 
 #define EV_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass))
@@ -52,7 +54,6 @@
 
 enum {
        PROP_0,
 
 enum {
        PROP_0,
-       PROP_STATUS,
        PROP_FIND_STATUS,
        PROP_CONTINUOUS,
        PROP_DUAL_PAGE,
        PROP_FIND_STATUS,
        PROP_CONTINUOUS,
        PROP_DUAL_PAGE,
@@ -218,6 +219,7 @@ static void       highlight_find_results                     (EvView
                                                              int                 page);
 static void       draw_one_page                              (EvView             *view,
                                                              gint                page,
                                                              int                 page);
 static void       draw_one_page                              (EvView             *view,
                                                              gint                page,
+                                                             cairo_t            *cr,
                                                              GdkRectangle       *page_area,
                                                              GtkBorder          *border,
                                                              GdkRectangle       *expose_area,
                                                              GdkRectangle       *page_area,
                                                              GtkBorder          *border,
                                                              GdkRectangle       *expose_area,
@@ -231,6 +233,7 @@ static void       find_changed_cb                            (EvDocument
                                                              int                 page,
                                                              EvView             *view);
 static void       job_finished_cb                            (EvPixbufCache      *pixbuf_cache,
                                                              int                 page,
                                                              EvView             *view);
 static void       job_finished_cb                            (EvPixbufCache      *pixbuf_cache,
+                                                             GdkRegion          *region,
                                                              EvView             *view);
 static void       page_changed_cb                            (EvPageCache        *page_cache,
                                                              int                 new_page,
                                                              EvView             *view);
 static void       page_changed_cb                            (EvPageCache        *page_cache,
                                                              int                 new_page,
@@ -300,14 +303,11 @@ static void       ev_view_handle_cursor_over_xy              (EvView *view,
                                                              gint x,
                                                              gint y);
 
                                                              gint x,
                                                              gint y);
 
-/*** Status messages ***/
-static void       ev_view_set_status                         (EvView             *view,
-                                                             const char         *message);
+/*** 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 void       update_find_status_message                 (EvView             *view,
                                                              gboolean            this_page);
 static void       ev_view_set_find_status                    (EvView             *view,
                                                              const char         *message);
-/*** Find ***/
 static void       jump_to_find_result                        (EvView             *view);
 static void       jump_to_find_page                          (EvView             *view, 
                                                              EvViewFindDirection direction,
 static void       jump_to_find_result                        (EvView             *view);
 static void       jump_to_find_page                          (EvView             *view, 
                                                              EvViewFindDirection direction,
@@ -1457,8 +1457,10 @@ tip_from_link (EvView *view, EvLink *link)
                case EV_LINK_ACTION_TYPE_GOTO_DEST:
                        page_label = ev_view_page_label_from_dest (view,
                                                                   ev_link_action_get_dest (action));
                case EV_LINK_ACTION_TYPE_GOTO_DEST:
                        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);
+                       if (page_label) {
+                               msg = g_strdup_printf (_("Go to page %s"), page_label);
+                               g_free (page_label);
+                       }
                        break;
                case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
                        if (title) {
                        break;
                case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
                        if (title) {
@@ -1468,7 +1470,6 @@ tip_from_link (EvView *view, EvLink *link)
                                msg = g_strdup_printf (_("Go to file ā€œ%sā€"),
                                                       ev_link_action_get_filename (action));
                        }
                                msg = g_strdup_printf (_("Go to file ā€œ%sā€"),
                                                       ev_link_action_get_filename (action));
                        }
-                       
                        break;
                case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
                        msg = g_strdup (ev_link_action_get_uri (action));
                        break;
                case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
                        msg = g_strdup (ev_link_action_get_uri (action));
@@ -1492,10 +1493,15 @@ tip_from_link (EvView *view, EvLink *link)
 static void
 ev_view_handle_cursor_over_xy (EvView *view, gint x, gint y)
 {
 static void
 ev_view_handle_cursor_over_xy (EvView *view, gint x, gint y)
 {
-       EvLink *link;
+       EvLink      *link;
+       EvFormField *field;
 
 
+       if (view->cursor == EV_VIEW_CURSOR_HIDDEN)
+               return;
+       
        link = ev_view_get_link_at_location (view, x, y);
        link = ev_view_get_link_at_location (view, x, y);
-
+       
+#if !GTK_CHECK_VERSION (2, 11, 7)
        if (view->link_tooltip == NULL) {
                view->link_tooltip = ev_tooltip_new (GTK_WIDGET (view));
        }
        if (view->link_tooltip == NULL) {
                view->link_tooltip = ev_tooltip_new (GTK_WIDGET (view));
        }
@@ -1504,8 +1510,12 @@ ev_view_handle_cursor_over_xy (EvView *view, gint x, gint y)
                view->hovered_link = link;
                ev_tooltip_deactivate (EV_TOOLTIP (view->link_tooltip));
        }
                view->hovered_link = link;
                ev_tooltip_deactivate (EV_TOOLTIP (view->link_tooltip));
        }
+#endif
 
         if (link) {
 
         if (link) {
+#if GTK_CHECK_VERSION (2, 11, 7)
+               g_object_set (view, "has-tooltip", TRUE, NULL);
+#else
                char *msg = tip_from_link (view, link);
 
                if (msg && g_utf8_validate (msg, -1, NULL)) {
                char *msg = tip_from_link (view, link);
 
                if (msg && g_utf8_validate (msg, -1, NULL)) {
@@ -1516,14 +1526,21 @@ ev_view_handle_cursor_over_xy (EvView *view, gint x, gint y)
                        ev_tooltip_activate (tooltip);
                }
                g_free (msg);
                        ev_tooltip_activate (tooltip);
                }
                g_free (msg);
-
+#endif
                ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
                ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
+       } else if ((field = ev_view_get_form_field_at_location (view, x, y))) {
+               if (field->is_read_only) {
+                       if (view->cursor == EV_VIEW_CURSOR_LINK ||
+                           view->cursor == EV_VIEW_CURSOR_IBEAM)
+                               ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
+               } else if (EV_IS_FORM_FIELD_TEXT (field)) {
+                       ev_view_set_cursor (view, EV_VIEW_CURSOR_IBEAM);
+               } else {
+                       ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
+               }
        } else if (location_in_text (view, x + view->scroll_x, y + view->scroll_y)) {
                ev_view_set_cursor (view, EV_VIEW_CURSOR_IBEAM);
        } else if (location_in_text (view, x + view->scroll_x, y + view->scroll_y)) {
                ev_view_set_cursor (view, EV_VIEW_CURSOR_IBEAM);
-       } else if (ev_view_get_form_field_at_location (view, x, y)) {
-               ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
        } else {
        } else {
-               ev_view_set_status (view, NULL);
                if (view->cursor == EV_VIEW_CURSOR_LINK ||
                    view->cursor == EV_VIEW_CURSOR_IBEAM)
                        ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
                if (view->cursor == EV_VIEW_CURSOR_LINK ||
                    view->cursor == EV_VIEW_CURSOR_IBEAM)
                        ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
@@ -1598,6 +1615,24 @@ ev_view_get_form_field_at_location (EvView  *view,
                return NULL;
 }
 
                return NULL;
 }
 
+static GdkRegion *
+ev_view_form_field_get_region (EvView      *view,
+                              EvFormField *field)
+{
+       EvRectangle  field_area;
+       GdkRectangle view_area;
+       GList       *forms_mapping;
+
+       forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache,
+                                                               field->page);
+       ev_form_field_mapping_get_area (forms_mapping, field, &field_area);
+       doc_rect_to_view_rect (view, field->page, &field_area, &view_area);
+       view_area.x -= view->scroll_x;
+       view_area.y -= view->scroll_y;
+
+       return gdk_region_rectangle (&view_area);
+}
+
 static gboolean
 ev_view_forms_remove_widgets (EvView *view)
 {
 static gboolean
 ev_view_forms_remove_widgets (EvView *view)
 {
@@ -1618,25 +1653,62 @@ ev_view_form_field_button_create_widget (EvView      *view,
                                         EvFormField *field)
 {
        EvFormFieldButton *field_button = EV_FORM_FIELD_BUTTON (field);
                                         EvFormField *field)
 {
        EvFormFieldButton *field_button = EV_FORM_FIELD_BUTTON (field);
+       GdkRegion         *field_region = NULL;
        
        switch (field_button->type) {
                case EV_FORM_FIELD_BUTTON_PUSH:
        
        switch (field_button->type) {
                case EV_FORM_FIELD_BUTTON_PUSH:
-                       break;
+                       return NULL;
                case EV_FORM_FIELD_BUTTON_CHECK:
                case EV_FORM_FIELD_BUTTON_RADIO: {
                case EV_FORM_FIELD_BUTTON_CHECK:
                case EV_FORM_FIELD_BUTTON_RADIO: {
-                       gboolean state;
+                       gboolean  state;
+                       GList    *forms_mapping, *l;
 
                        state = ev_document_forms_form_field_button_get_state (EV_DOCUMENT_FORMS (view->document),
                                                                               field);
 
                        state = ev_document_forms_form_field_button_get_state (EV_DOCUMENT_FORMS (view->document),
                                                                               field);
+
+                       /* FIXME: it actually depends on NoToggleToOff flags */
+                       if (field_button->type == EV_FORM_FIELD_BUTTON_RADIO &&
+                           state && field_button->state)
+                               return NULL;
+                       
+                       field_region = ev_view_form_field_get_region (view, field);
+
+                       /* For radio buttons and checkbox buttons that are in a set
+                        * 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);
+                       for (l = forms_mapping; l; l = g_list_next (l)) {
+                               EvFormField *button = ((EvFormFieldMapping *)(l->data))->field;
+                               GdkRegion   *button_region;
+
+                               if (button->id == field->id)
+                                       continue;
+
+                               /* FIXME: only buttons in the same group should be updated */
+                               if (!EV_IS_FORM_FIELD_BUTTON (button) ||
+                                   EV_FORM_FIELD_BUTTON (button)->type != field_button->type ||
+                                   EV_FORM_FIELD_BUTTON (button)->state != TRUE)
+                                       continue;
+
+                               button_region = ev_view_form_field_get_region (view, button);
+                               gdk_region_union (field_region, button_region);
+                               gdk_region_destroy (button_region);
+                       }
+                       
                        ev_document_forms_form_field_button_set_state (EV_DOCUMENT_FORMS (view->document),
                                                                       field, !state);
                        ev_document_forms_form_field_button_set_state (EV_DOCUMENT_FORMS (view->document),
                                                                       field, !state);
-                       ev_pixbuf_cache_reload_page (view->pixbuf_cache,
-                                                    field->page,
-                                                    view->rotation,
-                                                    view->scale);
+                       field_button->state = !state;
                }
                        break;
        }
                }
                        break;
        }
+
+       ev_pixbuf_cache_reload_page (view->pixbuf_cache,
+                                    field_region,
+                                    field->page,
+                                    view->rotation,
+                                    view->scale);
+       gdk_region_destroy (field_region);
        
        return NULL;
 }
        
        return NULL;
 }
@@ -1647,18 +1719,26 @@ ev_view_form_field_text_save (EvView    *view,
 {
        EvFormField *field;
 
 {
        EvFormField *field;
 
+       if (!view->document)
+               return;
+       
        field = g_object_get_data (G_OBJECT (widget), "form-field");
        
        if (field->changed) {
                EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (field);
        field = g_object_get_data (G_OBJECT (widget), "form-field");
        
        if (field->changed) {
                EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (field);
+               GdkRegion       *field_region;
+
+               field_region = ev_view_form_field_get_region (view, field);
                
                ev_document_forms_form_field_text_set_text (EV_DOCUMENT_FORMS (view->document),
                                                            field, field_text->text);
                field->changed = FALSE;
                ev_pixbuf_cache_reload_page (view->pixbuf_cache,
                
                ev_document_forms_form_field_text_set_text (EV_DOCUMENT_FORMS (view->document),
                                                            field, field_text->text);
                field->changed = FALSE;
                ev_pixbuf_cache_reload_page (view->pixbuf_cache,
+                                            field_region,
                                             field->page,
                                             view->rotation,
                                             view->scale);
                                             field->page,
                                             view->rotation,
                                             view->scale);
+               gdk_region_destroy (field_region);
        }
 }
 
        }
 }
 
@@ -1702,12 +1782,10 @@ ev_view_form_field_text_create_widget (EvView      *view,
                case EV_FORM_FIELD_TEXT_FILE_SELECT:
                        /* TODO */
                case EV_FORM_FIELD_TEXT_NORMAL:
                case EV_FORM_FIELD_TEXT_FILE_SELECT:
                        /* TODO */
                case EV_FORM_FIELD_TEXT_NORMAL:
-               case EV_FORM_FIELD_TEXT_PASSWORD:
                        text = gtk_entry_new ();
                        gtk_entry_set_has_frame (GTK_ENTRY (text), FALSE);
                        gtk_entry_set_max_length (GTK_ENTRY (text), field_text->max_len);
                        text = gtk_entry_new ();
                        gtk_entry_set_has_frame (GTK_ENTRY (text), FALSE);
                        gtk_entry_set_max_length (GTK_ENTRY (text), field_text->max_len);
-                       gtk_entry_set_visibility (GTK_ENTRY (text),
-                                                 !(field_text->type == EV_FORM_FIELD_TEXT_PASSWORD));
+                       gtk_entry_set_visibility (GTK_ENTRY (text), !field_text->is_password);
                        
                        if (txt) {
                                gtk_entry_set_text (GTK_ENTRY (text), txt);
                        
                        if (txt) {
                                gtk_entry_set_text (GTK_ENTRY (text), txt);
@@ -1726,7 +1804,7 @@ ev_view_form_field_text_create_widget (EvView      *view,
                
                        text = gtk_text_view_new ();
                        buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
                
                        text = gtk_text_view_new ();
                        buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
-               
+                       
                        if (txt) {
                                gtk_text_buffer_set_text (buffer, txt, -1);
                                g_free (txt);
                        if (txt) {
                                gtk_text_buffer_set_text (buffer, txt, -1);
                                g_free (txt);
@@ -1752,28 +1830,36 @@ ev_view_form_field_choice_save (EvView    *view,
 {
        EvFormField *field;
 
 {
        EvFormField *field;
 
+       if (!view->document)
+               return;
+       
        field = g_object_get_data (G_OBJECT (widget), "form-field");
 
        if (field->changed) {
                GList             *l;
                EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (field);
        field = g_object_get_data (G_OBJECT (widget), "form-field");
 
        if (field->changed) {
                GList             *l;
                EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (field);
+               GdkRegion         *field_region;
+
+               field_region = ev_view_form_field_get_region (view, field);
 
                if (field_choice->is_editable) {
                        ev_document_forms_form_field_choice_set_text (EV_DOCUMENT_FORMS (view->document),
                                                                      field, field_choice->text);
 
                if (field_choice->is_editable) {
                        ev_document_forms_form_field_choice_set_text (EV_DOCUMENT_FORMS (view->document),
                                                                      field, field_choice->text);
-               }
-               
-               ev_document_forms_form_field_choice_unselect_all (EV_DOCUMENT_FORMS (view->document), field);
-               for (l = field_choice->selected_items; l && l->data; l = g_list_next (l)) {
-                       ev_document_forms_form_field_choice_select_item (EV_DOCUMENT_FORMS (view->document),
-                                                                        field,
-                                                                        GPOINTER_TO_INT (l->data));
+               } else {
+                       ev_document_forms_form_field_choice_unselect_all (EV_DOCUMENT_FORMS (view->document), field);
+                       for (l = field_choice->selected_items; l; l = g_list_next (l)) {
+                               ev_document_forms_form_field_choice_select_item (EV_DOCUMENT_FORMS (view->document),
+                                                                                field,
+                                                                                GPOINTER_TO_INT (l->data));
+                       }
                }
                field->changed = FALSE;
                ev_pixbuf_cache_reload_page (view->pixbuf_cache,
                }
                field->changed = FALSE;
                ev_pixbuf_cache_reload_page (view->pixbuf_cache,
+                                            field_region,
                                             field->page,
                                             view->rotation,
                                             view->scale);
                                             field->page,
                                             view->rotation,
                                             view->scale);
+               gdk_region_destroy (field_region);
        }
 }
 
        }
 }
 
@@ -2357,8 +2443,9 @@ static gboolean
 ev_view_expose_event (GtkWidget      *widget,
                      GdkEventExpose *event)
 {
 ev_view_expose_event (GtkWidget      *widget,
                      GdkEventExpose *event)
 {
-       EvView *view = EV_VIEW (widget);
-       int i;
+       EvView  *view = EV_VIEW (widget);
+       cairo_t *cr;
+       gint     i;
 
        if (view->presentation) {
                switch (view->presentation_state) {
 
        if (view->presentation) {
                switch (view->presentation_state) {
@@ -2392,6 +2479,8 @@ ev_view_expose_event (GtkWidget      *widget,
        if (view->document == NULL)
                return FALSE;
 
        if (view->document == NULL)
                return FALSE;
 
+       cr = gdk_cairo_create (view->layout.bin_window);
+       
        for (i = view->start_page; i <= view->end_page; i++) {
                GdkRectangle page_area;
                GtkBorder border;
        for (i = view->start_page; i <= view->end_page; i++) {
                GdkRectangle page_area;
                GtkBorder border;
@@ -2403,12 +2492,14 @@ ev_view_expose_event (GtkWidget      *widget,
                page_area.x -= view->scroll_x;
                page_area.y -= view->scroll_y;
 
                page_area.x -= view->scroll_x;
                page_area.y -= view->scroll_y;
 
-               draw_one_page (view, i, &page_area, &border, &(event->area), &page_ready);
+               draw_one_page (view, i, cr, &page_area, &border, &(event->area), &page_ready);
 
                if (page_ready && EV_IS_DOCUMENT_FIND (view->document))
                        highlight_find_results (view, i);
        }
 
 
                if (page_ready && EV_IS_DOCUMENT_FIND (view->document))
                        highlight_find_results (view, i);
        }
 
+       cairo_destroy (cr);
+
        if (GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event)
                (* GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event) (widget, event);
 
        if (GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event)
                (* GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event) (widget, event);
 
@@ -2449,6 +2540,60 @@ ev_view_popup_menu (GtkWidget *widget)
        return ev_view_do_popup_menu (EV_VIEW (widget), x, y);
 }
 
        return ev_view_do_popup_menu (EV_VIEW (widget), x, y);
 }
 
+#if GTK_CHECK_VERSION (2, 11, 7)
+static void
+get_link_area (EvView       *view,
+              gint          x,
+              gint          y,
+              EvLink       *link,
+              GdkRectangle *area)
+{
+       EvRectangle  ev_rect;
+       GList       *link_mapping;
+       gint         page;
+       gint         x_offset = 0, y_offset = 0;
+
+       x += view->scroll_x;
+       y += view->scroll_y;
+       
+       find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
+       
+       link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page);
+       ev_link_mapping_get_area (link_mapping, link, &ev_rect);
+
+       doc_rect_to_view_rect (view, page, &ev_rect, area);
+       area->y -= view->scroll_y ;
+}
+
+static gboolean
+ev_view_query_tooltip (GtkWidget         *widget,
+                      gint               x,
+                      gint               y,
+                      gboolean           keyboard_tip,
+                      GtkTooltip        *tooltip)
+{
+       EvView *view = EV_VIEW (widget);
+       EvLink *link;
+       gchar  *text;
+
+       link = ev_view_get_link_at_location (view, x, y);
+       if (!link)
+               return FALSE;
+
+       text = tip_from_link (view, link);
+       if (text && g_utf8_validate (text, -1, NULL)) {
+               GdkRectangle link_area;
+
+               get_link_area (view, x, y, link, &link_area);
+               gtk_tooltip_set_text (tooltip, text);
+               gtk_tooltip_set_tip_area (tooltip, &link_area);
+       }
+       g_free (text);
+
+       return TRUE;
+}
+#endif /* GTK_CHECK_VERSION (2, 11, 7) */
+
 static gboolean
 ev_view_button_press_event (GtkWidget      *widget,
                            GdkEventButton *event)
 static gboolean
 ev_view_button_press_event (GtkWidget      *widget,
                            GdkEventButton *event)
@@ -3178,17 +3323,17 @@ ev_view_leave_notify_event (GtkWidget *widget, GdkEventCrossing   *event)
 {
        EvView *view = EV_VIEW (widget);
     
 {
        EvView *view = EV_VIEW (widget);
     
-       ev_view_set_status (view, NULL);
-
        if (view->cursor == EV_VIEW_CURSOR_LINK ||
            view->cursor == EV_VIEW_CURSOR_IBEAM)
                ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
 
        if (view->cursor == EV_VIEW_CURSOR_LINK ||
            view->cursor == EV_VIEW_CURSOR_IBEAM)
                ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
 
+#if !GTK_CHECK_VERSION (2, 11, 7)
        if (view->link_tooltip) {
                view->hovered_link = NULL;
                ev_tooltip_deactivate (EV_TOOLTIP (view->link_tooltip));
        }
        if (view->link_tooltip) {
                view->hovered_link = NULL;
                ev_tooltip_deactivate (EV_TOOLTIP (view->link_tooltip));
        }
-
+#endif
+       
        return FALSE;
 }
 
        return FALSE;
 }
 
@@ -3360,6 +3505,7 @@ draw_loading_text (EvView       *view,
 static void
 draw_one_page (EvView       *view,
               gint          page,
 static void
 draw_one_page (EvView       *view,
               gint          page,
+              cairo_t      *cr,
               GdkRectangle *page_area,
               GtkBorder    *border,
               GdkRectangle *expose_area,
               GdkRectangle *page_area,
               GtkBorder    *border,
               GdkRectangle *expose_area,
@@ -3398,7 +3544,6 @@ draw_one_page (EvView       *view,
                cairo_surface_t *page_surface = NULL;
                gint             selection_width, selection_height;
                cairo_surface_t *selection_surface = NULL;
                cairo_surface_t *page_surface = NULL;
                gint             selection_width, selection_height;
                cairo_surface_t *selection_surface = NULL;
-               cairo_t         *cr = NULL;
 
                page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
 
 
                page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
 
@@ -3416,16 +3561,10 @@ draw_one_page (EvView       *view,
                                        view->scale,
                                        &width, &height);
 
                                        view->scale,
                                        &width, &height);
 
-               cr = gdk_cairo_create (view->layout.bin_window);
-               
-               cairo_save (cr);
-               
                page_width = cairo_image_surface_get_width (page_surface);
                page_height = cairo_image_surface_get_height (page_surface);
                page_width = cairo_image_surface_get_width (page_surface);
                page_height = cairo_image_surface_get_height (page_surface);
-               
-               cairo_rectangle (cr, overlap.x, overlap.y, overlap.width, overlap.height);
-               cairo_clip (cr);
-               
+
+               cairo_save (cr);
                cairo_translate (cr, overlap.x, overlap.y);
                
                if (width != page_width || height != page_height) {
                cairo_translate (cr, overlap.x, overlap.y);
                
                if (width != page_width || height != page_height) {
@@ -3439,10 +3578,8 @@ draw_one_page (EvView       *view,
                cairo_surface_set_device_offset (page_surface,
                                                 overlap.x - real_page_area.x,
                                                 overlap.y - real_page_area.y);
                cairo_surface_set_device_offset (page_surface,
                                                 overlap.x - real_page_area.x,
                                                 overlap.y - real_page_area.y);
-
                cairo_set_source_surface (cr, page_surface, 0, 0);
                cairo_paint (cr);
                cairo_set_source_surface (cr, page_surface, 0, 0);
                cairo_paint (cr);
-
                cairo_restore (cr);
                
                /* Get the selection pixbuf iff we have something to draw */
                cairo_restore (cr);
                
                /* Get the selection pixbuf iff we have something to draw */
@@ -3456,16 +3593,13 @@ draw_one_page (EvView       *view,
                }
 
                if (!selection_surface) {
                }
 
                if (!selection_surface) {
-                       cairo_destroy (cr);
                        return;
                }
 
                selection_width = cairo_image_surface_get_width (selection_surface);
                selection_height = cairo_image_surface_get_height (selection_surface);
 
                        return;
                }
 
                selection_width = cairo_image_surface_get_width (selection_surface);
                selection_height = cairo_image_surface_get_height (selection_surface);
 
-               cairo_rectangle (cr, overlap.x, overlap.y, overlap.width, overlap.height);
-               cairo_clip (cr);
-               
+               cairo_save (cr);
                cairo_translate (cr, overlap.x, overlap.y);
 
                if (width != selection_width || height != selection_height) {
                cairo_translate (cr, overlap.x, overlap.y);
 
                if (width != selection_width || height != selection_height) {
@@ -3479,10 +3613,9 @@ draw_one_page (EvView       *view,
                cairo_surface_set_device_offset (selection_surface,
                                                 overlap.x - real_page_area.x,
                                                 overlap.y - real_page_area.y);
                cairo_surface_set_device_offset (selection_surface,
                                                 overlap.x - real_page_area.x,
                                                 overlap.y - real_page_area.y);
-
                cairo_set_source_surface (cr, selection_surface, 0, 0);
                cairo_paint (cr);
                cairo_set_source_surface (cr, selection_surface, 0, 0);
                cairo_paint (cr);
-               cairo_destroy (cr);
+               cairo_restore (cr);
        }
 }
 
        }
 }
 
@@ -3493,7 +3626,6 @@ ev_view_finalize (GObject *object)
 {
        EvView *view = EV_VIEW (object);
 
 {
        EvView *view = EV_VIEW (object);
 
-       g_free (view->status);
        g_free (view->find_status);
 
        clear_selection (view);
        g_free (view->find_status);
 
        clear_selection (view);
@@ -3520,11 +3652,12 @@ ev_view_destroy (GtkObject *object)
                view->pixbuf_cache = NULL;
        }
 
                view->pixbuf_cache = NULL;
        }
 
+#if !GTK_CHECK_VERSION (2, 11, 7)
        if (view->link_tooltip) {
                gtk_widget_destroy (view->link_tooltip);
                view->link_tooltip = NULL;
        }
        if (view->link_tooltip) {
                gtk_widget_destroy (view->link_tooltip);
                view->link_tooltip = NULL;
        }
-
+#endif
        if (view->goto_window) {
                gtk_widget_destroy (view->goto_window);
                view->goto_window = NULL;
        if (view->goto_window) {
                gtk_widget_destroy (view->goto_window);
                view->goto_window = NULL;
@@ -3628,11 +3761,8 @@ ev_view_get_property (GObject *object,
        EvView *view = EV_VIEW (object);
 
        switch (prop_id) {
        EvView *view = EV_VIEW (object);
 
        switch (prop_id) {
-               case PROP_STATUS:
-                       g_value_set_string (value, view->status);
-                       break;
                case PROP_FIND_STATUS:
                case PROP_FIND_STATUS:
-                       g_value_set_string (value, view->status);
+                       g_value_set_string (value, view->find_status);
                        break;
                case PROP_CONTINUOUS:
                        g_value_set_boolean (value, view->continuous);
                        break;
                case PROP_CONTINUOUS:
                        g_value_set_boolean (value, view->continuous);
@@ -3696,6 +3826,9 @@ ev_view_class_init (EvViewClass *class)
        widget_class->drag_motion = ev_view_drag_motion;
        widget_class->drag_data_received = ev_view_drag_data_received;
        widget_class->popup_menu = ev_view_popup_menu;
        widget_class->drag_motion = ev_view_drag_motion;
        widget_class->drag_data_received = ev_view_drag_data_received;
        widget_class->popup_menu = ev_view_popup_menu;
+#if GTK_CHECK_VERSION (2, 11, 7)
+       widget_class->query_tooltip = ev_view_query_tooltip;
+#endif
 
        gtk_object_class->destroy = ev_view_destroy;
 
 
        gtk_object_class->destroy = ev_view_destroy;
 
@@ -3745,13 +3878,6 @@ ev_view_class_init (EvViewClass *class)
                         G_TYPE_NONE, 1,
                         G_TYPE_OBJECT);
 
                         G_TYPE_NONE, 1,
                         G_TYPE_OBJECT);
 
-       g_object_class_install_property (object_class,
-                                        PROP_STATUS,
-                                        g_param_spec_string ("status",
-                                                             "Status Message",
-                                                             "The status message",
-                                                             NULL,
-                                                             G_PARAM_READABLE));
 
        g_object_class_install_property (object_class,
                                         PROP_FIND_STATUS,
 
        g_object_class_install_property (object_class,
                                         PROP_FIND_STATUS,
@@ -3836,6 +3962,15 @@ ev_view_class_init (EvViewClass *class)
        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);
        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);
+       
 }
 
 static void
 }
 
 static void
@@ -3895,9 +4030,15 @@ find_changed_cb (EvDocument *document, int page, EvView *view)
 
 static void
 job_finished_cb (EvPixbufCache *pixbuf_cache,
 
 static void
 job_finished_cb (EvPixbufCache *pixbuf_cache,
+                GdkRegion     *region,
                 EvView        *view)
 {
                 EvView        *view)
 {
-       gtk_widget_queue_draw (GTK_WIDGET (view));
+       if (region) {
+               gdk_window_invalidate_region (view->layout.bin_window,
+                                             region, TRUE);
+       } else {
+               gtk_widget_queue_draw (GTK_WIDGET (view));
+       }
 }
 
 static void
 }
 
 static void
@@ -4272,10 +4413,19 @@ ev_view_presentation_transition_start (EvView *view)
 
        duration = ev_document_transition_get_page_duration (EV_DOCUMENT_TRANSITION (view->document),
                                                             view->current_page);
 
        duration = ev_document_transition_get_page_duration (EV_DOCUMENT_TRANSITION (view->document),
                                                             view->current_page);
-       if (duration > 0)
-               view->trans_timeout_id = g_timeout_add (duration * 1000,
-                                                       (GSourceFunc) transition_next_page,
-                                                       view);
+       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
+       }
 }
 
 void
 }
 
 void
@@ -4615,13 +4765,14 @@ ev_view_zoom_for_size_single_page (EvView *view,
        ev_view_set_zoom (view, scale, FALSE);
 }
 
        ev_view_set_zoom (view, scale, FALSE);
 }
 
-void
+static void
 ev_view_set_zoom_for_size (EvView *view,
                           int     width,
                           int     height,
                           int     vsb_width,
                           int     hsb_height)
 {
 ev_view_set_zoom_for_size (EvView *view,
                           int     width,
                           int     height,
                           int     vsb_width,
                           int     hsb_height)
 {
+       g_return_if_fail (EV_IS_VIEW (view));
        g_return_if_fail (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
                          view->sizing_mode == EV_SIZING_BEST_FIT);
        g_return_if_fail (width >= 0);
        g_return_if_fail (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
                          view->sizing_mode == EV_SIZING_BEST_FIT);
        g_return_if_fail (width >= 0);
@@ -4642,28 +4793,7 @@ ev_view_set_zoom_for_size (EvView *view,
                ev_view_zoom_for_size_single_page (view, width, height, vsb_width, hsb_height);
 }
 
                ev_view_zoom_for_size_single_page (view, width, height, vsb_width, hsb_height);
 }
 
-/*** Status text messages ***/
-
-const char *
-ev_view_get_status (EvView *view)
-{
-       g_return_val_if_fail (EV_IS_VIEW (view), NULL);
-
-       return view->status;
-}
-
-static void
-ev_view_set_status (EvView *view, const char *message)
-{
-       g_return_if_fail (EV_IS_VIEW (view));
-
-       if (message != view->status) {
-               g_free (view->status);
-               view->status = g_strdup (message);
-               g_object_notify (G_OBJECT (view), "status");
-       }
-}
-
+/*** Find ***/
 static void
 update_find_status_message (EvView *view, gboolean this_page)
 {
 static void
 update_find_status_message (EvView *view, gboolean this_page)
 {
@@ -4713,8 +4843,6 @@ ev_view_set_find_status (EvView *view, const char *message)
        g_object_notify (G_OBJECT (view), "find-status");
 }
 
        g_object_notify (G_OBJECT (view), "find-status");
 }
 
-/*** Find ***/
-
 static void
 jump_to_find_result (EvView *view)
 {
 static void
 jump_to_find_result (EvView *view)
 {
@@ -5517,3 +5645,37 @@ ev_scroll_type_get_type (void)
   }
   return etype;
 }
   }
   return etype;
 }
+
+void
+ev_view_update_view_size (EvView *view, GtkScrolledWindow * scrolled_window)
+{
+       int width, height;
+       GtkRequisition vsb_requisition;
+       GtkRequisition hsb_requisition;
+       int scrollbar_spacing;
+       
+       /* Calculate the width available for the content */ 
+       width  = GTK_WIDGET (scrolled_window)->allocation.width;
+       height = GTK_WIDGET (scrolled_window)->allocation.height;
+
+       if (gtk_scrolled_window_get_shadow_type (scrolled_window) == GTK_SHADOW_IN 
+           && view) {
+               width -=  2 * GTK_WIDGET(view)->style->xthickness;
+               height -= 2 * GTK_WIDGET(view)->style->ythickness;
+       }
+
+       gtk_widget_size_request (scrolled_window->vscrollbar, &vsb_requisition);
+       gtk_widget_size_request (scrolled_window->hscrollbar, &hsb_requisition);
+       gtk_widget_style_get (GTK_WIDGET (scrolled_window), 
+                             "scrollbar_spacing", 
+                             &scrollbar_spacing, 
+                             NULL);
+       
+       if (EV_IS_VIEW(view)) {
+               ev_view_set_zoom_for_size (EV_VIEW (view),
+                                          MAX (1, width),
+                                          MAX (1, height),
+                                          vsb_requisition.width + scrollbar_spacing,
+                                          hsb_requisition.height + scrollbar_spacing);
+       }
+}