]> git.draconx.ca Git - fvwmconf.git/blob - scripts/C/xaspect.c
xaspect: Add copyright notice.
[fvwmconf.git] / scripts / C / xaspect.c
1 /*
2  * Copyright (C) 2007 Nick Bowler
3  * Copying and distribution of this file, with or without modification,
4  * are permitted in any medium without royalty provided the copyright
5  * notice and this notice are preserved.  This file is offered as-is,
6  * without any warranty.
7  */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <math.h>
12 #include <inttypes.h>
13 #include <xcb/xcb.h>
14
15 #define MKASPECT(w, h) { (double)w/h, #w ":" #h }
16
17 /* Table of common monitor aspect ratios.  Add to this as necessary. */
18 static struct aspect {
19         double ratio;
20         char *name;
21 } aspects[] = {
22         MKASPECT(16, 10),
23         MKASPECT(16, 9),
24         MKASPECT(8, 3),
25         MKASPECT(5, 4),
26         MKASPECT(4, 3)
27 };
28
29 /*
30  * Get the xcb screen structure for the specified screen, or NULL if it doesn't
31  * exist.
32  */
33 static xcb_screen_t *getscreen(xcb_connection_t *c, int screen)
34 {
35         xcb_screen_iterator_t iter;
36
37         iter = xcb_setup_roots_iterator(xcb_get_setup(c));
38         while (iter.rem) {
39                 if (screen == 0)
40                         return iter.data;
41                 screen--;
42                 xcb_screen_next(&iter);
43         }
44
45         return NULL;
46 }
47
48 char *testaspect(xcb_screen_t *screen)
49 {
50         unsigned int w = screen->width_in_millimeters;
51         unsigned int h = screen->height_in_millimeters;
52
53         double ratio = (double)w/h;
54         double diff = 0;
55         char *best = NULL;
56         int i;
57
58         for (i = 0; i < (sizeof aspects / sizeof aspects[0]); i++) {
59                 if (!best || fabs(aspects[i].ratio - ratio) < diff) {
60                         best = aspects[i].name;
61                         diff = fabs(aspects[i].ratio - ratio);
62                 }
63         }
64
65         return best;
66 }
67
68 struct options {
69         char *displayname;
70         int showdimensions;
71 } *parseoptions(int argc, char **argv)
72 {
73         static struct options opts = { 0 };
74         int i;
75
76         for (i = 1; i < argc; i++) {
77                 if (strcmp(argv[i], "-display") == 0) {
78                         if (++i < argc) {
79                                 opts.displayname = argv[i];
80                                 continue;
81                         }
82                         fprintf(stderr, "-display requires an argument\n");
83                 } else if (strcmp(argv[i], "-dimensions") == 0) {
84                         opts.showdimensions = 1;
85                 }
86         }
87
88         return &opts;
89 }
90
91 int main(int argc, char **argv)
92 {
93         xcb_connection_t *display;
94         xcb_screen_t     *screen;
95         int screen_num;
96
97         struct options *opts = parseoptions(argc, argv);
98         
99         display = xcb_connect(opts->displayname, &screen_num);
100         if (xcb_connection_has_error(display)) {
101                 fprintf(stderr, "Failed to open display.\n");
102                 xcb_disconnect(display);
103                 return EXIT_FAILURE;
104         }
105
106         screen = getscreen(display, screen_num);
107         if (!screen) {
108                 fprintf(stderr, "Invalid screen number.\n");
109                 xcb_disconnect(display);
110                 return EXIT_FAILURE;
111         }
112
113         if (opts->showdimensions) {
114                 printf("%" PRIu16 "x%" PRIu16 "-",
115                        screen->width_in_pixels, screen->height_in_pixels);
116         }
117         printf("%s\n", testaspect(screen));
118
119         xcb_disconnect(display);
120         return EXIT_SUCCESS;
121 }