X-Git-Url: https://git.draconx.ca/gitweb/fvwmconf.git/blobdiff_plain/383401a5e46855bc36fca8f9f2c98bb9f814f21a..6ea5fd2e47b06873f28160fc414f4ef90c82f2fe:/scripts/C/xaspect.c diff --git a/scripts/C/xaspect.c b/scripts/C/xaspect.c index 0dbc83d..0009424 100644 --- a/scripts/C/xaspect.c +++ b/scripts/C/xaspect.c @@ -1,21 +1,27 @@ +/* + * Copyright © 2008, 2017 Nick Bowler + * + * License WTFPL2: Do What The Fuck You Want To Public License, version 2. + * This is free software: you are free to do what the fuck you want to. + * There is NO WARRANTY, to the extent permitted by law. + */ + #include #include #include #include +#include #include -#define MKASPECT(w, h) { (double)w/h, #w ":" #h } - /* Table of common monitor aspect ratios. Add to this as necessary. */ -static struct aspect { - double ratio; - char *name; +static const struct aspect { + unsigned num, denom; } aspects[] = { - MKASPECT(16, 10), - MKASPECT(16, 9), - MKASPECT(8, 5), - MKASPECT(5, 4), - MKASPECT(4, 3) + { 16, 10 }, + { 16, 9 }, + { 8, 3 }, + { 5, 4 }, + { 4, 3 } }; /* @@ -37,37 +43,67 @@ static xcb_screen_t *getscreen(xcb_connection_t *c, int screen) return NULL; } -char *testaspect(xcb_screen_t *screen) +void find_nearest_aspect(xcb_screen_t *screen, struct aspect *out) { unsigned int w = screen->width_in_millimeters; unsigned int h = screen->height_in_millimeters; - double ratio = (double)w/h; - double diff = 0; - char *best = NULL; + double r = (double)w/h; + double d = HUGE_VAL; int i; for (i = 0; i < (sizeof aspects / sizeof aspects[0]); i++) { - if (!best || fabs(aspects[i].ratio - ratio) < diff) { - best = aspects[i].name; - diff = fabs(aspects[i].ratio - ratio); + double t = (double) aspects[i].num / aspects[i].denom; + double cmp; + + cmp = fabs(r - t); + if (cmp < d) { + *out = aspects[i]; + d = cmp; + } + + cmp = fabs(r - 1/t); + if (cmp < d) { + out->num = aspects[i].denom; + out->denom = aspects[i].num; + d = cmp; + } + } +} + +struct options { + char *displayname; + int showdimensions; +} *parseoptions(int argc, char **argv) +{ + static struct options opts = { 0 }; + int i; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-display") == 0) { + if (++i < argc) { + opts.displayname = argv[i]; + continue; + } + fprintf(stderr, "-display requires an argument\n"); + } else if (strcmp(argv[i], "-dimensions") == 0) { + opts.showdimensions = 1; } } - return best; + return &opts; } int main(int argc, char **argv) { + struct aspect screenaspect; xcb_connection_t *display; xcb_screen_t *screen; - char *dpynam = NULL; int screen_num; - if (argc > 2 && strcmp(argv[1], "-display") == 0) - dpynam = argv[2]; + struct options *opts = parseoptions(argc, argv); - display = xcb_connect(dpynam, &screen_num); + display = xcb_connect(opts->displayname, &screen_num); if (xcb_connection_has_error(display)) { fprintf(stderr, "Failed to open display.\n"); xcb_disconnect(display); @@ -81,7 +117,13 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - printf("%s\n", testaspect(screen)); + if (opts->showdimensions) { + printf("%" PRIu16 "x%" PRIu16 "-", + screen->width_in_pixels, screen->height_in_pixels); + } + + find_nearest_aspect(screen, &screenaspect); + printf("%u:%u\n", screenaspect.num, screenaspect.denom); xcb_disconnect(display); return EXIT_SUCCESS;