#include "ev-marshal.h"
#include "ev-view.h"
+#include "ev-utils.h"
#include "ev-selection.h"
#include "ev-document-find.h"
#include "ev-document-misc.h"
#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_STATUS,
PROP_PRESENTATION,
PROP_SIZING_MODE,
PROP_ZOOM,
+ PROP_ROTATION,
};
enum {
EV_VIEW_CURSOR_DRAG
} EvViewCursor;
+typedef enum {
+ EV_VIEW_FIND_NEXT,
+ EV_VIEW_FIND_PREV
+} EvViewFindDirection;
+
#define ZOOM_IN_FACTOR 1.2
#define ZOOM_OUT_FACTOR (1.0/ZOOM_IN_FACTOR)
char *status;
char *find_status;
+ /* Scrolling */
+ GtkAdjustment *hadjustment;
+ GtkAdjustment *vadjustment;
+
gint scroll_x;
gint scroll_y;
DragInfo drag_info;
/* Selection */
+ gint motion_x;
+ gint motion_y;
+ guint selection_update_id;
+
EvViewSelectionMode selection_mode;
SelectionInfo selection_info;
- gboolean pressed_button;
+ int pressed_button;
EvViewCursor cursor;
- GtkAdjustment *hadjustment;
- GtkAdjustment *vadjustment;
-
EvPageCache *page_cache;
EvPixbufCache *pixbuf_cache;
int find_result;
int spacing;
+ int rotation;
double scale;
gboolean continuous;
GdkEventMotion *event);
static gboolean ev_view_button_release_event (GtkWidget *widget,
GdkEventButton *event);
+static gboolean ev_view_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event);
+static void ev_view_style_set (GtkWidget *widget,
+ GtkStyle *old_style);
/*** Drawing ***/
static guint32 ev_gdk_color_to_rgb (const GdkColor *color);
const char *message);
/*** Find ***/
static void jump_to_find_result (EvView *view);
-static void jump_to_find_page (EvView *view);
+static void jump_to_find_page (EvView *view,
+ EvViewFindDirection direction);
/*** Selection ***/
static void compute_selections (EvView *view,
GdkPoint *start,
GdkPoint *stop);
static void clear_selection (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,
GtkSelectionData *selection_data,
static void
view_update_range_and_current_page (EvView *view)
{
+ if (view->pending_scroll != SCROLL_TO_KEEP_POSITION)
+ return;
+
/* Presentation trumps all other modes */
if (view->presentation) {
view->start_page = view->current_page;
ev_pixbuf_cache_set_page_range (view->pixbuf_cache,
view->start_page,
view->end_page,
+ view->rotation,
view->scale,
view->selection_info.selections);
}
GtkAdjustment *adjustment;
int value;
+ view->pending_scroll = SCROLL_TO_KEEP_POSITION;
+
adjustment = view->vadjustment;
if (rect->y < adjustment->value) {
}
}
-static void get_page_y_offset (EvView *view,
- int page,
- double zoom,
- int *y_offset)
+static void
+get_page_y_offset (EvView *view, int page, double zoom, int *y_offset)
{
int max_width, offset;
GtkBorder border;
g_return_if_fail (y_offset != NULL);
- ev_page_cache_get_max_width (view->page_cache, zoom, &max_width);
+ ev_page_cache_get_max_width (view->page_cache, view->rotation, zoom, &max_width);
compute_border (view, max_width, max_width, &border);
if (view->dual_page) {
- ev_page_cache_get_height_to_page (view->page_cache, page, zoom, NULL, &offset);
+ ev_page_cache_get_height_to_page (view->page_cache, page,
+ view->rotation, zoom, NULL, &offset);
offset += (page / 2 + 1) * view->spacing + (page / 2) * (border.top + border.bottom);
} else {
- ev_page_cache_get_height_to_page (view->page_cache, page, zoom, &offset, NULL);
+ ev_page_cache_get_height_to_page (view->page_cache, page,
+ view->rotation, zoom, &offset, NULL);
offset += (page + 1) * view->spacing + page * (border.top + border.bottom);
}
/* Get the size of the page */
ev_page_cache_get_size (view->page_cache, page,
+ view->rotation,
view->scale,
&width, &height);
compute_border (view, width, height, border);
gint max_width;
gint x, y;
- ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
+ ev_page_cache_get_max_width (view->page_cache, view->rotation,
+ view->scale, &max_width);
max_width = max_width + border->left + border->right;
/* Get the location of the bounding box */
if (view->dual_page) {
if (other_page < ev_page_cache_get_n_pages (view->page_cache)) {
ev_page_cache_get_size (view->page_cache,
other_page,
+ view->rotation,
view->scale,
&width_2, &height_2);
if (width_2 > width)
{
GdkRectangle page_area;
GtkBorder border;
+ double x, y, w, h;
int width, height;
+ ev_page_cache_get_size (view->page_cache, page,
+ view->rotation,
+ 1.0,
+ &width, &height);
+
+ if (view->rotation == 0) {
+ x = doc_rect->x1;
+ y = doc_rect->y1;
+ w = doc_rect->x2 - doc_rect->x1;
+ h = doc_rect->y2 - doc_rect->y1;
+ } else if (view->rotation == 90) {
+ x = width - doc_rect->y2;
+ y = doc_rect->x1;
+ w = doc_rect->y2 - doc_rect->y1;
+ h = doc_rect->x2 - doc_rect->x1;
+ } else if (view->rotation == 180) {
+ x = width - doc_rect->x2;
+ y = height - doc_rect->y2;
+ w = doc_rect->x2 - doc_rect->x1;
+ h = doc_rect->y2 - doc_rect->y1;
+ } else if (view->rotation == 270) {
+ x = doc_rect->y1;
+ y = height - doc_rect->x2;
+ w = doc_rect->y2 - doc_rect->y1;
+ h = doc_rect->x2 - doc_rect->x1;
+ } else {
+ g_assert_not_reached ();
+ }
+
get_page_extents (view, page, &page_area, &border);
- width = doc_rect->x2 - doc_rect->x1;
- height = doc_rect->y2 - doc_rect->y1;
- view_rect->x = floor (doc_rect->x1 * view->scale) + page_area.x;
- view_rect->y = floor (doc_rect->y1 * view->scale) + page_area.y;
- view_rect->width = ceil (width * view->scale);
- view_rect->height = ceil (height * view->scale);
+ view_rect->x = x * view->scale + page_area.x;
+ view_rect->y = y * view->scale + page_area.y;
+ view_rect->width = w * view->scale;
+ view_rect->height = h * view->scale;
}
static void
gint n_pages;
GtkBorder border;
- ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
+ ev_page_cache_get_max_width (view->page_cache, view->rotation,
+ view->scale, &max_width);
compute_border (view, max_width, max_width, &border);
n_pages = ev_page_cache_get_n_pages (view->page_cache) + 1;
GtkBorder border;
- ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
+ ev_page_cache_get_max_width (view->page_cache, view->rotation,
+ view->scale, &max_width);
n_pages = ev_page_cache_get_n_pages (view->page_cache);
compute_border (view, max_width, max_width, &border);
/* Find the largest of the two. */
ev_page_cache_get_size (view->page_cache,
view->current_page,
+ view->rotation,
view->scale,
&width, &height);
if (view->current_page + 1 < ev_page_cache_get_n_pages (view->page_cache)) {
gint width_2, height_2;
ev_page_cache_get_size (view->page_cache,
view->current_page + 1,
+ view->rotation,
view->scale,
&width_2, &height_2);
if (width_2 > width) {
ev_page_cache_get_size (view->page_cache,
view->current_page,
+ view->rotation,
view->scale,
&width, &height);
compute_border (view, width, height, &border);
return FALSE;
}
+
+static gboolean
+selection_update_idle_cb (EvView *view)
+{
+ GdkPoint point;
+ point.x = view->motion_x;
+ point.y = view->motion_y;
+ compute_selections (view, &view->selection_info.start, &point);
+
+ view->selection_update_id = 0;
+ return FALSE;
+}
+
static gboolean
ev_view_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event)
if (!view->document)
return FALSE;
- if (view->pressed_button == 1) {
- GdkPoint point;
-
+ /* For the Evince 0.4.x release, we limit selection to un-rotated
+ * documents only.
+ */
+ if (view->pressed_button == 1 &&
+ view->rotation == 0) {
view->selection_info.in_selection = TRUE;
- point.x = event->x + view->scroll_x;
- point.y = event->y + view->scroll_y;
- compute_selections (view, &view->selection_info.start, &point);
+ view->motion_x = event->x + view->scroll_x;
+ view->motion_y = event->y + view->scroll_y;
+
+ /* Queue an idle to handle the motion. We do this because
+ * handling any selection events in the motion could be slower
+ * than new motion events reach us. We always put it in the
+ * idle to make sure we catch up and don't visibly lag the
+ * mouse. */
+ if (! view->selection_update_id)
+ view->selection_update_id = g_idle_add ((GSourceFunc)selection_update_idle_cb, view);
return TRUE;
} else if (view->pressed_button == 2) {
return TRUE;
}
- } else if (view->pressed_button <= 0) {
+ /* For the Evince 0.4.x release, we limit links to un-rotated documents
+ * only.
+ */
+ } else if (view->pressed_button <= 0 &&
+ view->rotation == 0) {
EvLink *link;
link = get_link_at_location (view, event->x + view->scroll_x, event->y + view->scroll_y);
return FALSE;
}
+static gint
+ev_view_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ if (EV_VIEW (widget)->pixbuf_cache)
+ ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
+ gtk_widget_queue_draw (widget);
+
+ return FALSE;
+}
+
+static gint
+ev_view_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ if (EV_VIEW (widget)->pixbuf_cache)
+ ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
+ gtk_widget_queue_draw (widget);
+
+ return FALSE;
+}
+
+static gboolean
+ev_view_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event)
+{
+ 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);
+
+ return FALSE;
+}
+
+static void
+ev_view_style_set (GtkWidget *widget,
+ GtkStyle *old_style)
+{
+ if (EV_VIEW (widget)->pixbuf_cache)
+ ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
+
+ GTK_WIDGET_CLASS (ev_view_parent_class)->style_set (widget, old_style);
+}
+
+
/*** Drawing ***/
static guint32
alpha = 0x20;
}
- ev_document_find_get_result (find, page,
- i, &rectangle);
+ ev_document_find_get_result (find, page, i, &rectangle);
doc_rect_to_view_rect (view, page, &rectangle, &view_rectangle);
draw_rubberband (GTK_WIDGET (view), GTK_WIDGET(view)->window,
&view_rectangle, alpha);
selection = find_selection_for_page (view, page);
ev_page_cache_get_size (view->page_cache,
- page, view->scale,
+ page, view->rotation,
+ view->scale,
&width, &height);
/* Render the document itself */
real_page_area = *page_area;
if (current_pixbuf && view->selection_mode == EV_VIEW_SELECTION_TEXT && selection)
selection_pixbuf = ev_pixbuf_cache_get_selection_pixbuf (view->pixbuf_cache,
page,
- view->scale);
+ view->scale,
+ NULL);
if (current_pixbuf == NULL)
scaled_image = NULL;
case PROP_ZOOM:
ev_view_set_zoom (view, g_value_get_double (value), FALSE);
break;
+ case PROP_ROTATION:
+ ev_view_set_rotation (view, g_value_get_int (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
case PROP_ZOOM:
g_value_set_double (value, view->scale);
break;
+ case PROP_ROTATION:
+ g_value_set_int (value, view->rotation);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
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->focus_in_event = ev_view_focus_in;
+ widget_class->focus_out_event = ev_view_focus_out;
widget_class->size_request = ev_view_size_request;
widget_class->size_allocate = ev_view_size_allocate;
widget_class->realize = ev_view_realize;
widget_class->unrealize = ev_view_unrealize;
widget_class->scroll_event = ev_view_scroll_event;
+ widget_class->leave_notify_event = ev_view_leave_notify_event;
+ widget_class->style_set = ev_view_style_set;
gtk_object_class->destroy = ev_view_destroy;
class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
MAX_SCALE,
1.0,
G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_ROTATION,
+ g_param_spec_double ("rotation",
+ "Rotation",
+ "Rotation",
+ 0,
+ 360,
+ 0,
+ G_PARAM_READWRITE));
binding_set = gtk_binding_set_by_class (class);
static void
find_changed_cb (EvDocument *document, int page, EvView *view)
{
- jump_to_find_page (view);
+ jump_to_find_page (view, EV_VIEW_FIND_NEXT);
jump_to_find_result (view);
update_find_status_message (view);
{
view->page_cache = ev_page_cache_get (view->document);
g_signal_connect (view->page_cache, "page-changed", G_CALLBACK (page_changed_cb), view);
- view->pixbuf_cache = ev_pixbuf_cache_new (view->document);
+ 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);
}
view->pixbuf_cache = NULL;
}
- if (view->document) {
- ev_page_cache_clear (view->document);
+ if (view->page_cache) {
+ g_object_unref (view->page_cache);
+ view->page_cache = NULL;
}
}
ev_view_set_zoom (view, ZOOM_OUT_FACTOR, TRUE);
}
-static void
-ev_view_set_orientation (EvView *view,
- EvOrientation orientation)
+void
+ev_view_rotate_right (EvView *view)
{
- ev_document_set_orientation (view->document, orientation);
+ int rotation = view->rotation + 90;
- clear_caches (view);
- setup_caches (view);
+ if (rotation >= 360) {
+ rotation -= 360;
+ }
- gtk_widget_queue_resize (GTK_WIDGET (view));
+ ev_view_set_rotation (view, rotation);
}
void
-ev_view_rotate_right (EvView *view)
+ev_view_rotate_left (EvView *view)
{
- EvOrientation orientation, new_orientation;
+ int rotation = view->rotation - 90;
- orientation = ev_document_get_orientation (view->document);
- if (orientation == EV_ORIENTATION_PORTRAIT) {
- new_orientation = EV_ORIENTATION_LANDSCAPE;
- } else if (orientation == EV_ORIENTATION_LANDSCAPE) {
- new_orientation = EV_ORIENTATION_UPSIDEDOWN;
- } else if (orientation == EV_ORIENTATION_UPSIDEDOWN) {
- new_orientation = EV_ORIENTATION_SEASCAPE;
- } else {
- new_orientation = EV_ORIENTATION_PORTRAIT;
+ if (rotation < 0) {
+ rotation += 360;
}
- ev_view_set_orientation (view, new_orientation);
+
+ ev_view_set_rotation (view, rotation);
}
void
-ev_view_rotate_left (EvView *view)
+ev_view_set_rotation (EvView *view, int rotation)
{
- EvOrientation orientation, new_orientation;
+ view->rotation = rotation;
- orientation = ev_document_get_orientation (view->document);
- if (orientation == EV_ORIENTATION_PORTRAIT) {
- new_orientation = EV_ORIENTATION_SEASCAPE;
- } else if (orientation == EV_ORIENTATION_SEASCAPE) {
- new_orientation = EV_ORIENTATION_UPSIDEDOWN;
- } else if (orientation == EV_ORIENTATION_UPSIDEDOWN) {
- new_orientation = EV_ORIENTATION_LANDSCAPE;
- } else {
- new_orientation = EV_ORIENTATION_PORTRAIT;
+ if (view->pixbuf_cache) {
+ ev_pixbuf_cache_clear (view->pixbuf_cache);
+ gtk_widget_queue_resize (GTK_WIDGET (view));
}
- ev_view_set_orientation (view, new_orientation);
+
+ g_object_notify (G_OBJECT (view), "rotation");
+}
+
+int
+ev_view_get_rotation (EvView *view)
+{
+ return view->rotation;
}
static double
ev_page_cache_get_size (view->page_cache,
view->current_page,
+ view->rotation,
1.0,
&doc_width,
&doc_height);
gdouble scale;
ev_page_cache_get_max_width (view->page_cache,
+ view->rotation,
1.0,
&doc_width);
ev_page_cache_get_max_height (view->page_cache,
+ view->rotation,
1.0,
&doc_height);
compute_border (view, doc_width, doc_height, &border);
gdouble scale;
ev_page_cache_get_max_width (view->page_cache,
+ view->rotation,
1.0,
&doc_width);
ev_page_cache_get_max_height (view->page_cache,
+ view->rotation,
1.0,
&doc_height);
compute_border (view, doc_width, doc_height, &border);
/* Find the largest of the two. */
ev_page_cache_get_size (view->page_cache,
view->current_page,
+ view->rotation,
1.0,
&doc_width, &doc_height);
gint width_2, height_2;
ev_page_cache_get_size (view->page_cache,
other_page,
+ view->rotation,
1.0,
&width_2, &height_2);
if (width_2 > doc_width)
ev_page_cache_get_size (view->page_cache,
view->current_page,
+ view->rotation,
1.0,
&doc_width,
&doc_height);
n_results = ev_document_find_get_n_results (find, page);
- if (n_results > view->find_result) {
+ if (n_results > 0 && view->find_result < n_results) {
ev_document_find_get_result
(find, page, view->find_result, &rect);
}
static void
-jump_to_find_page (EvView *view)
+jump_to_find_page (EvView *view, EvViewFindDirection direction)
{
int n_pages, i;
for (i = 0; i < n_pages; i++) {
int has_results;
int page;
+
+ if (direction == EV_VIEW_FIND_NEXT)
+ page = view->find_page + i;
+ else
+ page = view->find_page - i;
+
- page = i + view->find_page;
if (page >= n_pages) {
page = page - n_pages;
}
-
+ 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) {
ev_page_cache_set_current_page (view->page_cache, page);
- jump_to_find_result (view);
break;
}
}
void
ev_view_find_next (EvView *view)
{
- EvPageCache *page_cache;
int n_results, n_pages;
EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
- 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);
+ n_pages = ev_page_cache_get_n_pages (view->page_cache);
view->find_result++;
if (view->find_result >= n_results) {
+
view->find_result = 0;
view->find_page++;
-
if (view->find_page >= n_pages) {
view->find_page = 0;
}
- jump_to_find_page (view);
+ jump_to_find_page (view, EV_VIEW_FIND_NEXT);
+ jump_to_find_result (view);
} else {
jump_to_find_result (view);
gtk_widget_queue_draw (GTK_WIDGET (view));
view->find_result--;
if (view->find_result < 0) {
- view->find_result = 0;
- view->find_page--;
+ view->find_page--;
if (view->find_page < 0) {
view->find_page = n_pages - 1;
}
- jump_to_find_page (view);
+ jump_to_find_page (view, EV_VIEW_FIND_PREV);
+ view->find_result = ev_document_find_get_n_results (find, view->current_page) - 1;
+ jump_to_find_result (view);
} else {
jump_to_find_result (view);
gtk_widget_queue_draw (GTK_WIDGET (view));
GList *list = NULL;
EvViewSelection *selection;
gint width, height;
+ int start_page, end_page;
g_assert (view->selection_mode == EV_VIEW_SELECTION_TEXT);
* affects. */
first = n_pages;
last = 0;
- for (i = 0; i < n_pages; i++) {
+ if (view->continuous) {
+ start_page = 0;
+ end_page = n_pages;
+ } else if (view->dual_page) {
+ start_page = view->start_page;
+ end_page = view->end_page + 1;
+ } else {
+ start_page = view->current_page;
+ end_page = view->current_page + 1;
+ }
+
+ for (i = start_page; i < end_page; i++) {
GdkRectangle page_area;
GtkBorder border;
GdkPoint *point;
ev_page_cache_get_size (view->page_cache, i,
+ view->rotation,
1.0, &width, &height);
selection = g_new0 (EvViewSelection, 1);
*/
static void
merge_selection_region (EvView *view,
- GList *list)
+ GList *new_list)
{
+ GList *old_list;
+ GList *new_list_ptr, *old_list_ptr;
- /* FIXME: actually write... */
- clear_selection (view);
- gtk_widget_queue_draw (GTK_WIDGET (view));
+ /* Update the selection */
+ old_list = ev_pixbuf_cache_get_selection_list (view->pixbuf_cache);
+ g_list_foreach (view->selection_info.selections, (GFunc)selection_free, NULL);
+ view->selection_info.selections = new_list;
+ ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, new_list);
+
+ new_list_ptr = new_list;
+ old_list_ptr = old_list;
+
+ while (new_list_ptr || old_list_ptr) {
+ EvViewSelection *old_sel, *new_sel;
+ int cur_page;
+ GdkRegion *region = NULL;
+
+ new_sel = (new_list_ptr) ? (new_list_ptr->data) : NULL;
+ old_sel = (old_list_ptr) ? (old_list_ptr->data) : NULL;
+
+ /* Assume that the lists are in order, and we run through them
+ * comparing them, one page at a time. We come out with the
+ * first page we see. */
+ if (new_sel && old_sel) {
+ if (new_sel->page < old_sel->page) {
+ new_list_ptr = new_list_ptr->next;
+ old_sel = NULL;
+ } else if (new_sel->page > old_sel->page) {
+ old_list_ptr = old_list_ptr->next;
+ new_sel = NULL;
+ } else {
+ new_list_ptr = new_list_ptr->next;
+ old_list_ptr = old_list_ptr->next;
+ }
+ } else if (new_sel) {
+ new_list_ptr = new_list_ptr->next;
+ } else if (old_sel) {
+ old_list_ptr = old_list_ptr->next;
+ }
+
+ g_assert (new_sel || old_sel);
- view->selection_info.selections = list;
- ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, list);
+ /* is the page we're looking at on the screen?*/
+ cur_page = new_sel ? new_sel->page : old_sel->page;
+ if (cur_page < view->start_page || cur_page > view->end_page)
+ continue;
+
+ /* seed the cache with a new page. We are going to need the new
+ * region too. */
+ if (new_sel) {
+ GdkRegion *tmp_region = NULL;
+ ev_pixbuf_cache_get_selection_pixbuf (view->pixbuf_cache,
+ cur_page,
+ view->scale,
+ &tmp_region);
+ if (tmp_region) {
+ new_sel->covered_region = gdk_region_copy (tmp_region);
+ }
+ }
+
+ /* Now we figure out what needs redrawing */
+ if (old_sel && new_sel) {
+ if (old_sel->covered_region &&
+ new_sel->covered_region) {
+ /* We only want to redraw the areas that have
+ * changed, so we xor the old and new regions
+ * and redraw if it's different */
+ region = gdk_region_copy (old_sel->covered_region);
+ gdk_region_xor (region, new_sel->covered_region);
+ if (gdk_region_empty (region)) {
+ gdk_region_destroy (region);
+ region = NULL;
+ }
+ } else if (old_sel->covered_region) {
+ region = gdk_region_copy (old_sel->covered_region);
+ } else if (new_sel->covered_region) {
+ region = gdk_region_copy (new_sel->covered_region);
+ }
+ } else if (old_sel && !new_sel) {
+ if (old_sel->covered_region && !gdk_region_empty (old_sel->covered_region)) {
+ region = gdk_region_copy (old_sel->covered_region);
+ }
+ } else if (!old_sel && new_sel) {
+ if (new_sel->covered_region && !gdk_region_empty (new_sel->covered_region)) {
+ region = gdk_region_copy (new_sel->covered_region);
+ }
+ } else {
+ g_assert_not_reached ();
+ }
+
+ /* Redraw the damaged region! */
+ if (region) {
+ GdkRectangle page_area;
+ GtkBorder border;
+
+ get_page_extents (view, cur_page, &page_area, &border);
+ gdk_region_offset (region,
+ page_area.x + border.left - view->scroll_x,
+ page_area.y + border.top - view->scroll_y);
+ gdk_window_invalidate_region (GTK_WIDGET (view)->window, region, TRUE);
+ gdk_region_destroy (region);
+ }
+ }
+
+ /* Free the old list, now that we're done with it. */
+ g_list_foreach (old_list, (GFunc) selection_free, NULL);
}
static void
static void
selection_free (EvViewSelection *selection)
{
+ if (selection->covered_region)
+ gdk_region_destroy (selection->covered_region);
g_free (selection);
}
EvViewSelection *selection;
ev_page_cache_get_size (view->page_cache,
- i, 1.0, &width, &height);
+ i,
+ view->rotation,
+ 1.0, &width, &height);
selection = g_new0 (EvViewSelection, 1);
selection->page = i;