diff --git a/zathura/document.c b/zathura/document.c index b33d186..d998e0f 100644 --- a/zathura/document.c +++ b/zathura/document.c @@ -37,6 +37,7 @@ struct zathura_document_s { double cell_height; /**< height of a page cell in the document (not transformed by scale and rotation) */ unsigned int view_width; /**< width of current viewport */ unsigned int view_height; /**< height of current viewport */ + double view_dpi; /**cell_height = 0.0; document->view_height = 0; document->view_width = 0; + document->view_dpi = 0.0; document->device_factors.x = 1.0; document->device_factors.y = 1.0; document->position_x = 0.0; @@ -495,6 +497,15 @@ zathura_document_set_viewport_height(zathura_document_t* document, unsigned int document->view_height = height; } +void +zathura_document_set_viewport_dpi(zathura_document_t* document, double dpi) +{ + if (document == NULL) { + return; + } + document->view_dpi = dpi; +} + void zathura_document_get_viewport_size(zathura_document_t* document, unsigned int *height, unsigned int* width) @@ -504,6 +515,15 @@ zathura_document_get_viewport_size(zathura_document_t* document, *width = document->view_width; } +double +zathura_document_get_viewport_dpi(zathura_document_t* document) +{ + if (document == NULL) { + return 0.0; + } + return document->view_dpi; +} + void zathura_document_set_device_factors(zathura_document_t* document, double x_factor, double y_factor) diff --git a/zathura/document.h b/zathura/document.h index a993411..d3b0b12 100644 --- a/zathura/document.h +++ b/zathura/document.h @@ -239,6 +239,15 @@ zathura_document_set_viewport_width(zathura_document_t* document, unsigned int w void zathura_document_set_viewport_height(zathura_document_t* document, unsigned int height); +/** + * Sets the viewport DPI (value based on the physical resolution of the monitor). + * + * @param[in] document The document instance + * @param[in] height The viewport DPI + */ +void +zathura_document_set_viewport_dpi(zathura_document_t* document, double dpi); + /** * Return the size of the viewport in pixels. * @@ -249,6 +258,15 @@ void zathura_document_get_viewport_size(zathura_document_t* document, unsigned int *height, unsigned int* width); +/** + * Return the size of the viewport in pixels. + * + * @param[in] document The document instance + * @return The viewport DPI (value based on the physical resolution of the monitor) + */ +double +zathura_document_get_viewport_dpi(zathura_document_t* document); + /** * Set the device scale factors (e.g. for HiDPI). These are generally integers * and equal for x and y. These scaling factors are only used when rendering to diff --git a/zathura/zathura.c b/zathura/zathura.c index c134fcb..e4c5f45 100644 --- a/zathura/zathura.c +++ b/zathura/zathura.c @@ -18,6 +18,10 @@ #include #include +#ifdef GDK_WINDOWING_WAYLAND +#include +#endif + #ifdef G_OS_UNIX #include #include @@ -134,6 +138,63 @@ create_directories(zathura_t* zathura) } } +void +zathura_update_view_dpi(zathura_t* zathura) +{ + if (zathura == NULL) { + return; + } + + /* get view widget GdkMonitor */ + GdkWindow* window = gtk_widget_get_window (zathura->ui.session->gtk.view); // NULL if not realized + if (window == NULL) { + return; + } + GdkDisplay* display = gtk_widget_get_display(zathura->ui.session->gtk.view); + if (display == NULL) { + return; + } + GdkMonitor* monitor = gdk_display_get_monitor_at_window(display, window); + if (monitor == NULL) { + return; + } + + /* physical width of monitor */ + int width_mm = gdk_monitor_get_width_mm(monitor); + + /* size of monitor in pixels */ + GdkRectangle monitor_geom; + gdk_monitor_get_geometry(monitor, &monitor_geom); + + /* calculate dpi, knowing that 1 inch = 25.4 mm */ + double dpi = 0.0; + if (width_mm == 0) { + girara_debug("cannot calculate DPI: monitor has zero width"); + } else { + dpi = monitor_geom.width * 25.4 / width_mm; + } + +#ifdef GDK_WINDOWING_WAYLAND + /* work around apparend bug in GDK: on Wayland, monitor geometry doesn't + * return values in application pixels as documented, but in device pixels. + * */ + if (GDK_IS_WAYLAND_DISPLAY(display)) + { + girara_debug("on Wayland, correcting DPI for device scale factor"); + /* not using the cached value for the scale factor here to avoid issues + * if this function is called before the cached value is updated */ + int device_factor = gtk_widget_get_scale_factor(zathura->ui.session->gtk.view); + if (device_factor != 0) { + dpi /= device_factor; + } + } +#endif + + girara_debug("monitor width: %d mm, pixels: %d, dpi: %f", width_mm, monitor_geom.width, dpi); + + zathura_document_set_viewport_dpi(zathura->document, dpi); +} + static bool init_ui(zathura_t* zathura) { @@ -962,6 +1023,8 @@ document_open(zathura_t* zathura, const char* path, const char* uri, const char* const unsigned int view_height = (unsigned int)floor(gtk_adjustment_get_page_size(vadjustment)); zathura_document_set_viewport_height(zathura->document, view_height); + zathura_update_view_dpi(zathura); + /* get initial device scale */ int device_factor = gtk_widget_get_scale_factor(zathura->ui.session->gtk.view); zathura_document_set_device_factors(zathura->document, device_factor, device_factor); diff --git a/zathura/zathura.h b/zathura/zathura.h index 84e0cb6..03785d0 100644 --- a/zathura/zathura.h +++ b/zathura/zathura.h @@ -287,6 +287,13 @@ void zathura_set_plugin_dir(zathura_t* zathura, const char* dir); */ void zathura_set_argv(zathura_t* zathura, char** argv); +/** + * Calculate and store the monitor DPI for the view widget + * + * @param zathura The zathura session + */ +void zathura_update_view_dpi(zathura_t* zathura); + /** * Opens a file *