27 #include <glib/gi18n-lib.h>
29 #include <gdk/gdkkeysyms.h>
40 #include "ev-view-marshal.h"
46 #include "ev-view-type-builtins.h"
49 #ifdef ENABLE_MULTIMEDIA
105 #define MIN_SCALE 0.2
106 #define ZOOM_IN_FACTOR 1.2
107 #define ZOOM_OUT_FACTOR (1.0/ZOOM_IN_FACTOR)
109 #define SCROLL_TIME 150
111 #define DEFAULT_PIXBUF_CACHE_SIZE 52428800
113 #define EV_STYLE_CLASS_DOCUMENT_PAGE "document-page"
114 #define EV_STYLE_CLASS_INVERTED "inverted"
116 #define ANNOT_POPUP_WINDOW_DEFAULT_WIDTH 200
117 #define ANNOT_POPUP_WINDOW_DEFAULT_HEIGHT 150
118 #define ANNOTATION_ICON_SIZE 24
168 GtkRequisition *requisition);
170 GtkRequisition *requisition);
172 GtkRequisition *requisition);
174 GtkRequisition *requisition);
176 GtkRequisition *requisition);
178 GtkAllocation *allocation);
180 GdkEventScroll *event);
185 GdkEventButton *event);
187 GdkEventMotion *event);
189 GdkEventButton *event);
191 GdkEventCrossing *event);
193 GdkEventCrossing *event);
210 GdkRectangle *page_area,
212 GdkRectangle *expose_area,
213 gboolean *page_ready);
216 cairo_region_t *region);
221 cairo_region_t *region,
271 GtkOrientation orientation);
302 GtkSelectionData *selection_data,
313 G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
316 #define EV_HEIGHT_TO_PAGE_CACHE_KEY "ev-height-to-page-cache"
319 ev_view_build_height_to_page_cache (
EvView *view,
322 gboolean swap, uniform;
324 double uniform_height, page_height, next_page_height;
326 gdouble u_width, u_height;
347 for (i = 0; i <= n_pages; i++) {
349 uniform_height = swap ? u_width : u_height;
356 page_height = swap ? w : h;
361 saved_height += page_height;
369 saved_height = swap ? w : h;
376 uniform_height = swap ? u_width : u_height;
378 if (i + 1 < n_pages + 2)
381 if (i + 1 < n_pages) {
385 next_page_height = swap ? w : h;
387 next_page_height = 0;
394 page_height = swap ? w : h;
399 if (i + 1 < n_pages + 2) {
402 saved_height += MAX(page_height, next_page_height);
436 ev_view_build_height_to_page_cache (view, cache);
437 g_object_set_data_full (G_OBJECT (view->
document),
461 ev_view_build_height_to_page_cache (view, cache);
466 *height = (gint)(h * view->
scale + 0.5);
471 *dual_height = (gint)(dh * view->
scale + 0.5);
477 GtkOrientation orientation)
479 GtkWidget *widget = GTK_WIDGET (view);
481 GtkWidget *swindow = gtk_widget_get_parent (GTK_WIDGET (view));
482 GtkAllocation allocation;
486 if (!GTK_IS_SCROLLED_WINDOW (swindow))
489 gtk_widget_get_allocation (widget, &allocation);
491 if (orientation == GTK_ORIENTATION_VERTICAL) {
493 sb = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (swindow));
498 sb = gtk_scrolled_window_get_hscrollbar (GTK_SCROLLED_WINDOW (swindow));
503 gtk_widget_style_get (swindow,
"scrollbar_spacing", &spacing, NULL);
504 gtk_widget_get_preferred_size (sb, &req, NULL);
506 return (orientation == GTK_ORIENTATION_VERTICAL ? req.width : req.height) + spacing;
511 gboolean *odd_left_out)
513 gboolean dual =
FALSE;
514 gboolean odd_left =
FALSE;
522 GtkAllocation allocation;
524 screen = gtk_widget_get_screen (GTK_WIDGET (view));
528 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
532 doc_width < doc_height &&
533 allocation.width > (2 * doc_width * scale) &&
534 allocation.height > (doc_height * scale * 0.9)) {
547 g_assert_not_reached ();
551 *odd_left_out = odd_left;
560 GtkOrientation orientation)
563 gdouble upper, lower;
565 if (orientation == GTK_ORIENTATION_VERTICAL) {
566 page_size = gtk_adjustment_get_page_size (view->
vadjustment);
567 upper = gtk_adjustment_get_upper (view->
vadjustment);
568 lower = gtk_adjustment_get_lower (view->
vadjustment);
575 CLAMP (y, lower, upper - page_size));
578 page_size = gtk_adjustment_get_page_size (view->
hadjustment);
579 upper = gtk_adjustment_get_upper (view->
hadjustment);
580 lower = gtk_adjustment_get_lower (view->
hadjustment);
587 CLAMP (x, lower, upper - page_size));
600 if ((orientation == GTK_ORIENTATION_VERTICAL && view->
pending_point.
y == 0) ||
601 (orientation == GTK_ORIENTATION_HORIZONTAL && view->
pending_point.
x == 0)) {
602 GdkRectangle page_area;
622 GtkOrientation orientation)
624 GtkWidget *widget = GTK_WIDGET (view);
625 GtkAdjustment *adjustment;
626 GtkAllocation allocation;
636 gtk_widget_get_allocation (widget, &allocation);
638 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
640 alloc_size = allocation.width;
645 alloc_size = allocation.height;
654 value = gtk_adjustment_get_value (adjustment);
655 upper = gtk_adjustment_get_upper (adjustment);
656 page_size = gtk_adjustment_get_page_size (adjustment);
658 zoom_center = page_size * 0.5;
664 factor = value / upper;
669 factor = (value + zoom_center) / upper;
674 upper = MAX (alloc_size, req_size);
675 page_size = alloc_size;
677 gtk_adjustment_set_page_size (adjustment, page_size);
678 gtk_adjustment_set_step_increment (adjustment, alloc_size * 0.1);
679 gtk_adjustment_set_page_increment (adjustment, alloc_size * 0.9);
680 gtk_adjustment_set_lower (adjustment, 0);
681 gtk_adjustment_set_upper (adjustment, upper);
689 new_value = CLAMP (upper * factor + 0.5, 0, upper - page_size);
690 gtk_adjustment_set_value (adjustment, (
int)new_value);
696 new_value = CLAMP (upper * factor - zoom_center + 0.5, 0, upper - page_size);
697 if (orientation == GTK_ORIENTATION_HORIZONTAL)
701 gtk_adjustment_set_value (adjustment, (
int)new_value);
705 gtk_adjustment_changed (adjustment);
720 GdkRectangle current_area, unused, page_area;
722 gboolean found =
FALSE;
723 gint area_max = -1, area;
724 gint best_current_page = -1;
730 current_area.x = gtk_adjustment_get_value (view->
hadjustment);
731 current_area.width = gtk_adjustment_get_page_size (view->
hadjustment);
732 current_area.y = gtk_adjustment_get_value (view->
vadjustment);
733 current_area.height = gtk_adjustment_get_page_size (view->
vadjustment);
739 if (gdk_rectangle_intersect (¤t_area, &page_area, &unused)) {
740 area = unused.width * unused.height;
746 best_current_page = i;
748 if (area > area_max) {
749 best_current_page = (area == area_max) ? MIN (i, best_current_page) : i;
769 best_current_page = MAX (best_current_page, view->
start_page);
771 if (best_current_page >= 0 && view->
current_page != best_current_page) {
802 for (i = start; i < view->
start_page && start != -1; i++) {
806 for (i = end; i > view->
end_page && end != -1; i--) {
826 gtk_widget_queue_draw (GTK_WIDGET (view));
831 GtkOrientation orientation,
832 GtkAdjustment *adjustment)
834 GtkAdjustment **to_set;
835 const gchar *prop_name;
837 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
839 prop_name =
"hadjustment";
842 prop_name =
"vadjustment";
845 if (adjustment && adjustment == *to_set)
849 g_signal_handlers_disconnect_by_func (*to_set,
852 g_object_unref (*to_set);
856 adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
857 g_signal_connect (adjustment,
"value_changed",
860 *to_set = g_object_ref_sink (adjustment);
863 g_object_notify (G_OBJECT (view), prop_name);
869 GdkModifierType modifiers,
870 GtkScrollType scroll,
871 GtkOrientation orientation)
873 guint keypad_keyval = keyval - GDK_KEY_Left + GDK_KEY_KP_Left;
875 gtk_binding_entry_add_signal (binding_set, keyval, modifiers,
877 GTK_TYPE_SCROLL_TYPE, scroll,
878 GTK_TYPE_ORIENTATION, orientation);
879 gtk_binding_entry_add_signal (binding_set, keypad_keyval, modifiers,
881 GTK_TYPE_SCROLL_TYPE, scroll,
882 GTK_TYPE_ORIENTATION, orientation);
887 GtkScrollType scroll)
889 GtkWidget *widget = GTK_WIDGET (view);
891 cairo_region_t *text_region, *region;
892 GtkAllocation allocation;
896 GdkRectangle page_area;
898 gdouble fraction = 1.0;
900 if (scroll != GTK_SCROLL_PAGE_BACKWARD && scroll != GTK_SCROLL_PAGE_FORWARD)
901 return gtk_adjustment_get_page_size (adjustment);
906 if (!text_region || cairo_region_is_empty (text_region))
907 return gtk_adjustment_get_page_size (adjustment);
909 gtk_widget_get_allocation (widget, &allocation);
911 rect.x = page_area.x + view->
scroll_x;
912 rect.y = view->
scroll_y + (scroll == GTK_SCROLL_PAGE_BACKWARD ? 5 : allocation.height - 5);
913 rect.width = page_area.width;
918 rect.x = doc_rect.
x1;
919 rect.y = doc_rect.
y1;
920 rect.width = doc_rect.
x2 - doc_rect.
x1;
921 rect.height = MAX (1, doc_rect.
y2 - doc_rect.
y1);
922 region = cairo_region_create_rectangle (&rect);
924 cairo_region_intersect (region, text_region);
925 if (cairo_region_num_rectangles (region)) {
928 cairo_region_t *sel_region;
930 cairo_region_get_rectangle (region, 0, &rect);
934 page_area.width - (border.left + border.right),
935 page_area.height - (border.left + border.right));
936 g_object_unref (ev_page);
938 doc_rect.
x1 = doc_rect.
x2 = rect.x + 0.5;
939 doc_rect.
y1 = doc_rect.
y2 = rect.y + 0.5;
949 if (cairo_region_num_rectangles (sel_region) > 0) {
950 cairo_region_get_rectangle (sel_region, 0, &rect);
951 fraction = 1 - (rect.height / gtk_adjustment_get_page_size (adjustment));
953 cairo_region_destroy (sel_region);
955 cairo_region_destroy (region);
957 return gtk_adjustment_get_page_size (adjustment) * fraction;
992 GtkScrollType scroll,
995 GtkAdjustment *adjustment;
996 double value, increment;
997 gdouble upper, lower;
999 gdouble step_increment;
1000 gboolean first_page =
FALSE;
1001 gboolean last_page =
FALSE;
1011 case GTK_SCROLL_PAGE_BACKWARD:
1012 case GTK_SCROLL_STEP_BACKWARD:
1015 case GTK_SCROLL_PAGE_FORWARD:
1016 case GTK_SCROLL_STEP_FORWARD:
1019 case GTK_SCROLL_START:
1022 case GTK_SCROLL_END:
1033 value = gtk_adjustment_get_value (adjustment);
1034 upper = gtk_adjustment_get_upper (adjustment);
1035 lower = gtk_adjustment_get_lower (adjustment);
1036 page_size = gtk_adjustment_get_page_size (adjustment);
1037 step_increment = gtk_adjustment_get_step_increment (adjustment);
1046 case GTK_SCROLL_PAGE_BACKWARD:
1048 if (value == lower && first_page) {
1051 }
else if (value == lower) {
1052 value = upper - page_size;
1057 value = MAX (value - increment, lower);
1060 case GTK_SCROLL_PAGE_FORWARD:
1062 if (value == (upper - page_size) && last_page) {
1065 }
else if (value == (upper - page_size)) {
1071 value = MIN (value + increment, upper - page_size);
1074 case GTK_SCROLL_STEP_BACKWARD:
1075 value -= step_increment;
1077 case GTK_SCROLL_STEP_FORWARD:
1078 value += step_increment;
1080 case GTK_SCROLL_STEP_DOWN:
1081 value -= step_increment / 10;
1083 case GTK_SCROLL_STEP_UP:
1084 value += step_increment / 10;
1086 case GTK_SCROLL_START:
1091 case GTK_SCROLL_END:
1092 value = upper - page_size;
1102 value = CLAMP (value, lower, upper - page_size);
1104 gtk_adjustment_set_value (adjustment, value);
1109 GtkScrollType scroll,
1110 GtkOrientation orientation)
1112 ev_view_scroll (view, scroll, orientation == GTK_ORIENTATION_HORIZONTAL);
1120 GtkWidget *widget = GTK_WIDGET (view);
1121 GtkAdjustment *adjustment;
1122 GtkAllocation allocation;
1128 gtk_widget_get_allocation (widget, &allocation);
1131 adj_value = gtk_adjustment_get_value (adjustment);
1133 if (rect->y < adj_value) {
1134 value = MAX (gtk_adjustment_get_lower (adjustment), rect->y -
MARGIN);
1135 gtk_adjustment_set_value (view->
vadjustment, value);
1136 }
else if (rect->y + rect->height > adj_value + allocation.height) {
1137 value = MIN (gtk_adjustment_get_upper (adjustment), rect->y + rect->height -
1138 allocation.height +
MARGIN);
1139 gtk_adjustment_set_value (view->
vadjustment, value);
1143 adj_value = gtk_adjustment_get_value (adjustment);
1145 if (rect->x < adj_value) {
1146 value = MAX (gtk_adjustment_get_lower (adjustment), rect->x -
MARGIN);
1147 gtk_adjustment_set_value (view->
hadjustment, value);
1148 }
else if (rect->x + rect->height > adj_value + allocation.width) {
1149 value = MIN (gtk_adjustment_get_upper (adjustment), rect->x + rect->width -
1150 allocation.width +
MARGIN);
1151 gtk_adjustment_set_value (view->
hadjustment, value);
1160 GtkWidget *widget = GTK_WIDGET (view);
1161 GtkStyleContext *context = gtk_widget_get_style_context (widget);
1162 GtkStateFlags state = gtk_widget_get_state_flags (widget);
1164 gtk_style_context_save (context);
1166 gtk_style_context_get_border (context, state, border);
1167 gtk_style_context_restore (context);
1183 width = (gint)(w * scale + 0.5);
1184 height = (gint)(h * scale + 0.5);
1187 *page_width = (rotation == 0 || rotation == 180) ? width : height;
1189 *page_height = (rotation == 0 || rotation == 180) ? height : width;
1216 width = (gint)(w * view->
scale + 0.5);
1217 height = (gint)(h * view->
scale + 0.5);
1220 *max_width = (view->
rotation == 0 || view->
rotation == 180) ? width : height;
1222 *max_height = (view->
rotation == 0 || view->
rotation == 180) ? height : width;
1232 g_return_if_fail (y_offset != NULL);
1238 offset += ((page + !odd_left) / 2 + 1) * view->
spacing +
1239 ((page + !odd_left) / 2 ) * (border.top + border.bottom);
1242 offset += (page + 1) * view->
spacing + page * (border.top + border.bottom);
1252 GdkRectangle *page_area,
1257 GtkAllocation allocation;
1259 widget = GTK_WIDGET (view);
1260 gtk_widget_get_allocation (widget, &allocation);
1265 page_area->width = width + border->left + border->right;
1266 page_area->height = height + border->top + border->bottom;
1274 max_width = max_width + border->left + border->right;
1277 x = view->
spacing + ((page % 2 == !odd_left) ? 0 : 1) * (max_width + view->
spacing);
1278 x = x + MAX (0, allocation.width - (max_width * 2 + view->
spacing * 3)) / 2;
1279 if (page % 2 == !odd_left)
1280 x = x + (max_width - width - border->left - border->right);
1283 x = x + MAX (0, allocation.width - (width + border->left + border->right + view->
spacing * 2)) / 2;
1295 gint width_2, height_2;
1296 gint max_width = width;
1297 gint max_height = height;
1298 GtkBorder overall_border;
1301 other_page = (page % 2 == !odd_left) ? page + 1: page - 1;
1305 && (0 <= other_page)) {
1307 &width_2, &height_2);
1308 if (width_2 > width)
1309 max_width = width_2;
1310 if (height_2 > height)
1311 max_height = height_2;
1320 if (page % 2 == !odd_left)
1321 x = x + max_width - width;
1323 x = x + (max_width + overall_border.left + overall_border.right) + view->
spacing;
1325 y = y + (max_height - height)/2;
1328 x = x + MAX (0, allocation.width -
1329 ((max_width + overall_border.left + overall_border.right) * 2 + view->
spacing * 3))/2;
1330 y = y + MAX (0, allocation.height - (height + view->
spacing * 2))/2;
1336 x = x + MAX (0, allocation.width - (width + border->left + border->right + view->
spacing * 2))/2;
1337 y = y + MAX (0, allocation.height - (height + border->top + border->bottom + view->
spacing * 2))/2;
1357 if (width) *width = w;
1358 if (height) *height = h;
1360 if (width) *width = h;
1361 if (height) *height = w;
1367 GdkPoint *view_point,
1368 GdkRectangle *page_area,
1370 double *doc_point_x,
1371 double *doc_point_y)
1373 *doc_point_x = MAX ((
double) (view_point->x - page_area->x - border->left) / view->
scale, 0);
1374 *doc_point_y = MAX ((
double) (view_point->y - page_area->y - border->right) / view->
scale, 0);
1379 GdkRectangle *view_rect,
1380 GdkRectangle *page_area,
1384 doc_rect->
x1 = MAX ((
double) (view_rect->x - page_area->x - border->left) / view->
scale, 0);
1385 doc_rect->
y1 = MAX ((
double) (view_rect->y - page_area->y - border->right) / view->
scale, 0);
1386 doc_rect->
x2 = doc_rect->
x1 + (double) view_rect->width / view->
scale;
1387 doc_rect->
y2 = doc_rect->
y1 + (
double) view_rect->height / view->
scale;
1394 GdkPoint *view_point)
1396 GdkRectangle page_area;
1398 double x, y, view_x, view_y;
1410 x = width - doc_point->
y;
1415 gdouble width, height;
1418 x = width - doc_point->
x;
1419 y = height - doc_point->
y;
1427 y = height - doc_point->
x;
1431 g_assert_not_reached ();
1436 view_x = CLAMP ((gint)(x * view->
scale + 0.5), 0, page_area.width);
1437 view_y = CLAMP ((gint)(y * view->
scale + 0.5), 0, page_area.height);
1438 view_point->x = view_x + page_area.x + border.left;
1439 view_point->y = view_y + page_area.y + border.top;
1446 GdkRectangle *view_rect)
1448 GdkRectangle page_area;
1456 w = doc_rect->
x2 - doc_rect->
x1;
1457 h = doc_rect->
y2 - doc_rect->
y1;
1464 x = width - doc_rect->
y2;
1466 w = doc_rect->
y2 - doc_rect->
y1;
1467 h = doc_rect->
x2 - doc_rect->
x1;
1471 gdouble width, height;
1474 x = width - doc_rect->
x2;
1475 y = height - doc_rect->
y2;
1476 w = doc_rect->
x2 - doc_rect->
x1;
1477 h = doc_rect->
y2 - doc_rect->
y1;
1485 y = height - doc_rect->
x2;
1486 w = doc_rect->
y2 - doc_rect->
y1;
1487 h = doc_rect->
x2 - doc_rect->
x1;
1491 g_assert_not_reached ();
1496 view_rect->x = (gint)(x * view->
scale + 0.5) + page_area.x + border.left;
1497 view_rect->y = (gint)(y * view->
scale + 0.5) + page_area.y + border.top;
1498 view_rect->width = (gint)(w * view->
scale + 0.5);
1499 view_rect->height = (gint)(h * view->
scale + 0.5);
1516 g_assert (x_offset);
1517 g_assert (y_offset);
1519 for (i = view->
start_page; i >= 0 && i <= view->end_page; i++) {
1520 GdkRectangle page_area;
1526 if ((x >= page_area.x + border.left) &&
1527 (x < page_area.x + page_area.width - border.right) &&
1528 (y >= page_area.y + border.top) &&
1529 (y < page_area.y + page_area.height - border.bottom)) {
1531 *x_offset = x - (page_area.x + border.left);
1532 *y_offset = y - (page_area.y + border.top);
1545 cairo_region_t *region;
1547 gint x_offset = 0, y_offset = 0;
1557 return cairo_region_contains_point (region, x_offset / view->
scale, y_offset / view->
scale);
1567 cairo_region_t *region;
1569 gint x_offset = 0, y_offset = 0;
1579 return cairo_region_contains_point (region, x_offset, y_offset);
1592 gdouble width, height;
1597 x_offset = x_offset / view->
scale;
1598 y_offset = y_offset / view->
scale;
1605 y = width - x_offset;
1606 }
else if (view->
rotation == 180) {
1607 x = width - x_offset;
1608 y = height - y_offset;
1609 }
else if (view->
rotation == 270) {
1610 x = height - y_offset;
1613 g_assert_not_reached ();
1630 gint x_offset = 0, y_offset = 0;
1658 GtkWidget *child_widget,
1668 child->
widget = child_widget;
1674 gtk_widget_set_parent (child_widget, GTK_WIDGET (view));
1680 GtkWidget *child_widget,
1689 ev_view_put (view, child_widget, area.x, area.y, page, doc_rect);
1699 gint x_new = 0, y_new = 0;
1725 return mapping ? mapping->
data : NULL;
1733 gboolean change_left, change_top;
1739 gdouble doc_width, doc_height;
1741 GtkAllocation allocation;
1743 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
1757 left -= (allocation.width / zoom - doc_width) / 2;
1758 top -= (allocation.height / zoom - doc_height) / 2;
1761 doc_point.
x = change_left ? left : 0;
1762 doc_point.
y = change_top ? top : 0;
1774 gboolean change_left;
1779 doc_point.
x = change_left ? left : 0;
1783 GtkAllocation allocation;
1784 gdouble doc_width, doc_height;
1787 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
1810 gboolean change_top;
1816 doc_point.
y = change_top ? top : 0;
1819 GtkAllocation allocation;
1823 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
1849 gdouble doc_width, doc_height;
1850 GtkAllocation allocation;
1852 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
1872 gdouble zoom, left, top;
1873 gboolean change_zoom, change_left, change_top;
1886 doc_point.
x = change_left ? left : 0;
1887 doc_point.
y = change_top ? top : 0;
1897 int page, n_pages, current_page;
1902 if (page < 0 || page >= n_pages)
1932 g_assert_not_reached ();
1948 const gchar *named_dest;
1955 g_object_unref (dest2);
1987 GList *show, *hide, *toggle;
1994 for (l = show; l; l = g_list_next (l)) {
1999 for (l = hide; l; l = g_list_next (l)) {
2004 for (l = toggle; l; l = g_list_next (l)) {
2032 if (g_ascii_strcasecmp (name,
"FirstPage") == 0) {
2033 return g_strdup (
_(
"Go to first page"));
2034 }
else if (g_ascii_strcasecmp (name,
"PrevPage") == 0) {
2035 return g_strdup (
_(
"Go to previous page"));
2036 }
else if (g_ascii_strcasecmp (name,
"NextPage") == 0) {
2037 return g_strdup (
_(
"Go to next page"));
2038 }
else if (g_ascii_strcasecmp (name,
"LastPage") == 0) {
2039 return g_strdup (
_(
"Go to last page"));
2040 }
else if (g_ascii_strcasecmp (name,
"GoToPage") == 0) {
2041 return g_strdup (
_(
"Go to page"));
2042 }
else if (g_ascii_strcasecmp (name,
"Find") == 0) {
2043 return g_strdup (
_(
"Find"));
2062 return title ? g_strdup (title) : NULL;
2071 msg = g_strdup_printf (
_(
"Go to page %s"), page_label);
2072 g_free (page_label);
2077 msg = g_strdup_printf (
_(
"Go to %s on file “%s”"), title,
2080 msg = g_strdup_printf (
_(
"Go to file “%s”"),
2088 msg = g_strdup_printf (
_(
"Launch %s"),
2096 msg = g_strdup (title);
2168 g_object_set (view,
"has-tooltip",
TRUE, NULL);
2178 gint x_new = 0, y_new = 0;
2220 GdkRectangle view_rect;
2221 cairo_region_t *region = NULL;
2230 region = cairo_region_create_rectangle (&view_rect);
2237 region = cairo_region_create_rectangle (&view_rect);
2239 cairo_region_union_rectangle (region, &view_rect);
2248 gdk_window_invalidate_region (gtk_widget_get_window (GTK_WIDGET (view)),
2250 cairo_region_destroy (region);
2261 gint x_new = 0, y_new = 0;
2288 return field_mapping ? field_mapping->
data : NULL;
2291 static cairo_region_t *
2295 GdkRectangle view_area;
2304 return cairo_region_create_rectangle (&view_area);
2327 cairo_region_t *region;
2352 cairo_region_t *button_region;
2354 if (button->
id == field->
id)
2364 cairo_region_union (region, button_region);
2365 cairo_region_destroy (button_region);
2372 field_button->
state = !state;
2380 cairo_region_destroy (region);
2391 if (!gtk_widget_has_focus (GTK_WIDGET (view)))
2392 gtk_widget_grab_focus (GTK_WIDGET (view));
2411 field = g_object_get_data (G_OBJECT (widget),
"form-field");
2415 cairo_region_t *field_region;
2420 field, field_text->
text);
2423 cairo_region_destroy (field_region);
2434 if (GTK_IS_ENTRY (widget)) {
2435 text = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
2436 }
else if (GTK_IS_TEXT_BUFFER (widget)) {
2437 GtkTextIter start, end;
2439 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (widget), &start, &end);
2440 text = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (widget),
2441 &start, &end,
FALSE);
2444 if (!field_text->
text ||
2445 (field_text->
text && g_ascii_strcasecmp (field_text->
text, text) != 0)) {
2446 g_free (field_text->
text);
2447 field_text->
text = text;
2454 GdkEventFocus *event,
2467 GtkWidget *text = NULL;
2473 switch (field_text->
type) {
2477 text = gtk_entry_new ();
2478 gtk_entry_set_has_frame (GTK_ENTRY (text),
FALSE);
2479 gtk_entry_set_max_length (GTK_ENTRY (text), field_text->
max_len);
2480 gtk_entry_set_visibility (GTK_ENTRY (text), !field_text->
is_password);
2483 gtk_entry_set_text (GTK_ENTRY (text), txt);
2487 g_signal_connect (text,
"focus-out-event",
2490 g_signal_connect (text,
"changed",
2493 g_signal_connect_after (text,
"activate",
2498 GtkTextBuffer *buffer;
2500 text = gtk_text_view_new ();
2501 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
2504 gtk_text_buffer_set_text (buffer, txt, -1);
2508 g_signal_connect (text,
"focus-out-event",
2511 g_signal_connect (buffer,
"changed",
2518 g_object_weak_ref (G_OBJECT (text),
2534 field = g_object_get_data (G_OBJECT (widget),
"form-field");
2539 cairo_region_t *field_region;
2545 field, field_choice->
text);
2551 GPOINTER_TO_INT (l->data));
2556 cairo_region_destroy (field_region);
2566 if (GTK_IS_COMBO_BOX (widget)) {
2569 item = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
2575 GINT_TO_POINTER (item));
2579 if (gtk_combo_box_get_has_entry (GTK_COMBO_BOX (widget))) {
2582 text = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget))));
2583 if (!field_choice->
text ||
2584 (field_choice->
text && g_ascii_strcasecmp (field_choice->
text, text) != 0)) {
2585 g_free (field_choice->
text);
2586 field_choice->
text = g_strdup (text);
2590 }
else if (GTK_IS_TREE_SELECTION (widget)) {
2591 GtkTreeSelection *selection = GTK_TREE_SELECTION (widget);
2592 GtkTreeModel *model;
2595 items = gtk_tree_selection_get_selected_rows (selection, &model);
2599 for (l = items; l && l->data; l = g_list_next (l)) {
2601 GtkTreePath *path = (GtkTreePath *)l->data;
2604 gtk_tree_model_get_iter (model, &iter, path);
2605 gtk_tree_model_get (model, &iter, 1, &item, -1);
2608 GINT_TO_POINTER (item));
2610 gtk_tree_path_free (path);
2613 g_list_free (items);
2625 GtkTreeModel *model;
2627 gint selected_item = 0;
2631 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
2632 for (i = 0; i < n_items; i++) {
2643 GINT_TO_POINTER (i));
2647 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
2648 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
2657 GtkCellRenderer *renderer;
2658 GtkWidget *tree_view;
2659 GtkTreeSelection *selection;
2661 tree_view = gtk_tree_view_new_with_model (model);
2662 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view),
FALSE);
2664 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
2666 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
2671 renderer = gtk_cell_renderer_text_new ();
2672 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
2678 choice = gtk_scrolled_window_new (NULL, NULL);
2679 gtk_container_add (GTK_CONTAINER (choice), tree_view);
2680 gtk_widget_show (tree_view);
2682 g_signal_connect (selection,
"changed",
2685 g_signal_connect_after (selection,
"changed",
2691 choice = gtk_combo_box_new_with_model_and_entry (model);
2692 gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (choice), 0);
2696 gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (choice))), text);
2700 g_signal_connect (choice,
"changed",
2703 g_signal_connect_after (gtk_bin_get_child (GTK_BIN (choice)),
2708 GtkCellRenderer *renderer;
2710 choice = gtk_combo_box_new_with_model (model);
2711 renderer = gtk_cell_renderer_text_new ();
2712 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (choice),
2714 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (choice),
2718 gtk_combo_box_set_active (GTK_COMBO_BOX (choice), selected_item);
2719 gtk_combo_box_popup (GTK_COMBO_BOX (choice));
2721 g_signal_connect (choice,
"changed",
2724 g_signal_connect_after (choice,
"changed",
2729 g_object_unref (model);
2731 g_object_weak_ref (G_OBJECT (choice),
2742 GtkWidget *field_widget = NULL;
2762 if (!field_widget) {
2763 if (!gtk_widget_has_focus (GTK_WIDGET (view)))
2764 gtk_widget_grab_focus (GTK_WIDGET (view));
2768 g_object_set_data_full (G_OBJECT (field_widget),
"form-field",
2769 g_object_ref (field),
2770 (GDestroyNotify)g_object_unref);
2777 gtk_widget_show (field_widget);
2778 gtk_widget_grab_focus (field_widget);
2805 #ifdef ENABLE_MULTIMEDIA
2806 gint x_new = 0, y_new = 0;
2833 return media_mapping ? media_mapping->
data : NULL;
2840 #ifdef ENABLE_MULTIMEDIA
2843 for (l = view->
children; l; l = g_list_next (l)) {
2861 #ifdef ENABLE_MULTIMEDIA
2865 GdkRectangle render_area;
2883 ev_view_put (view, player, render_area.x, render_area.y, page, &mapping->
area);
2884 gtk_widget_show (player);
2920 children = children->next;
2922 if (child->
window == window)
2935 GtkAllocation allocation;
2938 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
2939 gtk_window_get_size (GTK_WINDOW (child->
window), &width, &height);
2943 gtk_window_move (GTK_WINDOW (child->
window),
2945 child->
parent_x + allocation.width - width),
2947 child->
parent_y + allocation.height - height));
2955 gint root_x, root_y;
2958 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (view)),
2961 gint dest_x, dest_y;
2963 dest_x = child->
x + (root_x - child->
parent_x);
2964 dest_y = child->
y + (root_y - child->
parent_y);
2970 if (child->
visible && !gtk_widget_get_visible (window))
2971 gtk_widget_show (window);
2984 gint root_x, root_y;
2986 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (view)),
3000 gtk_widget_show (window);
3002 gtk_widget_hide (window);
3020 if (child->
page != page)
3025 gtk_widget_destroy (child->
window);
3029 children = children->next;
3045 gtk_widget_destroy (GTK_WIDGET (child->
window));
3079 GdkRectangle page_area;
3081 GdkRectangle view_rect;
3086 if (child->
x == x && child->
y == y)
3096 gtk_window_get_size (GTK_WINDOW (window), &width, &height);
3099 view_rect.width = width;
3100 view_rect.height = height;
3129 GdkRectangle view_rect;
3133 g_signal_connect (window,
"grab_focus",
3136 g_signal_connect (window,
"closed",
3139 g_signal_connect (window,
"moved",
3142 g_signal_connect_swapped (annot,
"notify::contents",
3154 view_rect.x, view_rect.y,
3155 doc_rect.
x1, doc_rect.
y1);
3168 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view)));
3213 gtk_widget_hide (window);
3223 gint x_new = 0, y_new = 0;
3234 if (annotations_mapping)
3250 return annotation_mapping ? annotation_mapping->
data : NULL;
3266 gtk_widget_show (window);
3295 g_object_set (annot,
3296 "rectangle", &popup_rect,
3298 "popup_is_open",
TRUE,
3301 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view)));
3312 GError *error = NULL;
3315 gtk_widget_get_screen (GTK_WIDGET (view)),
3320 g_warning (
"%s", error->message);
3321 g_error_free (error);
3335 GdkRectangle page_area;
3339 GdkColor color = { 0, 65535, 65535, 0 };
3340 GdkRectangle view_rect;
3341 cairo_region_t *region;
3344 if (annot_page == -1) {
3351 &start.
x, &start.
y);
3359 doc_rect.
x1 = end.
x;
3360 doc_rect.
y1 = end.
y;
3366 doc_rect.
x1 = start.
x;
3367 doc_rect.
y1 = start.
y;
3368 doc_rect.
x2 = end.
x;
3369 doc_rect.
y2 = end.
y;
3374 g_object_unref (page);
3378 g_assert_not_reached ();
3380 g_object_unref (page);
3386 popup_rect.
x1 = doc_rect.
x2;
3388 popup_rect.
y1 = doc_rect.
y2;
3390 g_object_set (annot,
3391 "rectangle", &popup_rect,
3393 "popup_is_open",
FALSE,
3394 "label", g_get_real_name (),
3409 region = cairo_region_create_rectangle (&view_rect);
3411 cairo_region_destroy (region);
3466 g_object_ref (annot);
3488 g_object_unref (annot);
3497 gint x_new = 0, y_new = 0;
3518 #define CURSOR_ON_MULTIPLIER 2
3519 #define CURSOR_OFF_MULTIPLIER 1
3520 #define CURSOR_PEND_MULTIPLIER 3
3521 #define CURSOR_DIVIDER 3
3523 static inline gboolean
3537 gtk_widget_has_focus (GTK_WIDGET (view)) &&
3540 GtkSettings *settings;
3543 settings = gtk_widget_get_settings (GTK_WIDGET (view));
3544 g_object_get (settings,
"gtk-cursor-blink", &blink, NULL);
3555 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (view));
3558 g_object_get (settings,
"gtk-cursor-blink-time", &time, NULL);
3566 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (view));
3569 g_object_get (settings,
"gtk-cursor-blink-timeout", &timeout, NULL);
3583 gfloat cursor_aspect_ratio;
3596 if (offset > n_areas)
3599 doc_rect = areas + offset;
3600 if (offset == n_areas ||
3601 ((doc_rect->
x1 == doc_rect->
x2 || doc_rect->
y1 == doc_rect->
y2) && offset > 0)) {
3609 prev = areas + offset - 1;
3610 last_rect.
x1 = prev->
x2;
3611 last_rect.
y1 = prev->
y1;
3612 last_rect.
x2 = prev->
x2 + (prev->
x2 - prev->
x1);
3613 last_rect.
y2 = prev->
y2;
3623 gtk_style_context_get_style (gtk_widget_get_style_context (GTK_WIDGET (view)),
3624 "cursor-aspect-ratio", &cursor_aspect_ratio,
3626 stem_width = area->height * cursor_aspect_ratio + 1;
3627 area->x -= (stem_width / 2);
3628 area->width = stem_width;
3637 GdkRectangle view_rect;
3642 widget = GTK_WIDGET (view);
3644 if (gtk_widget_has_focus (widget) &&
3646 gtk_widget_queue_draw_area (widget,
3647 view_rect.x, view_rect.y,
3648 view_rect.width, view_rect.height);
3656 GdkRectangle view_rect;
3661 widget = GTK_WIDGET (view);
3663 if (gtk_widget_has_focus (widget) &&
3665 gtk_widget_queue_draw_area (widget,
3666 view_rect.x, view_rect.y,
3667 view_rect.width, view_rect.height);
3678 if (view->
cursor_blink_time > 1000 * blink_timeout && blink_timeout < G_MAXINT / 1000) {
3753 if (n_pages > 0 && n_pages <= 3)
3806 gtk_widget_queue_draw (GTK_WIDGET (view));
3851 gtk_widget_queue_draw (GTK_WIDGET (view));
3859 GtkRequisition *requisition)
3870 requisition->width = 1;
3879 requisition->width = (max_width + border.left + border.right) * 2 + (view->
spacing * 3);
3883 g_assert_not_reached ();
3889 GtkRequisition *requisition)
3900 requisition->width = 1;
3909 requisition->width = max_width + (view->
spacing * 2) + border.left + border.right;
3913 g_assert_not_reached ();
3919 GtkRequisition *requisition)
3925 requisition->width = 1;
3926 requisition->height = 1;
3936 gint width_2, height_2;
3939 &width_2, &height_2);
3940 if (width_2 > width) {
3948 ((width + border.left + border.right) * 2) + (view->
spacing * 3);
3949 requisition->height = (height + border.top + border.bottom) + (view->
spacing * 2);
3954 GtkRequisition *requisition)
3960 requisition->width = 1;
3961 requisition->height = 1;
3970 width + border.left + border.right + (2 * view->
spacing);
3971 requisition->height = height + border.top + border.bottom + (2 * view->
spacing);
3976 GtkRequisition *requisition)
3997 GtkAllocation allocation;
3999 gtk_widget_get_allocation (widget, &allocation);
4023 GtkRequisition requisition;
4027 *minimum = *natural = requisition.width;
4035 GtkRequisition requisition;
4039 *minimum = *natural = requisition.height;
4044 GtkAllocation *allocation)
4048 gint root_x, root_y;
4050 gtk_widget_set_allocation (widget, allocation);
4052 if (gtk_widget_get_realized (widget))
4053 gdk_window_move_resize (gtk_widget_get_window (widget),
4057 allocation->height);
4069 allocation->height);
4086 for (l = view->
children; l && l->data; l = g_list_next (l)) {
4087 GdkRectangle view_area;
4090 if (!gtk_widget_get_visible (child->
widget))
4097 gtk_widget_set_size_request (child->
widget, view_area.width, view_area.height);
4098 gtk_widget_size_allocate (child->
widget, &view_area);
4102 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (view)),
4108 GdkRectangle view_rect;
4121 if (view_rect.x != child->
orig_x || view_rect.y != child->
orig_y) {
4134 gboolean fit_width, fit_height;
4136 state =
event->state & gtk_accelerator_get_default_mod_mask ();
4138 if (state == GDK_CONTROL_MASK) {
4143 switch (event->direction) {
4144 case GDK_SCROLL_DOWN:
4145 case GDK_SCROLL_RIGHT:
4150 case GDK_SCROLL_LEFT:
4154 case GDK_SCROLL_SMOOTH: {
4155 gdouble delta =
event->delta_x +
event->delta_y;
4171 if (state & GDK_SHIFT_MASK) {
4172 if (event->direction == GDK_SCROLL_UP)
4173 event->direction = GDK_SCROLL_LEFT;
4174 else if (event->direction == GDK_SCROLL_LEFT)
4175 event->direction = GDK_SCROLL_UP;
4176 else if (event->direction == GDK_SCROLL_DOWN)
4177 event->direction = GDK_SCROLL_RIGHT;
4178 else if (event->direction == GDK_SCROLL_RIGHT)
4179 event->direction = GDK_SCROLL_DOWN;
4180 else if (event->direction == GDK_SCROLL_SMOOTH) {
4182 gdouble tmp_delta =
event->delta_x;
4184 event->delta_x =
event->delta_y;
4185 event->delta_y = tmp_delta;
4188 event->state &= ~GDK_SHIFT_MASK;
4189 state &= ~GDK_SHIFT_MASK;
4194 if (state == 0 && !view->
continuous && (fit_width || fit_height)) {
4195 switch (event->direction) {
4196 case GDK_SCROLL_DOWN:
4202 case GDK_SCROLL_RIGHT:
4214 case GDK_SCROLL_LEFT:
4220 case GDK_SCROLL_SMOOTH: {
4222 if ((fit_width && fit_height) ||
4223 ((fit_height && event->delta_x == 0.0) ||
4224 (fit_width && event->delta_y == 0.0))) {
4226 view->
total_delta +=
event->delta_x +
event->delta_y;
4259 if (selection->
page == page)
4269 GtkAllocation allocation;
4271 GdkWindowAttr attributes;
4272 gint attributes_mask;
4274 gtk_widget_set_realized (widget,
TRUE);
4276 gtk_widget_get_allocation (widget, &allocation);
4278 attributes.window_type = GDK_WINDOW_CHILD;
4279 attributes.x = allocation.x;
4280 attributes.y = allocation.y;
4281 attributes.width = allocation.width;
4282 attributes.height = allocation.height;
4283 attributes.wclass = GDK_INPUT_OUTPUT;
4284 attributes.visual = gtk_widget_get_visual (widget);
4285 attributes.event_mask = gtk_widget_get_events (widget);
4287 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4289 window = gdk_window_new (gtk_widget_get_parent_window (widget),
4290 &attributes, attributes_mask);
4291 gtk_widget_set_window (widget, window);
4292 gdk_window_set_user_data (window, widget);
4294 gtk_style_context_set_background (gtk_widget_get_style_context (widget),
4302 GdkColor *style_color;
4304 gtk_style_context_get_style (context,
4310 color->red = style_color->red / 65535.0;
4311 color->green = style_color->green / 65535.0;
4312 color->blue = style_color->blue / 65535.0;
4315 gdk_color_free (style_color);
4317 gtk_style_context_save (context);
4318 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, color);
4319 gtk_style_context_restore (context);
4328 GdkRectangle view_rect;
4329 GdkRGBA cursor_color;
4334 get_cursor_color (gtk_widget_get_style_context (GTK_WIDGET (view)), &cursor_color);
4337 gdk_cairo_set_source_rgba (cr, &cursor_color);
4338 cairo_rectangle (cr, view_rect.x, view_rect.y, view_rect.width, view_rect.height);
4350 gtk_widget_has_focus (GTK_WIDGET (view)) &&
4360 GtkWidget *widget = GTK_WIDGET (view);
4362 GdkRectangle intersect;
4367 if (!gtk_widget_has_focus (GTK_WIDGET (view)))
4373 if (gdk_rectangle_intersect (&rect, clip, &intersect)) {
4374 gtk_render_focus (gtk_widget_get_style_context (widget),
4383 #ifdef EV_ENABLE_DEBUG
4385 stroke_view_rect (cairo_t *cr,
4387 GdkRectangle *view_rect)
4389 GdkRectangle intersect;
4391 if (gdk_rectangle_intersect (view_rect, clip, &intersect)) {
4392 cairo_rectangle (cr,
4393 intersect.x, intersect.y,
4394 intersect.width, intersect.height);
4400 stroke_doc_rect (
EvView *view,
4406 GdkRectangle view_rect;
4411 stroke_view_rect (cr, clip, &view_rect);
4415 show_chars_border (
EvView *view,
4428 cairo_set_source_rgb (cr, 1., 0., 0.);
4430 for (i = 0; i < n_areas; i++) {
4433 stroke_doc_rect (view, cr, page, clip, doc_rect);
4438 show_mapping_list_border (
EvView *view,
4449 stroke_doc_rect (view, cr, page, clip, &mapping->
area);
4454 show_links_border (
EvView *view,
4459 cairo_set_source_rgb (cr, 0., 0., 1.);
4460 show_mapping_list_border (view,cr, page, clip,
4465 show_forms_border (
EvView *view,
4470 cairo_set_source_rgb (cr, 0., 1., 0.);
4471 show_mapping_list_border (view, cr, page, clip,
4476 show_annots_border (
EvView *view,
4481 cairo_set_source_rgb (cr, 0., 1., 1.);
4482 show_mapping_list_border (view, cr, page, clip,
4487 show_images_border (
EvView *view,
4492 cairo_set_source_rgb (cr, 1., 0., 1.);
4493 show_mapping_list_border (view, cr, page, clip,
4498 show_media_border (
EvView *view,
4503 cairo_set_source_rgb (cr, 1., 1., 0.);
4504 show_mapping_list_border (view, cr, page, clip,
4510 show_selections_border (
EvView *view,
4515 cairo_region_t *region;
4517 GdkRectangle page_area;
4524 cairo_set_source_rgb (cr, 0.75, 0.50, 0.25);
4528 region = cairo_region_copy (region);
4529 cairo_region_intersect_rectangle (region, clip);
4530 n_rects = cairo_region_num_rectangles (region);
4531 for (i = 0; i < n_rects; i++) {
4532 GdkRectangle view_rect;
4534 cairo_region_get_rectangle (region, i, &view_rect);
4535 view_rect.x = (gint)(view_rect.x * view->
scale + 0.5);
4536 view_rect.y = (gint)(view_rect.y * view->
scale + 0.5);
4537 view_rect.width = (gint)(view_rect.width * view->
scale + 0.5);
4538 view_rect.height = (gint)(view_rect.height * view->
scale + 0.5);
4540 view_rect.x += page_area.x + border.left - view->
scroll_x;
4541 view_rect.y += page_area.y + border.right - view->
scroll_y;
4542 stroke_view_rect (cr, clip, &view_rect);
4544 cairo_region_destroy (region);
4548 draw_debug_borders (
EvView *view,
4553 EvDebugBorders borders = ev_debug_get_debug_borders();
4556 cairo_set_line_width (cr, 0.5);
4558 if (borders & EV_DEBUG_BORDER_CHARS)
4559 show_chars_border (view, cr, page, clip);
4560 if (borders & EV_DEBUG_BORDER_LINKS)
4561 show_links_border (view, cr, page, clip);
4562 if (borders & EV_DEBUG_BORDER_FORMS)
4563 show_forms_border (view, cr, page, clip);
4564 if (borders & EV_DEBUG_BORDER_ANNOTS)
4565 show_annots_border (view, cr, page, clip);
4566 if (borders & EV_DEBUG_BORDER_IMAGES)
4567 show_images_border (view, cr, page, clip);
4568 if (borders & EV_DEBUG_BORDER_MEDIA)
4569 show_media_border (view, cr, page, clip);
4570 if (borders & EV_DEBUG_BORDER_SELECTIONS)
4571 show_selections_border (view, cr, page, clip);
4583 GdkRectangle clip_rect;
4585 gtk_render_background (gtk_widget_get_style_context (widget),
4588 gtk_widget_get_allocated_width (widget),
4589 gtk_widget_get_allocated_height (widget));
4594 if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect))
4597 for (i = view->
start_page; i >= 0 && i <= view->end_page; i++) {
4598 GdkRectangle page_area;
4600 gboolean page_ready =
TRUE;
4608 draw_one_page (view, i, cr, &page_area, &border, &clip_rect, &page_ready);
4620 #ifdef EV_ENABLE_DEBUG
4622 draw_debug_borders (view, cr, i, &clip_rect);
4626 if (GTK_WIDGET_CLASS (ev_view_parent_class)->draw)
4627 GTK_WIDGET_CLASS (ev_view_parent_class)->draw (widget, cr);
4667 GList *items = NULL;
4674 items = g_list_prepend (items, image);
4678 items = g_list_prepend (items, link);
4682 items = g_list_prepend (items, annot);
4686 g_list_free (items);
4709 gint x_offset = 0, y_offset = 0;
4731 gint x_offset = 0, y_offset = 0;
4748 gboolean keyboard_tip,
4749 GtkTooltip *tooltip)
4758 const gchar *contents;
4761 GdkRectangle annot_area;
4764 gtk_tooltip_set_text (tooltip, contents);
4765 gtk_tooltip_set_tip_area (tooltip, &annot_area);
4776 if (text && g_utf8_validate (text, -1, NULL)) {
4777 GdkRectangle link_area;
4780 gtk_tooltip_set_text (tooltip, text);
4781 gtk_tooltip_set_tip_area (tooltip, &link_area);
4793 GdkEventButton *event)
4800 switch (event->type) {
4801 case GDK_2BUTTON_PRESS:
4804 case GDK_3BUTTON_PRESS:
4828 gint first_line_offset;
4829 gint last_line_offset = -1;
4838 while (i < n_areas && offset == -1) {
4841 first_line_offset = -1;
4842 while (doc_y >= rect->
y1 && doc_y <= rect->y2) {
4843 if (first_line_offset == -1) {
4844 if (doc_x <= rect->x1) {
4846 if (last_line_offset != -1) {
4852 dx1 = doc_x - last->
x2;
4853 dx2 = rect->
x1 - doc_x;
4856 offset = last_line_offset;
4863 last_line_offset = i + 1;
4866 first_line_offset = i;
4868 last_line_offset = i + 1;
4870 if (doc_x >= rect->
x1 && doc_x <= rect->x2) {
4875 if (doc_x <= rect->x1 + (rect->
x2 - rect->
x1) / 2)
4886 if (first_line_offset == -1)
4890 if (last_line_offset == -1)
4894 offset = last_line_offset;
4944 GdkEventButton *event,
4948 GdkRectangle prev_area = { 0, 0, 0, 0 };
4964 cairo_region_t *damage_region;
4966 damage_region = cairo_region_create_rectangle (&prev_area);
4967 cairo_region_union_rectangle (damage_region, &area);
4968 gdk_window_invalidate_region (gtk_widget_get_window (GTK_WIDGET (view)),
4969 damage_region,
TRUE);
4970 cairo_region_destroy (damage_region);
4978 GdkEventButton *event)
4988 if (!gtk_widget_has_focus (widget)) {
4989 gtk_widget_grab_focus (widget);
5007 if (event->button != 1)
5018 switch (event->button) {
5027 if (event->state & GDK_CONTROL_MASK)
5031 if (event->type == GDK_3BUTTON_PRESS) {
5033 }
else if (event->state & GDK_SHIFT_MASK) {
5036 end_point.x =
event->x + view->
scroll_x;
5037 end_point.y =
event->y + view->
scroll_y;
5055 GdkPoint view_point;
5057 GdkRectangle page_area;
5070 view_point.x =
event->x + view->
scroll_x;
5071 view_point.y =
event->y + view->
scroll_y;
5080 &page_area, &border,
5081 &doc_point.
x, &doc_point.
y);
5110 gtk_widget_queue_draw (widget);
5146 gtk_container_foreach (GTK_CONTAINER (view), (GtkCallback) gtk_widget_destroy, NULL);
5152 if (g_object_get_data (G_OBJECT (widget),
"form-field"))
5153 gtk_widget_destroy (widget);
5165 GdkDragContext *context,
5166 GtkSelectionData *selection_data,
5179 gtk_selection_data_set_text (selection_data,
5194 gtk_selection_data_set_pixbuf (selection_data, pixbuf);
5195 g_object_unref (pixbuf);
5201 const gchar *tmp_uri;
5210 g_object_unref (pixbuf);
5212 uris[0] = (gchar *)tmp_uri;
5214 gtk_selection_data_set_uris (selection_data, uris);
5221 GdkDragContext *context,
5226 if (gtk_drag_get_source_widget (context) == widget)
5227 gdk_drag_status (context, 0, time);
5229 gdk_drag_status (context, gdk_drag_context_get_suggested_action (context), time);
5248 gint x, y, shift = 0;
5249 GtkWidget *widget = GTK_WIDGET (view);
5250 GtkAllocation allocation;
5252 gtk_widget_get_allocation (widget, &allocation);
5255 if (y > allocation.height) {
5256 shift = (y - allocation.height) / 2;
5263 CLAMP (gtk_adjustment_get_value (view->
vadjustment) + shift,
5266 gtk_adjustment_get_page_size (view->
vadjustment)));
5268 if (x > allocation.width) {
5269 shift = (x - allocation.width) / 2;
5276 CLAMP (gtk_adjustment_get_value (view->
hadjustment) + shift,
5279 gtk_adjustment_get_page_size (view->
hadjustment)));
5309 gdouble dhadj_value, dvadj_value;
5310 gdouble oldhadjustment, oldvadjustment;
5311 gdouble h_page_size, v_page_size;
5312 gdouble h_upper, v_upper;
5313 GtkAllocation allocation;
5318 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
5320 h_page_size = gtk_adjustment_get_page_size (view->
hadjustment);
5321 v_page_size = gtk_adjustment_get_page_size (view->
vadjustment);
5323 dhadj_value = h_page_size *
5325 dvadj_value = v_page_size *
5328 oldhadjustment = gtk_adjustment_get_value (view->
hadjustment);
5329 oldvadjustment = gtk_adjustment_get_value (view->
vadjustment);
5331 h_upper = gtk_adjustment_get_upper (view->
hadjustment);
5332 v_upper = gtk_adjustment_get_upper (view->
vadjustment);
5336 if (((oldhadjustment + dhadj_value) > (h_upper - h_page_size)) ||
5337 ((oldhadjustment + dhadj_value) < 0))
5339 if (((oldvadjustment + dvadj_value) > (v_upper - v_page_size)) ||
5340 ((oldvadjustment + dvadj_value) < 0))
5344 MIN (oldhadjustment + dhadj_value,
5345 h_upper - h_page_size));
5347 MIN (oldvadjustment + dvadj_value,
5348 v_upper - v_page_size));
5359 GdkEventMotion *event)
5371 window = gtk_widget_get_window (widget);
5373 if (event->is_hint || event->window != window) {
5387 if (gtk_drag_check_threshold (widget,
5391 GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
5395 gtk_drag_begin (widget, target_list,
5397 1, (GdkEvent *)event);
5401 gtk_target_list_unref (target_list);
5406 if (gtk_drag_check_threshold (widget,
5410 GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
5415 gtk_drag_begin (widget, target_list,
5417 1, (GdkEvent *)event);
5421 gtk_target_list_unref (target_list);
5440 GdkRectangle page_area;
5454 &start.
x, &start.
y);
5462 rect.
x2 = rect.
x1 + current_area.
x2 - current_area.
x1;
5463 rect.
y2 = rect.
y1 + current_area.
y2 - current_area.
y1;
5472 g_assert_not_reached ();
5491 GdkPoint view_point;
5493 GdkRectangle page_area;
5502 view_point.x =
event->x + view->
scroll_x;
5503 view_point.y =
event->y + view->
scroll_y;
5507 if (!gtk_drag_check_threshold (widget,
5520 &doc_point.
x, &doc_point.
y);
5526 rect.
x2 = rect.
x1 + current_area.
x2 - current_area.
x1;
5527 rect.
y2 = rect.
y1 + current_area.
y2 - current_area.
y1;
5530 if (rect.
x2 > page_width) {
5531 rect.
x2 = page_width;
5532 rect.
x1 = page_width - current_area.
x2 + current_area.
x1;
5534 if (rect.
y2 > page_height) {
5535 rect.
y2 = page_height;
5536 rect.
y1 = page_height - current_area.
y2 + current_area.
y1;
5579 start = gtk_drag_check_threshold (widget,
5599 gdouble dhadj_value, dvadj_value;
5600 GtkAllocation allocation;
5608 gtk_widget_get_allocation (widget, &allocation);
5610 dhadj_value = gtk_adjustment_get_page_size (view->
hadjustment) *
5611 (gdouble)dx / allocation.width;
5612 dvadj_value = gtk_adjustment_get_page_size (view->
vadjustment) *
5613 (gdouble)dy / allocation.height;
5619 gtk_adjustment_get_page_size (view->
hadjustment)));
5623 gtk_adjustment_get_page_size (view->
vadjustment)));
5638 GdkEventButton *event)
5655 if (view->
pressed_button == 1 && event->state & GDK_CONTROL_MASK) {
5673 gboolean annot_added =
TRUE;
5688 if (area.
x1 == 0 && area.
y1 == 0 && area.
x2 == 0 && area.
y2 == 0) {
5690 annot_added =
FALSE;
5701 popup_rect.
x1 = area.
x2;
5703 popup_rect.
y1 = area.
y2;
5717 if (window == NULL) {
5718 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view)));
5786 if (event->button == 2) {
5796 g_signal_emit (view,
5812 GtkWidget *child_widget = NULL;
5813 GdkEventKey *new_event;
5821 child_widget = child->
widget;
5826 new_event = (GdkEventKey *) gdk_event_copy ((GdkEvent *)event);
5827 g_object_unref (new_event->window);
5828 new_event->window = gtk_widget_get_window (child_widget);
5829 if (new_event->window)
5830 g_object_ref (new_event->window);
5831 gtk_widget_realize (child_widget);
5832 handled = gtk_widget_event (child_widget, (GdkEvent *)new_event);
5833 gdk_event_free ((GdkEvent *)new_event);
5851 page += dual_page ? 2 : 1;
5856 if (dual_page && page == n_pages)
5872 page -= dual_page ? 2 : 1;
5877 if (dual_page && page == -1)
5894 PangoLogAttr *log_attrs = NULL;
5915 if (new_page != -1) {
5929 if (new_page != -1) {
5956 PangoLogAttr *log_attrs = NULL;
5979 PangoLogAttr *log_attrs = NULL;
6002 PangoLogAttr *log_attrs = NULL;
6014 for (i = view->
cursor_offset; i >= 0 && log_attrs[i].is_word_start; i--);
6022 for (j = i; j >= 0 && !log_attrs[j].is_word_start; j--);
6031 PangoLogAttr *log_attrs = NULL;
6043 for (i = view->
cursor_offset; i < n_attrs && log_attrs[i].is_word_end; i++);
6051 for (j = i; j < n_attrs && !log_attrs[j].is_word_end; j++);
6060 PangoLogAttr *log_attrs = NULL;
6071 for (i = view->
cursor_offset; i >= 0 && !log_attrs[i].is_mandatory_break; i--);
6080 PangoLogAttr *log_attrs = NULL;
6102 PangoLogAttr *log_attrs = NULL;
6113 for (i = view->
cursor_offset + 1; i <= n_attrs && !log_attrs[i].is_mandatory_break; i++);
6129 PangoLogAttr *log_attrs = NULL;
6149 GdkPoint *start_point,
6150 GdkPoint *end_point)
6169 cairo_rectangle_int_t rect;
6184 forward ? cairo_region_num_rectangles (selection->
covered_region) - 1 : 0,
6188 forward ? rect.x + rect.width : rect.x,
6189 rect.y + (rect.height / 2), &doc_x, &doc_y))
6198 GtkMovementStep step,
6200 gboolean extend_selections)
6203 GdkRectangle prev_rect;
6206 cairo_region_t *damage_region;
6207 gboolean clear_selections =
FALSE;
6221 case GTK_MOVEMENT_VISUAL_POSITIONS:
6233 case GTK_MOVEMENT_WORDS:
6243 case GTK_MOVEMENT_DISPLAY_LINES:
6253 case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
6259 case GTK_MOVEMENT_BUFFER_ENDS:
6266 g_assert_not_reached ();
6272 if (!clear_selections &&
6274 gtk_widget_error_bell (GTK_WIDGET (view));
6282 if (step == GTK_MOVEMENT_DISPLAY_LINES) {
6285 rect.y + (rect.height / 2));
6286 if (!clear_selections &&
6288 gtk_widget_error_bell (GTK_WIDGET (view));
6298 damage_region = cairo_region_create_rectangle (&rect);
6300 cairo_region_union_rectangle (damage_region, &prev_rect);
6310 gdk_window_invalidate_region (gtk_widget_get_window (GTK_WIDGET (view)),
6311 damage_region,
TRUE);
6312 cairo_region_destroy (damage_region);
6316 GdkPoint start_point, end_point;
6318 start_point.x = prev_rect.x + view->
scroll_x;
6319 start_point.y = prev_rect.y + (prev_rect.height / 2) + view->
scroll_y;
6321 end_point.x = rect.x;
6322 end_point.y = rect.y + rect.height / 2;
6325 }
else if (clear_selections)
6341 if (!gtk_widget_has_focus (widget))
6348 retval = gtk_bindings_activate_event (G_OBJECT (widget), event);
6358 gboolean handled =
FALSE;
6379 GdkEvent *current_event;
6381 gboolean is_space_key_press;
6383 current_event = gtk_get_current_event ();
6387 is_space_key_press = current_event->type == GDK_KEY_PRESS &&
6388 gdk_event_get_keyval (current_event, &keyval) &&
6389 (keyval == GDK_KEY_space || keyval == GDK_KEY_KP_Space);
6390 gdk_event_free (current_event);
6392 return is_space_key_press;
6432 gdouble speed, value;
6451 value = gtk_adjustment_get_value (view->
vadjustment);
6452 value = CLAMP (value + speed, 0,
6454 gtk_adjustment_get_page_size (view->
vadjustment));
6455 gtk_adjustment_set_value (view->
vadjustment, value);
6490 GdkEventFocus *event)
6500 gtk_widget_queue_draw (widget);
6507 GdkEventFocus *event)
6517 gtk_widget_queue_draw (widget);
6546 if (
EV_VIEW (widget)->pixbuf_cache)
6549 GTK_WIDGET_CLASS (ev_view_parent_class)->style_updated (widget);
6557 const GdkRectangle *rect,
6560 GtkStyleContext *context;
6563 context = gtk_widget_get_style_context (GTK_WIDGET (view));
6564 gtk_style_context_save (context);
6565 gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED, &color);
6566 gtk_style_context_restore (context);
6569 cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha);
6570 cairo_rectangle (cr,
6573 rect->width, rect->height);
6574 cairo_fill_preserve (cr);
6576 cairo_set_line_width (cr, 0.5);
6577 cairo_set_source_rgb (cr, color.red, color.green, color.blue);
6589 gint i, n_results = 0;
6593 for (i = 0; i < n_results; i++) {
6595 GdkRectangle view_rectangle;
6618 if (GPOINTER_TO_INT (mapping->
data) != page)
6624 cairo_set_source_rgb (cr, 1., 0., 0.);
6625 cairo_rectangle (cr,
6628 rect.width, rect.height);
6635 cairo_surface_t *surface,
6643 gdouble width, height;
6644 gdouble device_scale_x = 1, device_scale_y = 1;
6646 #ifdef HAVE_HIDPI_SUPPORT
6647 cairo_surface_get_device_scale (surface, &device_scale_x, &device_scale_y);
6649 width = cairo_image_surface_get_width (surface) / device_scale_x;
6650 height = cairo_image_surface_get_height (surface) / device_scale_y;
6653 cairo_translate (cr, x, y);
6655 if (width != target_width || height != target_height) {
6656 gdouble scale_x, scale_y;
6658 scale_x = (gdouble)target_width / width;
6659 scale_y = (gdouble)target_height / height;
6660 cairo_pattern_set_filter (cairo_get_source (cr),
6661 CAIRO_FILTER_NEAREST);
6662 cairo_scale (cr, scale_x, scale_y);
6664 offset_x /= scale_x;
6665 offset_y /= scale_y;
6668 cairo_surface_set_device_offset (surface,
6669 offset_x * device_scale_x,
6670 offset_y * device_scale_y);
6671 cairo_set_source_surface (cr, surface, 0, 0);
6681 GtkWidget *widget = GTK_WIDGET (view);
6682 GtkStateFlags state;
6683 GtkStyleContext *context;
6685 context = gtk_widget_get_style_context (widget);
6686 gtk_style_context_save (context);
6687 state = gtk_style_context_get_state (context) |
6688 (gtk_widget_has_focus (widget) ? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_ACTIVE);
6689 gtk_style_context_set_state (context, state);
6692 gtk_style_context_get_background_color (context, state, bg_color);
6695 gtk_style_context_get_color (context, state, fg_color);
6697 gtk_style_context_restore (context);
6702 cairo_region_t *region,
6710 cairo_translate (cr, x, y);
6711 cairo_scale (cr, scale_x, scale_y);
6712 gdk_cairo_region (cr, region);
6713 cairo_set_source_rgb (cr, color->red, color->green, color->blue);
6714 cairo_set_operator (cr, CAIRO_OPERATOR_MULTIPLY);
6715 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
6724 GdkRectangle *page_area,
6726 GdkRectangle *expose_area,
6727 gboolean *page_ready)
6729 GtkStyleContext *context;
6730 GdkRectangle overlap;
6731 GdkRectangle real_page_area;
6736 if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
6740 real_page_area = *page_area;
6742 real_page_area.x += border->left;
6743 real_page_area.y += border->top;
6744 real_page_area.width -= (border->left + border->right);
6745 real_page_area.height -= (border->top + border->bottom);
6748 context = gtk_widget_get_style_context (GTK_WIDGET (view));
6751 gtk_style_context_save (context);
6756 if (view->
continuous && page == current_page)
6757 gtk_style_context_set_state (context, GTK_STATE_FLAG_ACTIVE);
6759 gtk_render_background (context, cr, page_area->x, page_area->y, page_area->width, page_area->height);
6760 gtk_render_frame (context, cr, page_area->x, page_area->y, page_area->width, page_area->height);
6761 gtk_style_context_restore (context);
6763 if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) {
6765 cairo_surface_t *page_surface = NULL;
6766 cairo_surface_t *selection_surface = NULL;
6767 gint offset_x, offset_y;
6768 cairo_region_t *region = NULL;
6772 if (!page_surface) {
6773 if (page == current_page)
6776 *page_ready =
FALSE;
6781 if (page == current_page)
6785 offset_x = overlap.x - real_page_area.x;
6786 offset_y = overlap.y - real_page_area.y;
6788 draw_surface (cr, page_surface, overlap.x, overlap.y, offset_x, offset_y, width, height);
6797 if (selection_surface) {
6798 draw_surface (cr, selection_surface, overlap.x, overlap.y, offset_x, offset_y,
6807 double scale_x, scale_y;
6809 double device_scale_x = 1, device_scale_y = 1;
6811 scale_x = (gdouble)width / cairo_image_surface_get_width (page_surface);
6812 scale_y = (gdouble)height / cairo_image_surface_get_height (page_surface);
6814 #ifdef HAVE_HIDPI_SUPPORT
6815 cairo_surface_get_device_scale (page_surface, &device_scale_x, &device_scale_y);
6818 scale_x *= device_scale_x;
6819 scale_y *= device_scale_y;
6854 G_OBJECT_CLASS (ev_view_parent_class)->finalize (
object);
6863 g_signal_handlers_disconnect_by_data (view->
model, view);
6864 g_object_unref (view->
model);
6922 gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (view), NULL);
6923 gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (view), NULL);
6927 G_OBJECT_CLASS (ev_view_parent_class)->dispose (
object);
6940 g_value_set_boolean (value, view->
loading);
6961 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
6969 const GValue *value,
6980 (GtkAdjustment *) g_value_get_object (value));
6984 (GtkAdjustment *) g_value_get_object (value));
6988 gtk_widget_queue_resize (GTK_WIDGET (view));
6992 gtk_widget_queue_resize (GTK_WIDGET (view));
6995 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
7021 child = tmp_list->data;
7023 if (child->
widget == widget) {
7024 gtk_widget_unparent (widget);
7027 g_list_free_1 (tmp_list);
7033 tmp_list = tmp_list->next;
7039 gboolean include_internals,
7040 GtkCallback callback,
7041 gpointer callback_data)
7048 child = tmp_list->data;
7049 tmp_list = tmp_list->next;
7051 (* callback) (child->
widget, callback_data);
7058 gdouble min_width, min_height;
7059 gdouble width, height;
7069 screen = gtk_widget_get_screen (GTK_WIDGET (view));
7073 width = (rotation == 0 || rotation == 180) ? min_width : min_height;
7074 height = (rotation == 0 || rotation == 180) ? min_height : min_width;
7083 GdkScreen *old_screen)
7088 screen = gtk_widget_get_screen (widget);
7089 if (screen == old_screen)
7094 if (GTK_WIDGET_CLASS (ev_view_parent_class)->screen_changed) {
7095 GTK_WIDGET_CLASS (ev_view_parent_class)->screen_changed (widget, old_screen);
7101 GtkPanDirection direction,
7105 GtkAllocation allocation;
7107 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
7111 gtk_gesture_set_state (GTK_GESTURE (gesture),
7112 GTK_EVENT_SEQUENCE_DENIED);
7116 #define PAN_ACTION_DISTANCE 200
7119 gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
7122 if (direction == GTK_PAN_DIRECTION_LEFT ||
7123 gtk_widget_get_direction (GTK_WIDGET (view)) == GTK_TEXT_DIR_RTL)
7128 #undef PAN_ACTION_DISTANCE
7133 GdkEventSequence *sequence,
7136 if (!gtk_gesture_handles_sequence (gesture, sequence))
7149 GtkWidget *previous_toplevel)
7151 GtkWidget *parent = gtk_widget_get_parent (widget);
7156 gtk_gesture_pan_new (parent, GTK_ORIENTATION_HORIZONTAL);
7162 gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (view->
pan_gesture),
TRUE);
7163 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (view->
pan_gesture),
7173 GdkModifierType modifiers,
7174 GtkMovementStep step,
7177 guint keypad_keyval = keyval - GDK_KEY_Left + GDK_KEY_KP_Left;
7179 gtk_binding_entry_add_signal (binding_set, keyval, modifiers,
7181 GTK_TYPE_MOVEMENT_STEP, step,
7183 G_TYPE_BOOLEAN,
FALSE);
7184 gtk_binding_entry_add_signal (binding_set, keypad_keyval, modifiers,
7186 GTK_TYPE_MOVEMENT_STEP, step,
7188 G_TYPE_BOOLEAN,
FALSE);
7191 gtk_binding_entry_add_signal (binding_set, keyval, modifiers | GDK_SHIFT_MASK,
7193 GTK_TYPE_MOVEMENT_STEP, step,
7195 G_TYPE_BOOLEAN,
TRUE);
7196 gtk_binding_entry_add_signal (binding_set, keypad_keyval, modifiers | GDK_SHIFT_MASK,
7198 GTK_TYPE_MOVEMENT_STEP, step,
7200 G_TYPE_BOOLEAN,
TRUE);
7208 GtkTextDirection text_direction = GPOINTER_TO_INT (user_data);
7216 if (text_direction == GTK_TEXT_DIR_RTL)
7217 return (x1 < x2) ? 1 : ((x1 == x2) ? 0 : -1);
7219 return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1);
7222 return (y1 < y2) ? -1 : 1;
7227 GtkDirectionType direction,
7230 GList *mapping_list = NULL, *l;
7242 mapping_list = g_list_prepend (mapping_list, mapping);
7248 mapping_list = g_list_sort_with_data (g_list_reverse (mapping_list),
7250 GINT_TO_POINTER (gtk_widget_get_direction (GTK_WIDGET (view))));
7252 if (direction == GTK_DIR_TAB_BACKWARD)
7253 mapping_list = g_list_reverse (mapping_list);
7254 return mapping_list;
7263 gtk_widget_child_focus (GTK_WIDGET (view), GTK_DIR_TAB_FORWARD);
7265 return G_SOURCE_REMOVE;
7274 gtk_widget_child_focus (GTK_WIDGET (view), GTK_DIR_TAB_BACKWARD);
7276 return G_SOURCE_REMOVE;
7281 GtkDirectionType direction)
7292 GtkDirectionType direction)
7296 gboolean had_focused_element;
7303 l = g_list_next (l);
7304 focus_element = l ? l->
data : NULL;
7305 had_focused_element =
TRUE;
7308 focus_element = elements ? elements->
data : NULL;
7309 had_focused_element =
FALSE;
7312 g_list_free (elements);
7314 if (focus_element) {
7328 if (!had_focused_element)
7332 if (direction == GTK_DIR_TAB_FORWARD) {
7337 }
else if (direction == GTK_DIR_TAB_BACKWARD) {
7349 GtkDirectionType direction)
7354 if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD)
7358 return GTK_WIDGET_CLASS (ev_view_parent_class)->focus (widget, direction);
7363 GtkWidget *previous_parent)
7367 parent = gtk_widget_get_parent (widget);
7368 g_assert (!parent || GTK_IS_SCROLLED_WINDOW (parent));
7374 GObjectClass *object_class = G_OBJECT_CLASS (
class);
7375 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (
class);
7376 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (
class);
7377 GtkBindingSet *binding_set;
7409 #if GTK_CHECK_VERSION(3, 20, 0)
7410 gtk_widget_class_set_css_name (widget_class,
"evview");
7420 g_object_class_install_property (object_class,
7422 g_param_spec_boolean (
"is-loading",
7424 "Whether the view is loading",
7427 G_PARAM_STATIC_STRINGS));
7433 g_object_class_install_property (object_class,
7435 g_param_spec_boolean (
"can-zoom-in",
7437 "Whether the view can be zoomed in further",
7440 G_PARAM_STATIC_STRINGS));
7446 g_object_class_install_property (object_class,
7448 g_param_spec_boolean (
"can-zoom-out",
7450 "Whether the view can be zoomed out further",
7453 G_PARAM_STATIC_STRINGS));
7456 g_object_class_override_property (object_class,
PROP_HADJUSTMENT,
"hadjustment");
7457 g_object_class_override_property (object_class,
PROP_VADJUSTMENT,
"vadjustment");
7462 G_TYPE_FROM_CLASS (object_class),
7463 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7466 ev_view_marshal_VOID__ENUM_ENUM,
7468 GTK_TYPE_SCROLL_TYPE,
7469 GTK_TYPE_ORIENTATION);
7471 G_TYPE_FROM_CLASS (object_class),
7472 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7475 g_cclosure_marshal_VOID__OBJECT,
7479 G_TYPE_FROM_CLASS (object_class),
7480 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7483 g_cclosure_marshal_VOID__OBJECT,
7487 G_TYPE_FROM_CLASS (object_class),
7488 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7491 g_cclosure_marshal_VOID__POINTER,
7495 G_TYPE_FROM_CLASS (object_class),
7496 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7499 g_cclosure_marshal_VOID__VOID,
7503 G_TYPE_FROM_CLASS (object_class),
7504 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7507 g_cclosure_marshal_VOID__POINTER,
7511 G_TYPE_FROM_CLASS (object_class),
7512 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7515 g_cclosure_marshal_VOID__OBJECT,
7519 G_TYPE_FROM_CLASS (object_class),
7520 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7523 g_cclosure_marshal_VOID__OBJECT,
7527 G_TYPE_FROM_CLASS (object_class),
7528 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7531 g_cclosure_marshal_VOID__VOID,
7535 G_TYPE_FROM_CLASS (object_class),
7536 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
7539 ev_view_marshal_BOOLEAN__ENUM_INT_BOOLEAN,
7541 GTK_TYPE_MOVEMENT_STEP,
7545 G_TYPE_FROM_CLASS (object_class),
7549 ev_view_marshal_VOID__INT_INT,
7554 G_OBJECT_CLASS_TYPE (object_class),
7555 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
7558 g_cclosure_marshal_VOID__VOID,
7563 binding_set = gtk_binding_set_by_class (
class);
7592 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
7594 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
7596 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
7598 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
7600 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
7603 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
"scroll", 2,
7604 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_FORWARD,
7605 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL);
7606 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, GDK_SHIFT_MASK,
"scroll", 2,
7607 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_BACKWARD,
7608 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL);
7609 gtk_binding_entry_add_signal (binding_set, GDK_KEY_H, 0,
"scroll", 2,
7610 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD,
7611 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_HORIZONTAL);
7612 gtk_binding_entry_add_signal (binding_set, GDK_KEY_J, 0,
"scroll", 2,
7613 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD,
7614 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL);
7615 gtk_binding_entry_add_signal (binding_set, GDK_KEY_K, 0,
"scroll", 2,
7616 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD,
7617 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL);
7618 gtk_binding_entry_add_signal (binding_set, GDK_KEY_L, 0,
"scroll", 2,
7619 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD,
7620 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_HORIZONTAL);
7621 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
"scroll", 2,
7622 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_FORWARD,
7623 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL);
7624 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_SHIFT_MASK,
"scroll", 2,
7625 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_BACKWARD,
7626 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL);
7627 gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
"scroll", 2,
7628 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_BACKWARD,
7629 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL);
7630 gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK,
"scroll", 2,
7631 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_FORWARD,
7632 GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL);
7645 GdkEventSequence *sequence,
7675 GtkStyleContext *context;
7676 #if defined (ENABLE_MULTIMEDIA) && defined (GDK_WINDOWING_X11)
7680 gtk_widget_set_has_window (GTK_WIDGET (view),
TRUE);
7681 gtk_widget_set_can_focus (GTK_WIDGET (view),
TRUE);
7682 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (view),
FALSE);
7683 gtk_container_set_resize_mode (GTK_CONTAINER (view), GTK_RESIZE_QUEUE);
7685 context = gtk_widget_get_style_context (GTK_WIDGET (view));
7686 gtk_style_context_add_class (context,
"content-view");
7687 gtk_style_context_add_class (context,
"view");
7689 #if defined (ENABLE_MULTIMEDIA) && defined (GDK_WINDOWING_X11)
7694 visual = gdk_screen_get_system_visual (gdk_screen_get_default ());
7695 gtk_widget_set_visual (GTK_WIDGET (view), visual);
7698 gtk_widget_set_events (GTK_WIDGET (view),
7701 GDK_BUTTON_PRESS_MASK |
7702 GDK_BUTTON_RELEASE_MASK |
7704 GDK_SMOOTH_SCROLL_MASK |
7705 GDK_KEY_PRESS_MASK |
7706 GDK_POINTER_MOTION_MASK |
7707 GDK_POINTER_MOTION_HINT_MASK |
7708 GDK_ENTER_NOTIFY_MASK |
7709 GDK_LEAVE_NOTIFY_MASK);
7738 g_signal_connect (view,
"notify::scale-factor",
7741 view->
zoom_gesture = gtk_gesture_zoom_new (GTK_WIDGET (view));
7742 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (view->
zoom_gesture),
7767 gtk_widget_queue_resize (GTK_WIDGET (view));
7772 cairo_region_t *region,
7776 gdk_window_invalidate_region (gtk_widget_get_window (GTK_WIDGET (view)), region,
TRUE);
7778 gtk_widget_queue_draw (GTK_WIDGET (view));
7794 gtk_widget_queue_draw (GTK_WIDGET (view));
7802 GtkWidget *widget = GTK_WIDGET (view);
7808 if (!gtk_widget_get_realized (widget))
7812 value = (gint) gtk_adjustment_get_value (view->
hadjustment);
7820 value = (gint) gtk_adjustment_get_value (view->
vadjustment);
7827 for (l = view->
children; l && l->data; l = g_list_next (l)) {
7832 if (gtk_widget_get_visible (child->
widget) && gtk_widget_get_visible (widget))
7833 gtk_widget_queue_resize (widget);
7845 gtk_widget_queue_draw (widget);
7847 gdk_window_scroll (gtk_widget_get_window (widget), dx, dy);
7870 gboolean inverted_colors;
7944 g_object_notify (G_OBJECT (view),
"is-loading");
8012 view->
document = document ? g_object_ref (document) : NULL;
8033 gtk_widget_queue_resize (GTK_WIDGET (view));
8052 gtk_widget_queue_resize (GTK_WIDGET (view));
8068 gboolean inverted_colors;
8072 gtk_widget_queue_draw (GTK_WIDGET (view));
8085 gtk_widget_queue_resize (GTK_WIDGET (view));
8093 gboolean can_zoom_in;
8094 gboolean can_zoom_out;
8104 g_object_notify (G_OBJECT (view),
"can-zoom-in");
8109 g_object_notify (G_OBJECT (view),
"can-zoom-out");
8123 gtk_widget_queue_resize (GTK_WIDGET (view));
8130 #define EPSILON 0.0000001
8141 view->
scale = scale;
8145 gtk_widget_queue_resize (GTK_WIDGET (view));
8174 GdkPoint view_point;
8175 GdkRectangle page_area;
8182 &page_area, &border,
8188 gtk_widget_queue_resize (GTK_WIDGET (view));
8198 gtk_widget_queue_resize (GTK_WIDGET (view));
8209 gtk_widget_queue_resize (GTK_WIDGET (view));
8219 if (model == view->
model)
8223 g_signal_handlers_disconnect_by_data (view->
model, view);
8224 g_object_unref (view->
model);
8226 view->
model = g_object_ref (model);
8237 g_signal_connect (view->
model,
"notify::document",
8240 g_signal_connect (view->
model,
"notify::rotation",
8243 g_signal_connect (view->
model,
"notify::inverted-colors",
8246 g_signal_connect (view->
model,
"notify::sizing-mode",
8249 g_signal_connect (view->
model,
"notify::page-layout",
8252 g_signal_connect (view->
model,
"notify::scale",
8255 g_signal_connect (view->
model,
"notify::min-scale",
8258 g_signal_connect (view->
model,
"notify::max-scale",
8261 g_signal_connect (view->
model,
"notify::continuous",
8264 g_signal_connect (view->
model,
"notify::dual-odd-left",
8267 g_signal_connect (view->
model,
"notify::fullscreen",
8270 g_signal_connect (view->
model,
"page-changed",
8282 cairo_region_t *region)
8342 return (
double)target_width / doc_width;
8351 return (
double)target_height / doc_height;
8363 w_scale = (double)target_width / doc_width;
8364 h_scale = (double)target_height / doc_height;
8366 return MIN (w_scale, h_scale);
8376 double fit_width_scale;
8381 if (doc_height < doc_width) {
8382 double fit_height_scale;
8385 scale = MIN (fit_width_scale, fit_height_scale);
8387 double actual_scale;
8390 scale = MIN (fit_width_scale, actual_scale);
8401 gdouble doc_width, doc_height;
8411 doc_width = doc_height;
8418 width -= (2 * (border.left + border.right) + 3 * view->
spacing);
8419 height -= (border.top + border.bottom + 2 * view->
spacing);
8432 doc_width, doc_height, width - sb_size, height);
8435 g_assert_not_reached ();
8446 gdouble doc_width, doc_height;
8456 doc_width = doc_height;
8462 width -= (border.left + border.right + 2 * view->
spacing);
8463 height -= (border.top + border.bottom + 2 * view->
spacing);
8476 doc_width, doc_height, width - sb_size, height);
8479 g_assert_not_reached ();
8491 gdouble doc_width, doc_height;
8501 gdouble width_2, height_2;
8504 if (width_2 > doc_width)
8505 doc_width = width_2;
8506 if (height_2 > doc_height)
8507 doc_height = height_2;
8511 doc_width = doc_width * 2;
8512 width -= ((border.left + border.right)* 2 + 3 * view->
spacing);
8513 height -= (border.top + border.bottom + 2 * view->
spacing);
8526 doc_width, doc_height, width - sb_size, height);
8529 g_assert_not_reached ();
8540 gdouble doc_width, doc_height;
8550 width -= (border.left + border.right + 2 * view->
spacing);
8551 height -= (border.top + border.bottom + 2 * view->
spacing);
8564 doc_width, doc_height, width - sb_size, height);
8567 g_assert_not_reached ();
8584 g_return_if_fail (width >= 0);
8585 g_return_if_fail (height >= 0);
8603 GtkOrientation orientation)
8605 GtkRequisition requisition;
8606 GtkAllocation allocation;
8612 if (orientation == GTK_ORIENTATION_HORIZONTAL &&
8617 gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
8620 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
8621 if (requisition.width == 1) {
8624 if (allocation.width > 0.0)
8625 size = (double) requisition.width / allocation.width;
8630 if (requisition.height == 1) {
8633 if (allocation.height > 0.0)
8634 size = (double) requisition.height / allocation.height;
8664 if (n_results > 0 && view->
find_result < n_results) {
8666 GdkRectangle view_rect;
8695 for (i = 0; i < n_pages; i++) {
8704 if (page >= n_pages)
8705 page = page - n_pages;
8707 page = page + n_pages;
8739 view->
find_job = g_object_ref (job);
8769 gtk_widget_queue_draw (GTK_WIDGET (view));
8792 gtk_widget_queue_draw (GTK_WIDGET (view));
8811 gtk_widget_queue_draw (GTK_WIDGET (view));
8827 gtk_widget_queue_draw (GTK_WIDGET (view));
8847 gtk_widget_queue_draw (GTK_WIDGET (view));
8862 gtk_widget_queue_draw (GTK_WIDGET (view));
8887 GdkRectangle view_rect;
8900 page = GPOINTER_TO_INT (mapping->
data);
8905 gtk_widget_queue_draw (GTK_WIDGET (view));
8913 return rectangle->x <= point->x &&
8914 rectangle->y <= point->y &&
8915 point->x < rectangle->x + rectangle->width &&
8916 point->y < rectangle->y + rectangle->height;
8919 static inline gboolean
8923 return a->x == b->x && a->y == b->y;
8934 gint start_page, end_page;
8945 end_page = n_pages - 1;
8956 for (i = start_page; i <= end_page; i++) {
8957 GdkRectangle page_area;
8961 page_area.x -= border.left;
8962 page_area.y -= border.top;
8963 page_area.width += border.left + border.right;
8964 page_area.height += border.top + border.bottom;
8973 if (first != -1 && last != -1) {
8974 *first_page = first;
8999 for (i = first; i <= last; i++) {
9001 GdkRectangle page_area;
9004 gdouble width, height;
9009 selection->
page = i;
9010 selection->
style = style;
9012 selection->
rect.
x2 = width;
9013 selection->
rect.
y2 = height;
9023 &page_area, &border,
9036 &page_area, &border,
9041 list = g_list_prepend (list, selection);
9044 return g_list_reverse (list);
9055 GList *new_list_ptr, *old_list_ptr;
9064 new_list_ptr = new_list;
9065 old_list_ptr = old_list;
9067 while (new_list_ptr || old_list_ptr) {
9070 cairo_region_t *region = NULL;
9072 new_sel = (new_list_ptr) ? (new_list_ptr->data) : NULL;
9073 old_sel = (old_list_ptr) ? (old_list_ptr->data) : NULL;
9078 if (new_sel && old_sel) {
9079 if (new_sel->
page < old_sel->
page) {
9080 new_list_ptr = new_list_ptr->next;
9082 }
else if (new_sel->
page > old_sel->
page) {
9083 old_list_ptr = old_list_ptr->next;
9086 new_list_ptr = new_list_ptr->next;
9087 old_list_ptr = old_list_ptr->next;
9089 }
else if (new_sel) {
9090 new_list_ptr = new_list_ptr->next;
9091 }
else if (old_sel) {
9092 old_list_ptr = old_list_ptr->next;
9095 g_assert (new_sel || old_sel);
9098 cur_page = new_sel ? new_sel->
page : old_sel->
page;
9099 if (cur_page < view->start_page || cur_page > view->
end_page)
9105 cairo_region_t *tmp_region;
9115 if (old_sel && new_sel) {
9128 }
else if (old_sel && !new_sel) {
9132 }
else if (!old_sel && new_sel) {
9137 g_assert_not_reached ();
9142 GdkRectangle page_area;
9144 cairo_region_t *damage_region;
9149 damage_region = cairo_region_create ();
9154 n_rects = cairo_region_num_rectangles (region);
9155 for (i = 0; i < n_rects; i++) {
9156 cairo_rectangle_int_t rect;
9158 cairo_region_get_rectangle (region, i, &rect);
9159 rect.x += page_area.x + border.left - view->
scroll_x - 2;
9160 rect.y += page_area.y + border.top - view->
scroll_y - 2;
9163 cairo_region_union_rectangle (damage_region, &rect);
9165 cairo_region_destroy (region);
9167 gdk_window_invalidate_region (gtk_widget_get_window (GTK_WIDGET (view)),
9168 damage_region,
TRUE);
9169 cairo_region_destroy (damage_region);
9176 g_list_free_full (old_list, (GDestroyNotify)selection_free);
9207 GList *selections = NULL;
9215 for (i = 0; i < n_pages; i++) {
9216 gdouble width, height;
9222 selection->
page = i;
9225 selection->
rect.
x2 = width;
9226 selection->
rect.
y2 = height;
9228 selections = g_list_prepend (selections, selection);
9248 GdkPoint *start_point,
9249 GdkPoint *end_point)
9259 gchar *normalized_text;
9261 text = g_string_new (NULL);
9272 page, selection->
style,
9273 &(selection->
rect));
9274 g_object_unref (page);
9275 g_string_append (text, tmp);
9281 normalized_text = g_utf8_normalize (text->str, text->len, G_NORMALIZE_NFKC);
9282 g_string_free (text,
TRUE);
9283 return normalized_text;
9290 GtkClipboard *clipboard;
9292 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
9293 GDK_SELECTION_CLIPBOARD);
9294 gtk_clipboard_set_text (clipboard, text, -1);
9312 GtkSelectionData *selection_data,
9319 gtk_selection_data_set_text (selection_data,
9328 gtk_selection_data_set_text (selection_data, text, -1);
9347 GtkClipboard *clipboard;
9349 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view),
9350 GDK_SELECTION_PRIMARY);
9353 GtkTargetList *target_list;
9354 GtkTargetEntry *targets;
9357 target_list = gtk_target_list_new (NULL, 0);
9358 gtk_target_list_add_text_targets (target_list, 0);
9359 targets = gtk_target_table_new_from_list (target_list, &n_targets);
9360 gtk_target_list_unref (target_list);
9362 gtk_clipboard_set_with_owner (clipboard,
9366 G_OBJECT (ev_view));
9368 gtk_target_table_free (targets, n_targets);
9370 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (ev_view))
9371 gtk_clipboard_clear (clipboard);
9400 GdkCursor *cursor = NULL;
9404 if (view->
cursor == new_cursor) {
9408 view->
cursor = new_cursor;
9410 window = gtk_widget_get_window (GTK_WIDGET (view));
9411 widget = gtk_widget_get_toplevel (GTK_WIDGET (view));
9413 gdk_window_set_cursor (window, cursor);
9416 g_object_unref (cursor);
9439 if (next_page == -1)
9455 if (prev_page == -1)