]> git.draconx.ca Git - fvwmconf.git/blobdiff - scripts/C/xaspect.c
Improve wallpaper menu generation.
[fvwmconf.git] / scripts / C / xaspect.c
index 0dbc83dd1cb89a92a736746395498b063fc5db8a..0009424f24f3263d5c8fd56b31d7d87717ca59bf 100644 (file)
@@ -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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
+#include <inttypes.h>
 #include <xcb/xcb.h>
 
-#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;