From 66a70e1f03d81336881cfe447c7b9f0c6f5ea7c3 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Tue, 4 Sep 2012 15:50:13 -0400 Subject: [PATCH 01/10] Ignore axis inversion in common code. The core calibration routines function ignore the XYinfo invert member, so drop it altogether and instead treat axis inversion as an input/output consideration for some drivers. This fixes axis inversion for XorgPrintCalibrator (inversion would not have been enabled before). --- src/calibrator.cpp | 2 +- src/calibrator.hh | 17 +++++++-------- src/calibrator/Evdev.cpp | 40 +++++++++------------------------- src/calibrator/EvdevTester.cpp | 3 --- src/calibrator/XorgPrint.cpp | 18 +++++++-------- 5 files changed, 28 insertions(+), 52 deletions(-) diff --git a/src/calibrator.cpp b/src/calibrator.cpp index c60a1f6..735f487 100644 --- a/src/calibrator.cpp +++ b/src/calibrator.cpp @@ -139,7 +139,7 @@ bool Calibrator::finish(int width, int height) } // new axis origin and scaling - // based on old_axys: inversion/swapping is relative to the old axis + // based on old_axys: swapping is relative to the old axis XYinfo new_axis(old_axys); diff --git a/src/calibrator.hh b/src/calibrator.hh index 6e696e4..45ca3d9 100644 --- a/src/calibrator.hh +++ b/src/calibrator.hh @@ -63,17 +63,16 @@ const int num_blocks = 8; struct AxisInfo { int min, max; - bool invert; - AxisInfo() : min(-1), max(-1), invert(false) { } + AxisInfo() : min(-1), max(-1) { } AxisInfo(int mi, int ma, bool inv = false) : - min(mi), max(ma), invert(inv) { } + min(mi), max(ma) { } AxisInfo(const AxisInfo& old) : - min(old.min), max(old.max), invert(old.invert) { } + min(old.min), max(old.max) { } - void do_invert() { - invert = !invert; - } + int real_min() const { return std::min(min, max); } + int real_max() const { return std::max(min, max); } + bool is_inverted() const { return min > max; } }; /// struct to hold min/max info of the X and Y axis @@ -100,8 +99,8 @@ struct XYinfo { } void print(const char* xtra="\n") { - printf("XYinfo: x.min=%i, x.max=%i, y.min=%i, y.max=%i, swap_xy=%i, invert_x=%i, invert_y=%i%s", - x.min, x.max, y.min, y.max, swap_xy, x.invert, y.invert, xtra); + printf("XYinfo: x.min=%i, x.max=%i, y.min=%i, y.max=%i, swap_xy=%i%s", + x.min, x.max, y.min, y.max, swap_xy, xtra); } }; diff --git a/src/calibrator/Evdev.cpp b/src/calibrator/Evdev.cpp index 8a849b1..2725772 100644 --- a/src/calibrator/Evdev.cpp +++ b/src/calibrator/Evdev.cpp @@ -144,11 +144,16 @@ CalibratorEvdev::CalibratorEvdev(const char* const device_name0, AnyPropertyType, &act_type, &act_format, &nitems, &bytes_after, &data) == Success) { if (act_format == 8 && act_type == XA_INTEGER && nitems == 2) { - old_axys.x.invert = *((char*)data++); - old_axys.y.invert = *((char*)data); + bool invert_x = *((char*)data++); + bool invert_y = *((char*)data); if (verbose) - printf("DEBUG: Read InvertX=%i, InvertY=%i.\n", old_axys.x.invert, old_axys.y.invert); + printf("DEBUG: Read InvertX=%i, InvertY=%i.\n", invert_x, invert_y); + + if (invert_x) + std::swap(old_axys.x.min, old_axys.x.max); + if (invert_y) + std::swap(old_axys.y.min, old_axys.y.max); } } @@ -192,28 +197,6 @@ bool CalibratorEvdev::finish(int width, int height) float y_min = (clicked.y[UL] + clicked.y[UR])/2.0; float y_max = (clicked.y[LL] + clicked.y[LR])/2.0; - - // When evdev detects an invert_X/Y option, - // it performs the following *crazy* code just before returning - // val = (pEvdev->absinfo[i].maximum - val + pEvdev->absinfo[i].minimum); - // undo this crazy step before doing the regular calibration routine - if (old_axys.x.invert) { - x_min = width - x_min; - x_max = width - x_max; - // avoid invert_x property from here on, - // the calibration code can handle this dynamically! - new_axis.x.invert = false; - } - if (old_axys.y.invert) { - y_min = height - y_min; - y_max = height - y_max; - // avoid invert_y property from here on, - // the calibration code can handle this dynamically! - new_axis.y.invert = false; - } - // end of evdev inversion crazyness - - // Should x and y be swapped? if (abs(clicked.x[UL] - clicked.x[UR]) < abs(clicked.y[UL] - clicked.y[UR])) { new_axis.swap_xy = !new_axis.swap_xy; @@ -264,11 +247,8 @@ bool CalibratorEvdev::finish_data(const XYinfo new_axys) success &= set_swapxy(new_axys.swap_xy); } - // Evdev Axis Inversion - if (old_axys.x.invert != new_axys.x.invert || - old_axys.y.invert != new_axys.y.invert) { - success &= set_invert_xy(new_axys.x.invert, new_axys.y.invert); - } + // Evdev Axis Inversion + set_invert_xy(false, false); // Evdev Axis Calibration success &= set_calibration(new_axys); diff --git a/src/calibrator/EvdevTester.cpp b/src/calibrator/EvdevTester.cpp index 5022946..cd54152 100644 --- a/src/calibrator/EvdevTester.cpp +++ b/src/calibrator/EvdevTester.cpp @@ -149,11 +149,8 @@ void CalibratorEvdevTester::evdev_270_processvaluator(const XYinfo& devAxis, con calib_min); //if ((i == 0 && pEvdev->invert_x) || (i == 1 && pEvdev->invert_y)) - if ((i == 0 && axis.x.invert) || (i == 1 && axis.y.invert)) //val = (pEvdev->absinfo[i].maximum - val + // pEvdev->absinfo[i].minimum); - val = (absinfo_max[i] - val + - absinfo_min[i]); //valuator_mask_set(pEvdev->vals, i, val); vals[i] = val; diff --git a/src/calibrator/XorgPrint.cpp b/src/calibrator/XorgPrint.cpp index 49decff..0d6a3fd 100644 --- a/src/calibrator/XorgPrint.cpp +++ b/src/calibrator/XorgPrint.cpp @@ -74,13 +74,13 @@ bool CalibratorXorgPrint::output_xorgconfd(const XYinfo new_axys) printf("Section \"InputClass\"\n"); printf(" Identifier \"calibration\"\n"); printf(" MatchProduct \"%s\"\n", sysfs_name); - printf(" Option \"MinX\" \"%d\"\n", new_axys.x.min); - printf(" Option \"MaxX\" \"%d\"\n", new_axys.x.max); - printf(" Option \"MinY\" \"%d\"\n", new_axys.y.min); - printf(" Option \"MaxY\" \"%d\"\n", new_axys.y.max); + printf(" Option \"MinX\" \"%d\"\n", new_axys.x.real_min()); + printf(" Option \"MaxX\" \"%d\"\n", new_axys.x.real_max()); + printf(" Option \"MinY\" \"%d\"\n", new_axys.y.real_min()); + printf(" Option \"MaxY\" \"%d\"\n", new_axys.y.real_max()); printf(" Option \"SwapXY\" \"%d\" # unless it was already set to 1\n", new_axys.swap_xy); - printf(" Option \"InvertX\" \"%d\" # unless it was already set\n", new_axys.x.invert); - printf(" Option \"InvertY\" \"%d\" # unless it was already set\n", new_axys.y.invert); + printf(" Option \"InvertX\" \"%d\" # unless it was already set\n", new_axys.x.is_inverted()); + printf(" Option \"InvertY\" \"%d\" # unless it was already set\n", new_axys.y.is_inverted()); printf("EndSection\n"); if (not_sysfs_name) @@ -103,10 +103,10 @@ bool CalibratorXorgPrint::output_hal(const XYinfo new_axys) %d\n\ %d\n\ %d\n" - , sysfs_name, new_axys.x.min, new_axys.x.max, new_axys.y.min, new_axys.y.max); + , sysfs_name, new_axys.x.real_max(), new_axys.x.real_max(), new_axys.y.real_min(), new_axys.y.real_max()); printf(" %d\n", new_axys.swap_xy); - printf(" %d\n", new_axys.x.invert); - printf(" %d\n", new_axys.y.invert); + printf(" %d\n", new_axys.x.is_inverted()); + printf(" %d\n", new_axys.y.is_inverted()); printf("\n"); if (not_sysfs_name) From f6b63409cf290f80becc0eb29c8f51bb9e68ea8d Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Wed, 5 Sep 2012 11:56:44 -0400 Subject: [PATCH 02/10] Evdev: Don't override method "finish". This method is no longer different from the Calibrator method it overrides (since axis inversion is ignored). --- src/calibrator/Evdev.cpp | 58 ---------------------------------------- src/calibrator/Evdev.hpp | 2 -- 2 files changed, 60 deletions(-) diff --git a/src/calibrator/Evdev.cpp b/src/calibrator/Evdev.cpp index 2725772..e4bf3be 100644 --- a/src/calibrator/Evdev.cpp +++ b/src/calibrator/Evdev.cpp @@ -178,64 +178,6 @@ CalibratorEvdev::~CalibratorEvdev () { XCloseDisplay(display); } -// From Calibrator but with evdev specific invertion option -// KEEP IN SYNC with Calibrator::finish() !! -bool CalibratorEvdev::finish(int width, int height) -{ - if (get_numclicks() != NUM_POINTS) { - return false; - } - - // new axis origin and scaling - // based on old_axys: inversion/swapping is relative to the old axis - XYinfo new_axis(old_axys); - - - // calculate average of clicks - float x_min = (clicked.x[UL] + clicked.x[LL])/2.0; - float x_max = (clicked.x[UR] + clicked.x[LR])/2.0; - float y_min = (clicked.y[UL] + clicked.y[UR])/2.0; - float y_max = (clicked.y[LL] + clicked.y[LR])/2.0; - - // Should x and y be swapped? - if (abs(clicked.x[UL] - clicked.x[UR]) < abs(clicked.y[UL] - clicked.y[UR])) { - new_axis.swap_xy = !new_axis.swap_xy; - std::swap(x_min, y_min); - std::swap(x_max, y_max); - } - - // the screen was divided in num_blocks blocks, and the touch points were at - // one block away from the true edges of the screen. - const float block_x = width/(float)num_blocks; - const float block_y = height/(float)num_blocks; - // rescale these blocks from the range of the drawn touchpoints to the range of the - // actually clicked coordinates, and substract/add from the clicked coordinates - // to obtain the coordinates corresponding to the edges of the screen. - float scale_x = (x_max - x_min)/(width - 2*block_x); - x_min -= block_x * scale_x; - x_max += block_x * scale_x; - float scale_y = (y_max - y_min)/(height - 2*block_y); - y_min -= block_y * scale_y; - y_max += block_y * scale_y; - - // now, undo the transformations done by the X server, to obtain the true 'raw' value in X. - // The raw value was scaled from old_axis to the device min/max, and from the device min/max - // to the screen min/max - // hence, the reverse transformation is from screen to old_axis - x_min = scaleAxis(x_min, old_axys.x.max, old_axys.x.min, width, 0); - x_max = scaleAxis(x_max, old_axys.x.max, old_axys.x.min, width, 0); - y_min = scaleAxis(y_min, old_axys.y.max, old_axys.y.min, height, 0); - y_max = scaleAxis(y_max, old_axys.y.max, old_axys.y.min, height, 0); - - - // round and put in new_axis struct - new_axis.x.min = round(x_min); new_axis.x.max = round(x_max); - new_axis.y.min = round(y_min); new_axis.y.max = round(y_max); - - // finish the data, driver/calibrator specific - return finish_data(new_axis); -} - // Activate calibrated data and output it bool CalibratorEvdev::finish_data(const XYinfo new_axys) { diff --git a/src/calibrator/Evdev.hpp b/src/calibrator/Evdev.hpp index 066b0c8..625ca72 100644 --- a/src/calibrator/Evdev.hpp +++ b/src/calibrator/Evdev.hpp @@ -58,8 +58,6 @@ class CalibratorEvdev: public Calibrator const char* geometry=0); ~CalibratorEvdev(); - /// calculate and apply the calibration - virtual bool finish(int width, int height); virtual bool finish_data(const XYinfo new_axys); bool set_swapxy(const int swap_xy); From 1e9ae6ec274510f5001d8e589bb344ddd0a5e1a5 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Wed, 5 Sep 2012 11:57:20 -0400 Subject: [PATCH 03/10] Calibrator: Make method "finish" non-virtual. None of the drivers need to override this method any longer, and it is better not to as it leads to code duplciation so just don't allow it. --- src/calibrator.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibrator.hh b/src/calibrator.hh index 45ca3d9..02e174f 100644 --- a/src/calibrator.hh +++ b/src/calibrator.hh @@ -170,7 +170,7 @@ public: /// add a click with the given coordinates bool add_click(int x, int y); /// calculate and apply the calibration - virtual bool finish(int width, int height); + bool finish(int width, int height); /// get the sysfs name of the device, /// returns NULL if it can not be found const char* get_sysfs_name(); From ccd50be35f3c137ce14b6594fae05c31430d50f2 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Tue, 28 Aug 2012 12:04:34 -0400 Subject: [PATCH 04/10] Skip devices with too many axes. --- src/main_common.cpp | 51 +++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/main_common.cpp b/src/main_common.cpp index 08cc980..9873b4e 100644 --- a/src/main_common.cpp +++ b/src/main_common.cpp @@ -124,31 +124,46 @@ int Calibrator::find_device(const char* pre_device, bool list_devices, { XValuatorInfoPtr V = (XValuatorInfoPtr) any; XAxisInfoPtr ax = (XAxisInfoPtr) V->axes; + unsigned int axis_count = 0; if (V->mode != Absolute) { if (verbose) printf("DEBUG: Skipping device '%s' id=%i, does not report Absolute events.\n", list->name, (int)list->id); - } else if (V->num_axes < 2 || - (ax[0].min_value == -1 && ax[0].max_value == -1) || - (ax[1].min_value == -1 && ax[1].max_value == -1)) { - if (verbose) - printf("DEBUG: Skipping device '%s' id=%i, does not have two calibratable axes.\n", - list->name, (int)list->id); } else { - /* a calibratable device (has 2 axis valuators) */ - found++; - device_id = list->id; - device_name = my_strdup(list->name); - device_axys.x.min = ax[0].min_value; - device_axys.x.max = ax[0].max_value; - device_axys.y.min = ax[1].min_value; - device_axys.y.max = ax[1].max_value; - - if (list_devices) - printf("Device \"%s\" id=%i\n", device_name, (int)device_id); + for (int k=0; knum_axes; k++) + if (! (ax[k].min_value == -1 && ax[k].max_value == -1)) + axis_count++; + + if (axis_count < 2) { + if (verbose) + printf("DEBUG: Skipping device '%s' id=%i, does not have two calibratable axes (%u).\n", + list->name, (int)list->id, axis_count); + /* Note that devices with more than eight calibratable axes + * can be calibrated explicitly, but will not be + * automatically selected for calibration. This heuristic + * causes some devices that are not really pointer devices + * but sometimes appear to be (e.g. some USB keyboards) to + * be skipped. + */ + } else if (pre_device == NULL && axis_count > 8) { + if (verbose) + printf("DEBUG: Skipping device '%s' id=%i, has more than eight calibratable axes (%u).\n", + list->name, (int)list->id, axis_count); + } else { + /* a calibratable device */ + found++; + device_id = list->id; + device_name = my_strdup(list->name); + device_axys.x.min = ax[0].min_value; + device_axys.x.max = ax[0].max_value; + device_axys.y.min = ax[1].min_value; + device_axys.y.max = ax[1].max_value; + + if (list_devices) + printf("Device \"%s\" id=%i\n", device_name, (int)device_id); + } } - } /* From ee60066e18de066e00e097d2e0b430ead151f62b Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Tue, 28 Aug 2012 16:22:58 -0400 Subject: [PATCH 05/10] Separate detection of current calibration values. Refactor to move reading of calibration parameters into an explicit method ("detect_axys") in preparation. This is needed for some follow up fixes. --- src/calibrator.hh | 2 + src/calibrator/Evdev.cpp | 106 ++++++++++++++++++++++----------------- src/calibrator/Evdev.hpp | 2 + src/main_common.cpp | 32 ++++++++---- 4 files changed, 86 insertions(+), 56 deletions(-) diff --git a/src/calibrator.hh b/src/calibrator.hh index 02e174f..03bc213 100644 --- a/src/calibrator.hh +++ b/src/calibrator.hh @@ -167,6 +167,8 @@ public: void reset() { clicked.num = 0; clicked.x.clear(); clicked.y.clear();} + virtual void detect_axys() { return; } + /// add a click with the given coordinates bool add_click(int x, int y); /// calculate and apply the calibration diff --git a/src/calibrator/Evdev.cpp b/src/calibrator/Evdev.cpp index e4bf3be..f60e559 100644 --- a/src/calibrator/Evdev.cpp +++ b/src/calibrator/Evdev.cpp @@ -73,14 +73,14 @@ CalibratorEvdev::CalibratorEvdev(const char* const device_name0, #ifndef HAVE_XI_PROP throw WrongCalibratorException("Evdev: you need at least libXi 1.2 and inputproto 1.5 for dynamic recalibration of evdev."); -#else +#endif // XGetDeviceProperty vars Atom property; Atom act_type; int act_format; unsigned long nitems, bytes_after; - unsigned char *data, *ptr; + unsigned char *data; // get "Evdev Axis Calibration" property property = xinput_parse_atom(display, "Evdev Axis Calibration"); @@ -91,34 +91,67 @@ CalibratorEvdev::CalibratorEvdev(const char* const device_name0, XCloseDevice(display, dev); XCloseDisplay(display); throw WrongCalibratorException("Evdev: \"Evdev Axis Calibration\" property missing, not a (valid) evdev device"); - } else { - if (act_format != 32 || act_type != XA_INTEGER) { - XCloseDevice(display, dev); - XCloseDisplay(display); - throw WrongCalibratorException("Evdev: invalid \"Evdev Axis Calibration\" property format"); + XFree(data); + } - } else if (nitems == 0) { - if (verbose) - printf("DEBUG: Evdev Axis Calibration not set, setting to axis valuators to be sure.\n"); - - // No axis calibration set, set it to the default one - // QUIRK: when my machine resumes from a sleep, - // the calibration property is no longer exported through xinput, but still active - // not setting the values here would result in a wrong first calibration - (void) set_calibration(old_axys); - - } else if (nitems > 0) { - ptr = data; - - old_axys.x.min = *((long*)ptr); - ptr += sizeof(long); - old_axys.x.max = *((long*)ptr); - ptr += sizeof(long); - old_axys.y.min = *((long*)ptr); - ptr += sizeof(long); - old_axys.y.max = *((long*)ptr); - ptr += sizeof(long); + printf("Calibrating EVDEV driver for \"%s\" id=%i\n", device_name, (int)device_id); +} + +// protected pass-through constructor for subclasses +CalibratorEvdev::CalibratorEvdev(const char* const device_name0, + const XYinfo& axys0, + const int thr_misclick, + const int thr_doubleclick, + const OutputType output_type, + const char* geometry) + : Calibrator(device_name0, axys0, thr_misclick, thr_doubleclick, output_type, geometry) { } + +// Destructor +CalibratorEvdev::~CalibratorEvdev () { + XCloseDevice(display, dev); + XCloseDisplay(display); +} + +void CalibratorEvdev::detect_axys() +{ + // XGetDeviceProperty vars + Atom property; + Atom act_type; + int act_format; + unsigned long nitems, bytes_after; + unsigned char *data, *ptr; + + // get "Evdev Axis Calibration" property + property = xinput_parse_atom(display, "Evdev Axis Calibration"); + if (XGetDeviceProperty(display, dev, property, 0, 1000, False, + AnyPropertyType, &act_type, &act_format, + &nitems, &bytes_after, &data) == Success) + { + + if (act_format == 32 && act_type == XA_INTEGER) { + if (nitems == 0) { + if (verbose) + printf("DEBUG: Evdev Axis Calibration not set, setting to axis valuators to be sure.\n"); + + // No axis calibration set, set it to the default one + // QUIRK: when my machine resumes from a sleep, the calibration + // property is no longer exported through xinput, but still + // active not setting the values here would result in a wrong + // first calibration + (void) set_calibration(old_axys); + } else { + ptr = data; + + old_axys.x.min = *((long*)ptr); + ptr += sizeof(long); + old_axys.x.max = *((long*)ptr); + ptr += sizeof(long); + old_axys.y.min = *((long*)ptr); + ptr += sizeof(long); + old_axys.y.max = *((long*)ptr); + ptr += sizeof(long); + } } XFree(data); @@ -157,25 +190,8 @@ CalibratorEvdev::CalibratorEvdev(const char* const device_name0, } } - printf("Calibrating EVDEV driver for \"%s\" id=%i\n", device_name, (int)device_id); printf("\tcurrent calibration values (from XInput): min_x=%d, max_x=%d and min_y=%d, max_y=%d\n", old_axys.x.min, old_axys.x.max, old_axys.y.min, old_axys.y.max); -#endif // HAVE_XI_PROP - -} -// protected pass-through constructor for subclasses -CalibratorEvdev::CalibratorEvdev(const char* const device_name0, - const XYinfo& axys0, - const int thr_misclick, - const int thr_doubleclick, - const OutputType output_type, - const char* geometry) - : Calibrator(device_name0, axys0, thr_misclick, thr_doubleclick, output_type, geometry) { } - -// Destructor -CalibratorEvdev::~CalibratorEvdev () { - XCloseDevice(display, dev); - XCloseDisplay(display); } // Activate calibrated data and output it diff --git a/src/calibrator/Evdev.hpp b/src/calibrator/Evdev.hpp index 625ca72..96a92d7 100644 --- a/src/calibrator/Evdev.hpp +++ b/src/calibrator/Evdev.hpp @@ -58,6 +58,8 @@ class CalibratorEvdev: public Calibrator const char* geometry=0); ~CalibratorEvdev(); + virtual void detect_axys(); + virtual bool finish_data(const XYinfo new_axys); bool set_swapxy(const int swap_xy); diff --git a/src/main_common.cpp b/src/main_common.cpp index 9873b4e..64c760c 100644 --- a/src/main_common.cpp +++ b/src/main_common.cpp @@ -198,6 +198,7 @@ static void usage(char* cmd, unsigned thr_misclick) Calibrator* Calibrator::make_calibrator(int argc, char** argv) { + Calibrator *calibrator; bool list_devices = false; bool fake = false; bool precalib = false; @@ -370,7 +371,7 @@ Calibrator* Calibrator::make_calibrator(int argc, char** argv) // Different device/driver, different ways to apply the calibration values try { // try Usbtouchscreen driver - return new CalibratorUsbtouchscreen(device_name, device_axys, + calibrator = new CalibratorUsbtouchscreen(device_name, device_axys, thr_misclick, thr_doubleclick, output_type, geometry); } catch(WrongCalibratorException& x) { @@ -378,17 +379,26 @@ Calibrator* Calibrator::make_calibrator(int argc, char** argv) printf("DEBUG: Not usbtouchscreen calibrator: %s\n", x.what()); } - try { - // next, try Evdev driver (with XID) - return new CalibratorEvdev(device_name, device_axys, device_id, - thr_misclick, thr_doubleclick, output_type, geometry); - - } catch(WrongCalibratorException& x) { - if (verbose) - printf("DEBUG: Not evdev calibrator: %s\n", x.what()); + if (calibrator == NULL) { + try { + // next, try Evdev driver (with XID) + calibrator = new CalibratorEvdev(device_name, device_axys, device_id, + thr_misclick, thr_doubleclick, output_type, geometry); + + } catch(WrongCalibratorException& x) { + if (verbose) + printf("DEBUG: Not evdev calibrator: %s\n", x.what()); + } } // lastly, presume a standard Xorg driver (evtouch, mutouch, ...) - return new CalibratorXorgPrint(device_name, device_axys, - thr_misclick, thr_doubleclick, output_type, geometry); + if (calibrator == NULL) { + calibrator = new CalibratorXorgPrint(device_name, device_axys, + thr_misclick, thr_doubleclick, output_type, geometry); + } + + if (calibrator != NULL) + calibrator->detect_axys(); + + return calibrator; } From c2881f2127973addd42574a4ab5cb4afa2b0c3ce Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Wed, 29 Aug 2012 14:54:26 -0400 Subject: [PATCH 06/10] Make user-provided values override detected values. Previously, values specified by the user via the --precalib command-line option would be overridden by the detected values with EvdevCalibrator. Now, the detection of current parameters is not performed at all if the --precalib option was passed. --- src/calibrator.hh | 1 + src/main_common.cpp | 33 +++++++++++++-------------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/calibrator.hh b/src/calibrator.hh index 03bc213..00083dc 100644 --- a/src/calibrator.hh +++ b/src/calibrator.hh @@ -168,6 +168,7 @@ public: { clicked.num = 0; clicked.x.clear(); clicked.y.clear();} virtual void detect_axys() { return; } + void set_old_axys(XYinfo x) { old_axys = x; } /// add a click with the given coordinates bool add_click(int x, int y); diff --git a/src/main_common.cpp b/src/main_common.cpp index 64c760c..099087b 100644 --- a/src/main_common.cpp +++ b/src/main_common.cpp @@ -349,24 +349,6 @@ Calibrator* Calibrator::make_calibrator(int argc, char** argv) } } - // override min/max XY from command line ? - if (precalib) { - if (pre_axys.x.min != -1) - device_axys.x.min = pre_axys.x.min; - if (pre_axys.x.max != -1) - device_axys.x.max = pre_axys.x.max; - if (pre_axys.y.min != -1) - device_axys.y.min = pre_axys.y.min; - if (pre_axys.y.max != -1) - device_axys.y.max = pre_axys.y.max; - - if (verbose) { - printf("DEBUG: Setting precalibration: %i, %i, %i, %i\n", - device_axys.x.min, device_axys.x.max, - device_axys.y.min, device_axys.y.max); - } - } - // Different device/driver, different ways to apply the calibration values try { @@ -397,8 +379,19 @@ Calibrator* Calibrator::make_calibrator(int argc, char** argv) thr_misclick, thr_doubleclick, output_type, geometry); } - if (calibrator != NULL) - calibrator->detect_axys(); + if (calibrator != NULL) { + // override min/max XY from command line ? + if (precalib) { + if (verbose) { + printf("DEBUG: Setting precalibration: %i, %i, %i, %i\n", + pre_axys.x.min, pre_axys.x.max, + pre_axys.y.min, pre_axys.y.max); + } + calibrator->set_old_axys(pre_axys); + } else { + calibrator->detect_axys(); + } + } return calibrator; } From 49615479ad96a9af51b91c1d7fcc57f7b6b8e9ad Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Tue, 28 Aug 2012 14:07:15 -0400 Subject: [PATCH 07/10] Calibrator: Add virtual method "apply". This can be used for dynamic recalibration if the driver supports it. Currently only EvdevCalibrator provides an implementation. --- src/calibrator.cpp | 6 ++++++ src/calibrator.hh | 2 ++ src/calibrator/Evdev.cpp | 37 +++++++++++++++++++++++-------------- src/calibrator/Evdev.hpp | 2 ++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/calibrator.cpp b/src/calibrator.cpp index 735f487..977b379 100644 --- a/src/calibrator.cpp +++ b/src/calibrator.cpp @@ -47,6 +47,12 @@ Calibrator::Calibrator(const char* const device_name0, const XYinfo& axys0, //clicked.y(NUM_POINTS); } +bool Calibrator::apply(XYinfo new_axis) +{ + fprintf(stderr, "Dynamic recalibration not supported for this device.\n"); + return false; +} + bool Calibrator::add_click(int x, int y) { // Double-click detection diff --git a/src/calibrator.hh b/src/calibrator.hh index 00083dc..c29e326 100644 --- a/src/calibrator.hh +++ b/src/calibrator.hh @@ -170,6 +170,8 @@ public: virtual void detect_axys() { return; } void set_old_axys(XYinfo x) { old_axys = x; } + virtual bool apply(const XYinfo new_axys); + /// add a click with the given coordinates bool add_click(int x, int y); /// calculate and apply the calibration diff --git a/src/calibrator/Evdev.cpp b/src/calibrator/Evdev.cpp index f60e559..a823078 100644 --- a/src/calibrator/Evdev.cpp +++ b/src/calibrator/Evdev.cpp @@ -199,20 +199,7 @@ bool CalibratorEvdev::finish_data(const XYinfo new_axys) { bool success = true; - printf("\nDoing dynamic recalibration:\n"); - // Evdev Axes Swap - if (old_axys.swap_xy != new_axys.swap_xy) { - success &= set_swapxy(new_axys.swap_xy); - } - - // Evdev Axis Inversion - set_invert_xy(false, false); - - // Evdev Axis Calibration - success &= set_calibration(new_axys); - - // close - XSync(display, False); + success &= apply(new_axys); printf("\t--> Making the calibration permanent <--\n"); switch (output_type) { @@ -305,6 +292,28 @@ bool CalibratorEvdev::set_calibration(const XYinfo new_axys) return ret; } +bool CalibratorEvdev::apply(const XYinfo new_axys) +{ + bool success = true; + + printf("\nDoing dynamic recalibration:\n"); + // Evdev Axes Swap + if (old_axys.swap_xy != new_axys.swap_xy) { + success &= set_swapxy(new_axys.swap_xy); + } + + // Evdev Axis Inversion + set_invert_xy(false, false); + + // Evdev Axis Calibration + success &= set_calibration(new_axys); + + // close + XSync(display, False); + + return success; +} + Atom CalibratorEvdev::xinput_parse_atom(Display *display, const char *name) { Bool is_atom = True; diff --git a/src/calibrator/Evdev.hpp b/src/calibrator/Evdev.hpp index 96a92d7..48dea5b 100644 --- a/src/calibrator/Evdev.hpp +++ b/src/calibrator/Evdev.hpp @@ -66,6 +66,8 @@ class CalibratorEvdev: public Calibrator bool set_invert_xy(const int invert_x, const int invert_y); bool set_calibration(const XYinfo new_axys); + virtual bool apply(const XYinfo new_axys); + // xinput_ functions (from the xinput project) Atom xinput_parse_atom(Display *display, const char* name); XDeviceInfo* xinput_find_device_info(Display *display, const char* name, Bool only_extended); From 112fd9b0dfbc56eb3e358900d5817b9d12eefc99 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Wed, 29 Aug 2012 14:00:10 -0400 Subject: [PATCH 08/10] Add command-line option --reset. This forces calibration parameters to be set to the device defaults prior to calibration, which is need for accurate calibration in certain cases (i.e. when the previous values were off substantially). --- src/main_common.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main_common.cpp b/src/main_common.cpp index 099087b..9c7232d 100644 --- a/src/main_common.cpp +++ b/src/main_common.cpp @@ -202,6 +202,7 @@ Calibrator* Calibrator::make_calibrator(int argc, char** argv) bool list_devices = false; bool fake = false; bool precalib = false; + bool reset = false; XYinfo pre_axys; const char* pre_device = NULL; const char* geometry = NULL; @@ -255,6 +256,11 @@ Calibrator* Calibrator::make_calibrator(int argc, char** argv) pre_axys.y.max = atoi(argv[++i]); } else + // Get pre-calibration ? + if (strcmp("--reset", argv[i]) == 0) { + reset = true; + } else + // Get mis-click threshold ? if (strcmp("--misclick", argv[i]) == 0) { if (argc > i+1) @@ -391,6 +397,15 @@ Calibrator* Calibrator::make_calibrator(int argc, char** argv) } else { calibrator->detect_axys(); } + + if (reset) { + if (verbose) + printf("DEBUG: Resetting calibration parameters:\n"); + if (calibrator->apply(device_axys)) + calibrator->set_old_axys(device_axys); + else + fprintf(stderr, "Error: failed to reset calibration parameters.\n"); + } } return calibrator; From 7ffb2ffb1454ccb3e62034723d65f6592ef013e2 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Tue, 22 May 2012 10:21:30 -0400 Subject: [PATCH 09/10] gui_x11: Add on_key_press_event method to mirror gui_gtkmm. --- src/gui/x11.cpp | 7 ++++++- src/gui/x11.hpp | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gui/x11.cpp b/src/gui/x11.cpp index 67424ec..56721db 100644 --- a/src/gui/x11.cpp +++ b/src/gui/x11.cpp @@ -322,6 +322,11 @@ bool GuiCalibratorX11::on_button_press_event(XEvent event) return true; } +bool GuiCalibratorX11::on_key_press_event(XEvent event) +{ + exit(0); +} + void GuiCalibratorX11::draw_message(const char* msg) { int text_height = font_info->ascent + font_info->descent; @@ -360,7 +365,7 @@ void GuiCalibratorX11::give_timer_signal() break; case KeyPress: - exit(0); + instance->on_key_press_event(event); break; } } diff --git a/src/gui/x11.hpp b/src/gui/x11.hpp index 2bd4395..633bb7b 100644 --- a/src/gui/x11.hpp +++ b/src/gui/x11.hpp @@ -60,6 +60,7 @@ class GuiCalibratorX11 bool on_timer_signal(); bool on_expose_event(); bool on_button_press_event(XEvent event); + bool on_key_press_event(XEvent event); // Helper functions void set_display_size(int width, int height); From 3523a4530d9eaa3357ca0b523ed108ae16c87008 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Tue, 28 Aug 2012 16:47:37 -0400 Subject: [PATCH 10/10] Restore original calibration values on abort. --- src/calibrator.cpp | 9 ++++++++- src/calibrator.hh | 5 +++++ src/calibrator/Evdev.cpp | 2 ++ src/gui/gtkmm.cpp | 2 ++ src/gui/x11.cpp | 2 ++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/calibrator.cpp b/src/calibrator.cpp index 977b379..4185cfa 100644 --- a/src/calibrator.cpp +++ b/src/calibrator.cpp @@ -40,7 +40,7 @@ Calibrator::Calibrator(const char* const device_name0, const XYinfo& axys0, threshold_doubleclick(thr_doubleclick), threshold_misclick(thr_misclick), output_type(output_type0), geometry(geometry0) { - old_axys = axys0; + orig_axys = old_axys = axys0; clicked.num = 0; //clicked.x(NUM_POINTS); @@ -53,6 +53,13 @@ bool Calibrator::apply(XYinfo new_axis) return false; } +void Calibrator::abort() +{ + if (verbose) + printf("DEBUG: Restoring original calibration parameters:\n"); + apply(orig_axys); +} + bool Calibrator::add_click(int x, int y) { // Double-click detection diff --git a/src/calibrator.hh b/src/calibrator.hh index c29e326..cbcd3ad 100644 --- a/src/calibrator.hh +++ b/src/calibrator.hh @@ -172,6 +172,9 @@ public: virtual bool apply(const XYinfo new_axys); + // restore input device state + void abort(); + /// add a click with the given coordinates bool add_click(int x, int y); /// calculate and apply the calibration @@ -201,6 +204,8 @@ protected: const char* const device_name; /// Original values + XYinfo orig_axys; + /// Values in use during calibration XYinfo old_axys; /// Be verbose or not diff --git a/src/calibrator/Evdev.cpp b/src/calibrator/Evdev.cpp index a823078..8ee4dd6 100644 --- a/src/calibrator/Evdev.cpp +++ b/src/calibrator/Evdev.cpp @@ -192,6 +192,8 @@ void CalibratorEvdev::detect_axys() printf("\tcurrent calibration values (from XInput): min_x=%d, max_x=%d and min_y=%d, max_y=%d\n", old_axys.x.min, old_axys.x.max, old_axys.y.min, old_axys.y.max); + + orig_axys = old_axys; } // Activate calibrated data and output it diff --git a/src/gui/gtkmm.cpp b/src/gui/gtkmm.cpp index 5d2142c..aac0271 100644 --- a/src/gui/gtkmm.cpp +++ b/src/gui/gtkmm.cpp @@ -203,6 +203,7 @@ bool CalibrationArea::on_timer_signal() { time_elapsed += time_step; if (time_elapsed > max_time) { + calibrator->abort(); exit(0); } @@ -259,5 +260,6 @@ void CalibrationArea::draw_message(const char* msg) bool CalibrationArea::on_key_press_event(GdkEventKey *event) { (void) event; + calibrator->abort(); exit(0); } diff --git a/src/gui/x11.cpp b/src/gui/x11.cpp index 56721db..8c64210 100644 --- a/src/gui/x11.cpp +++ b/src/gui/x11.cpp @@ -273,6 +273,7 @@ bool GuiCalibratorX11::on_timer_signal() { time_elapsed += time_step; if (time_elapsed > max_time) { + calibrator->abort(); exit(0); } @@ -324,6 +325,7 @@ bool GuiCalibratorX11::on_button_press_event(XEvent event) bool GuiCalibratorX11::on_key_press_event(XEvent event) { + calibrator->abort(); exit(0); }