00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <errno.h>
00035 #include <unistd.h>
00036 #include <math.h>
00037 #include <string.h>
00038 #include <sys/ioctl.h>
00039
00040 #include <glib.h>
00041 #include <gtk/gtk.h>
00042 #include <gdk/gdk.h>
00043 #include <gdk/gdkx.h>
00044
00045 #include <X11/extensions/xcalibrate.h>
00046 #include <X11/extensions/Xrandr.h>
00047
00048 #include "h3600_ts.h"
00049 #include "calibrate.h"
00050 #include "i18n.h"
00051 #include "ts.h"
00052
00053 Display *dpy;
00054 int screen_x = 768;
00055 int screen_y = 1024;
00056 int flag_debug = 0;
00057 int flag_sanityCheck = 1;
00058 int flag_firstBoot = 0;
00059 int rotation = 0;
00060 int xcal_error_base;
00061 int xcal_event_base;
00062 int calibration_done = 0;
00063 GtkWidget *da;
00064 char* g_defaultcalfile = "/home/root/.pointercal";
00065 char* g_calfile = NULL;
00066 GdkGC* gc = NULL;
00067
00068
00069
00070
00071 void usage (const char *name)
00072 {
00073 fprintf (stderr, "usage: %s -view\n", name);
00074 fprintf (stderr, " %s [-rotate <0 | 90 | 180 | 270>]\n", name);
00075 fprintf (stderr, " %s -cal <xs> <xt> <ys> <yt> <xyswap>\n", name);
00076 fprintf (stderr, " %s [-nocheck]\n", name);
00077 fprintf (stderr, " %s [-firstboot]\n", name);
00078 fprintf (stderr, " %s [-debug]\n", name);
00079
00080 exit (1);
00081 }
00082
00083
00084
00085
00086 void parse_args(int argc, char *argv[])
00087 {
00088 int i;
00089 for (i = 1; i < argc; i++)
00090 {
00091 if (!strcmp (argv[i], "-view"))
00092 {
00093 ts_show_calibration();
00094 exit (0);
00095 }
00096 else if (!strcmp (argv[i], "-debug"))
00097 {
00098 flag_debug = 1;
00099 }
00100 else if (!strcmp (argv[i], "-firstboot"))
00101 {
00102 flag_firstBoot = 1;
00103 }
00104 else if (!strcmp (argv[i], "-nocheck"))
00105 {
00106 flag_sanityCheck = 0;
00107 }
00108 else if (!strcmp (argv[i], "-cal"))
00109 {
00110 if (argc > (i + 5))
00111 {
00112 ts_set_calibration(argv + i + 1);
00113 exit(0);
00114 }
00115 else
00116 {
00117 usage (argv[0]);
00118 }
00119 }
00120 else if (!strcmp (argv[i], "-rotate"))
00121 {
00122 if (argc > (i + 1))
00123 rotation = atoi (argv[++i]);
00124 else
00125 usage (argv[0]);
00126 }
00127 else
00128 {
00129 usage(argv[0]);
00130 }
00131 }
00132 }
00133
00134
00135
00136
00137 int xrandr_supported()
00138 {
00139 int xrr_event_base, xrr_error_base;
00140 int xrr_major, xrr_minor;
00141
00142 if (XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base) == False
00143 || XRRQueryVersion (dpy, &xrr_major, &xrr_minor) == 0
00144 || xrr_major != 1
00145 || xrr_minor < 1)
00146 return 0;
00147
00148 return 1;
00149 }
00150
00151
00152
00153
00154
00155 void next_target()
00156 {
00157 gtk_widget_queue_draw(da);
00158 gdk_flush();
00159 }
00160
00161
00162
00163
00164
00165 gboolean on_delayed_quit(gpointer data)
00166 {
00167 gtk_main_quit();
00168 return FALSE;
00169 }
00170
00171
00172
00173
00174 GdkFilterReturn evt_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data)
00175 {
00176 XEvent *xev = (XEvent*)xevent;
00177 int ret;
00178
00179 if (xev->type==xcal_event_base && (!calibration_done))
00180 {
00181 XCalibrateRawTouchscreenEvent *tev = (XCalibrateRawTouchscreenEvent*)xev;
00182 ret = ts_handle_event (tev->x, tev->y, tev->pressure);
00183
00184 if (ret==TS_CALIBRATION_DONE)
00185 {
00186 calibration_done = 1;
00187 ts_write_calibration (g_calfile);
00188 XCalibrateSetRawMode (dpy, False);
00189
00190 next_target();
00191 g_timeout_add_seconds(flag_firstBoot ? 1 : 2, on_delayed_quit, NULL);
00192 }
00193 }
00194 return GDK_FILTER_CONTINUE;
00195 }
00196
00197
00198
00199
00200 static void draw_cross(GtkWidget *widget, gdouble x, gdouble y)
00201 {
00202 int size = 8;
00203
00204 if (!gc)
00205 {
00206 gc = gdk_gc_new(widget->window);
00207 gdk_gc_copy(gc, widget->style->black_gc);
00208 gdk_gc_set_line_attributes (gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
00209 }
00210 gdk_draw_line(widget->window, gc,
00211 x-size, y-size, x+size, y+size);
00212 gdk_draw_line(widget->window, gc,
00213 x-size, y+size, x+size, y-size);
00214 }
00215
00216
00217
00218
00219 static gboolean da_expose (GtkWidget *da, GdkEventExpose *evt, gpointer data)
00220 {
00221 char *msg = NULL;
00222
00223 if (calibration_done)
00224 {
00225 msg = g_strdup(_("The stylus is now calibrated with this device."));
00226 }
00227 else
00228 {
00229 char *tip = NULL;
00230 tip = _("Touch the center of each cross with the stylus as they appear on the screen.\n\n"
00231 "For the most accurate result, hold the stylus comfortably in your hand and "
00232 "touch the screen at the same angle as you would when you write with a regular "
00233 "pen on paper.");
00234
00235 if (flag_firstBoot)
00236 {
00237 msg = g_strconcat(_("Before you continue, you need to calibrate the stylus. After this short "
00238 "calibration, you will be able to work more accurately with the device.\n\n"), tip, NULL);
00239 }
00240 else
00241 {
00242 msg = g_strdup(tip);
00243 }
00244 }
00245
00246
00247 PangoLayout *layout = gtk_widget_create_pango_layout(da, msg);
00248 pango_layout_set_width(layout, pango_units_from_double(screen_x)*2/3);
00249 int x, y;
00250 int lw, lh;
00251 ts_get_target(0, &x, &y);
00252 pango_layout_get_pixel_size(layout, &lw, &lh);
00253
00254
00255
00256
00257 int ypos = (((screen_y/2)+y)/2) - (lh/2);
00258 pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
00259 gdk_draw_layout(da->window, da->style->black_gc, screen_x/6, ypos, layout);
00260 g_object_unref(layout);
00261 if (!calibration_done)
00262 {
00263
00264 int x,y;
00265 ts_get_current_target(&x, &y);
00266 draw_cross(da, x, y);
00267 }
00268 g_free(msg);
00269 gdk_flush();
00270 return TRUE;
00271 }
00272
00273
00274 static gboolean my_gdk_flush(gpointer data)
00275 {
00276 gdk_flush();
00277 return FALSE;
00278 }
00279
00280
00281
00282
00283 int main (int argc, char *argv[])
00284 {
00285 GtkWidget *window;
00286 int screen;
00287
00288
00289 textdomain(GETTEXT_PACKAGE);
00290
00291
00292 gtk_init(&argc, &argv);
00293 parse_args(argc, argv);
00294 if ((g_calfile = getenv("TSLIB_CALIBFILE")) == NULL)
00295 {
00296 g_calfile = g_defaultcalfile;
00297 }
00298
00299 ts_read_current_settings(g_calfile);
00300
00301 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00302 gtk_window_set_title(GTK_WINDOW(window), PACKAGE " " VERSION);
00303 gtk_window_maximize(GTK_WINDOW(window));
00304 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
00305 gtk_container_set_border_width(GTK_CONTAINER(window), 0);
00306 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
00307 gtk_window_fullscreen(GTK_WINDOW(window));
00308
00309 gdk_window_add_filter(NULL, evt_filter, NULL);
00310
00311 GdkDisplay *gdpy = gdk_display_get_default();
00312 dpy = gdk_x11_display_get_xdisplay(gdpy);
00313 screen = DefaultScreen(dpy);
00314
00315 da = gtk_drawing_area_new ();
00316 gtk_widget_set_size_request (da, screen_x, screen_y);
00317 gtk_container_add (GTK_CONTAINER (window), da);
00318 g_signal_connect (da, "expose_event", G_CALLBACK (da_expose), NULL);
00319
00320 if (XCalibrateQueryExtension (dpy, &xcal_event_base, &xcal_error_base))
00321 {
00322 int r;
00323 r = XCalibrateSetRawMode (dpy, True);
00324 if (r)
00325 {
00326 fprintf (stderr, "failed to set raw mode: error %d\n", r);
00327 exit (1);
00328 }
00329 } else {
00330 fprintf (stderr, "XCalibrate extension not available, unable to calibrate\n");
00331 exit (1);
00332 }
00333
00334 if (xrandr_supported())
00335 {
00336
00337 XRRScreenConfiguration *rr_screen;
00338 XRRScreenSize *rr_sizes;
00339 int rr_num_sizes;
00340 Rotation current_rotation;
00341 rr_screen = XRRGetScreenInfo (dpy, RootWindow (dpy, screen));
00342 XRRRotations (dpy, screen, ¤t_rotation);
00343 rr_sizes = XRRSizes(dpy, screen, &rr_num_sizes);
00344 XRRFreeScreenConfigInfo (rr_screen);
00345
00346 switch (current_rotation)
00347 {
00348 case RR_Rotate_0: rotation = 0; break;
00349 case RR_Rotate_90: rotation = 90; break;
00350 case RR_Rotate_180: rotation = 180; break;
00351 case RR_Rotate_270: rotation = 270; break;
00352 }
00353
00354 if (rotation==90 || rotation==270)
00355 {
00356 screen_x = rr_sizes->height;
00357 screen_y = rr_sizes->width;
00358 }
00359 else
00360 {
00361 screen_x = rr_sizes->width;
00362 screen_y = rr_sizes->height;
00363 }
00364 }
00365 if (flag_debug)
00366 {
00367 fprintf (stderr, "Screen %dx%d rotated %d\n", screen_x, screen_y, rotation);
00368 }
00369
00370
00371 ts_init(screen_x, screen_y, rotation);
00372
00373 gtk_widget_show_all(window);
00374 g_idle_add(my_gdk_flush, NULL);
00375
00376 gtk_main();
00377
00378 return 0;
00379 }