📄 main.c
字号:
/*
* Copyright (C) 2003, 2004 Philip Blundell <philb@gnu.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <math.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xrandr.h>
#include <X11/Xft/Xft.h>
#include <X11/extensions/xcalibrate.h>
#include <X11/keysym.h>
#include "h3600_ts.h"
#include "calibrate.h"
Display *dpy;
int screen;
Window w;
Window crosshair_w;
GC crosshair_gc;
Cursor cursor;
Picture pict;
XRectangle rectangles[2];
XRenderColor rect_color;
int crosshair_x, crosshair_y;
int event;
XftColor xftcol;
XftDraw *xftdraw;
XftFont *xftfont;
int screen_x, screen_y;
int ts_fd;
int samples;
Pixmap bg_pixmap;
int flag_debug;
int rotation = 0;
int error_base, event_base;
int using_xcalibrate=0;
int moving;
#define CROSSHAIR_SIZE 25
#define OFFSET 24
#define WIDTH 3
#define SPEED 8
#define ENOUGH 5
#define MAX_SAMPLES 40
#define RAW_DEVICE "/dev/tsraw"
//#define FONTNAME "sans-10"
#define FONTNAME "Sans-24:bold"
#define XCAL_SCRIPT_FILE ".xtscal"
struct point
{
int x;
int y;
};
struct point sample[MAX_SAMPLES];
calibration cal;
void handle_ts_event (int x, int y, int pressure);
void
hide_cursor (Display *dpy, Window w)
{
Pixmap pix;
XColor col;
Cursor blank_curs;
pix = XCreatePixmap (dpy, w, 1, 1, 1);
memset (&col, 0, sizeof (col));
blank_curs = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 1, 1);
XFreePixmap (dpy, pix);
XDefineCursor (dpy, w, blank_curs);
}
void
draw_crosshair (void)
{
XftDraw *draw;
XRenderPictureAttributes att;
crosshair_gc = XCreateGC (dpy, crosshair_w, 0, NULL);
XSetForeground (dpy, crosshair_gc, WhitePixel (dpy, screen));
draw = XftDrawCreate (dpy, crosshair_w,
DefaultVisual (dpy, screen),
DefaultColormap (dpy, screen));
pict = XftDrawPicture (draw);
att.poly_edge = PolyEdgeSmooth;
XRenderChangePicture (dpy, pict, CPPolyEdge, &att);
rect_color.red = 0;
rect_color.green = 0;
rect_color.blue = 0xffff;
rect_color.alpha = 0xffff;
rectangles[0].x = 0;
rectangles[0].width = CROSSHAIR_SIZE;
rectangles[0].y = (CROSSHAIR_SIZE / 2) - (WIDTH / 2);
rectangles[0].height = WIDTH;
rectangles[1].x = (CROSSHAIR_SIZE / 2) - (WIDTH / 2);
rectangles[1].width = WIDTH;
rectangles[1].y = 0;
rectangles[1].height = CROSSHAIR_SIZE;
}
void
crosshair_expose (void)
{
XRenderFillRectangles (dpy, PictOpSrc, pict, &rect_color, rectangles, 2);
XFillArc (dpy, crosshair_w, crosshair_gc, (CROSSHAIR_SIZE / 2) - (WIDTH / 2) - 1,
(CROSSHAIR_SIZE / 2) - (WIDTH / 2) - 1,
WIDTH + 1, WIDTH + 1, 0, 360 * 64);
}
void
draw_background (void)
{
static const char *str[] =
{
/* "Touch the crosshairs to",
"calibrate the screen" */
"请点击十字线",
" 校准屏幕"
};
const char **sp;
int y;
y = screen_y / 3;
for (sp = str; *sp; sp++)
{
XGlyphInfo extents;
XftTextExtentsUtf8 (dpy, xftfont, *sp, strlen (*sp),
&extents);
XftDrawStringUtf8 (xftdraw, &xftcol, xftfont,
(screen_x / 2) - (extents.width / 2), y,
*sp, strlen (*sp));
y += extents.height + 4;
}
}
void
handle_events (void)
{
while (XPending (dpy))
{
XEvent e;
XNextEvent (dpy, &e);
switch (e.type)
{
case KeyPress:
if (XKeycodeToKeysym (dpy, e.xkey.keycode, 0) == XK_Escape)
exit (0);
break;
case Expose:
if (e.xexpose.window == crosshair_w)
crosshair_expose ();
break;
default:
if (e.type == event_base)
{
XCalibrateRawTouchscreenEvent *te = (XCalibrateRawTouchscreenEvent *)&e;
handle_ts_event (te->x, te->y, te->pressure);
}
break;
}
}
}
void
crosshair_to (int x, int y)
{
int dx, dy;
double r;
dx = x - crosshair_x;
dy = y - crosshair_y;
if (dx == 0 && dy == 0)
return;
moving = True;
r = (double)dy / (double)dx;
if (fabs (r) < 1.0)
{
int i, xs;
double fy = crosshair_y;
xs = (crosshair_x > x) ? -SPEED : SPEED;
for (i = crosshair_x; (i - x) / SPEED; )
{
int midpoint = (x + crosshair_x) / 2;
int distance_from_midpoint = abs(i - midpoint);
int distance_from_endpoint = abs(x - crosshair_x) / 2 - distance_from_midpoint;
int xsadjust = xs + (xs >> 3) * distance_from_endpoint / 10;
i += xsadjust;
fy += r * xsadjust;
XMoveWindow (dpy, crosshair_w, i, fy);
XFlush (dpy);
handle_events ();
usleep (5000);
}
}
else
{
int i, ys;
double fx = crosshair_x;
r = (double)dx / (double)dy;
ys = (crosshair_y > y) ? -SPEED : SPEED;
for (i = crosshair_y; (i - y) / SPEED; )
{
int midpoint = (y + crosshair_y) / 2;
int distance_from_midpoint = abs(i - midpoint);
int distance_from_endpoint = abs(y - crosshair_y) / 2 - distance_from_midpoint;
int ysadjust = ys + (ys >> 3) * distance_from_endpoint / 10;
i += ysadjust;
fx += r * ysadjust;
XMoveWindow (dpy, crosshair_w, fx, i);
XFlush (dpy);
handle_events ();
usleep (5000);
}
}
XMoveWindow (dpy, crosshair_w, x, y);
crosshair_x = x;
crosshair_y = y;
moving = False;
}
void
next_event (void)
{
crosshair_to (cal.xscr[event] - CROSSHAIR_SIZE / 2, cal.yscr[event] - CROSSHAIR_SIZE / 2);
}
int
sort_by_x (const void* a, const void *b)
{
return (((struct point *)a)->x - ((struct point *)b)->x);
}
int
sort_by_y (const void* a, const void *b)
{
return (((struct point *)a)->y - ((struct point *)b)->y);
}
void
set_calibration (calibration *cal)
{
TS_CAL tc;
int xtrans, ytrans, xscale, yscale, xyscale, yxscale;
calibration ocal = *cal;
if (using_xcalibrate)
{
FILE *fp;
if (flag_debug)
printf ("constants are: %d %d %d %d %d %d %d\n", cal->a[1], cal->a[2], cal->a[0], cal->a[4], cal->a[5], cal->a[3], cal->a[6]);
fp = fopen ("/etc/pointercal", "w");
if (!fp)
{
perror ("/etc/pointercal");
exit (1);
}
fprintf (fp, "%d %d %d %d %d %d %d\n", cal->a[1], cal->a[2], cal->a[0], cal->a[4], cal->a[5], cal->a[3], cal->a[6]);
fclose (fp);
return;
}
xtrans = cal->a[0] / cal->a[6];
ytrans = cal->a[3] / cal->a[6];
xscale = cal->a[1] * 256 / cal->a[6];
yscale = cal->a[5] * 256 / cal->a[6];
xyscale = cal->a[2] * 256 / cal->a[6];
yxscale = cal->a[4] * 256 / cal->a[6];
tc.xtrans = xtrans;
tc.ytrans = ytrans;
if (xscale == 0 || yscale == 0) {
tc.xscale = yxscale;
tc.yscale = xyscale;
tc.xyswap = 1;
} else {
tc.xscale = xscale;
tc.yscale = yscale;
tc.xyswap = 0;
}
fprintf (stderr, "constants are:%d %d %d %d %d %d %d\n", tc.xscale, tc.xtrans, tc.yscale, tc.ytrans, tc.xyswap, xyscale, yxscale);
{
char filepath[0x100];
FILE * fp;
sprintf(filepath, "%s/%s", getenv("HOME"), XCAL_SCRIPT_FILE);
fp = fopen(filepath, "w");
if(fp) {
fprintf(fp, "%d %d %d %d %d\n", tc.xscale, tc.xtrans, tc.yscale, tc.ytrans, tc.xyswap);
fclose(fp);
}
}
if (ioctl (ts_fd, TS_SET_CAL, (void *)&tc) != 0)
{
perror ("TS_SET_CAL");
exit (1);
}
}
void
handle_ts_event (int x, int y, int pressure)
{
if (moving)
{
/* Ignore any accidental clicks during animation */
return;
}
if (pressure)
{
if (samples < MAX_SAMPLES)
{
sample[samples].x = x;
sample[samples].y = y;
samples++;
}
}
else
{
if (samples > ENOUGH)
{
int middle, sx, sy;
middle = samples / 2;
qsort (sample, samples, sizeof(struct point), sort_by_x);
if (samples & 1)
sx = sample[middle].x;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -