Instead of guesstimating the values of the scrollbars adjustments after a change in zoom level, connect callbacks to the "changed" GtkAdjustment event (which is emitted when the bounds or page_size of the adjustment change, e.g. when the zoom level changes), and compute the new values from there.
cb_view_hadjustment_changed() centers the page horizontally if a "best-fit" or "width" zoom is being performed, or if "zoom-center" is true; otherwise, it keeps the view horizontally centered around the same area of the page. cb_view_vadjustment_changed() always keeps the view vertically centered around the same area of the page. --- This is in preparation for addressing <http://bugs.pwmt.org/issue99>. A patch will follow shortly. --- callbacks.c | 43 +++++++++++++++++++++++++++++++++++++++++++ callbacks.h | 19 +++++++++++++++++++ document.c | 32 ++++++++++++++++++++++++++++++++ document.h | 38 ++++++++++++++++++++++++++++++++++++++ marks.c | 3 +-- shortcuts.c | 5 ++--- utils.c | 49 +++++++++++++++++++++++++++++++------------------ utils.h | 24 +++++++++++++++++++++++- zathura.c | 2 ++ 9 files changed, 191 insertions(+), 24 deletions(-) diff --git a/callbacks.c b/callbacks.c index b72ebad..59123f8 100644 --- a/callbacks.c +++ b/callbacks.c @@ -109,6 +109,49 @@ cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpoi } void +cb_view_hadjustment_changed(GtkAdjustment* adjustment, gpointer data) +{ + zathura_t* zathura = data; + g_return_if_fail(zathura != NULL); + + 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; + set_adjustment(adjustment, value); + break; + default: + girara_setting_get(zathura->ui.session, "zoom-center", &zoom_center); + if (zoom_center) + goto center; + + ratio = zathura_document_get_hadjustment_ratio(zathura->document); + set_adjustment_from_ratio(adjustment, ratio); + break; + } +} + +void +cb_view_vadjustment_changed(GtkAdjustment* adjustment, gpointer data) +{ + zathura_t* zathura = data; + g_return_if_fail(zathura != NULL); + + double ratio = zathura_document_get_vadjustment_ratio(zathura->document); + set_adjustment_from_ratio(adjustment, ratio); +} + +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)) { g_return_if_fail(value != NULL); diff --git a/callbacks.h b/callbacks.h index 4ce2e2e..dcbce3e 100644 --- a/callbacks.h +++ b/callbacks.h @@ -35,6 +35,25 @@ void cb_buffer_changed(girara_session_t* session); * @param data NULL */ 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 changes (e.g. when the zoom level is changed). + * + * @param adjustment The horizontal adjustment of a gtkScrolledWindow + * @param data The zathura instance + */ +void cb_view_hadjustment_changed(GtkAdjustment *adjustment, gpointer data); + +/** + * This function gets called when the bounds or the page_size of the vertical + * scrollbar changes (e.g. when the zoom level is changed). + * + * @param adjustment The vertical adjustment of a gtkScrolledWindow + * @param data The zathura instance + */ +void cb_view_vadjustment_changed(GtkAdjustment *adjustment, gpointer data); + /** * This function gets called when the value of the "pages-per-row" * variable changes diff --git a/document.c b/document.c index 6b8d52b..b992010 100644 --- a/document.c +++ b/document.c @@ -48,6 +48,10 @@ struct zathura_document_s { void* data; /**< Custom data */ zathura_adjust_mode_t adjust_mode; /**< Adjust mode (best-fit, width) */ unsigned int page_offset; /**< Page offset */ + struct { + double horizontal; /**< Horizontal adjustment ratio */ + double vertical; /**< Vertical adjustment ratio */ + } adjustment_ratio; /** * Document pages @@ -391,6 +395,34 @@ zathura_document_set_page_offset(zathura_document_t* document, unsigned int page } } +double +zathura_document_get_hadjustment_ratio(zathura_document_t* document) +{ + if (document == NULL) + return 0.0; + + return document->adjustment_ratio.horizontal; +} + +double +zathura_document_get_vadjustment_ratio(zathura_document_t* document) +{ + if (document == NULL) + return 0.0; + + return document->adjustment_ratio.vertical; +} + +void +zathura_document_set_adjustment_ratios(zathura_document_t* document, + double hadjustment_ratio, + double vadjustment_ratio) +{ + g_return_if_fail(document != NULL); + document->adjustment_ratio.horizontal = hadjustment_ratio; + document->adjustment_ratio.vertical = vadjustment_ratio; +} + void zathura_document_get_cell_size(zathura_document_t* document, unsigned int* height, unsigned int* width) diff --git a/document.h b/document.h index 113344e..b8c3426 100644 --- a/document.h +++ b/document.h @@ -154,6 +154,44 @@ unsigned int zathura_document_get_page_offset(zathura_document_t* document); void zathura_document_set_page_offset(zathura_document_t* document, unsigned int page_offset); /** + * Returns the stored horizontal adjustment ratio + * + * It is the ratio between the the length from the lower bound to the middle of + * the slider, and the total length of the scrollbar. It is used to keep the + * view centered on the same area while zooming in or out. + * + * @param document The document instance + * @return The stored horizontal adjustment ratio + */ +double zathura_document_get_hadjustment_ratio(zathura_document_t* document); + +/** + * Returns the stored vertical adjustment ratio + * + * It is the ratio between the the length from the lower bound to the middle of + * the slider, and the total length of the scrollbar. It is used to keep the + * view centered on the same area while zooming in or out. + * + * @param document The document instance + * @return The stored vertical adjustment ratio + */ +double zathura_document_get_vadjustment_ratio(zathura_document_t* document); + +/** + * Stores the horizontal and vertical adjustment ratios + * + * The ratio is usually obtained from a call to compute_adjustment_ratio() from + * utils.h. + * + * @param document The document instance + * @param The horizontal adjustment ratio + * @param The vertical adjustment ratio + */ +void zathura_document_set_adjustment_ratios(zathura_document_t* document, + double hadjustment_ratio, + double vadjustment_ratio); + +/** * Returns the private data of the document * * @param document The document diff --git a/marks.c b/marks.c index d5e4d47..a60b63f 100644 --- a/marks.c +++ b/marks.c @@ -235,9 +235,8 @@ mark_evaluate(zathura_t* zathura, int key) /* search for existing mark */ GIRARA_LIST_FOREACH(zathura->global.marks, zathura_mark_t*, iter, mark) if (mark != NULL && mark->key == key) { - double old_scale = zathura_document_get_scale(zathura->document); zathura_document_set_scale(zathura->document, mark->scale); - readjust_view_after_zooming(zathura, old_scale, true); + readjust_view_after_zooming(zathura); render_all(zathura); position_set_delayed(zathura, mark->position_x, mark->position_y); diff --git a/shortcuts.c b/shortcuts.c index a3348af..394239d 100644 --- a/shortcuts.c +++ b/shortcuts.c @@ -105,7 +105,6 @@ sc_adjust_window(girara_session_t* session, girara_argument_t* argument, goto error_ret; } - float old_zoom = zathura_document_get_scale(zathura->document); zathura_document_set_adjust_mode(zathura->document, argument->n); if (argument->n == ZATHURA_ADJUST_NONE) { /* there is nothing todo */ @@ -181,7 +180,7 @@ sc_adjust_window(girara_session_t* session, girara_argument_t* argument, } /* keep position */ - readjust_view_after_zooming(zathura, old_zoom, false); + readjust_view_after_zooming(zathura); /* re-render all pages */ render_all(zathura); @@ -1215,7 +1214,7 @@ sc_zoom(girara_session_t* session, girara_argument_t* argument, girara_event_t* } /* keep position */ - readjust_view_after_zooming(zathura, old_zoom, true); + readjust_view_after_zooming(zathura); render_all(zathura); diff --git a/utils.c b/utils.c index fd052e5..c402512 100644 --- a/utils.c +++ b/utils.c @@ -255,6 +255,21 @@ set_adjustment(GtkAdjustment* adjustment, gdouble value) MIN(gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment), value))); } +void +set_adjustment_from_ratio(GtkAdjustment* adjustment, double ratio) +{ + if (ratio == 0.0) + return; + + gdouble lower = gtk_adjustment_get_lower(adjustment); + gdouble upper = gtk_adjustment_get_upper(adjustment); + gdouble page_size = gtk_adjustment_get_page_size(adjustment); + + gdouble value = (upper - lower) * ratio + lower - page_size / 2.0; + + set_adjustment(adjustment, value); +} + double page_calc_height_width(zathura_page_t* page, unsigned int* page_height, unsigned int* page_width, bool rotate) { @@ -332,33 +347,31 @@ zathura_page_get_widget(zathura_t* zathura, zathura_page_t* page) return zathura->pages[page_number]; } +double +compute_adjustment_ratio(GtkAdjustment* adjustment) +{ + gdouble lower = gtk_adjustment_get_lower(adjustment); + gdouble upper = gtk_adjustment_get_upper(adjustment); + gdouble page_size = gtk_adjustment_get_page_size(adjustment); + gdouble value = gtk_adjustment_get_value(adjustment); + return (value - lower + page_size / 2.0) / (upper - lower); +} + void -readjust_view_after_zooming(zathura_t *zathura, float old_zoom, bool delay) +readjust_view_after_zooming(zathura_t *zathura) { if (zathura == NULL || zathura->document == NULL) { return; } 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); - - double scale = zathura_document_get_scale(zathura->document); - gdouble valx = gtk_adjustment_get_value(hadjustment) / old_zoom * scale; - gdouble valy = gtk_adjustment_get_value(vadjustment) / old_zoom * scale; - bool zoom_center = false; - girara_setting_get(zathura->ui.session, "zoom-center", &zoom_center); - if (zoom_center) { - valx += gtk_adjustment_get_page_size(hadjustment) * (scale / old_zoom - 1) / 2; - } + GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(window); + GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(window); - if (delay == true) { - position_set_delayed(zathura, valx, valy); - } else { - set_adjustment(hadjustment, valx); - set_adjustment(vadjustment, valy); - } + zathura_document_set_adjustment_ratios(zathura->document, + compute_adjustment_ratio(hadjustment), + compute_adjustment_ratio(vadjustment)); } void diff --git a/utils.h b/utils.h index b480ab8..0f757d4 100644 --- a/utils.h +++ b/utils.h @@ -94,6 +94,17 @@ zathura_rectangle_t recalc_rectangle(zathura_page_t* page, zathura_rectangle_t r void set_adjustment(GtkAdjustment* adjust, gdouble value); /** + * Set the adjustment value from ratio + * + * The ratio is usually obtained from a previous call to + * compute_adjustment_ratio(). + * + * @param adjustment Adjustment instance + * @param ratio The ratio from which the adjustment value will be computed + */ +void set_adjustment_from_ratio(GtkAdjustment* adjustment, double ratio); + +/** * Calculate the page size according to the corrent scaling and rotation if * desired. * @param page the page @@ -133,13 +144,24 @@ void zathura_get_document_size(zathura_t* zathura, GtkWidget* zathura_page_get_widget(zathura_t* zathura, zathura_page_t* page); /** + * Compute the adjustment ratio + * + * That is, the ratio between the length from the lower bound to the middle of + * the slider, and the total length of the scrollbar. + * + * @param adjustment Adjustment from a gtkScrolledWindow + * @return Adjustment ratio + */ +double compute_adjustment_ratio(GtkAdjustment* adjustment); + +/** * Re-adjust view * * @param zathura Zathura instance * @param old_zoom Old zoom value * @param delay true if action should be delayed */ -void readjust_view_after_zooming(zathura_t* zathura, float old_zoom, bool delay); +void readjust_view_after_zooming(zathura_t* zathura); /** * Set if the search results should be drawn or not diff --git a/zathura.c b/zathura.c index 7485530..351ffed 100644 --- a/zathura.c +++ b/zathura.c @@ -155,8 +155,10 @@ zathura_init(zathura_t* zathura) /* callbacks */ GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); g_signal_connect(G_OBJECT(view_vadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); + g_signal_connect(G_OBJECT(view_vadjustment), "changed", G_CALLBACK(cb_view_vadjustment_changed), zathura); GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); g_signal_connect(G_OBJECT(view_hadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); + g_signal_connect(G_OBJECT(view_hadjustment), "changed", G_CALLBACK(cb_view_hadjustment_changed), zathura); /* page view alignment */ zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0); -- 1.7.10.4 _______________________________________________ zathura mailing list zathura@lists.pwmt.org http://lists.pwmt.org/mailman/listinfo/zathura