1 /* 2 * vim:ts=4:sw=4:expandtab 3 * 4 * i3 - an improved dynamic tiling window manager 5 * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 * 7 */ 8 #include "dpi.h" 9 10 #include <math.h> 11 #include <stdlib.h> 12 #include <stdio.h> 13 #include <xcb/xcb_xrm.h> 14 #include "xcb.h" 15 #include "i3lock.h" 16 17 extern bool debug_mode; 18 19 static long dpi; 20 21 extern xcb_screen_t *screen; 22 23 static long init_dpi_fallback(void) { 24 return (double)screen->height_in_pixels * 25.4 / (double)screen->height_in_millimeters; 25 } 26 27 /* 28 * Initialize the DPI setting. 29 * This will use the 'Xft.dpi' X resource if available and fall back to 30 * guessing the correct value otherwise. 31 */ 32 void init_dpi(void) { 33 xcb_xrm_database_t *database = NULL; 34 char *resource = NULL; 35 36 if (conn == NULL) { 37 goto init_dpi_end; 38 } 39 40 database = xcb_xrm_database_from_default(conn); 41 if (database == NULL) { 42 DEBUG("Failed to open the resource database.\n"); 43 goto init_dpi_end; 44 } 45 46 xcb_xrm_resource_get_string(database, "Xft.dpi", NULL, &resource); 47 if (resource == NULL) { 48 DEBUG("Resource Xft.dpi not specified, skipping.\n"); 49 goto init_dpi_end; 50 } 51 52 char *endptr; 53 double in_dpi = strtod(resource, &endptr); 54 if (in_dpi == HUGE_VAL || dpi < 0 || *endptr != '\0' || endptr == resource) { 55 DEBUG("Xft.dpi = %s is an invalid number and couldn't be parsed.\n", resource); 56 dpi = 0; 57 goto init_dpi_end; 58 } 59 dpi = (long)round(in_dpi); 60 61 DEBUG("Found Xft.dpi = %ld.\n", dpi); 62 63 init_dpi_end: 64 if (resource != NULL) { 65 free(resource); 66 } 67 68 if (database != NULL) { 69 xcb_xrm_database_free(database); 70 } 71 72 if (dpi == 0) { 73 DEBUG("Using fallback for calculating DPI.\n"); 74 dpi = init_dpi_fallback(); 75 DEBUG("Using dpi = %ld\n", dpi); 76 } 77 } 78 79 /* 80 * This function returns the value of the DPI setting. 81 * 82 */ 83 long get_dpi_value(void) { 84 return dpi; 85 } 86 87 /* 88 * Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI 89 * screen) to a corresponding amount of physical pixels on a standard or retina 90 * screen, e.g. 5 pixels on a 227 DPI MacBook Pro 13" Retina screen. 91 * 92 */ 93 int logical_px(const int logical) { 94 if (screen == NULL) { 95 /* Dpi info may not be available when parsing a config without an X 96 * server, such as for config file validation. */ 97 return logical; 98 } 99 100 /* There are many misconfigurations out there, i.e. systems with screens 101 * whose dpi is in fact higher than 96 dpi, but not significantly higher, 102 * so software was never adapted. We could tell people to reconfigure their 103 * systems to 96 dpi in order to get the behavior they expect/are used to, 104 * but since we can easily detect this case in code, let’s do it for them. 105 */ 106 if ((dpi / 96.0) < 1.25) 107 return logical; 108 return ceil((dpi / 96.0) * logical); 109 }
