diff --git a/adjustment.c b/adjustment.c index 9452c54..8eda6e3 100644 --- a/adjustment.c +++ b/adjustment.c @@ -2,6 +2,144 @@ #include "adjustment.h" #include "utils.h" +#include + + +double +page_calc_height_width(zathura_document_t* document, double height, double width, + unsigned int* page_height, unsigned int* page_width, bool rotate) +{ + g_return_val_if_fail(document != NULL && page_height != NULL && page_width != NULL, 0.0); + + double scale = zathura_document_get_scale(document); + double real_scale; + + if (rotate && zathura_document_get_rotation(document) % 180) { + *page_width = round(height * scale); + *page_height = round(width * scale); + real_scale = MAX(*page_width / height, *page_height / width); + } else { + *page_width = round(width * scale); + *page_height = round(height * scale); + real_scale = MAX(*page_width / width, *page_height / height); + } + + return real_scale; +} + +void +page_calc_position(zathura_document_t* document, double x, double y, + double *xn, double *yn) { + + g_return_if_fail(document != NULL && xn != NULL && yn != NULL); + + unsigned int rot = zathura_document_get_rotation(document); + + if (rot == 90) { + *xn = 1 - y; + *yn = x; + }else if (rot == 180) { + *xn = 1 - x; + *yn = 1 - y; + } else if (rot == 270) { + *xn = y; + *yn = 1 - x; + } else { + *xn = x; + *yn = y; + } +} + + +unsigned int +position_to_page_number(zathura_document_t* document, + double pos_x, double pos_y){ + + g_return_val_if_fail(document != NULL, 0); + + unsigned int doc_width, doc_height; + zathura_document_get_document_size(document, &doc_height, &doc_width); + + unsigned int cell_width, cell_height; + zathura_document_get_cell_size(document, &cell_height, &cell_width); + + unsigned int c0 = zathura_document_get_first_page_column(document); + unsigned int npag = zathura_document_get_number_of_pages(document); + unsigned int ncol = zathura_document_get_pages_per_row(document); + unsigned int nrow = (npag + c0 - 1 + ncol - 1) / ncol; /* number of rows */ + unsigned int pad = zathura_document_get_page_padding(document); + + unsigned int col = floor(pos_x * (double)doc_width / (double)(cell_width + pad)); + unsigned int row = floor(pos_y * (double)doc_height / (double)(cell_height + pad)); + + return ncol * (row % nrow) + (col % ncol) - (c0 - 1); +} + + +void +page_number_to_position(zathura_document_t* document, unsigned int page_number, + double xalign, double yalign, double *pos_x, double *pos_y) { + g_return_if_fail(document != NULL); + + unsigned int c0 = zathura_document_get_first_page_column(document); + unsigned int npag = zathura_document_get_number_of_pages(document); + unsigned int ncol = zathura_document_get_pages_per_row(document); + unsigned int nrow = (npag + c0 - 1 + ncol - 1) / ncol; /* number of rows */ + + /* row and column for page_number indexed from 0 */ + unsigned int row = (page_number + c0 - 1) / ncol; + unsigned int col = (page_number + c0 - 1) % ncol; + + /* sizes of page cell, viewport and document */ + unsigned int cell_height = 0, cell_width = 0; + zathura_document_get_cell_size(document, &cell_height, &cell_width); + + unsigned int view_height = 0, view_width = 0; + zathura_document_get_viewport_size(document, &view_height, &view_width); + + unsigned int doc_height = 0, doc_width = 0; + zathura_document_get_document_size(document, &doc_height, &doc_width); + + /* compute the shift to align to the viewport. If the page fits to viewport, just center it. */ + double shift_x = 0.5, shift_y = 0.5; + if (cell_width > view_width) { + shift_x = 0.5 + (xalign - 0.5) * ((double)cell_width - (double)view_width) / (double)cell_width; + } + + if (cell_height > view_height) { + shift_y = 0.5 + (yalign - 0.5) * ((double)cell_height - (double)view_height) / (double)cell_height; + } + + /* compute the position */ + *pos_x = ((double)col + shift_x) / (double)ncol; + *pos_y = ((double)row + shift_y) / (double)nrow; +} + + +bool +page_is_visible(zathura_document_t *document, unsigned int page_number) { + g_return_val_if_fail(document != NULL, false); + + /* position at the center of the viewport */ + double pos_x = zathura_document_get_position_x(document); + double pos_y = zathura_document_get_position_y(document); + + /* get the center of page page_number */ + double page_x, page_y; + page_number_to_position(document, page_number, 0.5, 0.5, &page_x, &page_y); + + unsigned int cell_width, cell_height; + zathura_document_get_cell_size(document, &cell_height, &cell_width); + + unsigned int doc_width, doc_height; + zathura_document_get_document_size(document, &doc_height, &doc_width); + + unsigned int view_width, view_height; + zathura_document_get_viewport_size(document, &view_height, &view_width); + + return ( fabs(pos_x - page_x) < 0.5 * (double)(view_width + cell_width) / (double)doc_width && + fabs(pos_y - page_y) < 0.5 * (double)(view_height + cell_height) / (double)doc_height); +} GtkAdjustment* zathura_adjustment_clone(GtkAdjustment* adjustment) diff --git a/adjustment.h b/adjustment.h index 63b4f88..96ceb4c 100644 --- a/adjustment.h +++ b/adjustment.h @@ -4,8 +4,73 @@ #define ZATHURA_ADJUSTMENT_H #include +#include +#include "document.h" -/* Clone a GtkAdjustment +/** + * Calculate the page size according to the corrent scaling and rotation if + * desired. + * + * @param document the document + * @param height width the original height and width + * @return page_height page_width the scaled and rotated height and width + * @param rotate honor page's rotation + * @return real scale after rounding + */ +double page_calc_height_width(zathura_document_t* document, double height, double width, + unsigned int* page_height, unsigned int* page_width, bool rotate); + +/** + * Calculate a page relative position after a rotation. The positions x y are + * relative to a page, i.e. 0=top of page, 1=bottom of page. They are NOT + * relative to the entire document. + * + * @param document the document + * @param x y the x y coordinates on the unrotated page + * @param xn yn the x y coordinates after rotation + */ +void page_calc_position(zathura_document_t* document, double x, double y, + double *xn, double *yn); + +/** + * Converts a relative position within the document to a page number. + * + * @param document The document + * @param pos_x pos_y the position relative to the document + * @return page sitting in that position + */ +unsigned int position_to_page_number(zathura_document_t* document, + double pos_x, double pos_y); + +/** + * Converts a page number to a position in units relative to the document + * + * We can specify where to aliwn the viewport and the page. For instance, xalign + * = 0 means align them on the left margin, xalign = 0.5 means centered, and + * xalign = 1.0 align them on the right margin. + * + * The return value is the position in in units relative to the document (0=top + * 1=bottom) of the point thet will lie at the center of the viewport. + * + * @param document The document + * @param page_number the given page number + * @param xalign yalign where to align the viewport and the page + * @return pos_x pos_y position that will lie at the center of the viewport. + */ +void page_number_to_position(zathura_document_t* document, unsigned int page_number, + double xalign, double yalign, double *pos_x, double *pos_y); + +/** + * Checks whether a given page falls within the viewport + * + * @param document The document + * @param page_number the page number + * @return true if the page intersects the viewport + */ +bool page_is_visible(zathura_document_t *document, unsigned int page_number); + +/** + * Clone a GtkAdjustment * * Creates a new adjustment with the same value, lower and upper bounds, step * and page increments and page_size as the original adjustment. diff --git a/bookmarks.c b/bookmarks.c index e7e792a..28f6b5e 100644 --- a/bookmarks.c +++ b/bookmarks.c @@ -25,14 +25,14 @@ zathura_bookmark_add(zathura_t* zathura, const gchar* id, unsigned int page) g_return_val_if_fail(zathura && zathura->document && zathura->bookmarks.bookmarks, NULL); g_return_val_if_fail(id, NULL); - double x = zathura_adjustment_get_ratio(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view))); - double y = zathura_adjustment_get_ratio(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view))); + double position_x = zathura_document_get_position_x(zathura->document); + double position_y = zathura_document_get_position_y(zathura->document); zathura_bookmark_t* old = zathura_bookmark_get(zathura, id); if (old != NULL) { old->page = page; - old->x = x; - old->y = y; + old->x = position_x; + old->y = position_y; if (zathura->database != NULL) { const char* path = zathura_document_get_path(zathura->document); @@ -52,8 +52,8 @@ zathura_bookmark_add(zathura_t* zathura, const gchar* id, unsigned int page) bookmark->id = g_strdup(id); bookmark->page = page; - bookmark->x = x; - bookmark->y = y; + bookmark->x = position_x; + bookmark->y = position_y; girara_list_append(zathura->bookmarks.bookmarks, bookmark); if (zathura->database != NULL) { diff --git a/callbacks.c b/callbacks.c index 2c6323a..cee7731 100644 --- a/callbacks.c +++ b/callbacks.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "callbacks.h" #include "links.h" @@ -48,78 +49,89 @@ cb_buffer_changed(girara_session_t* session) } } -void -cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpointer data) -{ - zathura_t* zathura = data; - if (zathura == NULL || zathura->document == NULL || zathura->ui.page_widget == NULL) { - return; - } - - GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - - /* current adjustment values */ - const GdkRectangle view_rect = { - .x = 0, - .y = 0, - .width = gtk_adjustment_get_page_size(view_hadjustment), - .height = gtk_adjustment_get_page_size(view_vadjustment) - }; - - int page_padding = 1; - girara_setting_get(zathura->ui.session, "page-padding", &page_padding); - - const GdkRectangle center = { - .x = (view_rect.width + 1) / 2, - .y = (view_rect.height + 1) / 2, - .width = (2 * page_padding) + 1, - .height = (2 * page_padding) + 1 - }; - +static void +update_visible_pages(zathura_t* zathura) { const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); - const double scale = zathura_document_get_scale(zathura->document); - bool updated = false; - /* find page that fits */ for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); - - GdkRectangle page_rect = { - .width = zathura_page_get_width(page) * scale, - .height = zathura_page_get_height(page) * scale - }; GtkWidget* page_widget = zathura_page_get_widget(zathura, page); ZathuraPage* zathura_page_widget = ZATHURA_PAGE(page_widget); - gtk_widget_translate_coordinates(page_widget, zathura->ui.session->gtk.view, - 0, 0, &page_rect.x, &page_rect.y); - if (gdk_rectangle_intersect(&view_rect, &page_rect, NULL) == TRUE) { + if (page_is_visible(zathura->document, page_id) == true) { + /* make page visible */ if (zathura_page_get_visibility(page) == false) { zathura_page_set_visibility(page, true); zathura_page_widget_update_view_time(zathura_page_widget); zathura_renderer_page_cache_add(zathura->sync.render_thread, zathura_page_get_index(page)); } - if (zathura->global.update_page_number == true && updated == false - && gdk_rectangle_intersect(¢er, &page_rect, NULL) == TRUE) { - zathura_document_set_current_page_number(zathura->document, page_id); - updated = true; - } + } else { + /* make page invisible */ if (zathura_page_get_visibility(page) == true) { zathura_page_set_visibility(page, false); /* If a page becomes invisible, abort the render request. */ zathura_page_widget_abort_render_request(zathura_page_widget); } + /* reset current search result */ girara_list_t* results = NULL; g_object_get(page_widget, "search-results", &results, NULL); - if (results != NULL) { g_object_set(page_widget, "search-current", 0, NULL); } } } +} + +void +cb_view_hadjustment_value_changed(GtkAdjustment* adjustment, gpointer data) +{ + zathura_t* zathura = data; + if (zathura == NULL || zathura->document == NULL) { + return; + } + + /* Do nothing in index mode */ + if (girara_mode_get(zathura->ui.session) == zathura->modes.index) { + return; + } + + update_visible_pages(zathura); + + double position_x = zathura_adjustment_get_ratio(adjustment); + double position_y = zathura_document_get_position_y(zathura->document); + unsigned int page_id = position_to_page_number(zathura->document, position_x, position_y); + + zathura_document_set_position_x(zathura->document, position_x); + zathura_document_set_position_y(zathura->document, position_y); + zathura_document_set_current_page_number(zathura->document, page_id); + + statusbar_page_number_update(zathura); +} + +void +cb_view_vadjustment_value_changed(GtkAdjustment* adjustment, gpointer data) +{ + zathura_t* zathura = data; + if (zathura == NULL || zathura->document == NULL) { + return; + } + + /* Do nothing in index mode */ + if (girara_mode_get(zathura->ui.session) == zathura->modes.index) { + return; + } + + update_visible_pages(zathura); + + double position_x = zathura_document_get_position_x(zathura->document); + double position_y = zathura_adjustment_get_ratio(adjustment); + unsigned int page_id = position_to_page_number(zathura->document, position_x, position_y); + + zathura_document_set_position_x(zathura->document, position_x); + zathura_document_set_position_y(zathura->document, position_y); + zathura_document_set_current_page_number(zathura->document, page_id); statusbar_page_number_update(zathura); } @@ -133,29 +145,23 @@ cb_view_hadjustment_changed(GtkAdjustment* adjustment, gpointer data) zathura_adjust_mode_t adjust_mode = zathura_document_get_adjust_mode(zathura->document); - gdouble lower, upper, page_size, value, ratio; - bool zoom_center = false; - - switch (adjust_mode) { - center: - case ZATHURA_ADJUST_BESTFIT: - case ZATHURA_ADJUST_WIDTH: - lower = gtk_adjustment_get_lower(adjustment); - upper = gtk_adjustment_get_upper(adjustment); - page_size = gtk_adjustment_get_page_size(adjustment); - value = ((upper - lower) - page_size) / 2.0; - zathura_adjustment_set_value(adjustment, value); - break; - default: - girara_setting_get(zathura->ui.session, "zoom-center", &zoom_center); - if (zoom_center) { - goto center; - } - - ratio = zathura_adjustment_get_ratio(zathura->ui.hadjustment); - zathura_adjustment_set_value_from_ratio(adjustment, ratio); - break; + /* Do nothing in index mode */ + if (girara_mode_get(zathura->ui.session) == zathura->modes.index) { + return; } + + /* Don't scroll we're focusing the inputbar. */ + if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) { + return; + } + + /* save the viewport size */ + unsigned int view_width = (unsigned int)floor(gtk_adjustment_get_page_size(adjustment)); + zathura_document_set_viewport_width(zathura->document, view_width); + + /* reset the adjustment, in case bounds have changed */ + double ratio = zathura_document_get_position_x(zathura->document); + zathura_adjustment_set_value_from_ratio(adjustment, ratio); } void @@ -167,93 +173,71 @@ cb_view_vadjustment_changed(GtkAdjustment* adjustment, gpointer data) zathura_adjust_mode_t adjust_mode = zathura_document_get_adjust_mode(zathura->document); + /* Do nothing in index mode */ + if (girara_mode_get(zathura->ui.session) == zathura->modes.index) { + return; + } + /* Don't scroll we're focusing the inputbar. */ if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) { return; } - double ratio = zathura_adjustment_get_ratio(zathura->ui.vadjustment); + /* save the viewport size */ + unsigned int view_height = (unsigned int)floor(gtk_adjustment_get_page_size(adjustment)); + zathura_document_set_viewport_height(zathura->document, view_height); + + /* reset the adjustment, in case bounds have changed */ + double ratio = zathura_document_get_position_y(zathura->document); zathura_adjustment_set_value_from_ratio(adjustment, ratio); } void -cb_adjustment_track_value(GtkAdjustment* adjustment, gpointer data) +cb_refresh_view(GtkWidget* GIRARA_UNUSED(view), gpointer data) { - GtkAdjustment* tracker = data; - - gdouble lower = gtk_adjustment_get_lower(adjustment); - gdouble upper = gtk_adjustment_get_upper(adjustment); - if (lower != gtk_adjustment_get_lower(tracker) || - upper != gtk_adjustment_get_upper(tracker)) { + zathura_t* zathura = data; + if (zathura == NULL || zathura->document == NULL) { return; } - gdouble value = gtk_adjustment_get_value(adjustment); - gtk_adjustment_set_value(tracker, value); + unsigned int page_id = zathura_document_get_current_page_number(zathura->document); + zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); + if (page == NULL) { + return; + } + + GtkAdjustment* vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); + GtkAdjustment* hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); + + double position_x = zathura_document_get_position_x(zathura->document); + double position_y = zathura_document_get_position_y(zathura->document); + + zathura_adjustment_set_value_from_ratio(vadj, position_y); + zathura_adjustment_set_value_from_ratio(hadj, position_x); + + statusbar_page_number_update(zathura); } void -cb_adjustment_track_bounds(GtkAdjustment* adjustment, gpointer data) -{ - GtkAdjustment* tracker = data; - gdouble value = gtk_adjustment_get_value(adjustment); - gdouble lower = gtk_adjustment_get_lower(adjustment); - gdouble upper = gtk_adjustment_get_upper(adjustment); - gdouble page_size = gtk_adjustment_get_page_size(adjustment); - gtk_adjustment_set_value(tracker, value); - gtk_adjustment_set_lower(tracker, lower); - gtk_adjustment_set_upper(tracker, upper); - gtk_adjustment_set_page_size(tracker, page_size); -} - -void -cb_pages_per_row_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data)) +cb_page_layout_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data)) { g_return_if_fail(value != NULL); g_return_if_fail(session != NULL); g_return_if_fail(session->global.data != NULL); zathura_t* zathura = session->global.data; - int pages_per_row = *(int*) value; - - if (pages_per_row < 1) { - pages_per_row = 1; - } - - unsigned int first_page_column = 1; - girara_setting_get(session, "first-page-column", &first_page_column); - - page_widget_set_mode(zathura, pages_per_row, first_page_column); - - if (zathura->document != NULL) { - unsigned int current_page = zathura_document_get_current_page_number(zathura->document); - page_set_delayed(zathura, current_page); - } -} - -void -cb_first_page_column_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data)) -{ - g_return_if_fail(value != NULL); - g_return_if_fail(session != NULL); - g_return_if_fail(session->global.data != NULL); - zathura_t* zathura = session->global.data; - - int first_page_column = *(int*) value; - - if (first_page_column < 1) { - first_page_column = 1; - } unsigned int pages_per_row = 1; girara_setting_get(session, "pages-per-row", &pages_per_row); - page_widget_set_mode(zathura, pages_per_row, first_page_column); + unsigned int first_page_column = 1; + girara_setting_get(session, "first-page-column", &first_page_column); - if (zathura->document != NULL) { - unsigned int current_page = zathura_document_get_current_page_number(zathura->document); - page_set_delayed(zathura, current_page); - } + unsigned int page_padding = 1; + girara_setting_get(zathura->ui.session, "page-padding", &page_padding); + + page_widget_set_mode(zathura, page_padding, pages_per_row, first_page_column); + zathura_document_set_page_layout(zathura->document, page_padding, pages_per_row, first_page_column); } void @@ -461,23 +445,19 @@ error_ret: } bool -cb_view_resized(GtkWidget* UNUSED(widget), GtkAllocation* allocation, zathura_t* zathura) +cb_view_resized(GtkWidget* UNUSED(widget), GtkAllocation* UNUSED(allocation), zathura_t* zathura) { if (zathura == NULL || zathura->document == NULL) { return false; } - static int height = -1; - static int width = -1; + /* adjust the scale according to settings. If nothing needs to be resized, + it does not trigger the resize event. - /* adjust only if the allocation changed */ - if (width != allocation->width || height != allocation->height) { - girara_argument_t argument = { zathura_document_get_adjust_mode(zathura->document), NULL }; - sc_adjust_window(zathura->ui.session, &argument, NULL, 0); - - width = allocation->width; - height = allocation->height; - } + The right viewport size is already in the document object, due to a + previous call to adjustment_changed. We don't want to use the allocation in + here, because we would have to subtract scrollbars, etc. */ + adjust_view(zathura); return false; } diff --git a/callbacks.h b/callbacks.h index e1af85d..48cbf90 100644 --- a/callbacks.h +++ b/callbacks.h @@ -27,6 +27,15 @@ gboolean cb_destroy(GtkWidget* widget, zathura_t* zathura); */ void cb_buffer_changed(girara_session_t* session); +/** + * This function gets called when the value of the horizontal scrollbars + * changes (e.g.: by scrolling, moving to another page) + * + * @param adjustment The hadjustment of the page view + * @param data NULL + */ +void cb_view_hadjustment_value_changed(GtkAdjustment *adjustment, gpointer data); + /** * This function gets called when the value of the vertical scrollbars * changes (e.g.: by scrolling, moving to another page) @@ -40,9 +49,7 @@ void cb_view_vadjustment_value_changed(GtkAdjustment *adjustment, gpointer data) * This function gets called when the bounds or the page_size of the horizontal * scrollbar change (e.g. when the zoom level is changed). * - * It adjusts the value of the horizontal scrollbar, possibly based on its - * previous adjustment, stored in the tracking adjustment - * zathura->ui.hadjustment. + * It adjusts the value of the horizontal scrollbar * * @param adjustment The horizontal adjustment of a gtkScrolledWindow * @param data The zathura instance @@ -61,26 +68,16 @@ void cb_view_hadjustment_changed(GtkAdjustment *adjustment, gpointer data); */ void cb_view_vadjustment_changed(GtkAdjustment *adjustment, gpointer data); -/* This function gets called when the value of the adjustment changes. +/** + * This function gets called when the program need to refresh the document view. * - * It updates the value of the tracking adjustment, only if the bounds of the - * adjustment have not changed (if they did change, - * cb_adjustment_track_bounds() will take care of updating everything). + * It adjusts the value of the scrollbars, triggering a redraw in the new + * position. * - * @param adjustment The adjustment instance - * @param data The tracking adjustment instance + * @param view The view GtkWidget + * @param data The zathura instance */ -void cb_adjustment_track_value(GtkAdjustment* adjustment, gpointer data); - -/* This function gets called when the bounds or the page_size of the adjustment - * change. - * - * It updates the value, bounds and page_size of the tracking adjustment. - * - * @param adjustment The adjustment instance - * @param data The tracking adjustment instance - */ -void cb_adjustment_track_bounds(GtkAdjustment* adjustment, gpointer data); +void cb_refresh_view(GtkWidget* view, gpointer data); /** * This function gets called when the value of the "pages-per-row" @@ -92,19 +89,7 @@ void cb_adjustment_track_bounds(GtkAdjustment* adjustment, gpointer data); * @param value The value * @param data Custom data */ -void cb_pages_per_row_value_changed(girara_session_t* session, const char* name, - girara_setting_type_t type, void* value, void* data); -/** - * This function gets called when the value of the "first-page-column" - * variable changes - * - * @param session The current girara session - * @param name The name of the row - * @param type The settings type - * @param value The value - * @param data Custom data - */ -void cb_first_page_column_value_changed(girara_session_t* session, const char* name, +void cb_page_layout_value_changed(girara_session_t* session, const char* name, girara_setting_type_t type, void* value, void* data); /** diff --git a/commands.c b/commands.c index b12c979..9b2e798 100644 --- a/commands.c +++ b/commands.c @@ -118,15 +118,9 @@ cmd_bookmark_open(girara_session_t* session, girara_list_t* argument_list) } zathura_jumplist_add(zathura); + page_set(zathura, bookmark->page - 1); if (bookmark->x != DBL_MIN && bookmark->y != DBL_MIN) { - GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - zathura_adjustment_set_value_from_ratio(hadjustment, bookmark->x); - zathura_adjustment_set_value_from_ratio(vadjustment, bookmark->y); - zathura_document_set_current_page_number(zathura->document, bookmark->page - 1); - statusbar_page_number_update(zathura); - } else { - page_set(zathura, bookmark->page - 1); + position_set(zathura, bookmark->x, bookmark->y); } zathura_jumplist_add(zathura); diff --git a/config.c b/config.c index fb126a4..33c1419 100644 --- a/config.c +++ b/config.c @@ -73,27 +73,6 @@ cb_color_change(girara_session_t* session, const char* name, render_all(zathura); } -static void -cb_page_padding_changed(girara_session_t* session, const char* UNUSED(name), - girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data)) -{ - g_return_if_fail(value != NULL); - g_return_if_fail(session != NULL); - g_return_if_fail(session->global.data != NULL); - zathura_t* zathura = session->global.data; - - int val = *(int*) value; - if (GTK_IS_TABLE(zathura->ui.page_widget) == TRUE) { -#if (GTK_MAJOR_VERSION == 3) - gtk_grid_set_row_spacing(GTK_GRID(zathura->ui.page_widget), val); - gtk_grid_set_column_spacing(GTK_GRID(zathura->ui.page_widget), val); -#else - gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_widget), val); - gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_widget), val); -#endif - } -} - static void cb_nohlsearch_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data)) @@ -149,21 +128,21 @@ config_load_default(zathura_t* zathura) girara_mode_set(gsession, zathura->modes.normal); /* zathura settings */ - girara_setting_add(gsession, "database", "plain", STRING, true, _("Database backend"), NULL, NULL); + girara_setting_add(gsession, "database", "plain", STRING, true, _("Database backend"), NULL, NULL); int_value = 10; - girara_setting_add(gsession, "zoom-step", &int_value, INT, false, _("Zoom step"), NULL, NULL); + girara_setting_add(gsession, "zoom-step", &int_value, INT, false, _("Zoom step"), NULL, NULL); int_value = 1; - girara_setting_add(gsession, "page-padding", &int_value, INT, false, _("Padding between pages"), cb_page_padding_changed, NULL); + girara_setting_add(gsession, "page-padding", &int_value, INT, false, _("Padding between pages"), cb_page_layout_value_changed, NULL); int_value = 1; - girara_setting_add(gsession, "pages-per-row", &int_value, INT, false, _("Number of pages per row"), cb_pages_per_row_value_changed, NULL); + girara_setting_add(gsession, "pages-per-row", &int_value, INT, false, _("Number of pages per row"), cb_page_layout_value_changed, NULL); int_value = 1; - girara_setting_add(gsession, "first-page-column", &int_value, INT, false, _("Column of the first page"),cb_first_page_column_value_changed, NULL); + girara_setting_add(gsession, "first-page-column", &int_value, INT, false, _("Column of the first page"), cb_page_layout_value_changed, NULL); float_value = 40; - girara_setting_add(gsession, "scroll-step", &float_value, FLOAT, false, _("Scroll step"), NULL, NULL); + girara_setting_add(gsession, "scroll-step", &float_value, FLOAT, false, _("Scroll step"), NULL, NULL); float_value = 40; - girara_setting_add(gsession, "scroll-hstep", &float_value, FLOAT, false, _("Horizontal scroll step"), NULL, NULL); + girara_setting_add(gsession, "scroll-hstep", &float_value, FLOAT, false, _("Horizontal scroll step"), NULL, NULL); float_value = 0.0; - girara_setting_add(gsession, "scroll-full-overlap", &float_value, FLOAT, false, _("Full page scroll overlap"), NULL, NULL); + girara_setting_add(gsession, "scroll-full-overlap", &float_value, FLOAT, false, _("Full page scroll overlap"), NULL, NULL); int_value = 10; girara_setting_add(gsession, "zoom-min", &int_value, INT, false, _("Zoom minimum"), NULL, NULL); int_value = 1000; @@ -175,13 +154,13 @@ config_load_default(zathura_t* zathura) girara_setting_add(gsession, "recolor-darkcolor", "#FFFFFF", STRING, false, _("Recoloring (dark color)"), cb_color_change, NULL); girara_setting_add(gsession, "recolor-lightcolor", "#000000", STRING, false, _("Recoloring (light color)"), cb_color_change, NULL); - girara_setting_add(gsession, "highlight-color", NULL, STRING, false, _("Color for highlighting"), cb_color_change, NULL); + girara_setting_add(gsession, "highlight-color", NULL, STRING, false, _("Color for highlighting"), cb_color_change, NULL); girara_setting_set(gsession, "highlight-color", "#9FBC00"); - girara_setting_add(gsession, "highlight-active-color", NULL, STRING, false, _("Color for highlighting (active)"), cb_color_change, NULL); + girara_setting_add(gsession, "highlight-active-color", NULL, STRING, false, _("Color for highlighting (active)"), cb_color_change, NULL); girara_setting_set(gsession, "highlight-active-color", "#00BC00"); - girara_setting_add(gsession, "render-loading-bg", NULL, STRING, false, _("'Loading ...' background color"), cb_color_change, NULL); + girara_setting_add(gsession, "render-loading-bg", NULL, STRING, false, _("'Loading ...' background color"), cb_color_change, NULL); girara_setting_set(gsession, "render-loading-bg", "#FFFFFF"); - girara_setting_add(gsession, "render-loading-fg", NULL, STRING, false, _("'Loading ...' foreground color"), cb_color_change, NULL); + girara_setting_add(gsession, "render-loading-fg", NULL, STRING, false, _("'Loading ...' foreground color"), cb_color_change, NULL); girara_setting_set(gsession, "render-loading-fg", "#000000"); bool_value = false; diff --git a/document.c b/document.c index ced8ea3..8b820b6 100644 --- a/document.c +++ b/document.c @@ -22,6 +22,7 @@ #include #include +#include "adjustment.h" #include "document.h" #include "utils.h" #include "zathura.h" @@ -50,6 +51,15 @@ struct zathura_document_s { void* data; /**< Custom data */ zathura_adjust_mode_t adjust_mode; /**< Adjust mode (best-fit, width) */ int page_offset; /**< Page offset */ + double cell_width; /**< width of a page cell in the document (not ransformed by scale and rotation) */ + double cell_height; /**< height of a page cell in the document (not ransformed by scale and rotation) */ + unsigned int view_width; /**< width of current viewport */ + unsigned int view_height; /**< height of current viewport */ + unsigned int pages_per_row; /**< number of pages in a row */ + unsigned int first_page_column; /**< column of the first page */ + unsigned int page_padding; /**< padding between pages */ + double position_x; /**< X adjustment */ + double position_y; /**< Y adjustment */ /** * Document pages @@ -124,6 +134,12 @@ zathura_document_open(zathura_plugin_manager_t* plugin_manager, const char* document->scale = 1.0; document->plugin = plugin; document->adjust_mode = ZATHURA_ADJUST_NONE; + document->cell_width = 0.0; + document->cell_height = 0.0; + document->view_height = 0; + document->view_width = 0; + document->position_x = 0.0; + document->position_y = 0.0; /* open document */ zathura_plugin_functions_t* functions = zathura_plugin_get_functions(plugin); @@ -155,6 +171,15 @@ zathura_document_open(zathura_plugin_manager_t* plugin_manager, const char* } document->pages[page_id] = page; + + /* cell_width and cell_height is the maximum of all the pages width and height */ + double width = zathura_page_get_width(page); + if (document->cell_width < width) + document->cell_width = width; + + double height = zathura_page_get_height(page); + if (document->cell_height < height) + document->cell_height = height; } return document; @@ -310,6 +335,46 @@ zathura_document_set_current_page_number(zathura_document_t* document, unsigned document->current_page_number = current_page; } +double +zathura_document_get_position_x(zathura_document_t* document) +{ + if (document == NULL) { + return 0; + } + + return document->position_x; +} + +double +zathura_document_get_position_y(zathura_document_t* document) +{ + if (document == NULL) { + return 0; + } + + return document->position_y; +} + +void +zathura_document_set_position_x(zathura_document_t* document, double position_x) +{ + if (document == NULL) { + return; + } + + document->position_x = position_x; +} + +void +zathura_document_set_position_y(zathura_document_t* document, double position_y) +{ + if (document == NULL) { + return; + } + + document->position_y = position_y; +} + double zathura_document_get_scale(zathura_document_t* document) { @@ -400,32 +465,99 @@ zathura_document_set_page_offset(zathura_document_t* document, unsigned int page document->page_offset = page_offset; } +void +zathura_document_set_viewport_width(zathura_document_t* document, unsigned int width) +{ + if (document == NULL) { + return; + } + document->view_width = width; +} + +void +zathura_document_set_viewport_height(zathura_document_t* document, unsigned int height) +{ + if (document == NULL) { + return; + } + document->view_height = height; +} + +void +zathura_document_get_viewport_size(zathura_document_t* document, + unsigned int *height, unsigned int* width) +{ + g_return_if_fail(document != NULL && height != NULL && width != NULL); + *height = document->view_height; + *width = document->view_width; +} + void zathura_document_get_cell_size(zathura_document_t* document, unsigned int* height, unsigned int* width) { g_return_if_fail(document != NULL && height != NULL && width != NULL); - unsigned int number_of_pages = - zathura_document_get_number_of_pages(document); - *width = 0; - *height = 0; + page_calc_height_width(document, document->cell_height, document->cell_width, + height, width, true); - /* Get the size of each cell of the table/grid, assuming it is homogeneous - * (i.e. each cell has the same dimensions. */ - for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) { - zathura_page_t* page = zathura_document_get_page(document, page_id); - if (page == NULL) - continue; +} - unsigned int page_width = 0, page_height = 0; - page_calc_height_width(page, &page_height, &page_width, true); +void +zathura_document_get_document_size(zathura_document_t* document, + unsigned int* height, unsigned int* width) +{ + g_return_if_fail(document != NULL && height != NULL && width != NULL); - if (*width < page_width) - *width = page_width; - if (*height < page_height) - *height = page_height; + + unsigned int npag = zathura_document_get_number_of_pages(document); + unsigned int ncol = zathura_document_get_pages_per_row(document); + unsigned int c0 = zathura_document_get_first_page_column(document); + unsigned int nrow = (npag + c0 - 1 + ncol - 1) / ncol; /* number of rows */ + unsigned int pad = zathura_document_get_page_padding(document); + + unsigned int cell_height=0, cell_width=0; + zathura_document_get_cell_size(document, &cell_height, &cell_width); + + *width = ncol * cell_width + (ncol - 1) * pad; + *height = nrow * cell_height + (nrow - 1) * pad; +} + +void +zathura_document_set_page_layout(zathura_document_t* document, unsigned int page_padding, + unsigned int pages_per_row, unsigned int first_page_column) +{ + g_return_if_fail(document != NULL); + document->page_padding = page_padding; + document->pages_per_row = pages_per_row; + document->first_page_column = first_page_column; +} + +unsigned int +zathura_document_get_page_padding(zathura_document_t* document) +{ + if (document == NULL) { + return 0; } + return document->page_padding; +} + +unsigned int +zathura_document_get_pages_per_row(zathura_document_t* document) +{ + if (document == NULL) { + return 0; + } + return document->pages_per_row; +} + +unsigned int +zathura_document_get_first_page_column(zathura_document_t* document) +{ + if (document == NULL) { + return 0; + } + return document->first_page_column; } zathura_error_t diff --git a/document.h b/document.h index 2ce1c68..4b23125 100644 --- a/document.h +++ b/document.h @@ -97,6 +97,42 @@ unsigned int zathura_document_get_current_page_number(zathura_document_t* docume void zathura_document_set_current_page_number(zathura_document_t* document, unsigned int current_page); +/** + * Returns the X position, as a value relative to the document width (0=left, + * 1=right). + * + * @param document The document + * @return X adjustment + */ +double zathura_document_get_position_x(zathura_document_t* document); + +/** + * Returns the Y position as value relative to the document height (0=top, + * 1=bottom) + * + * @param document The document + * @return Y adjustment + */ +double zathura_document_get_position_y(zathura_document_t* document); + +/** + * Sets the X position as a value relative to the document width (0=left, + * 1=right) + * + * @param document The document + * @param position_x the X adjustment + */ +void zathura_document_set_position_x(zathura_document_t* document, double position_x); + +/** + * Sets the Y position as a value relative to the document height (0=top, + * 1=bottom) + * + * @param document The document + * @param position_y the Y adjustment + */ +void zathura_document_set_position_y(zathura_document_t* document, double position_y); + /** * Returns the current scale value of the document * @@ -178,9 +214,37 @@ void* zathura_document_get_data(zathura_document_t* document); void zathura_document_set_data(zathura_document_t* document, void* data); /** - * Computes the size of a cell in the document's layout table, assuming that - * the table is homogeneous (i.e. every cell has the same dimensions). It takes - * the current scale into account. + * Sets the width of the viewport in pixels. + * + * @param[in] document The document instance + * @param[in] width The width of the viewport + */ +void +zathura_document_set_viewport_width(zathura_document_t* document, unsigned int width); + +/** + * Sets the height of the viewport in pixels. + * + * @param[in] document The document instance + * @param[in] height The height of the viewport + */ +void +zathura_document_set_viewport_height(zathura_document_t* document, unsigned int height); + +/** + * Return the size of the viewport in pixels. + * + * @param[in] document The document instance + * @param[out] height,width The width and height of the viewport + */ +void +zathura_document_get_viewport_size(zathura_document_t* document, + unsigned int *height, unsigned int* width); + +/** + * Return the size of a cell from the document's layout table in pixels. Assumes + * that the table is homogeneous (i.e. every cell has the same dimensions). It + * takes the current scale into account. * * @param[in] document The document instance * @param[out] height,width The computed height and width of the cell @@ -188,6 +252,52 @@ void zathura_document_set_data(zathura_document_t* document, void* data); void zathura_document_get_cell_size(zathura_document_t* document, unsigned int* height, unsigned int* width); +/** + * Compute the size of the entire document to be displayed in pixels. Takes into + * account the scale, the layout of the pages, and the padding between them. It + * should be equal to the allocation of zathura->ui.page_widget once it's shown. + * + * @param[in] document The document + * @param[out] height,width The height and width of the document + */ +void zathura_document_get_document_size(zathura_document_t* document, + unsigned int* height, unsigned int* width); + +/** + * Sets the layout of the pages in the document + * + * @param[in] document The document instance + * @param[in] page_padding pixels of padding between pages + * @param[in] pages_per_row number of pages per row + * @param[in] first_page_column column of the first page (first column is 1) + */ +void zathura_document_set_page_layout(zathura_document_t* document, unsigned int page_padding, + unsigned int pages_per_row, unsigned int first_page_column); + +/** + * Returns the padding in pixels betwen pages + * + * @param document The document + * @return The padding in pixels between pages + */ +unsigned int zathura_document_get_page_padding(zathura_document_t* document); + +/** + * Returns the number of pages per row + * + * @param document The document + * @return The number of pages per row + */ +unsigned int zathura_document_get_pages_per_row(zathura_document_t* document); + +/** + * Returns the column for the first page (first column = 1) + * + * @param document The document + * @return The column for the first page + */ +unsigned int zathura_document_get_first_page_column(zathura_document_t* document); + /** * Save the document * diff --git a/links.c b/links.c index 987fa8a..8db3b4b 100644 --- a/links.c +++ b/links.c @@ -6,10 +6,12 @@ #include #include +#include "adjustment.h" #include "links.h" #include "zathura.h" #include "document.h" #include "utils.h" +#include "page.h" struct zathura_link_s { zathura_rectangle_t position; /**< Position of the link */ @@ -140,34 +142,51 @@ zathura_link_evaluate(zathura_t* zathura, zathura_link_t* link) return; } - page_offset_t offset; - page_calculate_offset(zathura, page, &offset); + /* compute the position with the page aligned to the top and left + of the viewport */ + double pos_x = 0; + double pos_y = 0; + page_number_to_position(zathura->document, link->target.page_number, + 0.0, 0.0, &pos_x, &pos_y); - if (link->target.destination_type == ZATHURA_LINK_DESTINATION_XYZ) { - if (link->target.left != -1) { - offset.x += link->target.left * zathura_document_get_scale(zathura->document); - } + /* correct to place the target position at the top of the viewport */ + /* NOTE: link->target is in page units, needs to be scaled and rotated */ + unsigned int cell_height = 0; + unsigned int cell_width = 0; + zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width); - if (link->target.top != -1) { - offset.y += link->target.top * zathura_document_get_scale(zathura->document); - } - } + unsigned int doc_height = 0; + unsigned int doc_width = 0; + zathura_document_get_document_size(zathura->document, &doc_height, &doc_width); - zathura_jumplist_add(zathura); - - /* jump to the page */ - page_set(zathura, link->target.page_number); - - /* move to the target position */ bool link_hadjust = true; girara_setting_get(zathura->ui.session, "link-hadjust", &link_hadjust); - if (link_hadjust == true) { - position_set(zathura, offset.x, offset.y); + /* scale and rotate */ + double scale = zathura_document_get_scale(zathura->document); + double shiftx = link->target.left * scale / (double)cell_width; + double shifty = link->target.top * scale / (double)cell_height; + page_calc_position(zathura->document, shiftx, shifty, &shiftx, &shifty); + + /* shift the position or set to auto */ + if (link->target.destination_type == ZATHURA_LINK_DESTINATION_XYZ && + link->target.left != -1 && link_hadjust == true) { + pos_x += shiftx / (double)doc_width; } else { - position_set(zathura, -1, offset.y); + pos_x = -1; /* -1 means automatic */ } + if (link->target.destination_type == ZATHURA_LINK_DESTINATION_XYZ && + link->target.top != -1) { + pos_y += shifty / (double)doc_height; + } else { + pos_y = -1; /* -1 means automatic */ + } + + /* move to position */ + zathura_jumplist_add(zathura); + zathura_document_set_current_page_number(zathura->document, link->target.page_number); + position_set(zathura, pos_x, pos_y); zathura_jumplist_add(zathura); } break; diff --git a/marks.c b/marks.c index 41144ad..4cd294c 100644 --- a/marks.c +++ b/marks.c @@ -23,7 +23,8 @@ struct zathura_mark_s { int key; /**> Marks key */ double position_x; /**> Horizontal adjustment */ double position_y; /**> Vertical adjustment */ - float scale; /**> Zoom level */ + unsigned int page; /**> Page number */ + double scale; /**> Zoom level */ }; bool @@ -196,21 +197,16 @@ mark_add(zathura_t* zathura, int key) return; } - GtkScrolledWindow *window = GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view); - GtkAdjustment* v_adjustment = gtk_scrolled_window_get_vadjustment(window); - GtkAdjustment* h_adjustment = gtk_scrolled_window_get_hadjustment(window); + unsigned int page_id = zathura_document_get_current_page_number(zathura->document); + double position_x = zathura_document_get_position_x(zathura->document); + double position_y = zathura_document_get_position_y(zathura->document); - if (v_adjustment == NULL || h_adjustment == NULL) { - return; - } - - double position_x = gtk_adjustment_get_value(h_adjustment); - double position_y = gtk_adjustment_get_value(v_adjustment); - float scale = zathura_document_get_scale(zathura->document); + double scale = zathura_document_get_scale(zathura->document); /* search for existing mark */ GIRARA_LIST_FOREACH(zathura->global.marks, zathura_mark_t*, iter, mark) if (mark->key == key) { + mark->page = page_id; mark->position_x = position_x; mark->position_y = position_y; mark->scale = scale; @@ -222,6 +218,7 @@ mark_add(zathura_t* zathura, int key) zathura_mark_t* mark = g_malloc0(sizeof(zathura_mark_t)); mark->key = key; + mark->page = page_id; mark->position_x = position_x; mark->position_y = position_y; mark->scale = scale; @@ -243,12 +240,10 @@ mark_evaluate(zathura_t* zathura, int key) render_all(zathura); zathura_jumplist_add(zathura); + page_set(zathura, mark->page); position_set(zathura, mark->position_x, mark->position_y); zathura_jumplist_add(zathura); - cb_view_vadjustment_value_changed(NULL, zathura); - - zathura->global.update_page_number = true; return; } GIRARA_LIST_FOREACH_END(zathura->global.marks, zathura_mark_t*, iter, mark); diff --git a/render.c b/render.c index 913f463..0c941d9 100644 --- a/render.c +++ b/render.c @@ -4,7 +4,9 @@ #include #include #include "glib-compat.h" + #include "render.h" +#include "adjustment.h" #include "zathura.h" #include "document.h" #include "page.h" @@ -600,8 +602,14 @@ render(ZathuraRenderRequest* request, ZathuraRenderer* renderer) /* create cairo surface */ unsigned int page_width = 0; unsigned int page_height = 0; - const double real_scale = page_calc_height_width(page, &page_height, - &page_width, false); + + zathura_document_t* document = zathura_page_get_document(page); + double height = zathura_page_get_height(page); + double width = zathura_page_get_width(page); + + const double real_scale = page_calc_height_width(document, height, width, + &page_height, &page_width, false); + cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, page_width, page_height); @@ -705,7 +713,9 @@ render_all(zathura_t* zathura) zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); unsigned int page_height = 0, page_width = 0; - page_calc_height_width(page, &page_height, &page_width, true); + double height = zathura_page_get_height(page); + double width = zathura_page_get_width(page); + page_calc_height_width(zathura->document, height, width, &page_height, &page_width, true); GtkWidget* widget = zathura_page_get_widget(zathura, page); gtk_widget_set_size_request(widget, page_width, page_height); diff --git a/shortcuts.c b/shortcuts.c index 435d089..3908167 100644 --- a/shortcuts.c +++ b/shortcuts.c @@ -102,103 +102,8 @@ sc_adjust_window(girara_session_t* session, girara_argument_t* argument, zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); - unsigned int pages_per_row = 1; - girara_setting_get(session, "pages-per-row", &pages_per_row); - - unsigned int first_page_column = 1; - girara_setting_get(session, "first-page-column", &first_page_column); - - int padding = 1; - girara_setting_get(zathura->ui.session, "page-padding", &padding); - - if (zathura->ui.page_widget == NULL || zathura->document == NULL) { - goto error_ret; - } - zathura_document_set_adjust_mode(zathura->document, argument->n); - if (argument->n == ZATHURA_ADJUST_NONE) { - /* there is nothing todo */ - goto error_ret; - } - - /* get window size */ - GtkAllocation allocation; - gtk_widget_get_allocation(session->gtk.view, &allocation); - unsigned int width = allocation.width; - unsigned int height = allocation.height; - - /* scrollbar spacing */ - gint spacing; - gtk_widget_style_get(session->gtk.view, "scrollbar_spacing", &spacing, NULL); - width -= spacing; - - /* correct view size */ - if (gtk_widget_get_visible(GTK_WIDGET(session->gtk.inputbar)) == true) { - gtk_widget_get_allocation(session->gtk.inputbar, &allocation); - height += allocation.height; - } - - double scale = 1.0; - unsigned int cell_height = 0, cell_width = 0; - unsigned int document_height = 0, document_width = 0; - - zathura_document_set_scale(zathura->document, scale); - zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width); - zathura_get_document_size(zathura, cell_height, cell_width, - &document_height, &document_width); - - double page_ratio = (double)cell_height / (double)document_width; - double window_ratio = (double)height / (double)width; - - if (argument->n == ZATHURA_ADJUST_WIDTH || - (argument->n == ZATHURA_ADJUST_BESTFIT && page_ratio < window_ratio)) { - scale = (double)(width - (pages_per_row - 1) * padding) / - (double)(pages_per_row * cell_width); - zathura_document_set_scale(zathura->document, scale); - - bool show_vscrollbar = false; - girara_setting_get(session, "show-v-scrollbar", &show_vscrollbar); - - if (show_vscrollbar) { - /* If the document is taller than the view, there's a vertical - * scrollbar; we need to substract its width from the view's width. */ - zathura_get_document_size(zathura, cell_height, cell_width, - &document_height, &document_width); - if (height < document_height) { - GtkWidget* vscrollbar = gtk_scrolled_window_get_vscrollbar( - GTK_SCROLLED_WINDOW(session->gtk.view)); - - if (vscrollbar != NULL) { - int scroll_width; -#if (GTK_MAJOR_VERSION == 3) - gtk_widget_get_preferred_width(GTK_WIDGET(vscrollbar), NULL, &scroll_width); -#else - GtkRequisition requisition; - gtk_widget_get_requisition(vscrollbar, &requisition); - scroll_width = requisition.width; -#endif - if (0 < scroll_width && (unsigned int)scroll_width < width) { - width -= scroll_width; - scale = (double)(width - (pages_per_row - 1) * padding) / - (double)(pages_per_row * cell_width); - zathura_document_set_scale(zathura->document, scale); - } - } - } - } - } - else if (argument->n == ZATHURA_ADJUST_BESTFIT) { - scale = (double)height / (double)cell_height; - zathura_document_set_scale(zathura->document, scale); - } - else { - goto error_ret; - } - - /* re-render all pages */ - render_all(zathura); - -error_ret: + adjust_view(zathura); return false; } @@ -400,7 +305,6 @@ sc_mouse_scroll(girara_session_t* session, girara_argument_t* argument, girara_e gtk_adjustment_get_value(x_adj) - (event->x - x)); zathura_adjustment_set_value(y_adj, gtk_adjustment_get_value(y_adj) - (event->y - y)); - zathura->global.update_page_number = true; break; /* unhandled events */ @@ -570,7 +474,7 @@ sc_rotate(girara_session_t* session, girara_argument_t* argument, /* render all pages again */ render_all(zathura); - page_set_delayed(zathura, page_number); + page_set(zathura, page_number); return false; } @@ -591,18 +495,14 @@ sc_scroll(girara_session_t* session, girara_argument_t* argument, t = 1; } - GtkAdjustment* adjustment = NULL; - if ( (argument->n == LEFT) || (argument->n == FULL_LEFT) || (argument->n == HALF_LEFT) || - (argument->n == RIGHT) || (argument->n == FULL_RIGHT) || (argument->n == HALF_RIGHT)) { - adjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); - } else { - adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); - } + unsigned int view_width=0, view_height=0; + zathura_document_get_viewport_size(zathura->document, &view_height, &view_width); - gdouble view_size = gtk_adjustment_get_page_size(adjustment); - gdouble value = gtk_adjustment_get_value(adjustment); - gdouble max = gtk_adjustment_get_upper(adjustment) - view_size; - zathura->global.update_page_number = true; + unsigned int cell_width=0, cell_height=0; + zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width); + + unsigned int doc_width=0, doc_height=0; + zathura_document_get_document_size(zathura->document, &doc_height, &doc_width); float scroll_step = 40; girara_setting_get(session, "scroll-step", &scroll_step); @@ -622,108 +522,111 @@ sc_scroll(girara_session_t* session, girara_argument_t* argument, int padding = 1; girara_setting_get(session, "page-padding", &padding); - gdouble new_value; + double pos_x = zathura_document_get_position_x(zathura->document); + double pos_y = zathura_document_get_position_y(zathura->document); + double page_id = zathura_document_get_current_page_number(zathura->document); + double direction = 1.0; + /* if TOP or BOTTOM, go there and we are done */ + if (argument->n == TOP) { + position_set(zathura, -1, 0); + return false; + } else if (argument->n == BOTTOM) { + position_set(zathura, -1, 1.0); + return false; + } + + /* compute the direction of scrolling */ + if ( (argument->n == LEFT) || (argument->n == FULL_LEFT) || (argument->n == HALF_LEFT) || + (argument->n == UP) || (argument->n == FULL_UP) || (argument->n == HALF_UP)) { + direction = -1.0; + } else { + direction = 1.0; + } + + double vstep = (double)(cell_height + padding) / (double)doc_height; + double hstep = (double)(cell_width + padding) / (double)doc_width; + + /* compute new position */ switch(argument->n) { case FULL_UP: - case FULL_LEFT: - new_value = value - (1.0 - scroll_full_overlap) * view_size - padding; - break; case FULL_DOWN: + pos_y += direction * (1.0 - scroll_full_overlap) * vstep; + break; + + case FULL_LEFT: case FULL_RIGHT: - new_value = value + (1.0 - scroll_full_overlap) * view_size + padding; + pos_x += direction * (1.0 - scroll_full_overlap) * hstep; break; + case HALF_UP: - case HALF_LEFT: - new_value = value - ((view_size + padding) / 2); - break; case HALF_DOWN: + pos_y += direction * 0.5 * vstep; + break; + + case HALF_LEFT: case HALF_RIGHT: - new_value = value + ((view_size + padding) / 2); - break; - case LEFT: - new_value = value - scroll_hstep * t; + pos_x += direction * 0.5 * hstep; break; + case UP: - new_value = value - scroll_step * t; - break; - case RIGHT: - new_value = value + scroll_hstep * t; - break; case DOWN: - new_value = value + scroll_step * t; + pos_y += direction * t * scroll_step / (double)doc_height; break; - case TOP: - new_value = 0; + + case LEFT: + case RIGHT: + pos_x += direction * t * scroll_hstep / (double)doc_width; break; - case BOTTOM: - new_value = max; - break; - default: - new_value = value; } - if (scroll_wrap == true) { - if (new_value < 0) - new_value = max; - else if (new_value > max) - new_value = 0; + /* handle boundaries */ + double end_x = 0.5 * (double)view_width / (double)doc_width; + double end_y = 0.5 * (double)view_height / (double)doc_height; + + double new_x = scroll_wrap ? 1.0 - end_x : end_x; + double new_y = scroll_wrap ? 1.0 - end_y : end_y; + + if (pos_x < end_x) { + pos_x = new_x; + } else if (pos_x > 1.0 - end_x) { + pos_x = 1 - new_x; } - if (scroll_page_aware == true) { - int page_offset; - double page_size; + if (pos_y < end_y) { + pos_y = new_y; + } else if (pos_y > 1.0 - end_y) { + pos_y = 1 - new_y; + } - { - unsigned int page_id = zathura_document_get_current_page_number(zathura->document); - zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); - page_offset_t offset; - page_calculate_offset(zathura, page, &offset); + /* snap to the border if we change page */ + double dummy; + unsigned int new_page_id = position_to_page_number(zathura->document, pos_x, pos_y); + if (scroll_page_aware == true && page_id != new_page_id) { + switch(argument->n) { + case FULL_LEFT: + case HALF_LEFT: + page_number_to_position(zathura->document, new_page_id, 1.0, 0.0, &pos_x, &dummy); + break; - double scale = zathura_document_get_scale(zathura->document); + case FULL_RIGHT: + case HALF_RIGHT: + page_number_to_position(zathura->document, new_page_id, 0.0, 0.0, &pos_x, &dummy); + break; - if ((argument->n == LEFT) || (argument->n == FULL_LEFT) || (argument->n == HALF_LEFT) || - (argument->n == RIGHT) || (argument->n == FULL_RIGHT) || (argument->n == HALF_RIGHT)) { - page_offset = offset.x; - page_size = zathura_page_get_width(page) * scale; - } else { - page_offset = offset.y; - page_size = zathura_page_get_height(page) * scale; - } + case FULL_UP: + case HALF_UP: + page_number_to_position(zathura->document, new_page_id, 0.0, 1.0, &dummy, &pos_y); + break; - page_offset -= padding / 2; - page_size += padding; - } - - if ((argument->n == FULL_DOWN) || (argument->n == HALF_DOWN) || - (argument->n == FULL_RIGHT) || (argument->n == HALF_RIGHT)) { - if ((page_offset > value) && - (page_offset < value + view_size)) { - new_value = page_offset; - } else if ((page_offset <= value) && - (page_offset + page_size < value + view_size)) { - new_value = page_offset + page_size + 1; - } else if ((page_offset <= value) && - (page_offset + page_size < new_value + view_size)) { - new_value = page_offset + page_size - view_size + 1; - } - } else if ((argument->n == FULL_UP) || (argument->n == HALF_UP) || - (argument->n == FULL_LEFT) || (argument->n == HALF_LEFT)) { - if ((page_offset + 1 >= value) && - (page_offset < value + view_size)) { - new_value = page_offset - view_size; - } else if ((page_offset <= value) && - (page_offset + page_size + 1 < value + view_size)) { - new_value = page_offset + page_size - view_size; - } else if ((page_offset <= value) && - (page_offset > new_value)) { - new_value = page_offset; - } + case FULL_DOWN: + case HALF_DOWN: + page_number_to_position(zathura->document, new_page_id, 0.0, 0.0, &dummy, &pos_y); + break; } } - zathura_adjustment_set_value(adjustment, new_value); - + position_set(zathura, pos_x, pos_y); return false; } @@ -743,10 +646,9 @@ sc_jumplist(girara_session_t* session, girara_argument_t* argument, return true; } - GtkAdjustment* hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); - GtkAdjustment* vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); - double x = zathura_adjustment_get_ratio(hadj); - double y = zathura_adjustment_get_ratio(vadj); + double x = zathura_document_get_position_x(zathura->document); + double y = zathura_document_get_position_y(zathura->document); + zathura_jump_t* jump = NULL; zathura_jump_t* prev_jump = zathura_jumplist_current(zathura); bool go_to_current = false; @@ -786,11 +688,9 @@ sc_jumplist(girara_session_t* session, girara_argument_t* argument, } if (jump != NULL) { - zathura_adjustment_set_value_from_ratio(hadj, jump->x); - zathura_adjustment_set_value_from_ratio(vadj, jump->y); - zathura_document_set_current_page_number(zathura->document, jump->page); - statusbar_page_number_update(zathura); -} + page_set(zathura, jump->page); + position_set(zathura, jump->x, jump->y); + } return false; } @@ -1011,26 +911,35 @@ sc_search(girara_session_t* session, girara_argument_t* argument, zathura_rectangle_t* rect = girara_list_nth(results, target_idx); zathura_rectangle_t rectangle = recalc_rectangle(target_page, *rect); - page_offset_t offset; - page_calculate_offset(zathura, target_page, &offset); - zathura_jumplist_add(zathura); - - if (zathura_page_get_index(target_page) != cur_page) { - page_set(zathura, zathura_page_get_index(target_page)); - } - - GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - int y = offset.y - gtk_adjustment_get_page_size(view_vadjustment) / 2 + rectangle.y1; - zathura_adjustment_set_value(view_vadjustment, y); bool search_hadjust = true; girara_setting_get(session, "search-hadjust", &search_hadjust); + + /* compute the position of the center of the page */ + double pos_x = 0; + double pos_y = 0; + page_number_to_position(zathura->document, zathura_page_get_index(target_page), + 0.5, 0.5, &pos_x, &pos_y); + + /* correction to center the current result */ + /* NOTE: rectangle is in viewport units, already scaled and rotated */ + unsigned int cell_height = 0; + unsigned int cell_width = 0; + zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width); + + unsigned int doc_height = 0; + unsigned int doc_width = 0; + zathura_document_get_document_size(zathura->document, &doc_height, &doc_width); + + pos_y += (rectangle.y1 - (double)cell_height/2) / (double)doc_height; + if (search_hadjust == true) { - GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - int x = offset.x - gtk_adjustment_get_page_size(view_hadjustment) / 2 + rectangle.x1; - zathura_adjustment_set_value(view_hadjustment, x); + pos_x += (rectangle.x1 - (double)cell_width/2) / (double)doc_width; } + /* move to position */ + zathura_jumplist_add(zathura); + position_set(zathura, pos_x, pos_y); zathura_jumplist_add(zathura); } @@ -1208,24 +1117,14 @@ sc_toggle_index(girara_session_t* session, girara_argument_t* UNUSED(argument), gtk_widget_show(treeview); } - static double vvalue = 0; - static double hvalue = 0; - if (gtk_widget_get_visible(GTK_WIDGET(zathura->ui.index))) { girara_set_view(session, zathura->ui.page_widget_alignment); gtk_widget_hide(GTK_WIDGET(zathura->ui.index)); girara_mode_set(zathura->ui.session, zathura->modes.normal); - /* reset adjustment */ - position_set_delayed(zathura, hvalue, vvalue); + /* refresh view */ + refresh_view(zathura); } else { - /* save adjustment */ - GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); - GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); - - vvalue = gtk_adjustment_get_value(vadjustment); - hvalue = gtk_adjustment_get_value(hadjustment); - /* save current position to the jumplist */ zathura_jumplist_add(zathura); @@ -1315,7 +1214,7 @@ sc_toggle_fullscreen(girara_session_t* session, girara_argument_t* /* reset scale */ zathura_document_set_scale(zathura->document, zoom); render_all(zathura); - page_set_delayed(zathura, zathura_document_get_current_page_number(zathura->document)); + refresh_view(zathura); /* setm ode */ girara_mode_set(session, zathura->modes.normal); @@ -1343,7 +1242,7 @@ sc_toggle_fullscreen(girara_session_t* session, girara_argument_t* /* set full screen */ gtk_window_fullscreen(GTK_WINDOW(session->gtk.window)); - page_set_delayed(zathura, zathura_document_get_current_page_number(zathura->document)); + refresh_view(zathura); /* setm ode */ girara_mode_set(session, zathura->modes.fullscreen); @@ -1420,6 +1319,7 @@ sc_zoom(girara_session_t* session, girara_argument_t* argument, girara_event_t* } render_all(zathura); + refresh_view(zathura); return false; } diff --git a/synctex.c b/synctex.c index 6d8c71f..3a9ea29 100644 --- a/synctex.c +++ b/synctex.c @@ -97,7 +97,7 @@ synctex_record_hits(zathura_t* zathura, int page_idx, girara_list_t* hits, bool g_object_set(page_widget, "search-results", hits, NULL); if (first) { - page_set_delayed(zathura, zathura_page_get_index(page)); + page_set(zathura, zathura_page_get_index(page)); g_object_set(page_widget, "search-current", 0, NULL); } } diff --git a/utils.c b/utils.c index e92c8f3..cd40ec6 100644 --- a/utils.c +++ b/utils.c @@ -240,71 +240,6 @@ error_ret: return rectangle; } -double -page_calc_height_width(zathura_page_t* page, unsigned int* page_height, unsigned int* page_width, bool rotate) -{ - g_return_val_if_fail(page != NULL && page_height != NULL && page_width != NULL, 0.0); - - zathura_document_t* document = zathura_page_get_document(page); - if (document == NULL) { - return 0.0; - } - - double height = zathura_page_get_height(page); - double width = zathura_page_get_width(page); - double scale = zathura_document_get_scale(document); - double real_scale; - - if (rotate && zathura_document_get_rotation(document) % 180) { - *page_width = ceil(height * scale); - *page_height = ceil(width * scale); - real_scale = MAX(*page_width / height, *page_height / width); - } else { - *page_width = ceil(width * scale); - *page_height = ceil(height * scale); - real_scale = MAX(*page_width / width, *page_height / height); - } - - return real_scale; -} - -void -zathura_get_document_size(zathura_t* zathura, - unsigned int cell_height, unsigned int cell_width, - unsigned int* height, unsigned int* width) -{ - g_return_if_fail(zathura != NULL && zathura->document != NULL && - height != NULL && width != NULL); - - unsigned int pages_per_row = 1; - girara_setting_get(zathura->ui.session, "pages-per-row", &pages_per_row); - if (pages_per_row == 0) - pages_per_row = 1; - - unsigned int first_page_column = 1; - girara_setting_get(zathura->ui.session, "first-page-column", &first_page_column); - if (first_page_column < 1) - first_page_column = 1; - if (first_page_column > pages_per_row) - first_page_column = (first_page_column - 1) % pages_per_row + 1; - - int padding = 1; - girara_setting_get(zathura->ui.session, "page-padding", &padding); - - double scale = zathura_document_get_scale(zathura->document); - - cell_height = ceil(cell_height * scale); - cell_width = ceil(cell_width * scale); - - *width = pages_per_row * cell_width + (pages_per_row - 1) * padding; - unsigned int effective_number_of_pages = - zathura_document_get_number_of_pages(zathura->document) + - first_page_column - 1; - unsigned int rows = effective_number_of_pages / pages_per_row + - (effective_number_of_pages % pages_per_row ? 1 : 0); - *height = rows * cell_height + (rows - 1) * padding; -} - GtkWidget* zathura_page_get_widget(zathura_t* zathura, zathura_page_t* page) { diff --git a/utils.h b/utils.h index d42baf5..20da943 100644 --- a/utils.h +++ b/utils.h @@ -86,35 +86,6 @@ zathura_rectangle_t rotate_rectangle(zathura_rectangle_t rectangle, unsigned int */ zathura_rectangle_t recalc_rectangle(zathura_page_t* page, zathura_rectangle_t rectangle); -/** - * Calculate the page size according to the corrent scaling and rotation if - * desired. - * @param page the page - * @param page_height the resulting page height - * @param page_width the resultung page width - * @param rotate honor page's rotation - * @return real scale after rounding - */ -double -page_calc_height_width(zathura_page_t* page, unsigned int* page_height, unsigned int* page_width, bool rotate); - -/** - * Compute the size of the entire document to be displayed (in pixels), taking - * into account the scale, the layout of the pages, and the padding between - * them. It should be equal to the allocation of zathura->ui.page_widget once - * it's shown. - * - * @param[in] zathura The zathura instance - * @param[in] cell_height,cell_width The height and width of a cell containing - * a single page; it should be obtained - * using zathura_document_get_cell_size() - * with the document scale set to 1.0 - * @param[out] height,width The height and width of the document - */ -void zathura_get_document_size(zathura_t* zathura, - unsigned int cell_height, unsigned int cell_width, - unsigned int* height, unsigned int* width); - /** * Returns the page widget of the page * @@ -138,7 +109,7 @@ void document_draw_search_results(zathura_t* zathura, bool value); * * @param zathura The zathura instance * @param markup Enable markup - * @return Version string + * @return Version string */ char* zathura_get_version_string(zathura_t* zathura, bool markup); diff --git a/zathura.c b/zathura.c index 8ba2e80..86f3f8e 100644 --- a/zathura.c +++ b/zathura.c @@ -42,16 +42,6 @@ typedef struct zathura_document_info_s { int page_number; } zathura_document_info_t; -typedef struct page_set_delayed_s { - zathura_t* zathura; - unsigned int page; -} page_set_delayed_t; - -typedef struct position_set_delayed_s { - zathura_t* zathura; - double position_x; - double position_y; -} position_set_delayed_t; static gboolean document_info_open(gpointer data); static void zathura_jumplist_reset_current(zathura_t* zathura); @@ -65,7 +55,6 @@ zathura_create(void) zathura_t* zathura = g_malloc0(sizeof(zathura_t)); /* global settings */ - zathura->global.update_page_number = true; zathura->global.search_direction = FORWARD; /* plugins */ @@ -141,6 +130,21 @@ zathura_init(zathura_t* zathura) zathura->ui.session->events.buffer_changed = cb_buffer_changed; zathura->ui.session->events.unknown_command = cb_unknown_command; + /* zathura signals */ + zathura->signals.refresh_view = g_signal_new("refresh-view", + GTK_TYPE_WIDGET, + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); + + g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view", + G_CALLBACK(cb_refresh_view), zathura); + /* page view */ #if (GTK_MAJOR_VERSION == 3) zathura->ui.page_widget = gtk_grid_new(); @@ -155,37 +159,23 @@ zathura_init(zathura_t* zathura) g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura); - /* Setup hadjustment tracker */ GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment( - GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - zathura->ui.hadjustment = zathura_adjustment_clone(hadjustment); - g_object_ref_sink(zathura->ui.hadjustment); + GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* Connect hadjustment signals */ g_signal_connect(G_OBJECT(hadjustment), "value-changed", - G_CALLBACK(cb_view_vadjustment_value_changed), zathura); - g_signal_connect(G_OBJECT(hadjustment), "value-changed", - G_CALLBACK(cb_adjustment_track_value), zathura->ui.hadjustment); + G_CALLBACK(cb_view_hadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(hadjustment), "changed", G_CALLBACK(cb_view_hadjustment_changed), zathura); - g_signal_connect(G_OBJECT(hadjustment), "changed", - G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.hadjustment); - /* Setup vadjustment tracker */ GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment( - GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - zathura->ui.vadjustment = zathura_adjustment_clone(vadjustment); - g_object_ref_sink(zathura->ui.vadjustment); + GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* Connect vadjustment signals */ g_signal_connect(G_OBJECT(vadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); - g_signal_connect(G_OBJECT(vadjustment), "value-changed", - G_CALLBACK(cb_adjustment_track_value), zathura->ui.vadjustment); g_signal_connect(G_OBJECT(vadjustment), "changed", G_CALLBACK(cb_view_vadjustment_changed), zathura); - g_signal_connect(G_OBJECT(vadjustment), "changed", - G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.vadjustment); /* page view alignment */ zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0); @@ -225,18 +215,6 @@ zathura_init(zathura_t* zathura) /* signals */ g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura); - /* set page padding */ - int page_padding = 1; - girara_setting_get(zathura->ui.session, "page-padding", &page_padding); - -#if (GTK_MAJOR_VERSION == 3) - gtk_grid_set_row_spacing(GTK_GRID(zathura->ui.page_widget), page_padding); - gtk_grid_set_column_spacing(GTK_GRID(zathura->ui.page_widget), page_padding); -#else - gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding); - gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding); -#endif - /* database */ char* database = NULL; girara_setting_get(zathura->ui.session, "database", &database); @@ -304,13 +282,6 @@ zathura_free(zathura_t* zathura) girara_session_destroy(zathura->ui.session); } - if (zathura->ui.hadjustment != NULL) { - g_object_unref(G_OBJECT(zathura->ui.hadjustment)); - } - if (zathura->ui.vadjustment != NULL) { - g_object_unref(G_OBJECT(zathura->ui.vadjustment)); - } - /* stdin support */ if (zathura->stdin_support.file != NULL) { g_unlink(zathura->stdin_support.file); @@ -745,7 +716,10 @@ document_open(zathura_t* zathura, const char* path, const char* password, /* set widget size */ unsigned int page_height = 0; unsigned int page_width = 0; - page_calc_height_width(page, &page_height, &page_width, true); + + double height = zathura_page_get_height(page); + double width = zathura_page_get_width(page); + page_calc_height_width(zathura->document, height, width, &page_height, &page_width, true); gtk_widget_set_size_request(page_widget, page_width, page_height); @@ -756,8 +730,12 @@ document_open(zathura_t* zathura, const char* path, const char* password, } /* view mode */ - int pages_per_row = 1; - int first_page_column = 1; + unsigned int pages_per_row = 1; + unsigned int first_page_column = 1; + unsigned int page_padding = 1; + + girara_setting_get(zathura->ui.session, "page-padding", &page_padding); + if (file_info.pages_per_row > 0) { pages_per_row = file_info.pages_per_row; } else { @@ -772,7 +750,9 @@ document_open(zathura_t* zathura, const char* path, const char* password, girara_setting_set(zathura->ui.session, "pages-per-row", &pages_per_row); girara_setting_set(zathura->ui.session, "first-page-column", &first_page_column); - page_widget_set_mode(zathura, pages_per_row, first_page_column); + + page_widget_set_mode(zathura, page_padding, pages_per_row, first_page_column); + zathura_document_set_page_layout(zathura->document, page_padding, pages_per_row, first_page_column); girara_set_view(zathura->ui.session, zathura->ui.page_widget_alignment); @@ -799,16 +779,14 @@ document_open(zathura_t* zathura, const char* path, const char* password, g_free(file_uri); - /* adjust window */ - girara_argument_t argument = { zathura_document_get_adjust_mode(document), NULL }; - sc_adjust_window(zathura->ui.session, &argument, NULL, 0); + + /* adjust_view and set position*/ + adjust_view(zathura); /* set position */ + page_set(zathura, zathura_document_get_current_page_number(document)); if (file_info.position_x != 0 || file_info.position_y != 0) { - position_set_delayed(zathura, file_info.position_x, file_info.position_y); - } else { - page_set_delayed(zathura, zathura_document_get_current_page_number(document)); - cb_view_vadjustment_value_changed(NULL, zathura); + position_set(zathura, file_info.position_x, file_info.position_y); } return true; @@ -936,12 +914,8 @@ document_close(zathura_t* zathura, bool keep_monitor) girara_setting_get(zathura->ui.session, "first-page-column", &(file_info.first_page_column)); /* get position */ - GtkScrolledWindow *window = GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view); - GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(window); - GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(window); - - file_info.position_x = gtk_adjustment_get_value(hadjustment); - file_info.position_y = gtk_adjustment_get_value(vadjustment); + file_info.position_x = zathura_document_get_position_x(zathura->document); + file_info.position_y = zathura_document_get_position_y(zathura->document); /* save file info */ zathura_db_set_fileinfo(zathura->database, path, &file_info); @@ -991,31 +965,6 @@ document_close(zathura_t* zathura, bool keep_monitor) return true; } -static gboolean -page_set_delayed_impl(gpointer data) -{ - page_set_delayed_t* p = data; - page_set(p->zathura, p->page); - - g_free(p); - return FALSE; -} - -bool -page_set_delayed(zathura_t* zathura, unsigned int page_id) -{ - if (zathura == NULL || zathura->document == NULL || - (page_id >= zathura_document_get_number_of_pages(zathura->document))) { - return false; - } - - page_set_delayed_t* p = g_malloc(sizeof(page_set_delayed_t)); - p->zathura = zathura; - p->page = page_id; - gdk_threads_add_idle(page_set_delayed_impl, p); - return true; -} - bool page_set(zathura_t* zathura, unsigned int page_id) { @@ -1023,33 +972,17 @@ page_set(zathura_t* zathura, unsigned int page_id) goto error_out; } - /* render page */ zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); - if (page == NULL) { goto error_out; } zathura_document_set_current_page_number(zathura->document, page_id); - zathura->global.update_page_number = false; - page_offset_t offset; - page_calculate_offset(zathura, page, &offset); - - GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); - zathura_adjustment_set_value(view_hadjustment, offset.x); - zathura_adjustment_set_value(view_vadjustment, offset.y); - - /* refresh horizontal adjustment, to honor zoom-center */ - cb_view_hadjustment_changed(view_hadjustment, zathura); - - statusbar_page_number_update(zathura); - - return true; + /* negative position means auto */ + return position_set(zathura, -1, -1); error_out: - return false; } @@ -1089,7 +1022,8 @@ statusbar_page_number_update(zathura_t* zathura) } void -page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row, unsigned int first_page_column) +page_widget_set_mode(zathura_t* zathura, unsigned int page_padding, + unsigned int pages_per_row, unsigned int first_page_column) { /* show at least one page */ if (pages_per_row == 0) { @@ -1100,7 +1034,6 @@ page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row, unsigned in if (first_page_column < 1) { first_page_column = 1; } - if (first_page_column > pages_per_row) { first_page_column = ((first_page_column - 1) % pages_per_row) + 1; } @@ -1112,9 +1045,18 @@ page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row, unsigned in gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_widget), remove_page_from_table, (gpointer)0); unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); + #if (GTK_MAJOR_VERSION == 3) + gtk_grid_set_row_spacing(GTK_GRID(zathura->ui.page_widget), page_padding); + gtk_grid_set_column_spacing(GTK_GRID(zathura->ui.page_widget), page_padding); + #else - gtk_table_resize(GTK_TABLE(zathura->ui.page_widget), ceil((number_of_pages + first_page_column - 1) / pages_per_row), pages_per_row); + gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding); + gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding); + + unsigned int ncol = pages_per_row; + unsigned int nrow = (number_of_pages + first_page_column - 1 + ncol - 1) / ncol; + gtk_table_resize(GTK_TABLE(zathura->ui.page_widget), nrow, ncol); #endif for (unsigned int i = 0; i < number_of_pages; i++) { @@ -1133,94 +1075,126 @@ page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row, unsigned in gtk_widget_show_all(zathura->ui.page_widget); } -static gboolean -position_set_delayed_impl(gpointer data) -{ - position_set_delayed_t* p = (position_set_delayed_t*) data; - - GtkScrolledWindow *window = GTK_SCROLLED_WINDOW(p->zathura->ui.session->gtk.view); - GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(window); - GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(window); - - /* negative values mean: don't set the position */ - if (p->position_x >= 0) { - zathura_adjustment_set_value(hadjustment, p->position_x); - } - - if (p->position_y >= 0) { - zathura_adjustment_set_value(vadjustment, p->position_y); - } - - g_free(p); - - return FALSE; -} - -void -position_set_delayed(zathura_t* zathura, double position_x, double position_y) -{ - g_return_if_fail(zathura != NULL); - - position_set_delayed_t* p = g_malloc0(sizeof(position_set_delayed_t)); - - p->zathura = zathura; - p->position_x = position_x; - p->position_y = position_y; - - gdk_threads_add_idle(position_set_delayed_impl, p); -} - -void +bool position_set(zathura_t* zathura, double position_x, double position_y) { - g_return_if_fail(zathura != NULL); - - GtkScrolledWindow *window = GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view); - GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(window); - GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(window); - - /* negative values mean: don't set the position */ - if (position_x >= 0) { - zathura_adjustment_set_value(hadjustment, position_x); + if (zathura == NULL || zathura->document == NULL) { + goto error_out; } - if (position_y >= 0) { - zathura_adjustment_set_value(vadjustment, position_y); + double comppos_x, comppos_y; + unsigned int page_id = zathura_document_get_current_page_number(zathura->document); + + /* xalign = 0.5: center horizontally (with the page, not the document) */ + /* yalign = 0.0: align page an viewport edges at the top */ + page_number_to_position(zathura->document, page_id, 0.5, 0.0, &comppos_x, &comppos_y); + + /* automatic horizontal adjustment */ + zathura_adjust_mode_t adjust_mode = zathura_document_get_adjust_mode(zathura->document); + + /* negative position_x mean: use the computed value */ + if (position_x < 0) { + position_x = comppos_x; + bool zoom_center = false; + girara_setting_get(zathura->ui.session, "zoom-center", &zoom_center); + + /* center horizontally */ + if (adjust_mode == ZATHURA_ADJUST_BESTFIT || + adjust_mode == ZATHURA_ADJUST_WIDTH || + zoom_center) { + position_x = 0.5; + } } + + if (position_y < 0) { + position_y = comppos_y; + } + + /* set the position */ + zathura_document_set_position_x(zathura->document, position_x); + zathura_document_set_position_y(zathura->document, position_y); + + /* trigger a 'change' event for both adjustments */ + refresh_view(zathura); + + return true; + +error_out: + return false; } -static void -zathura_jumplist_hide_inputbar(zathura_t* zathura) -{ - g_return_if_fail(zathura != NULL && zathura->ui.session->gtk.inputbar != NULL); - girara_argument_t arg = { GIRARA_HIDE, NULL }; - girara_isc_completion(zathura->ui.session, &arg, NULL, 0); +void +refresh_view(zathura_t* zathura) { + g_return_if_fail(zathura != NULL); - if (zathura->ui.session->global.autohide_inputbar == true) { - /* XXX: This is a workaround for incremental-search. We should revisit this - * when we drop GTK+3 support and the inputbar is placed in a GtkOverlay - * widget. */ - char *input = gtk_editable_get_chars(GTK_EDITABLE(zathura->ui.session->gtk.inputbar_entry), 0, -1); - bool res = false; + /* emit a custom refresh-view signal */ + g_signal_emit(zathura->ui.session->gtk.view, zathura->signals.refresh_view, + 0, zathura); +} - girara_setting_get(zathura->ui.session, "incremental-search", &res); - if ((*input == '/' || *input == '?') && res == true) { - g_free(input); +bool +adjust_view(zathura_t* zathura) { + g_return_val_if_fail(zathura != NULL, false); - return; - } - /* */ - - gtk_widget_hide(zathura->ui.session->gtk.inputbar); + if (zathura->ui.page_widget == NULL || zathura->document == NULL) { + goto error_ret; } - /* we want to do it immediately */ - /* XXX: ... and we want this to go away */ - while (gtk_events_pending()) { - gtk_main_iteration(); + zathura_adjust_mode_t adjust_mode = zathura_document_get_adjust_mode(zathura->document); + if (adjust_mode == ZATHURA_ADJUST_NONE) { + /* there is nothing todo */ + goto error_ret; } + + unsigned int cell_height = 0, cell_width = 0; + unsigned int document_height = 0, document_width = 0; + unsigned int view_height = 0, view_width = 0; + + zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width); + zathura_document_get_document_size(zathura->document, &document_height, &document_width); + zathura_document_get_viewport_size(zathura->document, &view_height, &view_width); + + double scale = zathura_document_get_scale(zathura->document); + + if (view_height == 0 || view_width == 0 || cell_height == 0 || cell_width == 0) { + goto error_ret; + } + + double page_ratio = (double)cell_height / (double)document_width; + double view_ratio = (double)view_height / (double)view_width; + double newscale = scale; + + if (adjust_mode == ZATHURA_ADJUST_WIDTH || + (adjust_mode == ZATHURA_ADJUST_BESTFIT && page_ratio < view_ratio)) { + newscale = scale * (double)view_width / (double)document_width; + + } else if (adjust_mode == ZATHURA_ADJUST_BESTFIT) { + newscale = scale * (double)view_height / (double)cell_height; + + } else { + goto error_ret; + } + + /* save new scale and recompute cell size */ + zathura_document_set_scale(zathura->document, newscale); + unsigned int new_cell_height = 0, new_cell_width = 0; + zathura_document_get_cell_size(zathura->document, &new_cell_height, &new_cell_width); + + /* if the change in scale changes page cell dimensions by at least one pixel, render */ + if (abs(new_cell_width - cell_width) > 1 || + abs(new_cell_height - cell_height) > 1) { + render_all(zathura); + refresh_view(zathura); + + /* otherwise set the old scale and leave */ + } else { + zathura_document_set_scale(zathura->document, scale); + } + +error_ret: + return false; } bool @@ -1321,12 +1295,11 @@ zathura_jumplist_trim(zathura_t* zathura) void zathura_jumplist_add(zathura_t* zathura) { - g_return_if_fail(zathura != NULL && zathura->jumplist.list != NULL); - zathura_jumplist_hide_inputbar(zathura); + g_return_if_fail(zathura != NULL && zathura->document != NULL && zathura->jumplist.list != NULL); unsigned int pagenum = zathura_document_get_current_page_number(zathura->document); - double x = zathura_adjustment_get_ratio(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view))); - double y = zathura_adjustment_get_ratio(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view))); + double x = zathura_document_get_position_x(zathura->document); + double y = zathura_document_get_position_y(zathura->document); if (zathura->jumplist.size != 0) { zathura_jumplist_reset_current(zathura); @@ -1375,7 +1348,7 @@ zathura_jumplist_load(zathura_t* zathura, const char* file) static void zathura_jumplist_save(zathura_t* zathura) { - g_return_if_fail(zathura != NULL); + g_return_if_fail(zathura != NULL && zathura->document != NULL); zathura_jump_t* cur = zathura_jumplist_current(zathura); @@ -1383,7 +1356,7 @@ zathura_jumplist_save(zathura_t* zathura) if (cur) { cur->page = pagenum; - cur->x = zathura_adjustment_get_ratio(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view))); - cur->y = zathura_adjustment_get_ratio(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view))); + cur->x = zathura_document_get_position_x(zathura->document); + cur->y = zathura_document_get_position_y(zathura->document); } } diff --git a/zathura.h b/zathura.h index 1ed99a4..4b198ed 100644 --- a/zathura.h +++ b/zathura.h @@ -69,9 +69,6 @@ struct zathura_s GtkWidget *page_widget_alignment; GtkWidget *page_widget; /**< Widget that contains all rendered pages */ GtkWidget *index; /**< Widget to show the index of the document */ - - GtkAdjustment *hadjustment; /**< Tracking hadjustment */ - GtkAdjustment *vadjustment; /**< Tracking vadjustment */ } ui; struct @@ -104,7 +101,6 @@ struct zathura_s struct { - bool update_page_number; /**< Update current page number */ int search_direction; /**< Current search direction (FORWARD or BACKWARD) */ girara_list_t* marks; /**< Marker */ char** arguments; /**> Arguments that were passed at startup */ @@ -132,6 +128,11 @@ struct zathura_s unsigned int max_size; } jumplist; + struct + { + guint refresh_view; + } signals; + struct { gchar* file; @@ -295,40 +296,39 @@ bool document_close(zathura_t* zathura, bool keep_monitor); bool page_set(zathura_t* zathura, unsigned int page_id); /** - * Opens the page with the given number (delayed) + * Moves to the given position * - * @param zathura The zathura session - * @param page_id The id of the page that should be set + * @param zathura Zathura session + * @param position_x X coordinate + * @param position_y Y coordinate * @return If no error occured true, otherwise false, is returned. */ -bool page_set_delayed(zathura_t* zathura, unsigned int page_id); +bool position_set(zathura_t* zathura, double position_x, double position_y); /** - * Moves to the given position + * Refresh the page view * * @param zathura Zathura session - * @param position_x X coordinate - * @param position_y Y coordinate */ -void position_set_delayed(zathura_t* zathura, double position_x, double position_y); +void refresh_view(zathura_t* zathura); /** - * Moves to the given position + * Recompute the scale according to settings * * @param zathura Zathura session - * @param position_x X coordinate - * @param position_y Y coordinate */ -void position_set(zathura_t* zathura, double position_x, double position_y); +bool adjust_view(zathura_t* zathura); /** * Builds the box structure to show the rendered pages * * @param zathura The zathura session + * @param page_padding padding in pixels between pages * @param pages_per_row Number of shown pages per row * @param first_page_column Column on which first page start */ -void page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row, unsigned int first_page_column); +void page_widget_set_mode(zathura_t* zathura, unsigned int page_padding, + unsigned int pages_per_row, unsigned int first_page_column); /** * Updates the page number in the statusbar. Note that 1 will be added to the