• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

A generic touchscreen calibration program for X.Org


Commit MetaInfo

Revisioncc54f8ec926ac223c685ff4d8adfd87f10a0cafa (tree)
Time2010-01-08 08:07:46
AuthorTias Guns <tias@ulys...>
CommiterTias Guns

Log Message

Rewrite: split the one-huge-file into clean components

Change Summary

Incremental Difference

--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,7 @@
1-all: xinput_calibrator
1+all: xinput_calibrator.old xinput_calibrator.gtkmm
22
3-xinput_calibrator: xinput_calibrator.cc
4- g++ -Wall xinput_calibrator.cc `pkg-config --cflags --libs gtkmm-2.4` -o xinput_calibrator
3+xinput_calibrator.old: xinput_calibrator.cc
4+ g++ -Wall xinput_calibrator.cc `pkg-config --cflags --libs gtkmm-2.4` -o xinput_calibrator.old
5+
6+xinput_calibrator.gtkmm: main_gtkmm.cpp gui_gtkmm.cpp
7+ g++ -Wall main_gtkmm.cpp `pkg-config --cflags --libs gtkmm-2.4` -o xinput_calibrator.gtkmm
--- /dev/null
+++ b/calibrator.cpp
@@ -0,0 +1,88 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ * Copyright (c) 2009 Soren Hauberg
4+ *
5+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6+ * of this software and associated documentation files (the "Software"), to deal
7+ * in the Software without restriction, including without limitation the rights
8+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ * copies of the Software, and to permit persons to whom the Software is
10+ * furnished to do so, subject to the following conditions:
11+ *
12+ * The above copyright notice and this permission notice shall be included in
13+ * all copies or substantial portions of the Software.
14+ *
15+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+ * THE SOFTWARE.
22+ */
23+#include <algorithm>
24+#include "calibrator.hh"
25+
26+Calibrator::Calibrator(const char* const drivername0, const XYinfo& axys0)
27+ : drivername(drivername0), old_axys(axys0), num_clicks(0)
28+{
29+}
30+
31+int Calibrator::get_numclicks()
32+{
33+ return num_clicks;
34+}
35+
36+bool Calibrator::add_click(double x, double y)
37+{
38+ // Check that we don't click the same point twice
39+ if (num_clicks > 0 && click_threshold > 0
40+ && abs (x - clicked_x[num_clicks-1]) < click_threshold
41+ && abs (y - clicked_y[num_clicks-1]) < click_threshold)
42+ return false;
43+
44+ clicked_x[num_clicks] = x;
45+ clicked_y[num_clicks] = y;
46+ num_clicks ++;
47+
48+ return true;
49+}
50+
51+void Calibrator::finish(int width, int height)
52+{
53+ // Should x and y be swapped?
54+ const bool swap_xy = (abs (clicked_x [UL] - clicked_x [UR]) < abs (clicked_y [UL] - clicked_y [UR]));
55+ if (swap_xy) {
56+ std::swap(clicked_x[LL], clicked_x[UR]);
57+ std::swap(clicked_y[LL], clicked_y[UR]);
58+ }
59+
60+ // Compute min/max coordinates.
61+ XYinfo axys;
62+ // These are scaled using the values of old_axys
63+ const float scale_x = (old_axys.x_max - old_axys.x_min)/(float)width;
64+ axys.x_min = ((clicked_x[UL] + clicked_x[LL]) * scale_x/2) + old_axys.x_min;
65+ axys.x_max = ((clicked_x[UR] + clicked_x[LR]) * scale_x/2) + old_axys.x_min;
66+ const float scale_y = (old_axys.y_max - old_axys.y_min)/(float)height;
67+ axys.y_min = ((clicked_y[UL] + clicked_y[UR]) * scale_y/2) + old_axys.y_min;
68+ axys.y_max = ((clicked_y[LL] + clicked_y[LR]) * scale_y/2) + old_axys.y_min;
69+
70+ // Add/subtract the offset that comes from not having the points in the
71+ // corners (using the same coordinate system they are currently in)
72+ const int delta_x = (axys.x_max - axys.x_min) / (float)(num_blocks - 2);
73+ axys.x_min -= delta_x;
74+ axys.x_max += delta_x;
75+ const int delta_y = (axys.y_max - axys.y_min) / (float)(num_blocks - 2);
76+ axys.y_min -= delta_y;
77+ axys.y_max += delta_y;
78+
79+
80+ // If x and y has to be swapped we also have to swap the parameters
81+ if (swap_xy) {
82+ std::swap(axys.x_min, axys.y_max);
83+ std::swap(axys.y_min, axys.x_max);
84+ }
85+
86+ // finish the data, driver specific
87+ finish_data(axys, swap_xy);
88+}
--- /dev/null
+++ b/calibrator.hh
@@ -0,0 +1,47 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ * Copyright (c) 2009 Soren Hauberg
4+ *
5+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6+ * of this software and associated documentation files (the "Software"), to deal
7+ * in the Software without restriction, including without limitation the rights
8+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ * copies of the Software, and to permit persons to whom the Software is
10+ * furnished to do so, subject to the following conditions:
11+ *
12+ * The above copyright notice and this permission notice shall be included in
13+ * all copies or substantial portions of the Software.
14+ *
15+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+ * THE SOFTWARE.
22+ */
23+
24+#ifndef _calibrator_hh
25+#define _calibrator_hh
26+
27+// Abstract base class for calculating new calibration parameters
28+class Calibrator
29+{
30+public:
31+ Calibrator(const char* const drivername, const XYinfo& axys);
32+ ~Calibrator() {}
33+
34+ int get_numclicks();
35+ bool add_click(double x, double y);
36+ void finish(int width, int height);
37+
38+protected:
39+ virtual void finish_data(const XYinfo new_axys, int swap_xy) =0;
40+
41+ const char* const drivername;
42+ XYinfo old_axys;
43+ int num_clicks;
44+ double clicked_x[4], clicked_y[4];
45+};
46+
47+#endif
--- /dev/null
+++ b/calibrators/calibratorEvdev.cpp
@@ -0,0 +1,399 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+#include <ctype.h>
23+
24+#include <X11/Xlib.h>
25+#include <X11/extensions/XInput.h>
26+#include <X11/Xatom.h>
27+//#include <X11/Xutil.h>
28+
29+#ifndef EXIT_SUCCESS
30+#define EXIT_SUCCESS 1
31+#endif
32+#ifndef EXIT_FAILURE
33+#define EXIT_FAILURE 0
34+#endif
35+
36+/***************************************
37+ * Class for dynamic evdev calibration
38+ * uses xinput "Evdev Axis Calibration"
39+ ***************************************/
40+class CalibratorEvdev: public Calibrator
41+{
42+private:
43+ Display *display;
44+ XDeviceInfo *info;
45+ XDevice *dev;
46+public:
47+ CalibratorEvdev(const char* const drivername, const XYinfo& axys);
48+ ~CalibratorEvdev();
49+
50+ virtual void finish_data(const XYinfo new_axys, int swap_xy);
51+
52+ static Bool check_driver(const char* const name);
53+
54+ // xinput functions (from the xinput source)
55+ static Atom parse_atom(Display *display, const char* name);
56+ static XDeviceInfo* find_device_info(Display *display, const char* name, Bool only_extended);
57+ int do_set_prop(Display *display, Atom type, int format, int argc, char* argv[]);
58+};
59+
60+CalibratorEvdev::CalibratorEvdev(const char* const drivername0, const XYinfo& axys0)
61+ : Calibrator(drivername0, axys0)
62+{
63+ printf("Calibrating EVDEV driver for \"%s\"\n", drivername);
64+
65+ // init
66+ display = XOpenDisplay(NULL);
67+ if (display == NULL) {
68+ fprintf(stderr, "Unable to connect to X server\n");
69+ return;
70+ }
71+
72+ info = find_device_info(display, drivername, False);
73+ if (!info) {
74+ fprintf(stderr, "unable to find device %s\n", drivername);
75+ return;
76+ }
77+
78+ dev = XOpenDevice(display, info->id);
79+ if (!dev) {
80+ fprintf(stderr, "unable to open device '%s'\n", info->name);
81+ return;
82+ }
83+
84+ // get "Evdev Axis Calibration" property
85+ Atom property = parse_atom(display, "Evdev Axis Calibration");
86+ Atom act_type;
87+ int act_format;
88+ unsigned long nitems, bytes_after;
89+ unsigned char *data, *ptr;
90+ if (XGetDeviceProperty(display, dev, property, 0, 1000, False,
91+ AnyPropertyType, &act_type, &act_format,
92+ &nitems, &bytes_after, &data) == Success)
93+ {
94+ if (act_format != 32 || act_type != XA_INTEGER) {
95+ fprintf(stderr, "Error: unexpected format or type from \"Evdev Axis Calibration\" property.\n");
96+ }
97+
98+ if (nitems != 0) {
99+ ptr = data;
100+
101+ old_axys.x_min = *((long*)ptr);
102+ ptr += sizeof(long);
103+ old_axys.x_max = *((long*)ptr);
104+ ptr += sizeof(long);
105+ old_axys.y_min = *((long*)ptr);
106+ ptr += sizeof(long);
107+ old_axys.y_max = *((long*)ptr);
108+ ptr += sizeof(long);
109+
110+ printf("Read current calibration data from XInput: min_x=%d, max_x=%d and min_y=%d, max_y=%d\n",
111+ old_axys.x_min, old_axys.x_max, old_axys.y_min, old_axys.y_max);
112+ }
113+
114+ XFree(data);
115+ } else
116+ printf("\tFetch failure for 'Evdev Axis Calibration', continuing nonetheless\n");
117+}
118+
119+CalibratorEvdev::~CalibratorEvdev () {
120+ XCloseDevice(display, dev);
121+ XCloseDisplay(display);
122+}
123+
124+void CalibratorEvdev::finish_data(const XYinfo new_axys, int swap_xy)
125+{
126+ printf("\nTo make the settings permanent, create add a startup script for your window manager with the following command(s):\n");
127+ if (swap_xy)
128+ printf(" xinput set-int-prop \"%s\" \"Evdev Axes Swap\" 8 %d\n", drivername, swap_xy);
129+ printf(" xinput set-int-prop \"%s\" \"Evdev Axis Calibration\" 32 %d %d %d %d\n", drivername, new_axys.x_min, new_axys.x_max, new_axys.y_min, new_axys.y_max);
130+
131+ printf("\nDoing dynamic recalibration:\n");
132+ // Evdev Axes Swap
133+ if (swap_xy) {
134+ printf("\tSwapping X and Y axis...\n");
135+ // xinput set-int-prop "divername" "Evdev Axes Swap" 8 0
136+ char* arr_cmd[3];
137+ //arr_cmd[0] = "";
138+ char str_prop[50];
139+ sprintf(str_prop, "Evdev Axes Swap");
140+ arr_cmd[1] = str_prop;
141+ char str_swap_xy[20];
142+ sprintf(str_swap_xy, "%d", swap_xy);
143+ arr_cmd[2] = str_swap_xy;
144+
145+ do_set_prop(display, XA_INTEGER, 8, 3, arr_cmd);
146+ }
147+
148+ // Evdev Axis Calibration
149+ printf("\tSetting new calibration data: %d, %d, %d, %d\n", new_axys.x_min, new_axys.x_max, new_axys.y_min, new_axys.y_max);
150+ // xinput set-int-prop 4 223 32 5 500 8 300
151+ char* arr_cmd[6];
152+ //arr_cmd[0] = "";
153+ char str_prop[50];
154+ sprintf(str_prop, "Evdev Axis Calibration");
155+ arr_cmd[1] = str_prop;
156+ char str_min_x[20];
157+ sprintf(str_min_x, "%d", new_axys.x_min);
158+ arr_cmd[2] = str_min_x;
159+ char str_max_x[20];
160+ sprintf(str_max_x, "%d", new_axys.x_max);
161+ arr_cmd[3] = str_max_x;
162+ char str_min_y[20];
163+ sprintf(str_min_y, "%d", new_axys.y_min);
164+ arr_cmd[4] = str_min_y;
165+ char str_max_y[20];
166+ sprintf(str_max_y, "%d", new_axys.y_max);
167+ arr_cmd[5] = str_max_y;
168+
169+ do_set_prop(display, XA_INTEGER, 32, 6, arr_cmd);
170+
171+ // close
172+ XSync(display, False);
173+}
174+
175+Bool CalibratorEvdev::check_driver(const char *name) {
176+ Display *display;
177+ XDeviceInfo *info;
178+ XDevice *dev;
179+ int nprops;
180+ Atom *props;
181+ Bool found = False;
182+
183+ display = XOpenDisplay(NULL);
184+ if (display == NULL) {
185+ //fprintf(stderr, "Unable to connect to X server");
186+ return false;
187+ }
188+
189+ info = find_device_info(display, name, False);
190+ if (!info)
191+ {
192+ XCloseDisplay(display);
193+ //fprintf(stderr, "unable to find device %s\n", name);
194+ return false;
195+ }
196+
197+ dev = XOpenDevice(display, info->id);
198+ if (!dev)
199+ {
200+ XCloseDisplay(display);
201+ //fprintf(stderr, "unable to open device '%s'\n", info->name);
202+ return false;
203+ }
204+
205+ props = XListDeviceProperties(display, dev, &nprops);
206+ if (!nprops)
207+ {
208+ XCloseDevice(display, dev);
209+ XCloseDisplay(display);
210+ //printf("Device '%s' does not report any properties.\n", info->name);
211+ return false;
212+ }
213+
214+ // check if "Evdev Axis Calibration" exists, then its an evdev driver
215+ while(nprops--)
216+ {
217+ if (strcmp(XGetAtomName(display, props[nprops]),
218+ "Evdev Axis Calibration") == 0) {
219+ found = True;
220+ break;
221+ }
222+ }
223+
224+ XFree(props);
225+ XCloseDevice(display, dev);
226+ XCloseDisplay(display);
227+
228+ return found;
229+}
230+
231+Atom CalibratorEvdev::parse_atom(Display *display, const char *name) {
232+ Bool is_atom = True;
233+ int i;
234+
235+ for (i = 0; name[i] != '\0'; i++) {
236+ if (!isdigit(name[i])) {
237+ is_atom = False;
238+ break;
239+ }
240+ }
241+
242+ if (is_atom)
243+ return atoi(name);
244+ else
245+ return XInternAtom(display, name, False);
246+}
247+
248+XDeviceInfo* CalibratorEvdev::find_device_info(
249+Display *display, const char *name, Bool only_extended)
250+{
251+ XDeviceInfo *devices;
252+ XDeviceInfo *found = NULL;
253+ int loop;
254+ int num_devices;
255+ int len = strlen(name);
256+ Bool is_id = True;
257+ XID id = (XID)-1;
258+
259+ for (loop=0; loop<len; loop++) {
260+ if (!isdigit(name[loop])) {
261+ is_id = False;
262+ break;
263+ }
264+ }
265+
266+ if (is_id) {
267+ id = atoi(name);
268+ }
269+
270+ devices = XListInputDevices(display, &num_devices);
271+
272+ for (loop=0; loop<num_devices; loop++) {
273+ if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) &&
274+ ((!is_id && strcmp(devices[loop].name, name) == 0) ||
275+ (is_id && devices[loop].id == id))) {
276+ if (found) {
277+ fprintf(stderr,
278+ "Warning: There are multiple devices named \"%s\".\n"
279+ "To ensure the correct one is selected, please use "
280+ "the device ID instead.\n\n", name);
281+ return NULL;
282+ } else {
283+ found = &devices[loop];
284+ }
285+ }
286+ }
287+
288+ return found;
289+}
290+
291+int CalibratorEvdev::do_set_prop(
292+Display *display, Atom type, int format, int argc, char **argv)
293+{
294+ Atom prop;
295+ Atom old_type;
296+ char *name;
297+ int i;
298+ Atom float_atom;
299+ int old_format, nelements = 0;
300+ unsigned long act_nitems, bytes_after;
301+ char *endptr;
302+ union {
303+ unsigned char *c;
304+ short *s;
305+ long *l;
306+ Atom *a;
307+ } data;
308+
309+ if (argc < 3)
310+ {
311+ fprintf(stderr, "Wrong usage of do_set_prop, need at least 3 arguments\n");
312+ return EXIT_FAILURE;
313+ }
314+
315+ name = argv[1];
316+
317+ prop = parse_atom(display, name);
318+
319+ if (prop == None) {
320+ fprintf(stderr, "invalid property %s\n", name);
321+ return EXIT_FAILURE;
322+ }
323+
324+ float_atom = XInternAtom(display, "FLOAT", False);
325+
326+ nelements = argc - 2;
327+ if (type == None || format == 0) {
328+ if (XGetDeviceProperty(display, dev, prop, 0, 0, False, AnyPropertyType,
329+ &old_type, &old_format, &act_nitems,
330+ &bytes_after, &data.c) != Success) {
331+ fprintf(stderr, "failed to get property type and format for %s\n",
332+ name);
333+ return EXIT_FAILURE;
334+ } else {
335+ if (type == None)
336+ type = old_type;
337+ if (format == 0)
338+ format = old_format;
339+ }
340+
341+ XFree(data.c);
342+ }
343+
344+ if (type == None) {
345+ fprintf(stderr, "property %s doesn't exist, you need to specify "
346+ "its type and format\n", name);
347+ return EXIT_FAILURE;
348+ }
349+
350+ data.c = (unsigned char*)calloc(nelements, sizeof(long));
351+
352+ for (i = 0; i < nelements; i++)
353+ {
354+ if (type == XA_INTEGER) {
355+ switch (format)
356+ {
357+ case 8:
358+ data.c[i] = atoi(argv[2 + i]);
359+ break;
360+ case 16:
361+ data.s[i] = atoi(argv[2 + i]);
362+ break;
363+ case 32:
364+ data.l[i] = atoi(argv[2 + i]);
365+ break;
366+ default:
367+ fprintf(stderr, "unexpected size for property %s", name);
368+ return EXIT_FAILURE;
369+ }
370+ } else if (type == float_atom) {
371+ if (format != 32) {
372+ fprintf(stderr, "unexpected format %d for property %s\n",
373+ format, name);
374+ return EXIT_FAILURE;
375+ }
376+ *(float *)(data.l + i) = strtod(argv[2 + i], &endptr);
377+ if (endptr == argv[2 + i]) {
378+ fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]);
379+ return EXIT_FAILURE;
380+ }
381+ } else if (type == XA_ATOM) {
382+ if (format != 32) {
383+ fprintf(stderr, "unexpected format %d for property %s\n",
384+ format, name);
385+ return EXIT_FAILURE;
386+ }
387+ data.a[i] = parse_atom(display, argv[2 + i]);
388+ } else {
389+ fprintf(stderr, "unexpected type for property %s\n", name);
390+ return EXIT_FAILURE;
391+ }
392+ }
393+
394+ XChangeDeviceProperty(display, dev, prop, type, format, PropModeReplace,
395+ data.c, nelements);
396+ free(data.c);
397+ XCloseDevice(display, dev);
398+ return EXIT_SUCCESS;
399+}
--- /dev/null
+++ b/calibrators/calibratorUsbtouchscreen.cpp
@@ -0,0 +1,218 @@
1+/*
2+ * Copyright (c) 2009 Soren Hauberg
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+#include <string>
23+
24+/*************************
25+ * Variables for usbtouchscreen specifically
26+ *************************/
27+// The file to which the calibration parameters are saved.
28+// (XXX: is this distribution dependend?)
29+const char *modprobe_conf_local = "/etc/modprobe.conf.local";
30+
31+// Prefix to the kernel path where we can set the parameters
32+const char *module_prefix = "/sys/module/usbtouchscreen/parameters";
33+
34+// Names of kernel parameters
35+const char *p_range_x = "range_x";
36+const char *p_range_y = "range_y";
37+const char *p_min_x = "min_x";
38+const char *p_min_y = "min_y";
39+const char *p_max_x = "max_x";
40+const char *p_max_y = "max_y";
41+const char *p_transform_xy = "transform_xy";
42+const char *p_flip_x = "flip_x";
43+const char *p_flip_y = "flip_y";
44+const char *p_swap_xy = "swap_xy";
45+
46+
47+/**********************************
48+ * Class for usbtouchscreen driver,
49+ * writes output parameters to running kernel and to modprobe.conf
50+ **********************************/
51+class CalibratorUsbtouchscreen: public Calibrator
52+{
53+public:
54+ CalibratorUsbtouchscreen(const char* const drivername, const XYinfo& axys);
55+ ~CalibratorUsbtouchscreen();
56+
57+ virtual void finish_data(const XYinfo new_axys, int swap_xy);
58+
59+protected:
60+ // Globals for kernel parameters from startup.
61+ // We revert to these if the program aborts
62+ bool val_transform_xy, val_flip_x, val_flip_y, val_swap_xy;
63+
64+ // Helper functions
65+ char yesno(const bool value)
66+ {
67+ if (value)
68+ return 'Y';
69+ else
70+ return 'N';
71+ }
72+
73+ void read_int_parameter(const char *param, int &value)
74+ {
75+ char filename[100];
76+ sprintf(filename, "%s/%s", module_prefix, param);
77+ FILE *fid = fopen(filename, "r");
78+ if (fid == NULL) {
79+ fprintf(stderr, "Could not read parameter '%s'\n", param);
80+ return;
81+ }
82+
83+ fscanf(fid, "%d", &value);
84+ fclose(fid);
85+ }
86+
87+ void read_bool_parameter(const char *param, bool &value)
88+ {
89+ char filename[100];
90+ sprintf(filename, "%s/%s", module_prefix, param);
91+ FILE *fid = fopen(filename, "r");
92+ if (fid == NULL) {
93+ fprintf(stderr, "Could not read parameter '%s'\n", param);
94+ return;
95+ }
96+
97+ char val[3];
98+ fgets(val, 2, fid);
99+ fclose(fid);
100+
101+ value = (val[0] == yesno(true));
102+ }
103+
104+ void write_int_parameter(const char *param, const int value)
105+ {
106+ char filename[100];
107+ sprintf(filename, "%s/%s", module_prefix, param);
108+ FILE *fid = fopen(filename, "w");
109+ if (fid == NULL) {
110+ fprintf(stderr, "Could not save parameter '%s'\n", param);
111+ return;
112+ }
113+
114+ fprintf(fid, "%d", value);
115+ fclose(fid);
116+ }
117+
118+ void write_bool_parameter(const char *param, const bool value)
119+ {
120+ char filename[100];
121+ sprintf(filename, "%s/%s", module_prefix, param);
122+ FILE *fid = fopen(filename, "w");
123+ if (fid == NULL) {
124+ fprintf(stderr, "Could not save parameter '%s'\n", param);
125+ return;
126+ }
127+
128+ fprintf(fid, "%c", yesno (value));
129+ fclose(fid);
130+ }
131+};
132+
133+CalibratorUsbtouchscreen::CalibratorUsbtouchscreen(const char* const drivername0, const XYinfo& axys0)
134+ : Calibrator(drivername0, axys0)
135+{
136+ // Reset the currently running kernel
137+ read_bool_parameter(p_transform_xy, val_transform_xy);
138+ read_bool_parameter(p_flip_x, val_flip_x);
139+ read_bool_parameter(p_flip_y, val_flip_y);
140+ read_bool_parameter(p_swap_xy, val_swap_xy);
141+
142+ write_bool_parameter(p_transform_xy, false);
143+ write_bool_parameter(p_flip_x, false);
144+ write_bool_parameter(p_flip_y, false);
145+ write_bool_parameter(p_swap_xy, false);
146+}
147+
148+CalibratorUsbtouchscreen::~CalibratorUsbtouchscreen()
149+{
150+ // Dirty exit, so we restore the parameters of the running kernel
151+ write_bool_parameter (p_transform_xy, val_transform_xy);
152+ write_bool_parameter (p_flip_x, val_flip_x);
153+ write_bool_parameter (p_flip_y, val_flip_y);
154+ write_bool_parameter (p_swap_xy, val_swap_xy);
155+}
156+
157+void CalibratorUsbtouchscreen::finish_data(const XYinfo new_axys, int swap_xy)
158+{
159+ // New ranges
160+ const int range_x = (new_axys.x_max - new_axys.x_min);
161+ const int range_y = (new_axys.y_max - new_axys.y_min);
162+ // Should x and y be flipped ?
163+ const bool flip_x = (new_axys.x_min > new_axys.x_max);
164+ const bool flip_y = (new_axys.y_min > new_axys.y_max);
165+
166+ // Send the estimated parameters to the currently running kernel
167+ write_int_parameter(p_range_x, range_x);
168+ write_int_parameter(p_range_y, range_y);
169+ write_int_parameter(p_min_x, new_axys.x_min);
170+ write_int_parameter(p_max_x, new_axys.x_max);
171+ write_int_parameter(p_min_y, new_axys.y_min);
172+ write_int_parameter(p_max_y, new_axys.y_max);
173+ write_bool_parameter(p_transform_xy, true);
174+ write_bool_parameter(p_flip_x, flip_x);
175+ write_bool_parameter(p_flip_y, flip_y);
176+ write_bool_parameter(p_swap_xy, swap_xy);
177+
178+ // Read, then write calibration parameters to modprobe_conf_local,
179+ // to keep the for the next boot
180+ FILE *fid = fopen(modprobe_conf_local, "r");
181+ if (fid == NULL) {
182+ fprintf(stderr, "Error: Can't open '%s' for reading. Make sure you have the necesary rights\n", modprobe_conf_local);
183+ fprintf(stderr, "New calibration data NOT saved\n");
184+ return;
185+ }
186+
187+ std::string new_contents;
188+ const int len = 1024; // XXX: we currently don't handle lines that are longer than this
189+ char line[len];
190+ const char *opt = "options usbtouchscreen";
191+ const int opt_len = strlen(opt);
192+ while (fgets(line, len, fid)) {
193+ if (strncmp(line, opt, opt_len) == 0) {
194+ // This is the line we want to remove
195+ continue;
196+ }
197+ new_contents += line;
198+ }
199+ fclose(fid);
200+
201+ char new_opt[opt_len];
202+ sprintf(new_opt, "%s %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d %s=%c %s=%c %s=%c %s=%c\n",
203+ opt, p_range_x, range_x, p_range_y, range_y,
204+ p_min_x, new_axys.x_min, p_min_y, new_axys.y_min,
205+ p_max_x, new_axys.x_max, p_max_y, new_axys.y_max,
206+ p_transform_xy, yesno(true), p_flip_x, yesno(flip_x),
207+ p_flip_y, yesno(flip_y), p_swap_xy, yesno(swap_xy));
208+ new_contents += new_opt;
209+
210+ fid = fopen(modprobe_conf_local, "w");
211+ if (fid == NULL) {
212+ fprintf(stderr, "Error: Can't open '%s' for writing. Make sure you have the necesary rights\n", modprobe_conf_local);
213+ fprintf(stderr, "New calibration data NOT saved\n");
214+ return;
215+ }
216+ fprintf(fid, "%s", new_contents.c_str ());
217+ fclose(fid);
218+}
--- /dev/null
+++ b/calibrators/calibratorXorgPrint.cpp
@@ -0,0 +1,70 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+/***************************************
24+ * Class for generic Xorg driver,
25+ * outputs new Xorg.conf and FDI policy, on stdout
26+ ***************************************/
27+class CalibratorXorgPrint: public Calibrator
28+{
29+public:
30+ CalibratorXorgPrint(const char* const drivername, const XYinfo& axys);
31+
32+ virtual void finish_data(const XYinfo new_axys, int swap_xy);
33+};
34+
35+CalibratorXorgPrint::CalibratorXorgPrint(const char* const drivername0, const XYinfo& axys0)
36+ : Calibrator(drivername0, axys0)
37+{
38+ printf ("Calibrating Xorg driver \"%s\" (currently having min_x=%d, max_x=%d and min_y=%d, max_y=%d)\n",
39+ drivername, old_axys.x_min, old_axys.x_max,
40+ old_axys.y_min, old_axys.y_max);
41+ printf("\tIf the current calibration data is estimated wrong then either supply it manually with --precalib <minx> <maxx> <miny> <maxy> or run the 'get_precalib.sh' script to automatically get it from your current Xorg configuration (through hal).\n");
42+}
43+
44+void CalibratorXorgPrint::finish_data(const XYinfo new_axys, int swap_xy)
45+{
46+ // FDI policy output
47+ printf("\nNew method for making the calibration permanent: create an FDI policy file like /etc/hal/fdi/policy/touchscreen.fdi with:\n\
48+<match key=\"info.product\" contains=\"%%Name_Of_TouchScreen%%\">\n\
49+ <merge key=\"input.x11_options.minx\" type=\"string\">%d</merge>\n\
50+ <merge key=\"input.x11_options.miny\" type=\"string\">%d</merge>\n\
51+ <merge key=\"input.x11_options.maxx\" type=\"string\">%d</merge>\n\
52+ <merge key=\"input.x11_options.maxy\" type=\"string\">%d</merge>\n"
53+ , new_axys.x_min, new_axys.x_max, new_axys.y_min, new_axys.y_max);
54+ if (swap_xy != 0)
55+ printf(" <merge key=\"input.x11_options.swapxy\" type=\"string\">%d</merge>\n", swap_xy);
56+ printf("</match>\n");
57+
58+ // Xorg.conf output
59+ printf("\nOld method, edit /etc/X11/xorg.conf and add in the 'Section \"Device\"' of your touchscreen device:\n");
60+ printf("\tOption\t\"MinX\"\t\t\"%d\"\t# was \"%d\"\n",
61+ new_axys.x_min, old_axys.x_min);
62+ printf("\tOption\t\"MaxX\"\t\t\"%d\"\t# was \"%d\"\n",
63+ new_axys.x_max, old_axys.x_max);
64+ printf("\tOption\t\"MinY\"\t\t\"%d\"\t# was \"%d\"\n",
65+ new_axys.y_min, old_axys.y_min);
66+ printf("\tOption\t\"MaxY\"\t\t\"%d\"\t# was \"%d\"\n",
67+ new_axys.y_max, old_axys.y_max);
68+ if (swap_xy != 0)
69+ printf("\tOption\t\"SwapXY\"\t\"%d\"\n", swap_xy);
70+}
--- /dev/null
+++ b/gui_gtkmm.cpp
@@ -0,0 +1,192 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ * Copyright (c) 2009 Soren Hauberg
4+ *
5+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6+ * of this software and associated documentation files (the "Software"), to deal
7+ * in the Software without restriction, including without limitation the rights
8+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ * copies of the Software, and to permit persons to whom the Software is
10+ * furnished to do so, subject to the following conditions:
11+ *
12+ * The above copyright notice and this permission notice shall be included in
13+ * all copies or substantial portions of the Software.
14+ *
15+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+ * THE SOFTWARE.
22+ */
23+#include <gtkmm/main.h>
24+#include <gtkmm/window.h>
25+#include <gtkmm/drawingarea.h>
26+#include <cairomm/context.h>
27+
28+#include "calibrator.hh"
29+
30+
31+// Timeout parameters
32+const int time_step = 100; // in milliseconds
33+const int max_time = 15000; // 5000 = 5 sec
34+
35+// Clock appereance
36+const int clock_radius = 50;
37+const int clock_line_width = 10;
38+
39+// Text printed on screen
40+const int font_size = 20;
41+const std::string help_text = "Press the point with the stylus";
42+
43+
44+/*******************************************
45+ * GTK-mm class for the the calibration GUI
46+ *******************************************/
47+class CalibrationArea : public Gtk::DrawingArea
48+{
49+public:
50+ CalibrationArea(Calibrator* w);
51+
52+protected:
53+ // Data
54+ Calibrator* calibrator;
55+ double X[4], Y[4];
56+ int display_width, display_height;
57+ int time_elapsed;
58+
59+
60+ // Signal handlers
61+ bool on_timer_signal();
62+ bool on_expose_event(GdkEventExpose *event);
63+ bool on_button_press_event(GdkEventButton *event);
64+
65+ // Helper functions
66+ void redraw();
67+};
68+
69+CalibrationArea::CalibrationArea(Calibrator* calibrator0)
70+ : calibrator(calibrator0), time_elapsed(0)
71+{
72+ // Listen for mouse events
73+ add_events(Gdk::BUTTON_PRESS_MASK);
74+
75+ // Compute absolute circle centers
76+ const Glib::RefPtr<Gdk::Screen> S = get_screen();
77+ display_width = S->get_width();
78+ display_height = S->get_height();
79+
80+ const int delta_x = display_width/num_blocks;
81+ const int delta_y = display_height/num_blocks;
82+ X[UL] = delta_x; Y[UL] = delta_y;
83+ X[UR] = display_width - delta_x - 1; Y[UR] = delta_y;
84+ X[LL] = delta_x; Y[LL] = display_height - delta_y - 1;
85+ X[LR] = display_width - delta_x - 1; Y[LR] = display_height - delta_y - 1;
86+
87+ // Setup timer for animation
88+ sigc::slot<bool> slot = sigc::mem_fun(*this, &CalibrationArea::on_timer_signal);
89+ Glib::signal_timeout().connect(slot, time_step);
90+}
91+
92+
93+bool CalibrationArea::on_expose_event(GdkEventExpose *event)
94+{
95+ const double radius = 4;
96+ Glib::RefPtr<Gdk::Window> window = get_window();
97+ if (window) {
98+ Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
99+ cr->save();
100+
101+ cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height);
102+ cr->clip();
103+
104+ // Print the text
105+ Cairo::TextExtents extent;
106+ cr->set_font_size(font_size);
107+ cr->get_text_extents(help_text, extent);
108+ cr->move_to((display_width-extent.width)/2, 0.3*display_height);
109+ cr->show_text(help_text);
110+ cr->stroke();
111+
112+ // Draw the points
113+ int i = 0;
114+ for (; i < calibrator->get_numclicks(); i++) {
115+ cr->arc(X[i], Y[i], radius, 0.0, 2.0 * M_PI);
116+ cr->set_source_rgb(1.0, 1.0, 1.0);
117+ cr->fill_preserve();
118+ cr->stroke();
119+ }
120+
121+ cr->set_line_width(2);
122+ cr->arc(X[i], Y[i], radius, 0.0, 2.0 * M_PI);
123+ cr->set_source_rgb(0.8, 0.0, 0.0);
124+ //cr->fill_preserve();
125+ cr->stroke();
126+
127+ // Draw the clock background
128+ cr->arc(display_width/2, display_height/2, clock_radius/2, 0.0, 2.0 * M_PI);
129+ cr->set_source_rgb(0.5, 0.5, 0.5);
130+ cr->fill_preserve();
131+ cr->stroke();
132+
133+ cr->set_line_width(clock_line_width);
134+ cr->arc(display_width/2, display_height/2, (clock_radius - clock_line_width)/2,
135+ 0.0, 2.0 * M_PI * (double)time_elapsed/(double)max_time);
136+ cr->set_source_rgb(0.0, 0.0, 0.0);
137+ cr->stroke();
138+
139+ cr->restore();
140+ }
141+
142+ return true;
143+}
144+
145+void CalibrationArea::redraw()
146+{
147+ Glib::RefPtr<Gdk::Window> win = get_window();
148+ if (win) {
149+ const Gdk::Rectangle rect(0, 0, display_width, display_height);
150+ win->invalidate_rect(rect, false);
151+ }
152+}
153+
154+bool CalibrationArea::on_timer_signal()
155+{
156+ time_elapsed += time_step;
157+ if (time_elapsed > max_time) {
158+ exit(0);
159+ }
160+
161+ // Update clock
162+ Glib::RefPtr<Gdk::Window> win = get_window();
163+ if (win) {
164+ const Gdk::Rectangle rect(display_width/2 - clock_radius - clock_line_width,
165+ display_height/2 - clock_radius - clock_line_width,
166+ 2 * clock_radius + 1 + 2 * clock_line_width,
167+ 2 * clock_radius + 1 + 2 * clock_line_width);
168+ win->invalidate_rect(rect, false);
169+ }
170+
171+ return true;
172+}
173+
174+bool CalibrationArea::on_button_press_event(GdkEventButton *event)
175+{
176+ // Handle click
177+ time_elapsed = 0;
178+ calibrator->add_click(event->x_root, event->y_root);
179+
180+ // Are we done yet?
181+ if (calibrator->get_numclicks() >= 4) {
182+ // Recalibrate
183+ calibrator->finish(display_width, display_height);
184+
185+ exit(0);
186+ }
187+
188+ // Force a redraw
189+ redraw();
190+
191+ return true;
192+}
--- /dev/null
+++ b/main_common.hpp
@@ -0,0 +1,243 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ * Copyright (c) 2009 Soren Hauberg
4+ *
5+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6+ * of this software and associated documentation files (the "Software"), to deal
7+ * in the Software without restriction, including without limitation the rights
8+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ * copies of the Software, and to permit persons to whom the Software is
10+ * furnished to do so, subject to the following conditions:
11+ *
12+ * The above copyright notice and this permission notice shall be included in
13+ * all copies or substantial portions of the Software.
14+ *
15+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+ * THE SOFTWARE.
22+ */
23+#include <cstring>
24+#include <stdio.h>
25+#include <stdlib.h>
26+
27+#include <X11/Xlib.h>
28+#include <X11/extensions/XInput.h>
29+
30+/*
31+ * Number of blocks. We partition the screen into 'num_blocks' x 'num_blocks'
32+ * rectangles of equal size. We then ask the user to press points that are
33+ * located at the corner closes to the center of the four blocks in the corners
34+ * of the screen. The following ascii art illustrates the situation. We partition
35+ * the screen into 8 blocks in each direction. We then let the user press the
36+ * points marked with 'O'.
37+ *
38+ * +--+--+--+--+--+--+--+--+
39+ * | | | | | | | | |
40+ * +--O--+--+--+--+--+--O--+
41+ * | | | | | | | | |
42+ * +--+--+--+--+--+--+--+--+
43+ * | | | | | | | | |
44+ * +--+--+--+--+--+--+--+--+
45+ * | | | | | | | | |
46+ * +--+--+--+--+--+--+--+--+
47+ * | | | | | | | | |
48+ * +--+--+--+--+--+--+--+--+
49+ * | | | | | | | | |
50+ * +--+--+--+--+--+--+--+--+
51+ * | | | | | | | | |
52+ * +--O--+--+--+--+--+--O--+
53+ * | | | | | | | | |
54+ * +--+--+--+--+--+--+--+--+
55+ */
56+const int num_blocks = 8;
57+
58+// Threshold to keep the same point from being clicked twice.
59+// Set to zero if you don't want this check
60+const int click_threshold = 7;
61+
62+// Names of the points
63+enum {
64+ UL = 0, // Upper-left
65+ UR = 1, // Upper-right
66+ LL = 2, // Lower-left
67+ LR = 3 // Lower-right
68+};
69+
70+// struct to hold min/max info of the X and Y axis
71+struct XYinfo {
72+ int x_min;
73+ int x_max;
74+ int y_min;
75+ int y_max;
76+ XYinfo() : x_min(-1), x_max(-1), y_min(-1), y_max(-1) {}
77+ XYinfo(int xmi, int xma, int ymi, int yma) :
78+ x_min(xmi), x_max(xma), y_min(ymi), y_max(yma) {}
79+};
80+
81+// all need struct XYinfo, and some the consts too
82+#include "calibrator.cpp"
83+#include "calibrators/calibratorXorgPrint.cpp"
84+#include "calibrators/calibratorEvdev.cpp"
85+#include "calibrators/calibratorUsbtouchscreen.cpp"
86+
87+
88+
89+// find a calibratable device (using Xinput)
90+// retuns number of devices found,
91+// data of last driver is returned in the function parameters
92+int find_driver(const char* drivername, XYinfo& axys)
93+{
94+ int found = 0;
95+
96+ Display* display = XOpenDisplay(NULL);
97+ if (display == NULL) {
98+ fprintf(stderr, "Unable to connect to X server\n");
99+ exit(1);
100+ }
101+
102+ int xi_opcode, event, error;
103+ if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
104+ printf("X Input extension not available.\n");
105+ exit(1);
106+ }
107+
108+ int ndevices;
109+ XDeviceInfoPtr list, slist;
110+ slist=list=(XDeviceInfoPtr) XListInputDevices (display, &ndevices);
111+ for (int i=0; i<ndevices; i++, list++)
112+ {
113+ if (list->use == IsXKeyboard || list->use == IsXPointer)
114+ continue;
115+
116+ XAnyClassPtr any = (XAnyClassPtr) (list->inputclassinfo);
117+ for (int j=0; j<list->num_classes; j++)
118+ {
119+
120+ if (any->c_class == ValuatorClass)
121+ {
122+ XValuatorInfoPtr V = (XValuatorInfoPtr) any;
123+ XAxisInfoPtr ax = (XAxisInfoPtr) V->axes;
124+
125+ if (V->num_axes >= 2 &&
126+ !(ax[0].min_value == -1 && ax[0].max_value == -1) &&
127+ !(ax[1].min_value == -1 && ax[1].max_value == -1)) {
128+ /* a calibratable device (no mouse etc) */
129+ found++;
130+ drivername = strdup(list->name);
131+ axys.x_min = ax[0].min_value;
132+ axys.x_max = ax[0].max_value;
133+ axys.y_min = ax[1].min_value;
134+ axys.y_max = ax[1].max_value;
135+ }
136+
137+ }
138+
139+ /*
140+ * Increment 'any' to point to the next item in the linked
141+ * list. The length is in bytes, so 'any' must be cast to
142+ * a character pointer before being incremented.
143+ */
144+ any = (XAnyClassPtr) ((char *) any + any->length);
145+ }
146+
147+ }
148+ XFreeDeviceList(slist);
149+ XCloseDisplay(display);
150+
151+ return found;
152+}
153+
154+static void usage(char* cmd)
155+{
156+ fprintf(stderr, "Usage: %s [-h|--help] [--precalib <minx> <maxx> <miny> <maxy>]\n", cmd);
157+ fprintf(stderr, "\t--precalib: manually provide the current calibration setting (eg the values in xorg.conf)\n");
158+}
159+
160+Calibrator* main_common(int argc, char** argv)
161+{
162+ bool fake = false;
163+ bool precalib = false;
164+ XYinfo pre_axys;
165+
166+ // parse input
167+ if (argc > 1) {
168+ for (int i=1; i!=argc; i++) {
169+ // Display help ?
170+ if (strcmp("-h", argv[i]) == 0 ||
171+ strcmp("--help", argv[i]) == 0) {
172+ usage(argv[0]);
173+ exit(0);
174+ }
175+
176+ // Get pre-calibration ?
177+ if (strcmp("--precalib", argv[i]) == 0) {
178+ precalib = true;
179+ if (argc > i+1)
180+ pre_axys.x_min = atoi(argv[i+1]);
181+ if (argc > i+2)
182+ pre_axys.x_max = atoi(argv[i+2]);
183+ if (argc > i+3)
184+ pre_axys.y_min = atoi(argv[i+3]);
185+ if (argc > i+4)
186+ pre_axys.y_max = atoi(argv[i+4]);
187+ }
188+
189+ // Fake calibratable device ?
190+ if (strcmp("--fake", argv[i]) == 0) {
191+ fake = true;
192+ }
193+ }
194+ }
195+
196+ // find driver(s)
197+ const char* drivername = NULL;
198+ XYinfo axys;
199+ int nr_found = find_driver(drivername, axys);
200+ if (nr_found == 0) {
201+ if (fake) {
202+ // Fake a calibratable device
203+ drivername = "Fake_device";
204+ axys = XYinfo(0,0,0,0);
205+ } else {
206+ fprintf (stderr, "Error: No calibratable devices found.\n");
207+ exit(1);
208+ }
209+ }
210+ if (nr_found > 1) {
211+ printf ("Warning: multiple calibratable devices found, calibrating last one (%s)\n", drivername);
212+ }
213+
214+ // override min/max XY from command line ?
215+ if (precalib) {
216+ if (pre_axys.x_min != -1)
217+ axys.x_min = pre_axys.x_min;
218+ if (pre_axys.x_max != -1)
219+ axys.x_max = pre_axys.x_max;
220+ if (pre_axys.y_min != -1)
221+ axys.y_min = pre_axys.y_min;
222+ if (pre_axys.y_max != -1)
223+ axys.y_max = pre_axys.y_max;
224+ }
225+
226+ Calibrator* calibrator;
227+ // Different driver, different backend behaviour
228+ if (strcmp(drivername, "Usbtouchscreen") == 0)
229+ // Usbtouchscreen driver
230+ calibrator = new CalibratorUsbtouchscreen(drivername, axys);
231+ else {
232+ // unable to know device driver from its name alone
233+ // either its EVDEV or a normal Xorg touchscreen driver
234+ if (CalibratorEvdev::check_driver(drivername)) {
235+ // Evdev driver
236+ calibrator = new CalibratorEvdev(drivername, axys);
237+ } else {
238+ // EVTouch is handled as a normal Xorg driver
239+ calibrator = new CalibratorXorgPrint(drivername, axys);
240+ }
241+ }
242+ return calibrator;
243+}
--- /dev/null
+++ b/main_gtkmm.cpp
@@ -0,0 +1,53 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ * Copyright (c) 2009 Soren Hauberg
4+ *
5+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6+ * of this software and associated documentation files (the "Software"), to deal
7+ * in the Software without restriction, including without limitation the rights
8+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ * copies of the Software, and to permit persons to whom the Software is
10+ * furnished to do so, subject to the following conditions:
11+ *
12+ * The above copyright notice and this permission notice shall be included in
13+ * all copies or substantial portions of the Software.
14+ *
15+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+ * THE SOFTWARE.
22+ */
23+#include <stdexcept>
24+
25+// Must be before Xlib stuff
26+#include <gtkmm/main.h>
27+#include <gtkmm/window.h>
28+#include <gtkmm/drawingarea.h>
29+#include <cairomm/context.h>
30+
31+#include "main_common.hpp"
32+#include "gui_gtkmm.cpp"
33+
34+int main(int argc, char** argv)
35+{
36+ Calibrator* calibrator = main_common(argc, argv);
37+
38+ // GTK-mm setup
39+ Gtk::Main kit(argc, argv);
40+
41+ Gtk::Window win;
42+ win.fullscreen();
43+
44+ CalibrationArea area(calibrator);
45+ win.add(area);
46+ area.show();
47+
48+ Gtk::Main::run(win);
49+
50+ Gtk::Main::quit();
51+ delete calibrator;
52+ return 0;
53+}