From 69a05d516bd0c7e369a0ba1fb78aac57a5ea26f2 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Thu, 12 Mar 2020 12:30:51 +0100 Subject: Initial commit for the last i3lock commit at this time f3b061233e28ad0cf920c9421adc2459b6920812 --- dpi.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 dpi.c (limited to 'dpi.c') diff --git a/dpi.c b/dpi.c new file mode 100644 index 0000000..3cb08ee --- /dev/null +++ b/dpi.c @@ -0,0 +1,109 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * i3 - an improved dynamic tiling window manager + * © 2009 Michael Stapelberg and contributors (see also: LICENSE) + * + */ +#include "dpi.h" + +#include +#include +#include +#include +#include "xcb.h" +#include "i3lock.h" + +extern bool debug_mode; + +static long dpi; + +extern xcb_screen_t *screen; + +static long init_dpi_fallback(void) { + return (double)screen->height_in_pixels * 25.4 / (double)screen->height_in_millimeters; +} + +/* + * Initialize the DPI setting. + * This will use the 'Xft.dpi' X resource if available and fall back to + * guessing the correct value otherwise. + */ +void init_dpi(void) { + xcb_xrm_database_t *database = NULL; + char *resource = NULL; + + if (conn == NULL) { + goto init_dpi_end; + } + + database = xcb_xrm_database_from_default(conn); + if (database == NULL) { + DEBUG("Failed to open the resource database.\n"); + goto init_dpi_end; + } + + xcb_xrm_resource_get_string(database, "Xft.dpi", NULL, &resource); + if (resource == NULL) { + DEBUG("Resource Xft.dpi not specified, skipping.\n"); + goto init_dpi_end; + } + + char *endptr; + double in_dpi = strtod(resource, &endptr); + if (in_dpi == HUGE_VAL || dpi < 0 || *endptr != '\0' || endptr == resource) { + DEBUG("Xft.dpi = %s is an invalid number and couldn't be parsed.\n", resource); + dpi = 0; + goto init_dpi_end; + } + dpi = (long)round(in_dpi); + + DEBUG("Found Xft.dpi = %ld.\n", dpi); + +init_dpi_end: + if (resource != NULL) { + free(resource); + } + + if (database != NULL) { + xcb_xrm_database_free(database); + } + + if (dpi == 0) { + DEBUG("Using fallback for calculating DPI.\n"); + dpi = init_dpi_fallback(); + DEBUG("Using dpi = %ld\n", dpi); + } +} + +/* + * This function returns the value of the DPI setting. + * + */ +long get_dpi_value(void) { + return dpi; +} + +/* + * Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI + * screen) to a corresponding amount of physical pixels on a standard or retina + * screen, e.g. 5 pixels on a 227 DPI MacBook Pro 13" Retina screen. + * + */ +int logical_px(const int logical) { + if (screen == NULL) { + /* Dpi info may not be available when parsing a config without an X + * server, such as for config file validation. */ + return logical; + } + + /* There are many misconfigurations out there, i.e. systems with screens + * whose dpi is in fact higher than 96 dpi, but not significantly higher, + * so software was never adapted. We could tell people to reconfigure their + * systems to 96 dpi in order to get the behavior they expect/are used to, + * but since we can easily detect this case in code, let’s do it for them. + */ + if ((dpi / 96.0) < 1.25) + return logical; + return ceil((dpi / 96.0) * logical); +} -- cgit v1.3