• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

A generic touchscreen calibration program for X.Org


Commit MetaInfo

Revision081dbca29ffa089252e2bfbeaf1961f1c0002606 (tree)
Time2010-01-11 05:31:03
AuthorTias Guns <tias@ulys...>
CommiterTias Guns

Log Message

New X11 based gui,

Looks and feels like the gtkmm based one, but written purely in the X
windowing system.

Change Summary

Incremental Difference

--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,11 @@
1-all: xinput_calibrator.old xinput_calibrator.gtkmm
1+all: xinput_calibrator.x11 xinput_calibrator.gtkmm
22
3-xinput_calibrator.old: xinput_calibrator.cc
4- g++ -Wall xinput_calibrator.cc `pkg-config --cflags --libs gtkmm-2.4` -o xinput_calibrator.old
3+xinput_calibrator.x11: main_x11.cpp gui_x11.cpp
4+ g++ -Wall main_x11.cpp -lX11 -lXi -o xinput_calibrator.x11
5+ cp xinput_calibrator.x11 xinput_calibrator
56
67 xinput_calibrator.gtkmm: main_gtkmm.cpp gui_gtkmm.cpp
78 g++ -Wall main_gtkmm.cpp `pkg-config --cflags --libs gtkmm-2.4` -o xinput_calibrator.gtkmm
9+
10+clean:
11+ rm -f xinput_calibrator xinput_calibrator.x11 xinput_calibrator.gtkmm
--- /dev/null
+++ b/gui_x11.cpp
@@ -0,0 +1,320 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+#include <X11/X.h>
23+#include <X11/Xlib.h>
24+#include <X11/Xutil.h>
25+#include <X11/Xos.h> // strncpy, strlen
26+
27+#include <stdlib.h>
28+#include <stdio.h>
29+#include <signal.h>
30+#include <string.h>
31+
32+#include "calibrator.hh"
33+
34+
35+// Timeout parameters
36+const int time_step = 100; // in milliseconds
37+const int max_time = 15000; // 5000 = 5 sec
38+
39+// Clock appereance
40+const int cross_lines = 25;
41+const int cross_circle = 4;
42+const int clock_radius = 50;
43+const int clock_line_width = 10;
44+
45+// Text printed on screen
46+const int font_size = 16;
47+const int help_lines = 4;
48+const std::string help_text[help_lines] = {
49+ "Touchscreen Calibration",
50+ "Press the point, use a stylus to increase precision.",
51+ "",
52+ "(To abort, press any key or wait)"
53+};
54+
55+// color management
56+enum { BLACK=0, WHITE=1, GRAY=2, DIMGRAY=3, RED=4 };
57+const int nr_colors = 5;
58+const char* colors[nr_colors] = {"BLACK", "WHITE", "GRAY", "DIMGRAY", "RED"};
59+
60+
61+void sigalarm_handler(int num);
62+
63+
64+/*******************************************
65+ * X11 class for the the calibration GUI
66+ *******************************************/
67+class GuiCalibratorX11
68+{
69+public:
70+ GuiCalibratorX11(Calibrator* w);
71+ ~GuiCalibratorX11();
72+ static bool set_instance(GuiCalibratorX11* W);
73+ static void give_timer_signal();
74+
75+protected:
76+ // Data
77+ Calibrator* calibrator;
78+ double X[4], Y[4];
79+ int display_width, display_height;
80+ int time_elapsed;
81+
82+ // X11 vars
83+ Display* display;
84+ Window win;
85+ GC gc;
86+ XFontStruct* font_info;
87+ // color mngmt
88+ unsigned long pixel[nr_colors];
89+
90+
91+ // Signal handlers
92+ bool on_timer_signal();
93+ bool on_expose_event();
94+ bool on_button_press_event(XEvent event);
95+
96+ // Helper functions
97+ void redraw();
98+
99+private:
100+ static GuiCalibratorX11* instance;
101+};
102+GuiCalibratorX11* GuiCalibratorX11::instance = NULL;
103+
104+
105+GuiCalibratorX11::GuiCalibratorX11(Calibrator* calibrator0)
106+ : calibrator(calibrator0), time_elapsed(0)
107+{
108+ display = XOpenDisplay(NULL);
109+ if (display == NULL) {
110+ throw std::runtime_error("Unable to connect to X server");
111+ }
112+ // Load font and get font information structure
113+ font_info = XLoadQueryFont(display, "9x15");
114+ if (font_info == NULL) {
115+ XCloseDisplay(display);
116+ throw std::runtime_error("Unable to open 9x15 font");
117+ }
118+
119+ // Compute absolute circle centers
120+ int screen_num = DefaultScreen(display);
121+ display_width = DisplayWidth(display, screen_num);
122+ display_height = DisplayHeight(display, screen_num);
123+
124+ const int delta_x = display_width/num_blocks;
125+ const int delta_y = display_height/num_blocks;
126+ X[UL] = delta_x; Y[UL] = delta_y;
127+ X[UR] = display_width - delta_x - 1; Y[UR] = delta_y;
128+ X[LL] = delta_x; Y[LL] = display_height - delta_y - 1;
129+ X[LR] = display_width - delta_x - 1; Y[LR] = display_height - delta_y - 1;
130+
131+ // Register events on the window
132+ XSetWindowAttributes attributes;
133+ attributes.override_redirect = True;
134+ attributes.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
135+
136+ win = XCreateWindow(display, RootWindow(display, screen_num),
137+ 0, 0, display_width, display_height, 0,
138+ CopyFromParent, InputOutput, CopyFromParent,
139+ CWOverrideRedirect | CWEventMask,
140+ &attributes);
141+ XMapWindow(display, win);
142+
143+ // Listen to events
144+ XGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync,
145+ CurrentTime);
146+ XGrabPointer(display, win, False, ButtonPressMask, GrabModeAsync,
147+ GrabModeAsync, None, None, CurrentTime);
148+
149+ Colormap colormap = DefaultColormap(display, screen_num);
150+ XColor color;
151+ for (int i = 0; i != nr_colors; i++) {
152+ XParseColor(display, colormap, colors[i], &color);
153+ XAllocColor(display, colormap, &color);
154+ pixel[i] = color.pixel;
155+ }
156+ XSetWindowBackground(display, win, pixel[GRAY]);
157+ XClearWindow(display, win);
158+
159+ gc = XCreateGC(display, win, 0, NULL);
160+ XSetFont(display, gc, font_info->fid);
161+
162+ // Setup timer for animation
163+ signal(SIGALRM, sigalarm_handler);
164+ struct itimerval timer;
165+ timer.it_value.tv_sec = time_step/1000;
166+ timer.it_value.tv_usec = (time_step % 1000) * 1000;
167+ timer.it_interval = timer.it_value;
168+ setitimer(ITIMER_REAL, &timer, NULL);
169+}
170+
171+GuiCalibratorX11::~GuiCalibratorX11()
172+{
173+ XUngrabPointer(display, CurrentTime);
174+ XUngrabKeyboard(display, CurrentTime);
175+ XFreeGC(display, gc);
176+ XCloseDisplay(display);
177+}
178+
179+void GuiCalibratorX11::redraw()
180+{
181+ // Print the text
182+ int text_height = font_info->ascent + font_info->descent;
183+ int text_width = -1;
184+ for (int i = 0; i != help_lines; i++) {
185+ text_width = std::max(text_width, XTextWidth(font_info,
186+ help_text[i].c_str(), help_text[i].length()));
187+ }
188+
189+ int x = (display_width - text_width) / 2;
190+ int y = (display_height - text_height) / 2 - 60;
191+ XSetForeground(display, gc, pixel[BLACK]);
192+ XSetLineAttributes(display, gc, 2, LineSolid, CapRound, JoinRound);
193+ XDrawRectangle(display, win, gc, x - 10, y - (help_lines*text_height) - 10,
194+ text_width + 20, (help_lines*text_height) + 20);
195+
196+ // Print help lines
197+ y -= 3;
198+ for (int i = help_lines-1; i != -1; i--) {
199+ int w = XTextWidth(font_info, help_text[i].c_str(), help_text[i].length());
200+ XDrawString(display, win, gc, x + (text_width-w)/2, y,
201+ help_text[i].c_str(), help_text[i].length());
202+ y -= text_height;
203+ }
204+
205+ // Draw the points
206+ for (int i = 0; i <= calibrator->get_numclicks(); i++) {
207+ // set color: already clicked or not
208+ if (i < calibrator->get_numclicks())
209+ XSetForeground(display, gc, pixel[WHITE]);
210+ else
211+ XSetForeground(display, gc, pixel[RED]);
212+ XSetLineAttributes(display, gc, 1, LineSolid, CapRound, JoinRound);
213+
214+ XDrawLine(display, win, gc, X[i] - cross_lines, Y[i],
215+ X[i] + cross_lines, Y[i]);
216+ XDrawLine(display, win, gc, X[i], Y[i] - cross_lines,
217+ X[i], Y[i] + cross_lines);
218+ XDrawArc(display, win, gc, X[i] - cross_circle, Y[i] - cross_circle,
219+ (2 * cross_circle), (2 * cross_circle), 0, 360 * 64);
220+ }
221+
222+ // Draw the clock background
223+ XSetForeground(display, gc, pixel[DIMGRAY]);
224+ XSetLineAttributes(display, gc, 0, LineSolid, CapRound, JoinRound);
225+ XFillArc(display, win, gc, (display_width-clock_radius)/2, (display_height - clock_radius)/2,
226+ clock_radius, clock_radius, 0, 360 * 64);
227+}
228+
229+bool GuiCalibratorX11::on_expose_event()
230+{
231+ redraw();
232+
233+ return true;
234+}
235+
236+bool GuiCalibratorX11::on_timer_signal()
237+{
238+ time_elapsed += time_step;
239+ if (time_elapsed > max_time) {
240+ exit(0);
241+ }
242+
243+ // Update clock
244+ XSetForeground(display, gc, pixel[BLACK]);
245+ XSetLineAttributes(display, gc, clock_line_width,
246+ LineSolid, CapButt, JoinMiter);
247+ XDrawArc(display, win, gc, (display_width-clock_radius+clock_line_width)/2,
248+ (display_height-clock_radius+clock_line_width)/2,
249+ clock_radius-clock_line_width, clock_radius-clock_line_width,
250+ 90*64, ((double)time_elapsed/(double)max_time) * -360 * 64);
251+
252+ return true;
253+}
254+
255+bool GuiCalibratorX11::on_button_press_event(XEvent event)
256+{
257+ // Handle click
258+ time_elapsed = 0;
259+ calibrator->add_click(event.xbutton.x, event.xbutton.y);
260+
261+ // Are we done yet?
262+ if (calibrator->get_numclicks() >= 4) {
263+ // Recalibrate
264+ calibrator->finish(display_width, display_height);
265+
266+ exit(0);
267+ }
268+
269+ // Force a redraw
270+ redraw();
271+
272+ return true;
273+}
274+
275+void GuiCalibratorX11::give_timer_signal()
276+{
277+ if (instance != NULL) {
278+ // timer signal
279+ //check timeout
280+ instance->on_timer_signal();
281+
282+ // process events
283+ XEvent event;
284+ while (XCheckWindowEvent(instance->display, instance->win, -1, &event) == True) {
285+ switch (event.type) {
286+ case Expose:
287+ // only draw the last contiguous expose
288+ if (event.xexpose.count != 0)
289+ break;
290+ instance->on_expose_event();
291+ break;
292+
293+ case ButtonPress:
294+ instance->on_button_press_event(event);
295+ break;
296+
297+ case KeyPress:
298+ exit(0);
299+ break;
300+ }
301+ }
302+ }
303+}
304+
305+bool GuiCalibratorX11::set_instance(GuiCalibratorX11* W)
306+{
307+ bool wasSet = (instance != NULL);
308+ instance = W;
309+
310+ return wasSet;
311+}
312+
313+
314+// handle SIGALRM signal, pass to singleton
315+void sigalarm_handler(int num)
316+{
317+ if (num == SIGALRM) {
318+ GuiCalibratorX11::give_timer_signal();
319+ }
320+}
--- /dev/null
+++ b/main_x11.cpp
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#include "main_common.hpp"
24+#include "gui_x11.cpp"
25+
26+int main(int argc, char** argv)
27+{
28+ Calibrator* calibrator = main_common(argc, argv);
29+
30+ GuiCalibratorX11 gui(calibrator);
31+ GuiCalibratorX11::set_instance(&gui);
32+
33+ // wait for timer signal, processes events
34+ while(1)
35+ pause();
36+
37+ delete calibrator;
38+ return 0;
39+}