A generic touchscreen calibration program for X.Org
修订版 | e1d55df1b8115ad93828a4c1285b5cc7d8434a93 (tree) |
---|---|
时间 | 2009-11-29 22:52:52 |
作者 | Tias <tias@kata...> |
Commiter | Tias |
Add generic xinput methods for reading the current data and writing
example xorg.conf files.
@@ -24,6 +24,8 @@ | ||
24 | 24 | * Soren Hauberg (haub...@gmail.com) |
25 | 25 | * Tias Guns (ti..@ulyssis.org) |
26 | 26 | * |
27 | + * Version: 0.2.0 | |
28 | + * | |
27 | 29 | * Make: g++ -Wall xinput_calibrator.cc `pkg-config --cflags --libs gtkmm-2.4` -o xinput_calibrator |
28 | 30 | */ |
29 | 31 |
@@ -48,6 +50,10 @@ | ||
48 | 50 | * sensors at the corners. So, what we do is we ask the user to press points that |
49 | 51 | * have been pushed a bit closer to the center, and then we extrapolate the |
50 | 52 | * parameters. |
53 | + * | |
54 | + * In case of the usbtouchscreen kernel module, the new calibration data will be | |
55 | + * dynamically updated. In all other cases, the new xorg.conf values will be printed | |
56 | + * on stdout. | |
51 | 57 | */ |
52 | 58 | |
53 | 59 | #include <cstring> |
@@ -57,6 +63,9 @@ | ||
57 | 63 | #include <gtkmm/drawingarea.h> |
58 | 64 | #include <cairomm/context.h> |
59 | 65 | |
66 | +#include <X11/Xlib.h> | |
67 | +#include <X11/extensions/XInput.h> | |
68 | + | |
60 | 69 | /* Number of points the user should click */ |
61 | 70 | const int num_points = 4; |
62 | 71 |
@@ -101,7 +110,7 @@ const int click_threshold = 7; | ||
101 | 110 | |
102 | 111 | /* Timeout parameters */ |
103 | 112 | const int time_step = 100; /* 500 = 0.1 sec */ |
104 | -const int max_time = 5000; /* 5000 = 5 sec */ | |
113 | +const int max_time = 15000; /* 5000 = 5 sec */ | |
105 | 114 | |
106 | 115 | /* Clock Appereance */ |
107 | 116 | const int clock_radius = 25; |
@@ -247,6 +256,43 @@ void Calibrator::finish () | ||
247 | 256 | flip_x, flip_y); |
248 | 257 | } |
249 | 258 | |
259 | +/*************************** | |
260 | + * Class for generic driver, | |
261 | + * outputs new Xorg values (on stdout for now) | |
262 | + ***************************/ | |
263 | +class CalibratorXorgPrint: public Calibrator | |
264 | +{ | |
265 | +public: | |
266 | + CalibratorXorgPrint (const char*, int, int, int, int); | |
267 | + | |
268 | + virtual void finish_data (int, int, int, int, int, int, int); | |
269 | +}; | |
270 | + | |
271 | +CalibratorXorgPrint::CalibratorXorgPrint (const char* drivername0, int min_x, int max_x, int min_y, int max_y) | |
272 | + : Calibrator (drivername0, min_x, max_x, min_y, max_y) | |
273 | +{ | |
274 | + printf ("Calibrating driver %s with min_x=%d, max_x=%d and min_y=%d, max_y=%d\n", | |
275 | + drivername, oldcalib_min_x, oldcalib_max_x, oldcalib_min_y, oldcalib_max_y); | |
276 | +} | |
277 | + | |
278 | +void CalibratorXorgPrint::finish_data ( | |
279 | + int min_x, int max_x, int min_y, int max_y, int swap_xy, int flip_x, int flip_y) | |
280 | +{ | |
281 | + /* We ignore flip_x and flip_y, | |
282 | + * the min/max values will already be flipped and drivers can handle this */ | |
283 | + | |
284 | + printf ("Suggested new values for xorg.conf:\n"); | |
285 | + printf ("\tOption\t\"MinX\"\t\t\"%d\"\t# was \"%d\"\n", | |
286 | + min_x, oldcalib_min_x); | |
287 | + printf ("\tOption\t\"MaxX\"\t\t\"%d\"\t# was \"%d\"\n", | |
288 | + max_x, oldcalib_max_x); | |
289 | + printf ("\tOption\t\"MinY\"\t\t\"%d\"\t# was \"%d\"\n", | |
290 | + min_y, oldcalib_min_y); | |
291 | + printf ("\tOption\t\"MaxY\"\t\t\"%d\"\t# was \"%d\"\n", | |
292 | + max_y, oldcalib_max_y); | |
293 | + printf ("\tOption\t\"SwapXY\"\t\"%d\"\n", swap_xy); | |
294 | +} | |
295 | + | |
250 | 296 | |
251 | 297 | /********************************** |
252 | 298 | * Class for usbtouchscreen driver, |
@@ -450,7 +496,79 @@ protected: | ||
450 | 496 | CalibrationArea::CalibrationArea () |
451 | 497 | : num_clicks (0), time_elapsed (0) |
452 | 498 | { |
453 | - W = new CalibratorUsbts(); | |
499 | + /* Not sure this is the right place for this, but here we go | |
500 | + * Get driver name and axis information from XInput */ | |
501 | + { | |
502 | + int found = 0; | |
503 | + const char* drivername = ""; | |
504 | + int min_x = 0, max_x = 0; | |
505 | + int min_y = 0, max_y = 0; | |
506 | + | |
507 | + int ndevices; | |
508 | + Display *display; | |
509 | + XDeviceInfoPtr list, slist; | |
510 | + XAnyClassPtr any; | |
511 | + | |
512 | + if ((display = XOpenDisplay (0)) == NULL) | |
513 | + { | |
514 | + fprintf (stderr, "Error: No connection to Xserver - Terminating.\n"); | |
515 | + quit(1); | |
516 | + } | |
517 | + | |
518 | + slist=list=(XDeviceInfoPtr) XListInputDevices (display, &ndevices); | |
519 | + for (int i=0; i<ndevices; i++, list++) | |
520 | + { | |
521 | + if (list->use == IsXKeyboard || list->use == IsXPointer) | |
522 | + continue; | |
523 | + | |
524 | + any = (XAnyClassPtr) (list->inputclassinfo); | |
525 | + for (int j=0; j<list->num_classes; j++) | |
526 | + { | |
527 | + | |
528 | + if (any->c_class == ValuatorClass) | |
529 | + { | |
530 | + XValuatorInfoPtr V = (XValuatorInfoPtr) any; | |
531 | + XAxisInfoPtr ax = (XAxisInfoPtr) V->axes; | |
532 | + | |
533 | + if (V->num_axes >= 2 && | |
534 | + !(ax[0].min_value == -1 && ax[0].max_value == -1) && | |
535 | + !(ax[1].min_value == -1 && ax[1].max_value == -1)) { | |
536 | + /* a calibratable device (no mouse etc) */ | |
537 | + found++; | |
538 | + drivername = list->name; | |
539 | + min_x = ax[0].min_value; | |
540 | + max_x = ax[0].max_value; | |
541 | + min_y = ax[1].min_value; | |
542 | + max_y = ax[1].max_value; | |
543 | + } | |
544 | + | |
545 | + } | |
546 | + | |
547 | + /* | |
548 | + * Increment 'any' to point to the next item in the linked | |
549 | + * list. The length is in bytes, so 'any' must be cast to | |
550 | + * a character pointer before being incremented. | |
551 | + */ | |
552 | + any = (XAnyClassPtr) ((char *) any + any->length); | |
553 | + } | |
554 | + | |
555 | + } | |
556 | + XFreeDeviceList (slist); | |
557 | + | |
558 | + if (found == 0) { | |
559 | + fprintf (stderr, "Error: No calibratable devices found.\n"); | |
560 | + quit (1); | |
561 | + } | |
562 | + if (found > 1) | |
563 | + printf ("Warning: multiples calibratable devices found, calibrating last one (%s)\n", drivername); | |
564 | + | |
565 | + /* Different driver, different backend behaviour (case sensitive ?) */ | |
566 | + if (strcmp(drivername, "Usbtouchscreen") == 0) | |
567 | + W = new CalibratorUsbts(); | |
568 | + else | |
569 | + W = new CalibratorXorgPrint(drivername, | |
570 | + min_x, max_x, min_y, max_y); | |
571 | + } | |
454 | 572 | |
455 | 573 | /* Listen for mouse events */ |
456 | 574 | add_events (Gdk::BUTTON_PRESS_MASK); |