]> git.tdb.fi Git - geometrycompositor.git/blob - source/control.c
Fix correction counting in the control program
[geometrycompositor.git] / source / control.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <X11/Xlib.h>
5 #include <X11/Xatom.h>
6
7 typedef struct GeometryCorrection
8 {
9         char *monitor_name;
10         float keystone_vertical;
11         float cylinder_depth;
12         float vertical_center;
13         float perspective;
14 } GeometryCorrection;
15
16 GeometryCorrection *get_corrections(Display *display)
17 {
18         Window root;
19         Atom monitors_atom;
20         Atom correction_atom;
21         Atom prop_type;
22         int prop_format;
23         unsigned long overflow;
24         unsigned long names_length;
25         char *names;
26         unsigned long values_length;
27         short *values;
28         unsigned ncorrections;
29         unsigned i;
30         GeometryCorrection *corrections;
31         char *name_ptr;
32
33         root = DefaultRootWindow(display);
34         monitors_atom = XInternAtom(display, "GEOMETRY_CORRECTION_MONITORS", False);
35         correction_atom = XInternAtom(display, "GEOMETRY_CORRECTION", False);
36
37         XGetWindowProperty(display, root, monitors_atom, 0, 64, False, XA_STRING,
38                 &prop_type, &prop_format, &names_length, &overflow, (unsigned char **)&names);
39         if(prop_type!=XA_STRING || prop_format!=8)
40                 return NULL;
41
42         XGetWindowProperty(display, root, correction_atom, 0, 64, False, XA_INTEGER,
43                 &prop_type, &prop_format, &values_length, &overflow, (unsigned char **)&values);
44         if(prop_type!=XA_INTEGER || prop_format!=16)
45         {
46                 XFree(names);
47                 return NULL;
48         }
49
50         ncorrections = (names_length>0);
51         for(i=0; i<names_length; ++i)
52                 if(!names[i])
53                         ++ncorrections;
54         if(ncorrections*4>values_length)
55                 ncorrections = values_length/4;
56         corrections = (GeometryCorrection *)malloc((ncorrections+1)*sizeof(GeometryCorrection));
57
58         name_ptr = names;
59         for(i=0; i<ncorrections; ++i)
60         {
61                 unsigned namelen;
62
63                 namelen = strlen(name_ptr);
64                 corrections[i].monitor_name = (char *)malloc(namelen+1);
65                 strcpy(corrections[i].monitor_name, name_ptr);
66
67                 corrections[i].keystone_vertical = values[i*4]/10000.0f;
68                 corrections[i].cylinder_depth = values[i*4+1]/10000.0f;
69                 corrections[i].vertical_center = values[i*4+2]/10000.0f;
70                 corrections[i].perspective = values[i*4+3]/10000.0f;
71
72                 name_ptr += namelen+1;
73         }
74
75         corrections[ncorrections].monitor_name = NULL;
76
77         XFree(names);
78         XFree(values);
79
80         return corrections;
81 }
82
83 void set_corrections(Display *display, GeometryCorrection *corrections)
84 {
85         unsigned ncorrections;
86         unsigned total_len;
87         unsigned i;
88         char *names;
89         char *name_ptr;
90         short *values;
91         Window root;
92         Atom monitors_atom;
93         Atom correction_atom;
94
95         ncorrections = 0;
96         total_len = 0;
97         for(i=0; corrections[i].monitor_name; ++i)
98         {
99                 ++ncorrections;
100                 total_len += strlen(corrections[i].monitor_name);
101         }
102
103         names = (char *)malloc(total_len+ncorrections);
104         values = (short *)malloc(ncorrections*4*sizeof(short));
105         name_ptr = names;
106         for(i=0; i<ncorrections; ++i)
107         {
108                 strcpy(name_ptr, corrections[i].monitor_name);
109                 name_ptr += strlen(name_ptr)+1;
110
111                 values[i*4] = corrections[i].keystone_vertical*10000;
112                 values[i*4+1] = corrections[i].cylinder_depth*10000;
113                 values[i*4+2] = corrections[i].vertical_center*10000;
114                 values[i*4+3] = corrections[i].perspective*10000;
115         }
116
117         root = DefaultRootWindow(display);
118         monitors_atom = XInternAtom(display, "GEOMETRY_CORRECTION_MONITORS", False);
119         correction_atom = XInternAtom(display, "GEOMETRY_CORRECTION", False);
120         XChangeProperty(display, root, monitors_atom, XA_STRING, 8, PropModeReplace, (unsigned char *)names, total_len+ncorrections-1);
121         XChangeProperty(display, root, correction_atom, XA_INTEGER, 16, PropModeReplace, (unsigned char *)values, ncorrections*4);
122
123         free(names);
124         free(values);
125 }
126
127 int main(int argc, char **argv)
128 {
129         Display *display;
130         GeometryCorrection *corrections;
131         unsigned i;
132
133         if(argc!=6)
134         {
135                 fprintf(stderr, "Usage: %s <monitor> <keystone> <cylinder> <vcenter> <perspective>\n", argv[0]);
136                 return 1;
137         }
138
139         display = XOpenDisplay(NULL);
140
141         corrections = get_corrections(display);
142         if(corrections)
143         {
144                 for(i=0; corrections[i].monitor_name; ++i)
145                         if(!strcmp(corrections[i].monitor_name, argv[1]))
146                                 break;
147         }
148         else
149                 i = 0;
150
151         if(!corrections || !corrections[i].monitor_name)
152         {
153                 unsigned namelen;
154
155                 corrections = (GeometryCorrection *)realloc(corrections, (i+2)*sizeof(GeometryCorrection));
156                 namelen = strlen(argv[1]);
157                 corrections[i].monitor_name = (char *)malloc(namelen+1);
158                 strcpy(corrections[i].monitor_name, argv[1]);
159                 corrections[i+1].monitor_name = NULL;
160         }
161
162         corrections[i].keystone_vertical = strtod(argv[2], NULL);
163         corrections[i].cylinder_depth = strtod(argv[3], NULL);
164         corrections[i].vertical_center = strtod(argv[4], NULL);
165         corrections[i].perspective = strtod(argv[5], NULL);
166
167         set_corrections(display, corrections);
168
169         XCloseDisplay(display);
170
171         return 0;
172 }