xinput-calibrator-0.7.5+git20130410/000755 001750 001750 00000000000 12273145175 017061 5ustar00warp10warp10000000 000000 xinput-calibrator-0.7.5+git20130410/src/000755 001750 001750 00000000000 12273145175 017650 5ustar00warp10warp10000000 000000 xinput-calibrator-0.7.5+git20130410/src/calibrator.hh000644 001750 001750 00000020244 12273145175 022315 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * Copyright (c) 2009 Soren Hauberg * Copyright (c) 2011 Antoine Hue * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef _calibrator_hh #define _calibrator_hh #include #include #include #include // XXX: we currently don't handle lines that are longer than this #define MAX_LINE_LEN 1024 int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min); float scaleAxis(float Cx, int to_max, int to_min, int from_max, int from_min); /* * Number of blocks. We partition the screen into 'num_blocks' x 'num_blocks' * rectangles of equal size. We then ask the user to press points that are * located at the corner closes to the center of the four blocks in the corners * of the screen. The following ascii art illustrates the situation. We partition * the screen into 8 blocks in each direction. We then let the user press the * points marked with 'O'. * * +--+--+--+--+--+--+--+--+ * | | | | | | | | | * +--O--+--+--+--+--+--O--+ * | | | | | | | | | * +--+--+--+--+--+--+--+--+ * | | | | | | | | | * +--+--+--+--+--+--+--+--+ * | | | | | | | | | * +--+--+--+--+--+--+--+--+ * | | | | | | | | | * +--+--+--+--+--+--+--+--+ * | | | | | | | | | * +--+--+--+--+--+--+--+--+ * | | | | | | | | | * +--O--+--+--+--+--+--O--+ * | | | | | | | | | * +--+--+--+--+--+--+--+--+ */ const int num_blocks = 8; struct AxisInfo { int min, max; bool invert; AxisInfo() : min(-1), max(-1), invert(false) { } AxisInfo(int mi, int ma, bool inv = false) : min(mi), max(ma), invert(inv) { } AxisInfo(const AxisInfo& old) : min(old.min), max(old.max), invert(old.invert) { } void do_invert() { invert = !invert; } }; /// struct to hold min/max info of the X and Y axis struct XYinfo { /// Axis swapped bool swap_xy; /// X, Y axis AxisInfo x, y; XYinfo() : swap_xy(false) {} XYinfo(int xmi, int xma, int ymi, int yma, bool swap_xy_ = false, bool inv_x = false, bool inv_y = false) : swap_xy(swap_xy_), x(xmi, xma, inv_x), y(ymi, yma, inv_y) {} XYinfo(const XYinfo& old) : swap_xy(old.swap_xy), x(old.x), y(old.y) {} void do_xf86ScaleAxis(const XYinfo& to, const XYinfo& from) { x.min = xf86ScaleAxis(x.min, to.x.max, to.x.min, from.x.max, from.x.min); x.max = xf86ScaleAxis(x.max, to.x.max, to.x.min, from.x.max, from.x.min); y.min = xf86ScaleAxis(y.min, to.y.max, to.y.min, from.y.max, from.y.min); y.max = xf86ScaleAxis(y.max, to.y.max, to.y.min, from.y.max, from.y.min); } 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); } }; /// Names of the points enum { UL = 0, // Upper-left UR = 1, // Upper-right LL = 2, // Lower-left LR = 3, // Lower-right NUM_POINTS }; /// Output types enum OutputType { OUTYPE_AUTO, OUTYPE_XORGCONFD, OUTYPE_HAL, OUTYPE_XINPUT }; class WrongCalibratorException : public std::invalid_argument { public: WrongCalibratorException(const std::string& msg = "") : std::invalid_argument(msg) {} }; /// Base class for calculating new calibration parameters class Calibrator { public: /// Parse arguments and create calibrator static Calibrator* make_calibrator(int argc, char** argv); /// Constructor /// /// The constructor will throw an exception, /// if the touchscreen is not of the type it supports Calibrator(const char* const device_name, const XYinfo& axys, const int thr_misclick=0, const int thr_doubleclick=0, const OutputType output_type=OUTYPE_AUTO, const char* geometry=0, const bool use_timeout=1, const char* output_filename = 0); virtual ~Calibrator() {} /// set the doubleclick treshold void set_threshold_doubleclick(int t) { threshold_doubleclick = t; } /// set the misclick treshold void set_threshold_misclick(int t) { threshold_misclick = t; } /// get the number of clicks already registered int get_numclicks() const { return clicked.num; } /// return geometry string or NULL const char* get_geometry() const { return geometry; } /// reset clicks void reset() { clicked.num = 0; clicked.x.clear(); clicked.y.clear();} /// 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); /// get the sysfs name of the device, /// returns NULL if it can not be found const char* get_sysfs_name(); const bool get_use_timeout() const { return use_timeout; } /// get output filename set at cmdline or NULL const char* get_output_filename() const { return output_filename; } protected: /// check whether the coordinates are along the respective axis bool along_axis(int xy, int x0, int y0); /// Apply new calibration, implementation dependent virtual bool finish_data(const XYinfo new_axys) =0; /// Check whether the given name is a sysfs device name bool is_sysfs_name(const char* name); /// Check whether the X server has xorg.conf.d support bool has_xorgconfd_support(Display* display=NULL); static int find_device(const char* pre_device, bool list_devices, XID& device_id, const char*& device_name, XYinfo& device_axys); protected: /// Name of the device (driver) const char* const device_name; /// Original values XYinfo old_axys; /// Be verbose or not static bool verbose; /// Clicked values (screen coordinates) struct { /// actual number of clicks registered int num; /// click coordinates std::vector x, y; } clicked; // Threshold to keep the same point from being clicked twice. // Set to zero if you don't want this check int threshold_doubleclick; // Threshold to detect mis-clicks (clicks not along axes) // A lower value forces more precise calibration // Set to zero if you don't want this check int threshold_misclick; // Type of output OutputType output_type; // manually specified geometry string const char* geometry; const bool use_timeout; // manually specified output filename const char* output_filename; // sysfs path/file static const char* SYSFS_INPUT; static const char* SYSFS_DEVNAME; }; // Interfance for a CalibratorTester class CalibratorTesterInterface { public: // emulate the driver processing the coordinates in 'raw' virtual XYinfo emulate_driver(const XYinfo& raw, bool useNewAxis, const XYinfo& screen, const XYinfo& device) = 0; virtual void new_axis_print() = 0; //* From Calibrator /// add a click with the given coordinates virtual bool add_click(int x, int y) = 0; /// calculate and apply the calibration virtual bool finish(int width, int height) = 0; }; #endif xinput-calibrator-0.7.5+git20130410/src/calibrator/000755 001750 001750 00000000000 12273145175 021772 5ustar00warp10warp10000000 000000 xinput-calibrator-0.7.5+git20130410/src/calibrator/EvdevTester.hpp000644 001750 001750 00000004674 12273145175 024756 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef CALIBRATOR_EVDEV_TESTER_HPP #define CALIBRATOR_EVDEV_TESTER_HPP #include "calibrator.hh" #include "calibrator/Evdev.hpp" /*************************************** * Class for testing the evdev * calibration routine ***************************************/ class CalibratorEvdevTester: public CalibratorTesterInterface, public CalibratorEvdev { protected: // store the new axis for use in driver emulation XYinfo new_axis; public: CalibratorEvdevTester(const char* const device_name, const XYinfo& axys, const int thr_misclick=0, const int thr_doubleclick=0, const OutputType output_type=OUTYPE_AUTO, const char* geometry=0); virtual bool finish_data(const XYinfo new_axis); // emulate the driver processing the coordinates in 'raw' virtual XYinfo emulate_driver(const XYinfo& raw, bool useNewAxis, const XYinfo& screen, const XYinfo& device); virtual void new_axis_print() { new_axis.print(); } //* From CalibratorEvdev virtual bool add_click(int x, int y) { return CalibratorEvdev::add_click(x, y); } virtual bool finish(int width, int height) { return CalibratorEvdev::finish(width, height); } // evdev 2.7.0 EvdevProcessValuators code, modified to fit us void evdev_270_processvaluator(const XYinfo& devAxis, const XYinfo& axis, int* vals); }; #endif xinput-calibrator-0.7.5+git20130410/src/calibrator/Usbtouchscreen.hpp000644 001750 001750 00000004607 12273145175 025506 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Soren Hauberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef CALIBRATOR_USBTOUCHSCREEN_HPP #define CALIBRATOR_USBTOUCHSCREEN_HPP #include "calibrator.hh" /********************************** * Class for usbtouchscreen driver, * writes output parameters to running kernel and to modprobe.conf **********************************/ class CalibratorUsbtouchscreen: public Calibrator { public: CalibratorUsbtouchscreen(const char* const device_name, const XYinfo& axys, const int thr_misclick=0, const int thr_doubleclick=0, const OutputType output_type=OUTYPE_AUTO, const char* geometry=0, const bool use_timeout=false, const char* output_filename = 0); virtual ~CalibratorUsbtouchscreen(); virtual bool finish_data(const XYinfo new_axys); protected: // Globals for kernel parameters from startup. // We revert to these if the program aborts bool val_transform_xy, val_flip_x, val_flip_y, val_swap_xy; // Helper functions char yesno(const bool value) { if (value) return 'Y'; else return 'N'; } void read_int_parameter(const char *param, int &value); void read_bool_parameter(const char *param, bool &value); void write_int_parameter(const char *param, const int value); void write_bool_parameter(const char *param, const bool value); }; #endif xinput-calibrator-0.7.5+git20130410/src/calibrator/EvdevTester.cpp000644 001750 001750 00000014427 12273145175 024746 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "calibrator/Evdev.hpp" #include "calibrator/EvdevTester.hpp" #include CalibratorEvdevTester::CalibratorEvdevTester(const char* const device_name0, const XYinfo& axys0, const int thr_misclick, const int thr_doubleclick, const OutputType output_type, const char* geometry) : CalibratorEvdev(device_name0, axys0, thr_misclick, thr_doubleclick, output_type, geometry) { //printf("Starting test driver\n"); } bool CalibratorEvdevTester::finish_data(const XYinfo axis) { new_axis = axis; return true; } XYinfo CalibratorEvdevTester::emulate_driver(const XYinfo& raw, bool useNewAxis, const XYinfo& screen, const XYinfo& device) { XYinfo calibAxis; if (useNewAxis) calibAxis = new_axis; else calibAxis = old_axys; // call evdev's code (minimally modified to fit us) int mins[2] = {raw.x.min, raw.y.min}; evdev_270_processvaluator(device, calibAxis, mins); int maxs[2] = {raw.x.max, raw.y.max}; evdev_270_processvaluator(device, calibAxis, maxs); XYinfo result(mins[0], maxs[0], mins[1], maxs[1]); // the last step is usually done by the X server, // or transparently somewhere on the way result.do_xf86ScaleAxis(screen, device); return result; } // return in 'vals' void CalibratorEvdevTester::evdev_270_processvaluator(const XYinfo& devAxis, const XYinfo& axis, int* vals) { //int vals[2] = {valX, valY}; int absinfo_min[2] = {devAxis.x.min, devAxis.y.min}; int absinfo_max[2] = {devAxis.x.max, devAxis.y.max}; /* * Code from xf86-input-evdev: src/evdev.c * function: static void EvdevProcessValuators(InputInfoPtr pInfo) * last change: 2011-12-14 'Fix absolute events with swapped axes' * last change id: 8d6dfd13b0c4177305555294218e366a6cddc83f * * All valuator_mask_isset() test can be skipped here: * its a requirement to have both X and Y coordinates */ int i; // if (pEvdev->swap_axes) { if (axis.swap_xy) { int swapped_isset[2] = {0, 0}; int swapped_values[2]; for(i = 0; i <= 1; i++) { //if (valuator_mask_isset(pEvdev->vals, i)) { swapped_isset[1 - i] = 1; /* in all sensible cases, the absinfo is the same for the * X and Y axis. In that case, the below simplifies to: * wapped_values[1 - i] = vals[i] * However, the code below accounts for the oddball * device for which this would not be the case. */ swapped_values[1 - i] = //xf86ScaleAxis(valuator_mask_get(pEvdev->vals, i), // pEvdev->absinfo[1 - i].maximum, // pEvdev->absinfo[1 - i].minimum, // pEvdev->absinfo[i].maximum, // pEvdev->absinfo[i].minimum); xf86ScaleAxis(vals[i], absinfo_max[1 - i], absinfo_min[1 - i], absinfo_max[i], absinfo_min[i]); //} } for (i = 0; i <= 1; i++) { if (swapped_isset[i]) //valuator_mask_set(pEvdev->vals, i, swapped_values[i]); vals[i] = swapped_values[i]; //else // valuator_mask_unset(pEvdev->vals, i); } } for (i = 0; i <= 1; i++) { int val; int calib_min; int calib_max; //if (!valuator_mask_isset(pEvdev->vals, i)) // continue; //val = valuator_mask_get(pEvdev->vals, i); val = vals[i]; if (i == 0) { //calib_min = pEvdev->calibration.min_x; calib_min = axis.x.min; //calib_max = pEvdev->calibration.max_x; calib_max = axis.x.max; } else { //calib_min = pEvdev->calibration.min_y; calib_min = axis.y.min; //calib_max = pEvdev->calibration.max_y; calib_max = axis.y.max; } //if (pEvdev->flags & EVDEV_CALIBRATED) if (true) //val = xf86ScaleAxis(val, pEvdev->absinfo[i].maximum, // pEvdev->absinfo[i].minimum, calib_max, // calib_min); val = xf86ScaleAxis(val, absinfo_max[i], absinfo_min[i], calib_max, 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; } //return vals; } xinput-calibrator-0.7.5+git20130410/src/calibrator/Tester.cpp000644 001750 001750 00000005076 12273145175 023754 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "calibrator/Tester.hpp" #include CalibratorTester::CalibratorTester(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) { //printf("Starting test driver\n"); } bool CalibratorTester::finish_data(const XYinfo axis) { new_axis = axis; return true; } XYinfo CalibratorTester::emulate_driver(const XYinfo& raw, bool useNewAxis, const XYinfo& screen, const XYinfo& device) { XYinfo calibAxis; if (useNewAxis) calibAxis = new_axis; else calibAxis = old_axys; /** * The most simple and intuitive calibration implementation * if only all drivers sticked to this... * Note that axis inversion is automatically supported * by the ScaleAxis implementation (swapping max/min on * one axis will result in the inversion being calculated) */ // placeholder for the new coordinates XYinfo result(raw); // swap coordinates if asked if (calibAxis.swap_xy) { result.x.min = raw.y.min; result.x.max = raw.y.max; result.y.min = raw.x.min; result.y.max = raw.x.max; } result.do_xf86ScaleAxis(device, calibAxis); // the last step is usually done by the X server, // or transparently somewhere on the way result.do_xf86ScaleAxis(screen, device); return result; } xinput-calibrator-0.7.5+git20130410/src/calibrator/Tester.hpp000644 001750 001750 00000004471 12273145175 023757 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef CALIBRATOR_TESTER_HPP #define CALIBRATOR_TESTER_HPP #include "calibrator.hh" /*************************************** * Class for testing the generic * calibration routine ***************************************/ class CalibratorTester: public CalibratorTesterInterface, public Calibrator { protected: // store the new axis for use in driver emulation XYinfo new_axis; public: CalibratorTester(const char* const device_name, const XYinfo& axys, const int thr_misclick=0, const int thr_doubleclick=0, const OutputType output_type=OUTYPE_AUTO, const char* geometry=0); virtual bool finish_data(const XYinfo new_axis); // emulate the driver processing the coordinates in 'raw' virtual XYinfo emulate_driver(const XYinfo& raw, bool useNewAxis, const XYinfo& screen, const XYinfo& device); virtual void new_axis_print() { new_axis.print(); } //* From Calibrator virtual bool add_click(int x, int y) { return Calibrator::add_click(x, y); } virtual bool finish(int width, int height) { return Calibrator::finish(width, height); } }; #endif xinput-calibrator-0.7.5+git20130410/src/calibrator/Evdev.hpp000644 001750 001750 00000006646 12273145175 023570 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * Copyright 2007 Peter Hutterer (xinput_ methods from xinput) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef CALIBRATOR_EVDEV_HPP #define CALIBRATOR_EVDEV_HPP #include "calibrator.hh" #include /*************************************** * Class for dynamic evdev calibration * uses xinput "Evdev Axis Calibration" ***************************************/ class CalibratorEvdev: public Calibrator { private: Display *display; XDeviceInfo *devInfo; XDevice *dev; protected: // protected constructor: should only be used by subclasses! // (pass-through to Calibrator) CalibratorEvdev(const char* const device_name, const XYinfo& axys, const int thr_misclick=0, const int thr_doubleclick=0, const OutputType output_type=OUTYPE_AUTO, const char* geometry=0, const bool use_timeout=false, const char* output_filename = 0); public: CalibratorEvdev(const char* const device_name, const XYinfo& axys, XID device_id=(XID)-1, const int thr_misclick=0, const int thr_doubleclick=0, const OutputType output_type=OUTYPE_AUTO, const char* geometry=0, const bool use_timeout=false, const char* output_filename = 0); virtual ~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); bool set_invert_xy(const int invert_x, const int invert_y); bool set_calibration(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); bool xinput_do_set_int_prop( const char * name, Display *display, int format, int argc, const int* argv); protected: bool output_xorgconfd(const XYinfo new_axys); bool output_hal(const XYinfo new_axys); bool output_xinput(const XYinfo new_axys); }; #endif xinput-calibrator-0.7.5+git20130410/src/calibrator/Makefile.am000644 001750 001750 00000000142 12273145175 024023 0ustar00warp10warp10000000 000000 EXTRA_DIST = \ Evdev.cpp \ Usbtouchscreen.cpp \ XorgPrint.cpp \ Tester.cpp \ EvdevTester.cpp xinput-calibrator-0.7.5+git20130410/src/calibrator/XorgPrint.cpp000644 001750 001750 00000015662 12273145175 024444 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "calibrator/XorgPrint.hpp" #include CalibratorXorgPrint::CalibratorXorgPrint(const char* const device_name0, const XYinfo& axys0, const int thr_misclick, const int thr_doubleclick, const OutputType output_type, const char* geometry, const bool use_timeout, const char* output_filename) : Calibrator(device_name0, axys0, thr_misclick, thr_doubleclick, output_type, geometry, use_timeout, output_filename) { printf("Calibrating standard Xorg driver \"%s\"\n", device_name); printf("\tcurrent calibration values: 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); printf("\tIf these values are estimated wrong, either supply it manually with the --precalib option, or run the 'get_precalib.sh' script to automatically get it (through HAL).\n"); } bool CalibratorXorgPrint::finish_data(const XYinfo new_axys) { bool success = true; printf("\t--> Making the calibration permanent <--\n"); switch (output_type) { case OUTYPE_AUTO: // xorg.conf.d or alternatively hal config if (has_xorgconfd_support()) { success &= output_xorgconfd(new_axys); } else { success &= output_hal(new_axys); } break; case OUTYPE_XORGCONFD: success &= output_xorgconfd(new_axys); break; case OUTYPE_HAL: success &= output_hal(new_axys); break; default: fprintf(stderr, "ERROR: XorgPrint Calibrator does not support the supplied --output-type\n"); success = false; } return success; } bool CalibratorXorgPrint::output_xorgconfd(const XYinfo new_axys) { const char* sysfs_name = get_sysfs_name(); bool not_sysfs_name = (sysfs_name == NULL); if (not_sysfs_name) sysfs_name = "!!Name_Of_TouchScreen!!"; if(output_filename == NULL || not_sysfs_name) printf(" copy the snippet below into '/etc/X11/xorg.conf.d/99-calibration.conf' (/usr/share/X11/xorg.conf.d/ in some distro's)\n"); else printf(" writing calibration script to '%s'\n", output_filename); // xorg.conf.d snippet char line[MAX_LINE_LEN]; std::string outstr; outstr += "Section \"InputClass\"\n"; outstr += " Identifier \"calibration\"\n"; sprintf(line, " MatchProduct \"%s\"\n", sysfs_name); outstr += line; sprintf(line, " Option \"MinX\" \"%d\"\n", new_axys.x.min); outstr += line; sprintf(line, " Option \"MaxX\" \"%d\"\n", new_axys.x.max); outstr += line; sprintf(line, " Option \"MinY\" \"%d\"\n", new_axys.y.min); outstr += line; sprintf(line, " Option \"MaxY\" \"%d\"\n", new_axys.y.max); outstr += line; sprintf(line, " Option \"SwapXY\" \"%d\" # unless it was already set to 1\n", new_axys.swap_xy); outstr += line; sprintf(line, " Option \"InvertX\" \"%d\" # unless it was already set\n", new_axys.x.invert); outstr += line; sprintf(line, " Option \"InvertY\" \"%d\" # unless it was already set\n", new_axys.y.invert); outstr += line; outstr += "EndSection\n"; // console out printf("%s", outstr.c_str()); if (not_sysfs_name) printf("\nChange '%s' to your device's name in the config above.\n", sysfs_name); // file out else if(output_filename != NULL) { FILE* fid = fopen(output_filename, "w"); if (fid == NULL) { fprintf(stderr, "Error: Can't open '%s' for writing. Make sure you have the necessary rights\n", output_filename); fprintf(stderr, "New calibration data NOT saved\n"); return false; } fprintf(fid, "%s", outstr.c_str()); fclose(fid); } return true; } bool CalibratorXorgPrint::output_hal(const XYinfo new_axys) { const char* sysfs_name = get_sysfs_name(); bool not_sysfs_name = (sysfs_name == NULL); if (not_sysfs_name) sysfs_name = "!!Name_Of_TouchScreen!!"; if(output_filename == NULL || not_sysfs_name) printf(" copy the policy below into '/etc/hal/fdi/policy/touchscreen.fdi'\n"); else printf(" writing HAL calibration data to '%s'\n", output_filename); // HAL policy output char line[MAX_LINE_LEN]; std::string outstr; sprintf(line, "\n", sysfs_name); outstr += line; sprintf(line, " %d\n", new_axys.x.min); outstr += line; sprintf(line, " %d\n", new_axys.x.max); outstr += line; sprintf(line, " %d\n", new_axys.y.min); outstr += line; sprintf(line, " %d\n", new_axys.y.max); outstr += line; sprintf(line, " %d\n", new_axys.swap_xy); outstr += line; sprintf(line, " %d\n", new_axys.x.invert); outstr += line; sprintf(line, " %d\n", new_axys.y.invert); outstr += line; outstr += "\n"; // console out printf("%s", outstr.c_str()); if (not_sysfs_name) printf("\nChange '%s' to your device's name in the config above.\n", sysfs_name); // file out else if(output_filename != NULL) { FILE* fid = fopen(output_filename, "w"); if (fid == NULL) { fprintf(stderr, "Error: Can't open '%s' for writing. Make sure you have the necessary rights\n", output_filename); fprintf(stderr, "New calibration data NOT saved\n"); return false; } fprintf(fid, "%s", outstr.c_str()); fclose(fid); } return true; } xinput-calibrator-0.7.5+git20130410/src/calibrator/Usbtouchscreen.cpp000644 001750 001750 00000017133 12273145175 025477 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Soren Hauberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "calibrator/Usbtouchscreen.hpp" #include #include #include /************************* * Variables for usbtouchscreen specifically *************************/ // The file to which the calibration parameters are saved. // (XXX: is this distribution dependend?) static const char *modprobe_conf_local = "/etc/modprobe.conf.local"; // Prefix to the kernel path where we can set the parameters static const char *module_prefix = "/sys/module/usbtouchscreen/parameters"; // Names of kernel parameters static const char *p_range_x = "range_x"; static const char *p_range_y = "range_y"; static const char *p_min_x = "min_x"; static const char *p_min_y = "min_y"; static const char *p_max_x = "max_x"; static const char *p_max_y = "max_y"; static const char *p_transform_xy = "transform_xy"; static const char *p_flip_x = "flip_x"; static const char *p_flip_y = "flip_y"; static const char *p_swap_xy = "swap_xy"; CalibratorUsbtouchscreen::CalibratorUsbtouchscreen(const char* const device_name0, const XYinfo& axys0, const int thr_misclick, const int thr_doubleclick, const OutputType output_type, const char* geometry, const bool use_timeout, const char* output_filename) : Calibrator(device_name0, axys0, thr_misclick, thr_doubleclick, output_type, geometry, use_timeout, output_filename) { if (strcmp(device_name, "Usbtouchscreen") != 0) throw WrongCalibratorException("Not a usbtouchscreen device"); // Reset the currently running kernel read_bool_parameter(p_transform_xy, val_transform_xy); read_bool_parameter(p_flip_x, val_flip_x); read_bool_parameter(p_flip_y, val_flip_y); read_bool_parameter(p_swap_xy, val_swap_xy); write_bool_parameter(p_transform_xy, false); write_bool_parameter(p_flip_x, false); write_bool_parameter(p_flip_y, false); write_bool_parameter(p_swap_xy, false); printf("Calibrating Usbtouchscreen, through the kernel module\n"); } CalibratorUsbtouchscreen::~CalibratorUsbtouchscreen() { // Dirty exit, so we restore the parameters of the running kernel write_bool_parameter (p_transform_xy, val_transform_xy); write_bool_parameter (p_flip_x, val_flip_x); write_bool_parameter (p_flip_y, val_flip_y); write_bool_parameter (p_swap_xy, val_swap_xy); } bool CalibratorUsbtouchscreen::finish_data(const XYinfo new_axys) { if (output_type != OUTYPE_AUTO) { fprintf(stderr, "ERROR: Usbtouchscreen Calibrator does not support the supplied --output-type\n"); return false; } // New ranges const int range_x = (new_axys.x.max - new_axys.x.min); const int range_y = (new_axys.y.max - new_axys.y.min); // Should x and y be flipped ? const bool flip_x = (new_axys.x.min > new_axys.x.max); const bool flip_y = (new_axys.y.min > new_axys.y.max); // Send the estimated parameters to the currently running kernel write_int_parameter(p_range_x, range_x); write_int_parameter(p_range_y, range_y); write_int_parameter(p_min_x, new_axys.x.min); write_int_parameter(p_max_x, new_axys.x.max); write_int_parameter(p_min_y, new_axys.y.min); write_int_parameter(p_max_y, new_axys.y.max); write_bool_parameter(p_transform_xy, true); write_bool_parameter(p_flip_x, flip_x); write_bool_parameter(p_flip_y, flip_y); write_bool_parameter(p_swap_xy, new_axys.swap_xy); // Read, then write calibration parameters to modprobe_conf_local, // or the file set by --output-filename to keep the for the next boot const char* filename = output_filename == NULL ? modprobe_conf_local : output_filename; FILE *fid = fopen(filename, "r"); if (fid == NULL) { fprintf(stderr, "Error: Can't open '%s' for reading. Make sure you have the necessary rights\n", filename); fprintf(stderr, "New calibration data NOT saved\n"); return false; } std::string new_contents; const int len = MAX_LINE_LEN; char line[len]; const char *opt = "options usbtouchscreen"; const int opt_len = strlen(opt); while (fgets(line, len, fid)) { if (strncmp(line, opt, opt_len) == 0) { // This is the line we want to remove continue; } new_contents += line; } fclose(fid); char *new_opt = new char[opt_len]; 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", opt, p_range_x, range_x, p_range_y, range_y, p_min_x, new_axys.x.min, p_min_y, new_axys.y.min, p_max_x, new_axys.x.max, p_max_y, new_axys.y.max, p_transform_xy, yesno(true), p_flip_x, yesno(flip_x), p_flip_y, yesno(flip_y), p_swap_xy, yesno(new_axys.swap_xy)); new_contents += new_opt; fid = fopen(filename, "w"); if (fid == NULL) { fprintf(stderr, "Error: Can't open '%s' for writing. Make sure you have the necessary rights\n", filename); fprintf(stderr, "New calibration data NOT saved\n"); return false; } fprintf(fid, "%s", new_contents.c_str ()); fclose(fid); return true; } void CalibratorUsbtouchscreen::read_int_parameter(const char *param, int &value) { int dummy; char filename[100]; sprintf(filename, "%s/%s", module_prefix, param); FILE *fid = fopen(filename, "r"); if (fid == NULL) { fprintf(stderr, "Could not read parameter '%s'\n", param); return; } dummy = fscanf(fid, "%d", &value); fclose(fid); } void CalibratorUsbtouchscreen::read_bool_parameter(const char *param, bool &value) { char *dummy; char filename[100]; sprintf(filename, "%s/%s", module_prefix, param); FILE *fid = fopen(filename, "r"); if (fid == NULL) { fprintf(stderr, "Could not read parameter '%s'\n", param); return; } char val[3]; dummy = fgets(val, 2, fid); fclose(fid); value = (val[0] == yesno(true)); } void CalibratorUsbtouchscreen::write_int_parameter(const char *param, const int value) { char filename[100]; sprintf(filename, "%s/%s", module_prefix, param); FILE *fid = fopen(filename, "w"); if (fid == NULL) { fprintf(stderr, "Could not save parameter '%s'\n", param); return; } fprintf(fid, "%d", value); fclose(fid); } void CalibratorUsbtouchscreen::write_bool_parameter(const char *param, const bool value) { char filename[100]; sprintf(filename, "%s/%s", module_prefix, param); FILE *fid = fopen(filename, "w"); if (fid == NULL) { fprintf(stderr, "Could not save parameter '%s'\n", param); return; } fprintf(fid, "%c", yesno (value)); fclose(fid); } xinput-calibrator-0.7.5+git20130410/src/calibrator/XorgPrint.hpp000644 001750 001750 00000003536 12273145175 024446 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef CALIBRATOR_XORGPRINT_HPP #define CALIBRATOR_XORGPRINT_HPP #include "calibrator.hh" /*************************************** * Class for generic Xorg driver, * outputs new Xorg.conf and FDI policy, on stdout ***************************************/ class CalibratorXorgPrint: public Calibrator { public: CalibratorXorgPrint(const char* const device_name, const XYinfo& axys, const int thr_misclick=0, const int thr_doubleclick=0, const OutputType output_type=OUTYPE_AUTO, const char* geometry=0, const bool use_timeout=false, const char* output_filename = 0); virtual bool finish_data(const XYinfo new_axys); protected: bool output_xorgconfd(const XYinfo new_axys); bool output_hal(const XYinfo new_axys); }; #endif xinput-calibrator-0.7.5+git20130410/src/calibrator/Evdev.cpp000644 001750 001750 00000052051 12273145175 023552 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * Copyright 2007 Peter Hutterer (xinput_ methods from xinput) * Copyright (c) 2011 Antoine Hue (invertX/Y) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "calibrator/Evdev.hpp" #include #include #include #include #include #include #include #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 1 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 0 #endif // Constructor CalibratorEvdev::CalibratorEvdev(const char* const device_name0, const XYinfo& axys0, XID device_id, const int thr_misclick, const int thr_doubleclick, const OutputType output_type, const char* geometry, const bool use_timeout, const char* output_filename) : Calibrator(device_name0, axys0, thr_misclick, thr_doubleclick, output_type, geometry, use_timeout, output_filename) { // init display = XOpenDisplay(NULL); if (display == NULL) { throw WrongCalibratorException("Evdev: Unable to connect to X server"); } // normaly, we already have the device id if (device_id == (XID)-1) { devInfo = xinput_find_device_info(display, device_name, False); if (!devInfo) { XCloseDisplay(display); throw WrongCalibratorException("Evdev: Unable to find device"); } device_id = devInfo->id; } dev = XOpenDevice(display, device_id); if (!dev) { XCloseDisplay(display); throw WrongCalibratorException("Evdev: Unable to open device"); } #ifndef HAVE_XI_PROP throw WrongCalibratorException("Evdev: you need at least libXi 1.2 and inputproto 1.5 for dynamic recalibration of evdev."); #else // 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) { 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"); } 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); } XFree(data); } // get "Evdev Axes Swap" property property = xinput_parse_atom(display, "Evdev Axes Swap"); if (XGetDeviceProperty(display, dev, property, 0, 1000, False, AnyPropertyType, &act_type, &act_format, &nitems, &bytes_after, &data) == Success) { if (act_format == 8 && act_type == XA_INTEGER && nitems == 1) { old_axys.swap_xy = *((char*)data); if (verbose) printf("DEBUG: Read axes swap value of %i.\n", old_axys.swap_xy); } } // get "Evdev Axes Inversion" property property = xinput_parse_atom(display, "Evdev Axis Inversion"); if (XGetDeviceProperty(display, dev, property, 0, 1000, False, 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); if (verbose) printf("DEBUG: Read InvertX=%i, InvertY=%i.\n", old_axys.x.invert, old_axys.y.invert); } } 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, const bool use_timeout, const char* output_filename) : Calibrator(device_name0, axys0, thr_misclick, thr_doubleclick, output_type, geometry, output_filename) { } // Destructor CalibratorEvdev::~CalibratorEvdev () { XCloseDevice(display, dev); 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; // 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; 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) { 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 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 Calibration success &= set_calibration(new_axys); // close XSync(display, False); printf("\t--> Making the calibration permanent <--\n"); switch (output_type) { case OUTYPE_AUTO: // xorg.conf.d or alternatively xinput commands if (has_xorgconfd_support()) { success &= output_xorgconfd(new_axys); } else { success &= output_xinput(new_axys); } break; case OUTYPE_XORGCONFD: success &= output_xorgconfd(new_axys); break; case OUTYPE_HAL: success &= output_hal(new_axys); break; case OUTYPE_XINPUT: success &= output_xinput(new_axys); break; default: fprintf(stderr, "ERROR: Evdev Calibrator does not support the supplied --output-type\n"); success = false; } return success; } bool CalibratorEvdev::set_swapxy(const int swap_xy) { printf("\tSwapping X and Y axis...\n"); // xinput set-int-prop "divername" "Evdev Axes Swap" 8 0 int arr_cmd[1]; arr_cmd[0] = swap_xy; bool ret = xinput_do_set_int_prop("Evdev Axes Swap", display, 8, 1, arr_cmd); if (verbose) { if (ret == true) printf("DEBUG: Successfully set swapped X and Y axes = %d.\n", swap_xy); else printf("DEBUG: Failed to set swap X and Y axes.\n"); } return ret; } bool CalibratorEvdev::set_invert_xy(const int invert_x, const int invert_y) { printf("\tInverting X and/or Y axis...\n"); // xinput set-int-prop "divername" "Evdev Axis Inversion" 8 0 0 int arr_cmd[2]; arr_cmd[0] = invert_x; arr_cmd[1] = invert_y; int ret = xinput_do_set_int_prop("Evdev Axis Inversion", display, 8, 2, arr_cmd); if (verbose) { if (ret == true) printf("DEBUG: Successfully set invert axis X=%d, Y=%d.\n", invert_x, invert_y); else printf("DEBUG: Failed to set axis inversion.\n"); } return ret; } bool CalibratorEvdev::set_calibration(const XYinfo new_axys) { printf("\tSetting calibration data: %d, %d, %d, %d\n", new_axys.x.min, new_axys.x.max, new_axys.y.min, new_axys.y.max); // xinput set-int-prop 4 223 32 5 500 8 300 int arr_cmd[4]; arr_cmd[0] = new_axys.x.min; arr_cmd[1] = new_axys.x.max; arr_cmd[2] = new_axys.y.min; arr_cmd[3] = new_axys.y.max; int ret = xinput_do_set_int_prop("Evdev Axis Calibration", display, 32, 4, arr_cmd); if (verbose) { if (ret == true) printf("DEBUG: Successfully applied axis calibration.\n"); else printf("DEBUG: Failed to apply axis calibration.\n"); } return ret; } Atom CalibratorEvdev::xinput_parse_atom(Display *display, const char *name) { Bool is_atom = True; int i; for (i = 0; name[i] != '\0'; i++) { if (!isdigit(name[i])) { is_atom = False; break; } } if (is_atom) return atoi(name); else return XInternAtom(display, name, False); } XDeviceInfo* CalibratorEvdev::xinput_find_device_info( Display *display, const char *name, Bool only_extended) { XDeviceInfo *devices; XDeviceInfo *found = NULL; int loop; int num_devices; int len = strlen(name); Bool is_id = True; XID id = (XID)-1; for (loop=0; loop= IsXExtensionDevice)) && ((!is_id && strcmp(devices[loop].name, name) == 0) || (is_id && devices[loop].id == id))) { if (found) { fprintf(stderr, "Warning: There are multiple devices named \"%s\".\n" "To ensure the correct one is selected, please use " "the device ID instead.\n\n", name); return NULL; } else { found = &devices[loop]; } } } return found; } // Set Integer property on X bool CalibratorEvdev::xinput_do_set_int_prop( const char * name, Display *display, int format, int argc, const int *argv ) { #ifndef HAVE_XI_PROP return false; #else Atom prop; Atom old_type; int i; int old_format; unsigned long act_nitems, bytes_after; union { unsigned char *c; short *s; long *l; Atom *a; } data; if (argc < 1) { fprintf(stderr, "Wrong usage of xinput_do_set_prop, need at least 1 arguments\n"); return false; } prop = xinput_parse_atom(display, name); if (prop == None) { fprintf(stderr, "invalid property %s\n", name); return false; } if ( format == 0) { if (XGetDeviceProperty(display, dev, prop, 0, 0, False, AnyPropertyType, &old_type, &old_format, &act_nitems, &bytes_after, &data.c) != Success) { fprintf(stderr, "failed to get property type and format for %s\n", name); return false; } else { format = old_format; } XFree(data.c); } data.c = (unsigned char*)calloc(argc, sizeof(long)); for (i = 0; i < argc; i++) { switch (format) { case 8: data.c[i] = argv[i]; case 16: data.s[i] = argv[i]; break; case 32: data.l[i] = argv[i]; break; default: fprintf(stderr, "unexpected size for property %s\n", name); return false; } } XChangeDeviceProperty(display, dev, prop, XA_INTEGER, format, PropModeReplace, data.c, argc); free(data.c); return true; #endif // HAVE_XI_PROP } bool CalibratorEvdev::output_xorgconfd(const XYinfo new_axys) { const char* sysfs_name = get_sysfs_name(); bool not_sysfs_name = (sysfs_name == NULL); if (not_sysfs_name) sysfs_name = "!!Name_Of_TouchScreen!!"; if(output_filename == NULL || not_sysfs_name) printf(" copy the snippet below into '/etc/X11/xorg.conf.d/99-calibration.conf' (/usr/share/X11/xorg.conf.d/ in some distro's)\n"); else printf(" writing xorg.conf calibration data to '%s'\n", output_filename); // xorg.conf.d snippet char line[MAX_LINE_LEN]; std::string outstr; outstr += "Section \"InputClass\"\n"; outstr += " Identifier \"calibration\"\n"; sprintf(line, " MatchProduct \"%s\"\n", sysfs_name); outstr += line; sprintf(line, " Option \"Calibration\" \"%d %d %d %d\"\n", new_axys.x.min, new_axys.x.max, new_axys.y.min, new_axys.y.max); outstr += line; sprintf(line, " Option \"SwapAxes\" \"%d\"\n", new_axys.swap_xy); outstr += line; outstr += "EndSection\n"; // console out printf("%s", outstr.c_str()); if (not_sysfs_name) printf("\nChange '%s' to your device's name in the snippet above.\n", sysfs_name); // file out else if(output_filename != NULL) { FILE* fid = fopen(output_filename, "w"); if (fid == NULL) { fprintf(stderr, "Error: Can't open '%s' for writing. Make sure you have the necessary rights\n", output_filename); fprintf(stderr, "New calibration data NOT saved\n"); return false; } fprintf(fid, "%s", outstr.c_str()); fclose(fid); } return true; } bool CalibratorEvdev::output_hal(const XYinfo new_axys) { const char* sysfs_name = get_sysfs_name(); bool not_sysfs_name = (sysfs_name == NULL); if (not_sysfs_name) sysfs_name = "!!Name_Of_TouchScreen!!"; if(output_filename == NULL || not_sysfs_name) printf(" copy the policy below into '/etc/hal/fdi/policy/touchscreen.fdi'\n"); else printf(" writing HAL calibration data to '%s'\n", output_filename); // HAL policy output char line[MAX_LINE_LEN]; std::string outstr; sprintf(line, "\n", sysfs_name); outstr += line; sprintf(line, " %d %d %d %d\n", new_axys.x.min, new_axys.x.max, new_axys.y.min, new_axys.y.max); outstr += line; sprintf(line, " %d\n", new_axys.swap_xy); outstr += "\n"; // console out printf("%s", outstr.c_str()); if (not_sysfs_name) printf("\nChange '%s' to your device's name in the config above.\n", sysfs_name); // file out else if(output_filename != NULL) { FILE* fid = fopen(output_filename, "w"); if (fid == NULL) { fprintf(stderr, "Error: Can't open '%s' for writing. Make sure you have the necessary rights\n", output_filename); fprintf(stderr, "New calibration data NOT saved\n"); return false; } fprintf(fid, "%s", outstr.c_str()); fclose(fid); } return true; } bool CalibratorEvdev::output_xinput(const XYinfo new_axys) { if(output_filename == NULL) printf(" Install the 'xinput' tool and copy the command(s) below in a script that starts with your X session\n"); else printf(" writing calibration script to '%s'\n", output_filename); // create startup script char line[MAX_LINE_LEN]; std::string outstr; sprintf(line, " xinput set-int-prop \"%s\" \"Evdev Axis Calibration\" 32 %d %d %d %d\n", device_name, new_axys.x.min, new_axys.x.max, new_axys.y.min, new_axys.y.max); outstr += line; sprintf(line, " xinput set-int-prop \"%s\" \"Evdev Axes Swap\" 8 %d\n", device_name, new_axys.swap_xy); outstr += line; // console out printf("%s", outstr.c_str()); // file out if(output_filename != NULL) { FILE* fid = fopen(output_filename, "w"); if (fid == NULL) { fprintf(stderr, "Error: Can't open '%s' for writing. Make sure you have the necessary rights\n", output_filename); fprintf(stderr, "New calibration data NOT saved\n"); return false; } fprintf(fid, "%s", outstr.c_str()); fclose(fid); } return true; } xinput-calibrator-0.7.5+git20130410/src/calibrator.cpp000644 001750 001750 00000026156 12273145175 022510 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * Copyright (c) 2009 Soren Hauberg * Copyright (c) 2011 Antoine Hue * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include "calibrator.hh" // static instances bool Calibrator::verbose = false; const char* Calibrator::SYSFS_INPUT="/sys/class/input"; const char* Calibrator::SYSFS_DEVNAME="device/name"; Calibrator::Calibrator(const char* const device_name0, const XYinfo& axys0, const int thr_misclick, const int thr_doubleclick, const OutputType output_type0, const char* geometry0, const bool use_timeout0, const char* output_filename0) : device_name(device_name0), threshold_doubleclick(thr_doubleclick), threshold_misclick(thr_misclick), output_type(output_type0), geometry(geometry0), use_timeout(use_timeout0), output_filename(output_filename0) { old_axys = axys0; clicked.num = 0; //clicked.x(NUM_POINTS); //clicked.y(NUM_POINTS); } bool Calibrator::add_click(int x, int y) { // Double-click detection if (threshold_doubleclick > 0 && clicked.num > 0) { int i = clicked.num - 1; while (i >= 0) { if (abs(x - clicked.x[i]) <= threshold_doubleclick && abs(y - clicked.y[i]) <= threshold_doubleclick) { if (verbose) { printf("DEBUG: Not adding click %i (X=%i, Y=%i): within %i pixels of previous click\n", clicked.num, x, y, threshold_doubleclick); } return false; } i--; } } // Mis-click detection if (threshold_misclick > 0 && clicked.num > 0) { bool misclick = true; switch (clicked.num) { case 1: // check that along one axis of first point if (along_axis(x,clicked.x[UL],clicked.y[UL]) || along_axis(y,clicked.x[UL],clicked.y[UL])) { misclick = false; } else if (verbose) { printf("DEBUG: Mis-click detected, click %i (X=%i, Y=%i) not aligned with click 0 (X=%i, Y=%i) (threshold=%i)\n", clicked.num, x, y, clicked.x[UL], clicked.y[UL], threshold_misclick); } break; case 2: // check that along other axis of first point than second point if ((along_axis( y, clicked.x[UL], clicked.y[UL]) && along_axis( clicked.x[UR], clicked.x[UL], clicked.y[UL])) || (along_axis( x, clicked.x[UL], clicked.y[UL]) && along_axis( clicked.y[UR], clicked.x[UL], clicked.y[UL]))) { misclick = false; } else if (verbose) { printf("DEBUG: Mis-click detected, click %i (X=%i, Y=%i) not aligned with click 0 (X=%i, Y=%i) or click 1 (X=%i, Y=%i) (threshold=%i)\n", clicked.num, x, y, clicked.x[UL], clicked.y[UL], clicked.x[UR], clicked.y[UR], threshold_misclick); } break; case 3: // check that along both axis of second and third point if ( ( along_axis( x, clicked.x[UR], clicked.y[UR]) && along_axis( y, clicked.x[LL], clicked.y[LL]) ) ||( along_axis( y, clicked.x[UR], clicked.y[UR]) && along_axis( x, clicked.x[LL], clicked.y[LL]) ) ) { misclick = false; } else if (verbose) { printf("DEBUG: Mis-click detected, click %i (X=%i, Y=%i) not aligned with click 1 (X=%i, Y=%i) or click 2 (X=%i, Y=%i) (threshold=%i)\n", clicked.num, x, y, clicked.x[UR], clicked.y[UR], clicked.x[LL], clicked.y[LL], threshold_misclick); } } if (misclick) { reset(); return false; } } clicked.x.push_back(x); clicked.y.push_back(y); clicked.num++; if (verbose) printf("DEBUG: Adding click %i (X=%i, Y=%i)\n", clicked.num-1, x, y); return true; } inline bool Calibrator::along_axis(int xy, int x0, int y0) { return ((abs(xy - x0) <= threshold_misclick) || (abs(xy - y0) <= threshold_misclick)); } bool Calibrator::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); } const char* Calibrator::get_sysfs_name() { if (is_sysfs_name(device_name)) return device_name; // TODO: more mechanisms return NULL; } bool Calibrator::is_sysfs_name(const char* name) { DIR* dp = opendir(SYSFS_INPUT); if (dp == NULL) return false; while (dirent* ep = readdir(dp)) { if (strncmp(ep->d_name, "event", strlen("event")) == 0) { // got event name, get its sysfs device name char filename[40]; // actually 35, but hey... (void) sprintf(filename, "%s/%s/%s", SYSFS_INPUT, ep->d_name, SYSFS_DEVNAME); std::ifstream ifile(filename); if (ifile.is_open()) { if (!ifile.eof()) { std::string devname; std::getline(ifile, devname); if (devname == name) { if (verbose) printf("DEBUG: Found that '%s' is a sysfs name.\n", name); return true; } } ifile.close(); } } } (void) closedir(dp); if (verbose) printf("DEBUG: Name '%s' does not match any in '%s/event*/%s'\n", name, SYSFS_INPUT, SYSFS_DEVNAME); return false; } bool Calibrator::has_xorgconfd_support(Display* dpy) { bool has_support = false; Display* display = dpy; if (dpy == NULL) // no connection to reuse display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Unable to connect to X server\n"); exit(1); } if (strstr(ServerVendor(display), "X.Org") && VendorRelease(display) >= 10800000) { has_support = true; } if (dpy == NULL) // no connection to reuse XCloseDisplay(display); return has_support; } /* * FROM xf86Xinput.c * * Cx - raw data from touch screen * to_max - scaled highest dimension * (remember, this is of rows - 1 because of 0 origin) * to_min - scaled lowest dimension * from_max - highest raw value from touch screen calibration * from_min - lowest raw value from touch screen calibration * * This function is the same for X or Y coordinates. * You may have to reverse the high and low values to compensate for * different orgins on the touch screen vs X. * * e.g. to scale from device coordinates into screen coordinates, call * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); */ int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min) { int X; int64_t to_width = to_max - to_min; int64_t from_width = from_max - from_min; if (from_width) { X = (int) (((to_width * (Cx - from_min)) / from_width) + to_min); } else { X = 0; printf("Divide by Zero in xf86ScaleAxis\n"); exit(1); } if (X > to_max) X = to_max; if (X < to_min) X = to_min; return X; } // same but without rounding to min/max float scaleAxis(float Cx, int to_max, int to_min, int from_max, int from_min) { float X; int64_t to_width = to_max - to_min; int64_t from_width = from_max - from_min; if (from_width) { X = (((to_width * (Cx - from_min)) / from_width) + to_min); } else { X = 0; printf("Divide by Zero in scaleAxis\n"); exit(1); } /* no rounding to max/min if (X > to_max) X = to_max; if (X < to_min) X = to_min; */ return X; } xinput-calibrator-0.7.5+git20130410/src/main_gtkmm.cpp000644 001750 001750 00000004124 12273145175 022500 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * Copyright (c) 2009 Soren Hauberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Must be before Xlib stuff #include #include #include #include "calibrator.hh" #include "gui/gtkmm.hpp" int main(int argc, char** argv) { Calibrator* calibrator = Calibrator::make_calibrator(argc, argv); // GTK-mm setup Gtk::Main kit(argc, argv); Glib::RefPtr< Gdk::Screen > screen = Gdk::Screen::get_default(); //int num_monitors = screen->get_n_monitors(); TODO, multiple monitors? Gdk::Rectangle rect; screen->get_monitor_geometry(0, rect); Gtk::Window win; // when no window manager: explicitely take size of full screen win.move(rect.get_x(), rect.get_y()); win.resize(rect.get_width(), rect.get_height()); // in case of window manager: set as full screen to hide window decorations win.fullscreen(); CalibrationArea area(calibrator); win.add(area); area.show(); Gtk::Main::run(win); Gtk::Main::quit(); delete calibrator; return 0; } xinput-calibrator-0.7.5+git20130410/src/main_common.cpp000644 001750 001750 00000036346 12273145175 022664 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * Copyright (c) 2009 Soren Hauberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "calibrator.hh" // Calibrator implementations #include "calibrator/Usbtouchscreen.hpp" #include "calibrator/Evdev.hpp" #include "calibrator/XorgPrint.hpp" #include #include #include #include #include #include #include // strdup: non-ansi static char* my_strdup(const char* s) { size_t len = strlen(s) + 1; void* p = malloc(len); if (p == NULL) return NULL; return (char*) memcpy(p, s, len); } /** * find a calibratable touchscreen device (using XInput) * * if pre_device is NULL, the last calibratable device is selected. * retuns number of devices found, * the data of the device is returned in the last 3 function parameters */ int Calibrator::find_device(const char* pre_device, bool list_devices, XID& device_id, const char*& device_name, XYinfo& device_axys) { bool pre_device_is_id = true; bool pre_device_is_sysfs = false; int found = 0; Display* display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Unable to connect to X server\n"); exit(1); } int xi_opcode, event, error; if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) { fprintf(stderr, "X Input extension not available.\n"); exit(1); } // verbose, get Xi version if (verbose) { XExtensionVersion *version = XGetExtensionVersion(display, INAME); if (version && (version != (XExtensionVersion*) NoSuchExtension)) { printf("DEBUG: %s version is %i.%i\n", INAME, version->major_version, version->minor_version); XFree(version); } } if (pre_device != NULL) { // check whether the pre_device is an ID (only digits) int len = strlen(pre_device); for (int loop=0; loopuse == IsXKeyboard || list->use == IsXPointer) // virtual master device continue; // if we are looking for a specific device if (pre_device != NULL) { if ((pre_device_is_id && list->id == (XID) atoi(pre_device)) || (!pre_device_is_id && strcmp(list->name, pre_device_is_sysfs ? pre_device_sysfs.c_str() : pre_device ) == 0)) { // OK, fall through } else { // skip, not this device continue; } } XAnyClassPtr any = (XAnyClassPtr) (list->inputclassinfo); for (int j=0; jnum_classes; j++) { if (any->c_class == ValuatorClass) { XValuatorInfoPtr V = (XValuatorInfoPtr) any; XAxisInfoPtr ax = (XAxisInfoPtr) V->axes; 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); } } /* * Increment 'any' to point to the next item in the linked * list. The length is in bytes, so 'any' must be cast to * a character pointer before being incremented. */ any = (XAnyClassPtr) ((char *) any + any->length); } } XFreeDeviceList(slist); XCloseDisplay(display); return found; } static void usage(char* cmd, unsigned thr_misclick) { fprintf(stderr, "Usage: %s [-h|--help] [-v|--verbose] [--list] [--device ] [--precalib ] [--misclick ] [--output-type ] [--fake] [--geometry x] [--no-timeout]\n", cmd); fprintf(stderr, "\t-h, --help: print this help message\n"); fprintf(stderr, "\t-v, --verbose: print debug messages during the process\n"); fprintf(stderr, "\t--list: list calibratable input devices and quit\n"); fprintf(stderr, "\t--device : select a specific device to calibrate\n"); fprintf(stderr, "\t--precalib: manually provide the current calibration setting (eg. the values in xorg.conf)\n"); fprintf(stderr, "\t--misclick: set the misclick threshold (0=off, default: %i pixels)\n", thr_misclick); fprintf(stderr, "\t--output-type : type of config to ouput (auto=automatically detect, default: auto)\n"); fprintf(stderr, "\t--fake: emulate a fake device (for testing purposes)\n"); fprintf(stderr, "\t--geometry: manually provide the geometry (width and height) for the calibration window\n"); fprintf(stderr, "\t--no-timeout: turns off the timeout\n"); fprintf(stderr, "\t--output-filename: write calibration data to file (USB: override default /etc/modprobe.conf.local\n"); } Calibrator* Calibrator::make_calibrator(int argc, char** argv) { bool list_devices = false; bool fake = false; bool precalib = false; bool use_timeout = true; XYinfo pre_axys; const char* pre_device = NULL; const char* geometry = NULL; const char* output_filename = NULL; unsigned thr_misclick = 15; unsigned thr_doubleclick = 7; OutputType output_type = OUTYPE_AUTO; // parse input if (argc > 1) { for (int i=1; i!=argc; i++) { // Display help ? if (strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) { fprintf(stderr, "xinput_calibrator, v%s\n\n", VERSION); usage(argv[0], thr_misclick); exit(0); } else // Verbose output ? if (strcmp("-v", argv[i]) == 0 || strcmp("--verbose", argv[i]) == 0) { verbose = true; } else // Just list devices ? if (strcmp("--list", argv[i]) == 0) { list_devices = true; } else // Select specific device ? if (strcmp("--device", argv[i]) == 0) { if (argc > i+1) pre_device = argv[++i]; else { fprintf(stderr, "Error: --device needs a device name or id as argument; use --list to list the calibratable input devices.\n\n"); usage(argv[0], thr_misclick); exit(1); } } else // Get pre-calibration ? if (strcmp("--precalib", argv[i]) == 0) { precalib = true; if (argc > i+1) pre_axys.x.min = atoi(argv[++i]); if (argc > i+1) pre_axys.x.max = atoi(argv[++i]); if (argc > i+1) pre_axys.y.min = atoi(argv[++i]); if (argc > i+1) pre_axys.y.max = atoi(argv[++i]); } else // Get mis-click threshold ? if (strcmp("--misclick", argv[i]) == 0) { if (argc > i+1) thr_misclick = atoi(argv[++i]); else { fprintf(stderr, "Error: --misclick needs a number (the pixel threshold) as argument. Set to 0 to disable mis-click detection.\n\n"); usage(argv[0], thr_misclick); exit(1); } } else // Get output type ? if (strcmp("--output-type", argv[i]) == 0) { if (argc > i+1) { i++; // eat it or exit if (strcmp("auto", argv[i]) == 0) output_type = OUTYPE_AUTO; else if (strcmp("xorg.conf.d", argv[i]) == 0) output_type = OUTYPE_XORGCONFD; else if (strcmp("hal", argv[i]) == 0) output_type = OUTYPE_HAL; else if (strcmp("xinput", argv[i]) == 0) output_type = OUTYPE_XINPUT; else { fprintf(stderr, "Error: --output-type needs one of auto|xorg.conf.d|hal|xinput.\n\n"); usage(argv[0], thr_misclick); exit(1); } } else { fprintf(stderr, "Error: --output-type needs one argument.\n\n"); usage(argv[0], thr_misclick); exit(1); } } else // specify window geometry? if (strcmp("--geometry", argv[i]) == 0) { geometry = argv[++i]; } else // Fake calibratable device ? if (strcmp("--fake", argv[i]) == 0) { fake = true; } else // Disable timeout if (strcmp("--no-timeout", argv[i]) == 0) { use_timeout = false; } else // Output file if (strcmp("--output-filename", argv[i]) == 0) { output_filename = argv[++i]; } // unknown option else { fprintf(stderr, "Unknown option: %s\n\n", argv[i]); usage(argv[0], thr_misclick); exit(0); } } } /// Choose the device to calibrate XID device_id = (XID) -1; const char* device_name = NULL; XYinfo device_axys; if (fake) { // Fake a calibratable device device_name = "Fake_device"; device_axys = XYinfo(0,1000,0,1000); if (verbose) { printf("DEBUG: Faking device: %s\n", device_name); } } else { // Find the right device int nr_found = find_device(pre_device, list_devices, device_id, device_name, device_axys); if (list_devices) { // printed the list in find_device if (nr_found == 0) printf("No calibratable devices found.\n"); exit(2); } if (nr_found == 0) { if (pre_device == NULL) fprintf (stderr, "Error: No calibratable devices found.\n"); else fprintf (stderr, "Error: Device \"%s\" not found; use --list to list the calibratable input devices.\n", pre_device); exit(1); } else if (nr_found > 1) { printf ("Warning: multiple calibratable devices found, calibrating last one (%s)\n\tuse --device to select another one.\n", device_name); } if (verbose) { printf("DEBUG: Selected device: %s\n", device_name); } } // 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 { // try Usbtouchscreen driver return new CalibratorUsbtouchscreen(device_name, device_axys, thr_misclick, thr_doubleclick, output_type, geometry, use_timeout, output_filename); } catch(WrongCalibratorException& x) { if (verbose) 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, use_timeout, output_filename); } 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, use_timeout, output_filename); } xinput-calibrator-0.7.5+git20130410/src/Makefile.am000644 001750 001750 00000004511 12273145175 021705 0ustar00warp10warp10000000 000000 # # Copyright (c) 2010 Petr Stetiar # Copyright (c) 2010 Tias Guns # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # SUBDIRS = \ calibrator \ gui AM_CXXFLAGS = -Wall -ansi -pedantic bin_PROGRAMS = xinput_calibrator tester COMMON_SRCS=calibrator.cpp calibrator/XorgPrint.cpp calibrator/Evdev.cpp calibrator/Usbtouchscreen.cpp main_common.cpp gui/gui_common.cpp # only one of the BUILD_ flags should be set if BUILD_X11 xinput_calibrator_SOURCES = gui/x11.cpp main_x11.cpp $(COMMON_SRCS) xinput_calibrator_LDADD = $(XINPUT_LIBS) $(XRANDR_LIBS) $(X11_LIBS) xinput_calibrator_CXXFLAGS = $(XINPUT_CFLAGS) $(X11_CFLAGS) $(XRANDR_CFLAGS) $(AM_CXXFLAGS) endif if BUILD_GTKMM xinput_calibrator_SOURCES = gui/gtkmm.cpp main_gtkmm.cpp $(COMMON_SRCS) xinput_calibrator_LDADD = $(XINPUT_LIBS) $(GTKMM_LIBS) xinput_calibrator_CXXFLAGS = $(XINPUT_CFLAGS) $(GTKMM_CFLAGS) $(AM_CXXFLAGS) # only include the needed gtkmm stuff # lets hope this has no side-effects xinput_calibrator_LDFLAGS = -Wl,--as-needed endif tester_SOURCES = tester.cpp calibrator.cpp calibrator/Tester.cpp calibrator/Evdev.cpp calibrator/EvdevTester.cpp tester_LDADD = $(XINPUT_LIBS) $(XRANDR_LIBS) $(X11_LIBS) tester_CXXFLAGS = $(XINPUT_CFLAGS) $(X11_CFLAGS) $(XRANDR_CFLAGS) $(AM_CXXFLAGS) EXTRA_DIST = \ calibrator.cpp \ calibrator.hh \ main_common.cpp xinput-calibrator-0.7.5+git20130410/src/main_x11.cpp000644 001750 001750 00000003034 12273145175 021771 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include // for pause() #include "calibrator.hh" #include "gui/x11.hpp" int main(int argc, char** argv) { Calibrator* calibrator = Calibrator::make_calibrator(argc, argv); GuiCalibratorX11::make_instance( calibrator ); #ifdef HAVE_TIMERFD while (1) GuiCalibratorX11::give_timer_signal(); #else // wait for timer signal, processes events while(1) pause(); #endif delete calibrator; return 0; } xinput-calibrator-0.7.5+git20130410/src/tester.cpp000644 001750 001750 00000011124 12273145175 021661 0ustar00warp10warp10000000 000000 #include #include #include #include "calibrator.hh" #include "calibrator/Tester.hpp" #include "calibrator/EvdevTester.hpp" int main() { // screen dimensions int width = 800; int height = 600; XYinfo screen_res(0, width, 0, height); int delta_x = width/(float)num_blocks; int delta_y = height/(float)num_blocks; XYinfo target(delta_x, width-delta_x, delta_y, height-delta_y); int slack = 2; // amount of pixels result can be off target XYinfo dev_res(0, 1000, 0, 1000); std::vector old_axes; old_axes.push_back( XYinfo(0, 1000, 0, 1000) ); old_axes.push_back( XYinfo(1000, 0, 0, 1000) ); old_axes.push_back( XYinfo(0, 1000, 1000, 0) ); old_axes.push_back( XYinfo(1000, 0, 0, 1000) ); old_axes.push_back( XYinfo(0, 1000, 0, 1000, 1, 0, 0) ); old_axes.push_back( XYinfo(0, 1000, 0, 1000, 1, 0, 1) ); old_axes.push_back( XYinfo(0, 1000, 0, 1000, 1, 1, 0) ); old_axes.push_back( XYinfo(0, 1000, 0, 1000, 1, 1, 1) ); old_axes.push_back( XYinfo(1000, 0, 0, 1000, 1, 0, 0) ); old_axes.push_back( XYinfo(1000, 0, 0, 1000, 1, 0, 1) ); old_axes.push_back( XYinfo(1000, 0, 0, 1000, 1, 1, 0) ); old_axes.push_back( XYinfo(1000, 0, 0, 1000, 1, 1, 1) ); // non device-resolution calibs old_axes.push_back( XYinfo(42, 929, 20, 888) ); // xf86ScaleAxis rounds to min/max, this can lead to inaccurate // results! Can we fix that? old_axes.push_back( XYinfo(42, 929, 20, 888) ); //old_axes.push_back( XYinfo(-9, 895, 124, 990) ); // this is the true axis // rounding error when raw_coords are swapped??? //old_axes.push_back( XYinfo(75, 750, 20, 888) ); // rounding error on X axis //old_axes.push_back( XYinfo(42, 929, 120, 888) ); // rounding error on Y axis // raw device coordinates to emulate std::vector raw_coords; // normal raw_coords.push_back( XYinfo(105, 783, 233, 883) ); // invert x, y, x+y raw_coords.push_back( XYinfo(783, 105, 233, 883) ); raw_coords.push_back( XYinfo(105, 783, 883, 233) ); raw_coords.push_back( XYinfo(783, 105, 883, 233) ); // swap raw_coords.push_back( XYinfo(233, 883, 105, 783) ); // swap and inverts raw_coords.push_back( XYinfo(233, 883, 783, 105) ); raw_coords.push_back( XYinfo(883, 233, 105, 783) ); raw_coords.push_back( XYinfo(883, 233, 783, 105) ); CalibratorTesterInterface* calib; for (unsigned t=0; t<=1; t++) { if (t == 0) printf("CalibratorTester\n"); else if (t == 1) printf("CalibratorEvdevTester\n"); for (unsigned a=0; a != old_axes.size(); a++) { XYinfo old_axis(old_axes[a]); printf("Old axis: "); old_axis.print(); for (unsigned c=0; c != raw_coords.size(); c++) { XYinfo raw(raw_coords[c]); //printf("Raw: "); raw.print(); // reset calibrator object if (t == 0) calib = new CalibratorTester("Tester", old_axis); else if (t == 1) calib = new CalibratorEvdevTester("Tester", old_axis); // clicked from raw XYinfo clicked = calib->emulate_driver(raw, false, screen_res, dev_res);// false=old_axis //printf("\tClicked: "); clicked.print(); // emulate screen clicks calib->add_click(clicked.x.min, clicked.y.min); calib->add_click(clicked.x.max, clicked.y.min); calib->add_click(clicked.x.min, clicked.y.max); calib->add_click(clicked.x.max, clicked.y.max); calib->finish(width, height); // test result XYinfo result = calib->emulate_driver(raw, true, screen_res, dev_res); // true=new_axis int maxdiff = std::max(abs(target.x.min - result.x.min), std::max(abs(target.x.max - result.x.max), std::max(abs(target.y.min - result.y.min), abs(target.y.max - result.y.max)))); // no n-ary max in c++?? if (maxdiff > slack) { printf("-\n"); printf("Old axis: "); old_axis.print(); printf("Raw: "); raw.print(); printf("Clicked: "); clicked.print(); printf("New axis: "); calib->new_axis_print(); printf("Error: difference between target and result: %i > %i:\n", maxdiff, slack); printf("\tTarget: "); target.print(); printf("\tResult: "); result.print(); exit(1); } printf("%i", maxdiff); } // loop over raw_coords printf(". OK\n"); } // loop over old_axes printf("\n"); } // loop over calibrators } xinput-calibrator-0.7.5+git20130410/src/gui/000755 001750 001750 00000000000 12273145175 020434 5ustar00warp10warp10000000 000000 xinput-calibrator-0.7.5+git20130410/src/gui/gui_common.hpp000644 001750 001750 00000003156 12273145175 023306 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2013 Andreas Müller * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef GUI_GUI_COMMON_HPP #define GUI_GUI_COMMON_HPP #include "calibrator.hh" #include #include // Timeout parameters const int time_step = 100; // in milliseconds const int max_time = 15000; // in milliseconds, 5000 = 5 sec // Clock appereance const int cross_lines = 25; const int cross_circle = 4; const int clock_radius = 50; const int clock_line_width = 10; // Text printed on screen const int font_size = 16; void get_display_texts(std::list *texts, Calibrator *calibrator); #endif xinput-calibrator-0.7.5+git20130410/src/gui/gtkmm.hpp000644 001750 001750 00000004004 12273145175 022262 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * Copyright (c) 2009 Soren Hauberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef GUI_GTKMM_HPP #define GUI_GTKMM_HPP #include #include "calibrator.hh" #include /******************************************* * GTK-mm class for the the calibration GUI *******************************************/ class CalibrationArea : public Gtk::DrawingArea { public: CalibrationArea(Calibrator* w); protected: // Data Calibrator* calibrator; double X[4], Y[4]; int display_width, display_height; int time_elapsed; std::list display_texts; const char* message; // Signal handlers bool on_timer_signal(); bool on_expose_event(GdkEventExpose *event); bool on_button_press_event(GdkEventButton *event); bool on_key_press_event(GdkEventKey *event); // Helper functions void set_display_size(int width, int height); void redraw(); void draw_message(const char* msg); }; #endif xinput-calibrator-0.7.5+git20130410/src/gui/Makefile.am000644 001750 001750 00000000067 12273145175 022473 0ustar00warp10warp10000000 000000 EXTRA_DIST = \ gui_common.cpp \ gtkmm.cpp \ x11.cpp xinput-calibrator-0.7.5+git20130410/src/gui/x11.hpp000644 001750 001750 00000004505 12273145175 021562 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef GUI_CALIBRATOR_X11 #define GUI_CALIBRATOR_X11 #include "calibrator.hh" #include /******************************************* * X11 class for the the calibration GUI *******************************************/ class GuiCalibratorX11 { public: static void make_instance(Calibrator* w); static void give_timer_signal(); protected: GuiCalibratorX11(Calibrator* w); ~GuiCalibratorX11(); // Data Calibrator* calibrator; double X[NUM_POINTS], Y[NUM_POINTS]; int display_width, display_height; int time_elapsed; std::list display_texts; // X11 vars Display* display; int screen_num; Window win; GC gc; XFontStruct* font_info; #ifdef HAVE_TIMERFD int timer_fd; #endif // color management enum { BLACK=0, WHITE=1, GRAY=2, DIMGRAY=3, RED=4, NUM_COLORS }; static const char* colors[NUM_COLORS]; unsigned long pixel[NUM_COLORS]; // Signal handlers bool on_timer_signal(); bool on_expose_event(); bool on_button_press_event(XEvent event); // Helper functions void set_display_size(int width, int height); void redraw(); void draw_message(const char* msg); private: static GuiCalibratorX11* instance; }; #endif xinput-calibrator-0.7.5+git20130410/src/gui/x11.cpp000644 001750 001750 00000032015 12273145175 021552 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "gui/x11.hpp" #include "gui/gui_common.hpp" #include #include #include #include // strncpy, strlen #ifdef HAVE_X11_XRANDR // support for multi-head setups #include #endif #ifdef HAVE_TIMERFD #include #endif #include #include #include #include #include const char* GuiCalibratorX11::colors[GuiCalibratorX11::NUM_COLORS] = {"BLACK", "WHITE", "GRAY", "DIMGRAY", "RED"}; #ifndef HAVE_TIMERFD void sigalarm_handler(int num); #endif /// Create singleton instance associated to calibrator w void GuiCalibratorX11::make_instance(Calibrator* w) { instance = new GuiCalibratorX11(w); } // Singleton instance GuiCalibratorX11* GuiCalibratorX11::instance = NULL; GuiCalibratorX11::GuiCalibratorX11(Calibrator* calibrator0) : calibrator(calibrator0), time_elapsed(0) { // setup strings get_display_texts(&display_texts, calibrator0); display = XOpenDisplay(NULL); if (display == NULL) { throw std::runtime_error("Unable to connect to X server"); } screen_num = DefaultScreen(display); // Load font and get font information structure font_info = XLoadQueryFont(display, "9x15"); if (font_info == NULL) { // fall back to native font font_info = XLoadQueryFont(display, "fixed"); if (font_info == NULL) { XCloseDisplay(display); throw std::runtime_error("Unable to open neither '9x15' nor 'fixed' font"); } } #ifdef HAVE_X11_XRANDR // get screensize from xrandr int nsizes; XRRScreenSize* randrsize = XRRSizes(display, screen_num, &nsizes); if (nsizes != 0) { Rotation current = 0; XRRRotations(display, screen_num, ¤t); bool rot = current & RR_Rotate_90 || current & RR_Rotate_270; int width = rot ? randrsize->height : randrsize->width; int height = rot ? randrsize->width : randrsize->height; set_display_size(width, height); } else { set_display_size(DisplayWidth(display, screen_num), DisplayHeight(display, screen_num)); } # else set_display_size(DisplayWidth(display, screen_num), DisplayHeight(display, screen_num)); #endif // parse geometry string const char* geo = calibrator->get_geometry(); if (geo != NULL) { int gw,gh; int res = sscanf(geo,"%dx%d",&gw,&gh); if (res != 2) { fprintf(stderr,"Warning: error parsing geometry string - using defaults.\n"); } else { set_display_size( gw, gh ); } } // Register events on the window XSetWindowAttributes attributes; attributes.override_redirect = True; attributes.event_mask = ExposureMask | KeyPressMask | ButtonPressMask; win = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, display_width, display_height, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect | CWEventMask, &attributes); XMapWindow(display, win); // Listen to events XGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabPointer(display, win, False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); Colormap colormap = DefaultColormap(display, screen_num); XColor color; for (int i = 0; i != NUM_COLORS; i++) { XParseColor(display, colormap, colors[i], &color); XAllocColor(display, colormap, &color); pixel[i] = color.pixel; } XSetWindowBackground(display, win, pixel[GRAY]); XClearWindow(display, win); gc = XCreateGC(display, win, 0, NULL); XSetFont(display, gc, font_info->fid); // Setup timer for animation #ifdef HAVE_TIMERFD struct itimerspec timer; unsigned int period = time_step * 1000; // microseconds unsigned int sec = period/1000000; unsigned int ns = (period - (sec * 1000000)) * 1000; timer.it_value.tv_sec = sec; timer.it_value.tv_nsec = ns; timer.it_interval = timer.it_value; timer_fd = timerfd_create(CLOCK_MONOTONIC, 0); timerfd_settime(timer_fd, 0, &timer, NULL); #else signal(SIGALRM, sigalarm_handler); struct itimerval timer; timer.it_value.tv_sec = time_step/1000; timer.it_value.tv_usec = (time_step % 1000) * 1000; timer.it_interval = timer.it_value; setitimer(ITIMER_REAL, &timer, NULL); #endif } GuiCalibratorX11::~GuiCalibratorX11() { XUngrabPointer(display, CurrentTime); XUngrabKeyboard(display, CurrentTime); XFreeGC(display, gc); XCloseDisplay(display); } void GuiCalibratorX11::set_display_size(int width, int height) { display_width = width; display_height = height; // Compute absolute circle centers const int delta_x = display_width/num_blocks; const int delta_y = display_height/num_blocks; X[UL] = delta_x; Y[UL] = delta_y; X[UR] = display_width - delta_x - 1; Y[UR] = delta_y; X[LL] = delta_x; Y[LL] = display_height - delta_y - 1; X[LR] = display_width - delta_x - 1; Y[LR] = display_height - delta_y - 1; // reset calibration if already started calibrator->reset(); } void GuiCalibratorX11::redraw() { if (calibrator->get_geometry() == NULL) { int width; int height; #ifdef HAVE_X11_XRANDR // check that screensize did not change int nsizes; XRRScreenSize* randrsize = XRRSizes(display, screen_num, &nsizes); if (nsizes != 0) { Rotation current = 0; XRRRotations(display, screen_num, ¤t); bool rot = current & RR_Rotate_90 || current & RR_Rotate_270; width = rot ? randrsize->height : randrsize->width; height = rot ? randrsize->width : randrsize->height; } else { width = DisplayWidth(display, screen_num); height = DisplayHeight(display, screen_num); } #else width = DisplayWidth(display, screen_num); height = DisplayHeight(display, screen_num); #endif if (display_width != width || display_height != height) { set_display_size(width, height); } } // Print the text int text_height = font_info->ascent + font_info->descent; int text_width = -1; for (std::list::iterator it = display_texts.begin(); it != display_texts.end(); it++) { text_width = std::max(text_width, XTextWidth(font_info, (*it).c_str(), (*it).length())); } int x = (display_width - text_width) / 2; int y = (display_height - text_height) / 2 - 60; XSetForeground(display, gc, pixel[BLACK]); XSetLineAttributes(display, gc, 2, LineSolid, CapRound, JoinRound); XDrawRectangle(display, win, gc, x - 10, y - (display_texts.size()*text_height) - 10, text_width + 20, (display_texts.size()*text_height) + 20); // Print help lines y -= 3; for (std::list::reverse_iterator rev_it = display_texts.rbegin(); rev_it != display_texts.rend(); rev_it++) { int w = XTextWidth(font_info, (*rev_it).c_str(), (*rev_it).length()); XDrawString(display, win, gc, x + (text_width-w)/2, y, (*rev_it).c_str(), (*rev_it).length()); y -= text_height; } // Draw the points for (int i = 0; i <= calibrator->get_numclicks(); i++) { // set color: already clicked or not if (i < calibrator->get_numclicks()) XSetForeground(display, gc, pixel[WHITE]); else XSetForeground(display, gc, pixel[RED]); XSetLineAttributes(display, gc, 1, LineSolid, CapRound, JoinRound); XDrawLine(display, win, gc, X[i] - cross_lines, Y[i], X[i] + cross_lines, Y[i]); XDrawLine(display, win, gc, X[i], Y[i] - cross_lines, X[i], Y[i] + cross_lines); XDrawArc(display, win, gc, X[i] - cross_circle, Y[i] - cross_circle, (2 * cross_circle), (2 * cross_circle), 0, 360 * 64); } // Draw the clock background if(calibrator->get_use_timeout()){ XSetForeground(display, gc, pixel[DIMGRAY]); XSetLineAttributes(display, gc, 0, LineSolid, CapRound, JoinRound); XFillArc(display, win, gc, (display_width-clock_radius)/2, (display_height - clock_radius)/2, clock_radius, clock_radius, 0, 360 * 64); } } bool GuiCalibratorX11::on_expose_event() { redraw(); return true; } bool GuiCalibratorX11::on_timer_signal() { // Update clock if(calibrator->get_use_timeout()) { time_elapsed += time_step; if (time_elapsed > max_time) { exit(0); } XSetForeground(display, gc, pixel[BLACK]); XSetLineAttributes(display, gc, clock_line_width, LineSolid, CapButt, JoinMiter); XDrawArc(display, win, gc, (display_width-clock_radius+clock_line_width)/2, (display_height-clock_radius+clock_line_width)/2, clock_radius-clock_line_width, clock_radius-clock_line_width, 90*64, ((double)time_elapsed/(double)max_time) * -360 * 64); } return true; } bool GuiCalibratorX11::on_button_press_event(XEvent event) { // Clear window, maybe a bit overdone, but easiest for me atm. // (goal is to clear possible message and other clicks) XClearWindow(display, win); // Handle click time_elapsed = 0; bool success = calibrator->add_click(event.xbutton.x, event.xbutton.y); if (!success && calibrator->get_numclicks() == 0) { draw_message("Mis-click detected, restarting..."); } // Are we done yet? if (calibrator->get_numclicks() >= 4) { // Recalibrate success = calibrator->finish(display_width, display_height); if (success) { exit(0); } else { // TODO, in GUI ? fprintf(stderr, "Error: unable to apply or save configuration values"); exit(1); } } // Force a redraw redraw(); return true; } void GuiCalibratorX11::draw_message(const char* msg) { int text_height = font_info->ascent + font_info->descent; int text_width = XTextWidth(font_info, msg, strlen(msg)); int x = (display_width - text_width) / 2; int y = (display_height - text_height) / 2 + clock_radius + 60; XSetForeground(display, gc, pixel[BLACK]); XSetLineAttributes(display, gc, 2, LineSolid, CapRound, JoinRound); XDrawRectangle(display, win, gc, x - 10, y - text_height - 10, text_width + 20, text_height + 25); XDrawString(display, win, gc, x, y, msg, strlen(msg)); } void GuiCalibratorX11::give_timer_signal() { if (instance != NULL) { // timer signal #ifdef HAVE_TIMERFD uint64_t missed; ssize_t ret; /* Wait for the next timer event. If we have missed any the * number is written to "missed" */ ret = read(instance->timer_fd, &missed, sizeof (missed)); if (ret == -1) { fprintf(stderr, "failed reading timer"); } #endif //check timeout instance->on_timer_signal(); // process events XEvent event; while (XCheckWindowEvent(instance->display, instance->win, -1, &event) == True) { switch (event.type) { case Expose: // only draw the last contiguous expose if (event.xexpose.count != 0) break; instance->on_expose_event(); break; case ButtonPress: instance->on_button_press_event(event); break; case KeyPress: exit(0); break; } } } } #ifndef HAVE_TIMERFD // handle SIGALRM signal, pass to singleton void sigalarm_handler(int num) { if (num == SIGALRM) { GuiCalibratorX11::give_timer_signal(); } } #endif xinput-calibrator-0.7.5+git20130410/src/gui/gui_common.cpp000644 001750 001750 00000003461 12273145175 023300 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2013 Andreas Müller * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "gui/gui_common.hpp" void get_display_texts(std::list *texts, Calibrator *calibrator) { std::string str; /* 1st line */ str = "Touchscreen Calibration"; const char* sysfs_name = calibrator->get_sysfs_name(); if(sysfs_name != NULL) { str += " for '"; str += sysfs_name; str += "'"; } texts->push_back(str); /* 2nd line */ str = "Press the point, use a stylus to increase precision."; texts->push_back(str); /* 3rd line */ str = ""; texts->push_back(str); /* 4th line */ str = "(To abort, press any key"; if(calibrator->get_use_timeout()) str += " or wait)"; else str += ")"; texts->push_back(str); } xinput-calibrator-0.7.5+git20130410/src/gui/gtkmm.cpp000644 001750 001750 00000020555 12273145175 022266 0ustar00warp10warp10000000 000000 /* * Copyright (c) 2009 Tias Guns * Copyright (c) 2009 Soren Hauberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "gui/gtkmm.hpp" #include "gui/gui_common.hpp" CalibrationArea::CalibrationArea(Calibrator* calibrator0) : calibrator(calibrator0), time_elapsed(0), message(NULL) { // setup strings get_display_texts(&display_texts, calibrator0); // Listen for mouse events add_events(Gdk::KEY_PRESS_MASK | Gdk::BUTTON_PRESS_MASK); set_flags(Gtk::CAN_FOCUS); // parse geometry string const char* geo = calibrator->get_geometry(); if (geo != NULL) { int gw,gh; int res = sscanf(geo,"%dx%d",&gw,&gh); if (res != 2) { fprintf(stderr,"Warning: error parsing geometry string - using defaults.\n"); geo = NULL; } else { set_display_size( gw, gh ); } } if (geo == NULL) set_display_size(get_width(), get_height()); // Setup timer for animation if(calibrator->get_use_timeout()){ sigc::slot slot = sigc::mem_fun(*this, &CalibrationArea::on_timer_signal); Glib::signal_timeout().connect(slot, time_step); } } void CalibrationArea::set_display_size(int width, int height) { display_width = width; display_height = height; // Compute absolute circle centers const int delta_x = display_width/num_blocks; const int delta_y = display_height/num_blocks; X[UL] = delta_x; Y[UL] = delta_y; X[UR] = display_width - delta_x - 1; Y[UR] = delta_y; X[LL] = delta_x; Y[LL] = display_height - delta_y - 1; X[LR] = display_width - delta_x - 1; Y[LR] = display_height - delta_y - 1; // reset calibration if already started calibrator->reset(); } bool CalibrationArea::on_expose_event(GdkEventExpose *event) { // check that screensize did not change (if no manually specified geometry) if (calibrator->get_geometry() == NULL && (display_width != get_width() || display_height != get_height()) ) { set_display_size(get_width(), get_height()); } Glib::RefPtr window = get_window(); if (window) { Cairo::RefPtr cr = window->create_cairo_context(); cr->save(); cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height); cr->clip(); // Print the text cr->set_font_size(font_size); double text_height = -1; double text_width = -1; Cairo::TextExtents extent; for (std::list::iterator it = display_texts.begin(); it != display_texts.end(); it++) { cr->get_text_extents(*it, extent); text_width = std::max(text_width, extent.width); text_height = std::max(text_height, extent.height); } text_height += 2; double x = (display_width - text_width) / 2; double y = (display_height - text_height) / 2 - 60; cr->set_line_width(2); cr->rectangle(x - 10, y - (display_texts.size()*text_height) - 10, text_width + 20, (display_texts.size()*text_height) + 20); // Print help lines y -= 3; for (std::list::reverse_iterator rev_it = display_texts.rbegin(); rev_it != display_texts.rend(); rev_it++) { cr->get_text_extents(*rev_it, extent); cr->move_to(x + (text_width-extent.width)/2, y); cr->show_text(*rev_it); y -= text_height; } cr->stroke(); // Draw the points for (int i = 0; i <= calibrator->get_numclicks(); i++) { // set color: already clicked or not if (i < calibrator->get_numclicks()) cr->set_source_rgb(1.0, 1.0, 1.0); else cr->set_source_rgb(0.8, 0.0, 0.0); cr->set_line_width(1); cr->move_to(X[i] - cross_lines, Y[i]); cr->rel_line_to(cross_lines*2, 0); cr->move_to(X[i], Y[i] - cross_lines); cr->rel_line_to(0, cross_lines*2); cr->stroke(); cr->arc(X[i], Y[i], cross_circle, 0.0, 2.0 * M_PI); cr->stroke(); } if(calibrator->get_use_timeout()){ // Draw the clock background cr->arc(display_width/2, display_height/2, clock_radius/2, 0.0, 2.0 * M_PI); cr->set_source_rgb(0.5, 0.5, 0.5); cr->fill_preserve(); cr->stroke(); } cr->set_line_width(clock_line_width); cr->arc(display_width/2, display_height/2, (clock_radius - clock_line_width)/2, 3/2.0*M_PI, (3/2.0*M_PI) + ((double)time_elapsed/(double)max_time) * 2*M_PI); cr->set_source_rgb(0.0, 0.0, 0.0); cr->stroke(); // Draw the message (if any) if (message != NULL) { // Frame the message cr->set_font_size(font_size); Cairo::TextExtents extent; cr->get_text_extents(this->message, extent); text_width = extent.width; text_height = extent.height; x = (display_width - text_width) / 2; y = (display_height - text_height + clock_radius) / 2 + 60; cr->set_line_width(2); cr->rectangle(x - 10, y - text_height - 10, text_width + 20, text_height + 25); // Print the message cr->move_to(x, y); cr->show_text(this->message); cr->stroke(); } cr->restore(); } return true; } void CalibrationArea::redraw() { Glib::RefPtr win = get_window(); if (win) { const Gdk::Rectangle rect(0, 0, display_width, display_height); win->invalidate_rect(rect, false); } } bool CalibrationArea::on_timer_signal() { if (calibrator->get_use_timeout()) { time_elapsed += time_step; if (time_elapsed > max_time) { exit(0); } // Update clock Glib::RefPtr win = get_window(); if (win) { const Gdk::Rectangle rect(display_width/2 - clock_radius - clock_line_width, display_height/2 - clock_radius - clock_line_width, 2 * clock_radius + 1 + 2 * clock_line_width, 2 * clock_radius + 1 + 2 * clock_line_width); win->invalidate_rect(rect, false); } } return true; } bool CalibrationArea::on_button_press_event(GdkEventButton *event) { // Handle click time_elapsed = 0; bool success = calibrator->add_click((int)event->x_root, (int)event->y_root); if (!success && calibrator->get_numclicks() == 0) { draw_message("Mis-click detected, restarting..."); } else { draw_message(NULL); } // Are we done yet? if (calibrator->get_numclicks() >= 4) { // Recalibrate success = calibrator->finish(display_width, display_height); if (success) { exit(0); } else { // TODO, in GUI ? fprintf(stderr, "Error: unable to apply or save configuration values"); exit(1); } } // Force a redraw redraw(); return true; } void CalibrationArea::draw_message(const char* msg) { this->message = msg; } bool CalibrationArea::on_key_press_event(GdkEventKey *event) { (void) event; exit(0); } xinput-calibrator-0.7.5+git20130410/COPYING000644 001750 001750 00000003214 12273145175 020114 0ustar00warp10warp10000000 000000 Copyright (c) 2010 Tias Guns and others See the respective files for detailed copyright information. Source code: MIT/X11 License ------------ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Icon xinput_calibrator.svg: CC by-sa --------------------------- (c) Tias Guns The screen and triangle are from the Tango Desktop Project, which is in the Public Domain. The hand is from Ubuntu's human-icon-theme, which is CC by-sa (c) Jeff Waugh (c) Daniel Holbach (c) Martin Pitt Creative Commons Attribution-ShareAlike 3.0 License Agreement http://creativecommons.org/licenses/by-sa/3.0/ xinput-calibrator-0.7.5+git20130410/scripts/000755 001750 001750 00000000000 12273145175 020550 5ustar00warp10warp10000000 000000 xinput-calibrator-0.7.5+git20130410/scripts/xinput_calibrator.svg000644 001750 001750 00000164561 12273145175 025037 0ustar00warp10warp10000000 000000 xinput-calibrator-0.7.5+git20130410/scripts/xinput_calibrator_get_hal_calibration.sh000755 001750 001750 00000004655 12273145175 030704 0ustar00warp10warp10000000 000000 #!/bin/sh # Get running calibration data from lshal # (needed to recalibrate it, most easily fetchable from lshal) export PATH=".:$PATH" #FIND="hal-find-by-property" CAPAB="hal-find-by-capability" GET="hal-get-property" BINARY="xinput_calibrator" if [ "$(which $CAPAB)" = "" ]; then echo "Error: Can not find executable $CAPAB" exit 1 fi if [ "$(which $GET)" = "" ]; then echo "Error: Can not find executable $GET" exit 1 fi #udis=$($FIND --key input.x11_driver --string evtouch) udis=$($CAPAB --capability input) if [ "$udis" = "" ]; then echo "HAL Error: No input devices found (tested: info.capabilities 'input'))" exit 1 fi echo "Trying all available input devices:" # possibly multiple screens, iterate over each possibility count=0 cmd="" for udi in $udis; do name=$($GET --udi $udi --key info.product) minx=$($GET --udi $udi --key input.x11_options.minx 2> /dev/null) maxx=$($GET --udi $udi --key input.x11_options.maxx 2> /dev/null) miny=$($GET --udi $udi --key input.x11_options.miny 2> /dev/null) maxy=$($GET --udi $udi --key input.x11_options.maxy 2> /dev/null) # missing values ? if [ "$minx" = "" ] || [ "$maxx" = "" ] || [ "$miny" = "" ] || [ "$maxy" = "" ]; then if [ "$minx" = "" ] && [ "$maxx" = "" ] && [ "$miny" = "" ] && [ "$maxy" = "" ]; then # no calibration data available echo "\t'$name': no calibration data available" else # partial calibration data available ??? echo "Error: '$name', only partial calibration data available (MinX='$minx' MaxX='$maxx' MinY='$miny' MaxY='$maxy'). All 4 current calibration values are need to recalibrate the device !" fi else count=$((count += 1)) cmd="$BINARY --precalib $minx $maxx $miny $maxy" echo "\t'$name': values found, calibrate by running:" echo "$cmd" fi done if [ $count -gt 1 ]; then echo "Found multiple calibratable touchscreen devices, select one from above and execute the calibration program with the given parameters." else if [ $count -eq 0 ]; then echo "Warning: No existing calibration data found, no parameters used." cmd="$BINARY" fi if [ "$(which $BINARY)" = "" ]; then echo "Error: can not find calibration program ($BINARY), please run it with the above parameters yourself." else echo "\nRunning calibration program..." $cmd fi fi xinput-calibrator-0.7.5+git20130410/scripts/xinput_calibrator.desktop000644 001750 001750 00000000454 12273145175 025677 0ustar00warp10warp10000000 000000 [Desktop Entry] Name=Calibrate Touchscreen Name[de]=Touchscreen Kalibrieren Name[nl]=Touchscreen Kalibreren Comment=Run the calibration tool for touchscreens Exec=/bin/sh -c "xinput_calibrator; cat" Terminal=true Type=Application Icon=xinput_calibrator StartupNotify=true Categories=System;Settings; xinput-calibrator-0.7.5+git20130410/scripts/xinput_calibrator_pointercal.sh000755 001750 001750 00000001700 12273145175 027056 0ustar00warp10warp10000000 000000 #!/bin/sh # script to make the changes permanent (xinput is called with every Xorg start) # # can be used from Xsession.d # script needs tee and sed (busybox variants are enough) # # original script: Martin Jansa , 2010-01-31 # updated by Tias Guns , 2010-02-15 # updated by Koen Kooi , 2012-02-28 PATH="/usr/bin:$PATH" BINARY="xinput_calibrator" CALFILE="/etc/pointercal.xinput" LOGFILE="/var/log/xinput_calibrator.pointercal.log" if [ -e $CALFILE ] ; then if grep replace $CALFILE ; then echo "Empty calibration file found, removing it" rm $CALFILE else echo "Using calibration data stored in $CALFILE" . $CALFILE && exit 0 fi fi CALDATA=`$BINARY --output-type xinput -v | tee $LOGFILE | grep ' xinput set' | sed 's/^ //g; s/$/;/g'` if [ ! -z "$CALDATA" ] ; then echo $CALDATA > $CALFILE echo "Calibration data stored in $CALFILE (log in $LOGFILE)" fi xinput-calibrator-0.7.5+git20130410/scripts/xinput_calibrator.xpm000644 001750 001750 00000013504 12273145175 025032 0ustar00warp10warp10000000 000000 /* XPM */ static char *xinput_calibrator[] = { /* columns rows colors chars-per-pixel */ "32 32 229 2", " c #303030", ". c #393939", "X c #3D3A4A", "o c #353462", "O c #3C3C68", "+ c #3C3C7F", "@ c #434343", "# c #4D4B4B", "$ c #564E48", "% c #5F5743", "& c #51514F", "* c #474453", "= c #494754", "- c #4D4A54", "; c #44435D", ": c #48465B", "> c #504D56", ", c #504D5C", "< c #515151", "1 c #685D40", "2 c #6A5F4D", "3 c #605858", "4 c #5F605F", "5 c #6D6340", "6 c #6D624C", "7 c #7C6D46", "8 c #7A6D4E", "9 c #706754", "0 c #776E57", "q c #7B6E53", "w c #746C5A", "e c #7C7052", "r c #7B705A", "t c #424060", "y c #45446E", "u c #565564", "i c #585564", "p c #52506A", "a c #444475", "s c #444478", "d c #525277", "f c #55557D", "g c #5B5B7E", "h c #605D62", "j c #635E6C", "k c #666168", "l c #6C666E", "z c #7F7462", "x c #6D6677", "c c #65657D", "v c #777073", "b c #787672", "n c #75707E", "m c #7D7D7C", "M c #8B7A37", "N c #807346", "B c #82714A", "V c #8C7D4A", "C c #867757", "Z c #8C7E5F", "A c #837761", "S c #837862", "D c #8B7F60", "F c #877E68", "G c #B39615", "H c #958537", "J c #A18A2D", "K c #AD9623", "L c #BA9F21", "P c #A08A30", "I c #A08A3A", "U c #B59F3B", "Y c #BCA123", "T c #BCA129", "R c #BAA339", "E c #CEB21E", "W c #D8BB1F", "Q c #D3B623", "! c #DBBF21", "~ c #D7BB2C", "^ c #C2AE3C", "/ c #CFBA30", "( c #DEC225", ") c #DBC037", "_ c #DEC43B", "` c #E1C629", "' c #E4CA2D", "] c #E7CD31", "[ c #E8CF34", "{ c #E7CF3B", "} c #E9D034", "| c #EDD53A", " . c #F0DA3F", ".. c #948040", "X. c #988540", "o. c #9F8C41", "O. c #938257", "+. c #B09F4C", "@. c #908364", "#. c #948768", "$. c #87807B", "%. c #968E79", "&. c #9E9173", "*. c #9D927B", "=. c #A18F66", "-. c #A29576", ";. c #AD9C73", ":. c #A1967C", ">. c #B9A87F", ",. c #C3AC43", "<. c #C9B243", "1. c #CFB843", "2. c #CCB649", "3. c #D5BC41", "4. c #C3AF7D", "5. c #DDC440", "6. c #DAC65E", "7. c #E1C944", "8. c #EFD843", "9. c #E6D14A", "0. c #E3CD52", "q. c #E0CC5B", "w. c #EEDA50", "e. c #ECD85D", "r. c #EEDC6B", "t. c #F4E365", "y. c #3D3D80", "u. c #424283", "i. c #4B4C89", "p. c #525280", "a. c #5D5D80", "s. c #53558D", "d. c #535496", "f. c #575890", "g. c #5C5D92", "h. c #636382", "j. c #6A6A85", "k. c #6E6E88", "l. c #73738C", "z. c #626496", "x. c #676898", "c. c #696B99", "v. c #7B7B93", "b. c #757498", "n. c #6E70A0", "m. c #7879A4", "M. c #838483", "N. c #8C8C8B", "B. c #949493", "V. c #989997", "C. c #999A99", "Z. c #A39A87", "A. c #A59C8D", "S. c #A79E95", "D. c #ADA081", "F. c #A9A08B", "G. c #B3A685", "H. c #B3A78F", "J. c #BAAD8E", "K. c #AAA296", "L. c #A0A19C", "P. c #A9A199", "I. c #B6AC93", "U. c #BAAD91", "Y. c #BDB299", "T. c #8789AB", "R. c #9B9EB6", "E. c #A3A3A1", "W. c #A7A8A7", "Q. c #AEA8A2", "!. c #ABACAB", "~. c #AEB0AC", "^. c #B2B2B2", "/. c #B7B9B5", "(. c #B9BCB6", "). c #BBBEB9", "_. c #C1AF88", "`. c #C0B18D", "'. c #CCBA8E", "]. c #C2B492", "[. c #CCBB95", "{. c #CDBE9A", "}. c #D0BF98", "|. c #C4BAA3", " X c #C9BEA3", ".X c #BEC1BC", "XX c #CFC09F", "oX c #D2C29C", "OX c #CEC2A8", "+X c #D5C6A4", "@X c #D6C8A7", "#X c #D7C9A9", "$X c #D9CBAD", "%X c #D6CAB3", "&X c #DBCEB3", "*X c #DDD1B6", "=X c #DDD2BA", "-X c #E0D5BD", ";X c #ACAFC0", ":X c #AFB1C0", ">X c #BBBEC5", ",X c #BBBEC8", "X.XfXm jXjX", "jXjXE.hXn.v.l.b.v.l.l.l.l.l.k.k.k.j.j.j.h.j.j.h.h.j :X2XdXM.jXjX", "jXjXW.gXc.l.l.u i c k.j.j.j.j.j.j.h.h.h.h.h.c c o.T R.3XaXM.jXjX", "jXjX!.gXc.k.u Z.+Xw j.j.j.h.h.h.h.h.c h.h.g l R 0.,.T.(.iXM.jXjX", "jXjX^.gXx.j.- Y.=Xq h.h.h.h.h.h.c a.a.g g B 2.9.` ,.m.OXwXM.jXjX", "jXjX^.gXz.h.> }.{.q a.h.g g g g g g d t P q.{ ` ` <.b.3XwXN.jXjX", "jXjX(.dXz.h.- oXoXq a.g g g g f f O $ ,.e.[ ' ` ( 3.l.(.qXB.jXjX", "jXjXXX jX", "jXjXwX4Xy.; 1 +X#XF $X$X-.@X@X&.oXO./ ] ' ' ` ( ! ) H 8X6X%X@ jX", "jXM.wX,Xy.k Z @X$X*.&XOXJ.#X@XG.oX=.^ 7.) 7.~ 5.Q 5.H 5X6X3X# jX", "jXM.iX.~.6X6X6X6X6X6X6X3X3X3X9X& jX", "jXv.0X6X.XI.Z.-X-X&XeXeX*X&X%X$X$X_.L..X)..X(.(.(.(.(.(..X3X< jX", "jXjXM.C.N.OXU.&XeX=XeXeX-X-X-X$X&X'.b M.M.M.M.M.m m m m b 4 jXjX", "jXjXjXjXjXY.{.=XeX-XeXtX-X-X-X$X-X}.jXjXjXjXjXjXjXjXjXjXjXjXjXjX", "jXjXjXjXjXI.$X*XeX-XrXyXeXeX-X&X=XoXjXjXjXjXjXjXjXjXjXjXjXjXjXjX", "jXjXjXjXjXjX*X=XrXeXtXyXtXrXeX*X=X].jXjXjXjXjXjXjXjXjXjXjXjXjXjX", "jXjXjXjXjXjXOX*XrXeXtXuXtXrXeX*X*X:.jXjXjXjXjXjXjXjXjXjXjXjXjXjX", "jXjXjXjXjXjXH.*XtXeXtXpXtXtXrX=X*XjXjXjXjXjXjXjXjXjXjXjXjXjXjXjX", "jXjXjXjXjXjX%.*XrXeXuXsXuXtXrX-X|.jXjXjXjXjXjXjXjXjXjXjXjXjXjXjX", "jXjXjXjXjXjXjX%XrXeXuXsXuXyXrX-XZ.jXjXjXjXjXjXjXjXjXjXjXjXjXjXjX", "jXjXjXjXjXjXjXjXA.A.S.Q.P.K.K.A.jXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjX", "jXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjX" }; xinput-calibrator-0.7.5+git20130410/scripts/Makefile.am000644 001750 001750 00000000531 12273145175 022603 0ustar00warp10warp10000000 000000 EXTRA_DIST = \ xinput_calibrator.desktop \ xinput_calibrator_get_hal_calibration.sh \ xinput_calibrator_pointercal.sh \ xinput_calibrator.svg \ xinput_calibrator.xpm icon_DATA = xinput_calibrator.svg xinput_calibrator.xpm icondir = $(datadir)/pixmaps util_DATA = xinput_calibrator.desktop utildir = $(datadir)/applications xinput-calibrator-0.7.5+git20130410/autogen.sh000755 001750 001750 00000000303 12273145175 021056 0ustar00warp10warp10000000 000000 #! /bin/sh srcdir=`dirname $0` test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` cd $srcdir autoreconf -v --install || exit 1 cd $ORIGDIR || exit $? $srcdir/configure --enable-maintainer-mode "$@" xinput-calibrator-0.7.5+git20130410/Changelog000644 001750 001750 00000007667 12273145175 020713 0ustar00warp10warp10000000 000000 xinput_calibrator 0.7.5 [2010-09-12] Major features: * support multi-head setups in the GUIs (Alexey Kuznetsov) * now builds and runs on older systems too * output xorg.conf.d snippets (Peter Hutterer) * simpler and cleaner output, with --output-type to select output type Enhancements: * only link to needed libraries * start --fake with sensible non-zero calibration values * various spelling fixes (thanks Paul Wise) * remove udev configuration (xorg.conf.d instead, Peter Hutterer) * remove bogus partial xorg config output, superseded by xorg.conf.d * sysfs name detection, when device name is sysfs name * dynamically detect xorg.conf.d support * updated manpage * icon, license is CC-BY-SA 3.0 * autotools cleanups (thanks Paul Wise) xinput_calibrator 0.7.0 [2010-08-01] Major features: * Automatic mis-click detection ! * Now compiles only one binary (with gtkmm if availabe, otherwise x11) * .desktop file for menu entry * Made a tango-based calibration icon * Manpage information about making calibration permanent Bug fixes/enhancements: * A COPYING file to explicitise MIT/X11 license * Proper make dist (Thierry Reding) * Packaging fixes (David Ludlow) xinput_calibrator 0.6.1 [2010-03-21] Bug fixes/enhancements: * More robust device detection: non-master device with axis valuators, in absolute mode and at least two calibratable axes. (reported by Sam Lin, Eric Drechsel) * Require libtool in configure.ac * fix miny and maxx printing order for UDEV and HAL (Mario Domenech Goulart) xinput_calibrator 0.6.0 [2010-02-15] Major features: * switch to autotools based build system (Petr Štetiar) * add -v option, prints debug messages * add --list option, lists calibratable devices * add support for --device option, selects a specific device * Add a manpage Minor features: * make it compile with strict flags (Petr Štetiar) * Load font fixed when 9x15 fails in GuiCalibratorX11 (Marco Cavallini) * add support for specific device id for evdev (necessary when 2 devices have the same name) * xorg print: clean up output and added udev rule * evdev: print ways to make config permanent (easier when evdev >= 2.3.0) * scripts/xinput_calibrator.desktop a sample .desktop file * scripts/xinput_calibrator_pointercal.sh script to make the changes permanent (xinput is called with every Xorg start) Bug fixes/enhancements: * fix double free in evdev calibrator (reported by Marco Cavallini) * Check that XInput >= 1.5 in evdev calibrator (reported by Marcin Juszkiewicz) * check that the device is a XI_TOUCHSCREEN * set evdev calibration to default when none is apparently set (fixes sleep/resume quirk) * swap_xy in dynamic evdev: unswap if already swapped For the complete changeset, see the git log xinput_calibrator 0.5.0 [2010-01-11] Major features: * Rewrite: split the one-huge-file into clean components * New X11 based gui: like the gtkmm one, but in pure X11 Minor features: * Add --fake option (for development/testing) * make the touch points more visuals: draw a cross through them * press any key to quit * help text of 4 lines Bug fixes: * Use strdup() due to pointer scope autofree [Thanks Sam Lin] * clarify that the license is the pure MIT/X11 license xinput_calibrator 0.4.1 [2009-12-1] Other: * Add README and Changelog file xinput_calibrator 0.4.0 [2009-12-1] New features/improvements: * Add example FDI policy file for generic touchscreen, next to example xorg.conf values * Add support for providing the current calibration on the command line (with --precalib), add help information (-h or --help). Included a script that reads the current calibration data from lshal, and runs the calibration program with the right --precalib data * Add support for dynamic evdev re-calibration xinput_calibrator 0.2.0 [2009-09-10] New features/improvements: * Add generic xinput methods for reading the current data and writing example xorg.conf files. * put usbtouchscreen specific stuff in a new subclass * Initial code from http://lists.x.org/archives/xorg/2008-September/039064.html xinput-calibrator-0.7.5+git20130410/Makefile.am000644 001750 001750 00000002352 12273145175 021117 0ustar00warp10warp10000000 000000 # # Copyright (c) 2010 Petr Stetiar # Copyright (c) 2010 Tias Guns # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # AUTOMAKE_OPTIONS = foreign SUBDIRS = src man scripts EXTRA_DIST = autogen.sh Changelog xinput-calibrator-0.7.5+git20130410/man/000755 001750 001750 00000000000 12273145175 017634 5ustar00warp10warp10000000 000000 xinput-calibrator-0.7.5+git20130410/man/Makefile.am000644 001750 001750 00000002204 12273145175 021666 0ustar00warp10warp10000000 000000 # # Copyright (c) 2010 Tias Guns # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # dist_man_MANS = xinput_calibrator.1 xinput-calibrator-0.7.5+git20130410/man/xinput_calibrator.1000644 001750 001750 00000007420 12273145175 023452 0ustar00warp10warp10000000 000000 .\" .TH "xinput_calibrator" "1" "" "Tias Guns" "" .SH "NAME" xinput_calibrator \- A generic touchscreen calibration program for X.Org .SH "SYNOPSIS" .B xinput_calibrator [OPTIONS] .SH "DESCRIPTION" xinput_calibrator is a program for calibrating your touchscreen, when using the X Window System. .PP It currently features: .br \- works for any standard Xorg touchscreen driver (uses XInput protocol) .br \- mis\-click detection (prevents bogus calibration) .br \- dynamically recalibrates the evdev driver .br \- outputs the calibration as xorg.conf.d snippet or HAL policy file .br \- and more .PP see http://www.freedesktop.org/wiki/Software/xinput_calibrator .SH "OPTIONS" .TP 8 .B \-h, \-\-help Print a help message listing the version and available options. .PP .TP 8 .B \-v, \-\-verbose Print debug messages during the process. .PP .TP 8 .B \-\-list List the calibratable input devices. .PP .TP 8 .B \-\-device \fIdevice_name_or_id\fP Select a specific device to calibrate; use \-\-list to list the calibratable input devices. .PP .TP 8 .B \-\-precalib \fImin_x\fP \fImax_x\fP \fImin_y\fP \fImax_y\fP Manually provide the current calibration setting. .br This is useful if the calibration values are stored in your xorg.conf, but the driver does not export them through XInput (eg. the calibrator can not know these values) .PP .TP 8 .B \-\-misclick \fInr_of_pixels\fP set the misclick threshold (0=off, default: 15 pixels) .PP .TP 8 .B \-\-no-timeout turns off the timeout .PP .TP 8 .B \-\-output\-type \fIauto|xorg.conf.d|hal|xinput\fP type of config to ouput (auto=automatically detect, default: auto) .PP .TP 8 .B \-\-fake Emulate a fake driver (for testing purposes) .br Useful to test the calibrator without applying the values, and possibly even without having a touchscreen. .PP .TP 8 .B \-\-geometry \fIwidth\fPx\fIheight\fP Manually provide the geometry (width and height) for the calibration window. .SH "USAGE" Run xinput_calibrator in a terminal, as it prints out the calibration values and instructions on standard output. .PP After clicking the 4 calibration points, xinput_calibrator will calculate the new calibration values. Depending on the Xorg touchscreen driver you use, the new values can be made permanent in different ways: .TP 4 .B Evdev: Automatically recalibrates the driver for this session, .br Supports following \-\-output\-types: auto, xorg.conf.d, hal, xinput .TP 4 .B Usbtouchscreen: Automatically recalibrates the *kernel module*, saved in /etc/modprobe.conf.local .br Supports following \-\-output\-types: auto .TP 4 .B Other Xorg touchscreen drivers: No automatic calibration possible, .br Supports following \-\-output\-types: auto, xorg.conf.d, hal .SH "EXAMPLES" To run the calibrator, type in your terminal: .LP xinput_calibrator .PP If something goes wrong, or not as expected, turn on verbose messages: .LP xinput_calibrator \-v .PP If you have to manually provide the current calibration values (when using EVDEV, you can use this to reset the calibration first): .LP xinput_calibrator \-\-precalib 0 1000 0 1000 .SH "TROUBLESHOOTING" .B In general, run the calibrator with the \fI\-v\fP option, it will tell you what happens and what goes wrong. .B Mis\-click detection, the calibrator can automatically detect clicks with unreasonable values. This prevents you from ending up with a bogus calibration. .LP If you keep getting the message 'Mis\-click detected, restarting...', one of the following is happening: 1. you are bad at clicking on crosses, use a stylus or increase the \-\-misclick threshold 2. your device is not properly supported by the kernel, it interprets the clicks wrong 3. your screen has a non\-linear deformation, 4\-point calibration can not help you .SH "SEE ALSO" xinput(1) .SH "AUTHORS" .nf Tias Guns .fi xinput-calibrator-0.7.5+git20130410/configure.ac000644 001750 001750 00000006714 12273145175 021357 0ustar00warp10warp10000000 000000 # # Copyright (c) 2010 Petr Stetiar # Copyright (c) 2010 Tias Guns # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # AC_PREREQ([2.57]) AC_INIT(xinput_calibrator,[0.7.5], [http://github.com/tias/xinput_calibrator/issues],, [http://www.freedesktop.org/wiki/Software/xinput_calibrator]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE AC_PROG_CC AC_PROG_CXX AC_PROG_LIBTOOL AC_PROG_INSTALL AC_PATH_X AC_CHECK_HEADERS([stdlib.h string.h string list]) AC_HEADER_STDBOOL AC_FUNC_STRTOD PKG_CHECK_MODULES(XINPUT, x11 xext xi inputproto) AC_SUBST(XINPUT_CFLAGS) AC_SUBST(XINPUT_LIBS) PKG_CHECK_MODULES(XI_PROP, [xi >= 1.2] [inputproto >= 1.5], AC_DEFINE(HAVE_XI_PROP, 1, [Xinput properties available]), foo="bar") AC_ARG_WITH([gui], AS_HELP_STRING([--with-gui=default], [Use gtkmm GUI if available, x11 GUI otherwise (default)]),,[with_gui=default]) AC_ARG_WITH([gui], AS_HELP_STRING([--with-gui=gtkmm], [Use gtkmm GUI])) AC_ARG_WITH([gui], AS_HELP_STRING([--with-gui=x11], [Use native x11 GUI])) AC_MSG_CHECKING([gui]) AC_MSG_RESULT($with_gui) AS_IF([test "x$with_gui" = xdefault || test "x$with_gui" = xgtkmm], [ PKG_CHECK_MODULES(GTKMM, [gtkmm-2.4], with_gui="gtkmm", [if test "x$with_gui" = xgtkmm; then AC_MSG_ERROR([GTKMM GUI requested, but gtkmm-2.4 not found]) fi]) AC_SUBST(GTKMM_CFLAGS) AC_SUBST(GTKMM_LIBS) ]) AM_CONDITIONAL([BUILD_GTKMM], [test "x$with_gui" = xgtkmm]) AS_IF([test "x$with_gui" = xdefault || test "x$with_gui" = xx11], [ PKG_CHECK_MODULES(X11, [x11], with_gui="x11", with_gui="no") AC_SUBST(X11_CFLAGS) AC_SUBST(X11_LIBS) # check for xrandr too PKG_CHECK_MODULES(XRANDR, [xrandr], AC_DEFINE(HAVE_X11_XRANDR, 1), foo="bar") AC_SUBST(XRANDR_CFLAGS) AC_SUBST(XRANDR_LIBS) ]) AM_CONDITIONAL([BUILD_X11], [test "x$with_gui" = xx11]) AC_CACHE_CHECK(for timerfd_create(2) system call, glib_cv_timerfd,AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ #include #include ],[ int main (void) { timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC); return 0; } ])],glib_cv_timerfd=yes,glib_cv_timerfd=no)) if test x"$glib_cv_timerfd" = x"yes"; then AC_DEFINE(HAVE_TIMERFD, 1, [we have the timerfd_create(2) system call]) fi AM_CONDITIONAL(HAVE_TIMERFD, [test "$glib_cv_timerfd" = "yes"]) AC_SUBST(VERSION) AC_OUTPUT([Makefile scripts/Makefile src/Makefile src/calibrator/Makefile src/gui/Makefile man/Makefile]) xinput-calibrator-0.7.5+git20130410/README000644 001750 001750 00000004547 12273145175 017753 0ustar00warp10warp10000000 000000 xinput calibrator: A generic touchscreen calibration program for X.Org Version: 0.7.5 Website: http://www.freedesktop.org/wiki/Software/xinput_calibrator Source: http://github.com/tias/xinput_calibrator Bugs: http://github.com/tias/xinput_calibrator/issues Build instructions: ------------------- ./autogen.sh Sets up build environment, run ./autogen.sh --help to see the build options Notable build options: --with-gui=gtkmm Use gtkmm GUI --with-gui=x11 Use native x11 GUI make Builds the software with the configured GUI Usage: ------ Simply run: xinput_calibrator For more information, run with --help or check the manpage. The scripts/ directory constains scripts to get calibration from hal or use a pointercal file to reapply xinput commands across reboots More about the project: ----------------------- Because all existing calibrators were driver dependent and hard to use, xinput_calibrator was created. The goal of xinput_calibrator is to: * work for any Xorg driver (use Xinput to get axis valuators), * output the calibration as Xorg.conf, HAL policy and udev rule, * support advanced driver options, such as Evdev's dynamic calibration, * have a very intuitive GUI (normal X client). Xinput_calibrator is based on a simple calibrator that was proposed on the Xorg mailinglist. The first release(v0.2.0) improved upon it by reading axis valuators from Xinput, hence making it generic for all touchscreen drivers. The announcement was done on the Xorg mailinglist, and the code is on Tias' webpage. Starting from v0.4.0, it writes Xorg.conf and (HAL) FDI policy file values, and contains a wrapper script to get axis valuator information for the evtouch driver (evtouch does not export the current calibration through its axis valuators). It is also the first program to support dynamic evdev calibration, by using its advanced Xinput functionality. The v0.5.0 version is written entirely in the X window system, needing no external dependencies. Because of its modular structure, other frontends can be easily created too. Version v0.6.0 has a proper build system and gained a lot of features thanks to the feedback of different users. Version 0.7.0 has mis-click detection and proper packaging support: proper make dist, one binary, has manpage, menu entry and icon. DEB and RPM package meta-data in their respective VCS branches.