Merge lp:~mtdev-team/mtview/trunk.v1.1.3 into lp:mtview
- trunk.v1.1.3
- Merge into trunk
Proposed by
Henrik Rydberg
Status: | Merged |
---|---|
Merged at revision: | 18 |
Proposed branch: | lp:~mtdev-team/mtview/trunk.v1.1.3 |
Merge into: | lp:mtview |
Diff against target: |
453 lines (+248/-87) 3 files modified
configure.ac (+9/-1) tools/Makefile.am (+8/-0) tools/mtview.c (+231/-86) |
To merge this branch: | bzr merge lp:~mtdev-team/mtview/trunk.v1.1.3 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chase Douglas | Approve | ||
Review via email: mp+50774@code.launchpad.net |
This proposal supersedes a proposal from 2011-02-21.
Commit message
Description of the change
v1.0.2: Reworked mtview with optional XI2.1 support and the ability to draw in multiple windows simultaneously.
v1.0.3: Adjusted api to latest version (February 2011).
To post a comment you must log in.
Revision history for this message
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal | # |
review:
Needs Fixing
Revision history for this message
Henrik Rydberg (rydberg) wrote : Posted in a previous version of this proposal | # |
Like this? (new branch pushed)
Revision history for this message
Henrik Rydberg (rydberg) wrote : | # |
I am going ahead and merging this since the problem is trivially fixed.
Revision history for this message
Chase Douglas (chasedouglas) wrote : | # |
To finish off, yes, this looks good :). I forgot about a dentist appointment, so I had to run!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'configure.ac' |
2 | --- configure.ac 2011-01-03 18:56:34 +0000 |
3 | +++ configure.ac 2011-02-22 16:17:18 +0000 |
4 | @@ -1,7 +1,7 @@ |
5 | # Initialize Autoconf |
6 | AC_PREREQ([2.60]) |
7 | AC_INIT([Multitouch Viewer], |
8 | - [1.1.1], |
9 | + [1.1.3], |
10 | [], |
11 | [mtview]) |
12 | AC_CONFIG_SRCDIR([Makefile.am]) |
13 | @@ -27,6 +27,14 @@ |
14 | PKG_CHECK_MODULES([FRAME], [utouch-frame >= 1.0]) |
15 | PKG_CHECK_MODULES([X11], [x11]) |
16 | |
17 | +AC_ARG_WITH([xi], AS_HELP_STRING([--with-xi], [Build with XI2.1 support])) |
18 | +AM_CONDITIONAL([HAVE_XI], [test "x$with_xi" != "x"]) |
19 | + |
20 | +AS_IF([test "x$with_xi" = "xyes"], [ |
21 | + PKG_CHECK_MODULES(XINPUT, x11 xext [xi >= 1.4.1.99.1] [inputproto >= 2.0.99.1]) |
22 | + AC_DEFINE([HAVE_XI], [1], [XI2.1 support]) |
23 | +]) |
24 | + |
25 | AC_CONFIG_FILES([Makefile |
26 | tools/Makefile |
27 | mtview.pc]) |
28 | |
29 | === modified file 'tools/Makefile.am' |
30 | --- tools/Makefile.am 2011-01-02 13:26:14 +0000 |
31 | +++ tools/Makefile.am 2011-02-22 16:17:18 +0000 |
32 | @@ -4,3 +4,11 @@ |
33 | |
34 | mtview_SOURCES = mtview.c |
35 | mtview_LDFLAGS = -lX11 -lutouch-frame -lutouch-evemu -lmtdev -lm |
36 | + |
37 | +if HAVE_XI |
38 | + |
39 | +AM_CFLAGS = $(XINPUT_CFLAGS) |
40 | + |
41 | +mtview_LDFLAGS += $(XINPUT_LIBS) |
42 | + |
43 | +endif |
44 | |
45 | === modified file 'tools/mtview.c' |
46 | --- tools/mtview.c 2011-01-02 13:26:14 +0000 |
47 | +++ tools/mtview.c 2011-02-22 16:17:18 +0000 |
48 | @@ -1,22 +1,29 @@ |
49 | +#include "config.h" |
50 | #include <X11/Xlib.h> |
51 | #include <stdio.h> |
52 | #include <fcntl.h> |
53 | #include <utouch/frame-mtdev.h> |
54 | +#if HAVE_XI |
55 | +#include <utouch/frame-xi2.h> |
56 | +#endif |
57 | +#include <stdlib.h> |
58 | +#include <unistd.h> |
59 | #include <string.h> |
60 | #include <math.h> |
61 | |
62 | -#define XMARG 16 |
63 | -#define YMARG 16 |
64 | #define DEF_FRAC 0.15 |
65 | #define DEF_WIDTH 0.05 |
66 | |
67 | #define DIM_TOUCH 32 |
68 | |
69 | +static int opcode; |
70 | + |
71 | struct windata { |
72 | Display *dsp; |
73 | - Window root, win; |
74 | + Window win; |
75 | GC gc; |
76 | - int screen, width, height; |
77 | + int screen; |
78 | + float off_x, off_y; |
79 | unsigned long white, black; |
80 | unsigned long color[DIM_TOUCH]; |
81 | int id[DIM_TOUCH]; |
82 | @@ -32,26 +39,28 @@ |
83 | return lrand48() & 0xffffff; |
84 | } |
85 | |
86 | -static void clear_screen(struct windata *w) |
87 | +static void clear_screen(utouch_frame_handle fh, struct windata *w) |
88 | { |
89 | + const struct utouch_surface *s = utouch_frame_get_surface(fh); |
90 | + int width = s->mapped_max_x - s->mapped_min_x; |
91 | + int height = s->mapped_max_y - s->mapped_min_y; |
92 | + |
93 | XSetForeground(w->dsp, w->gc, w->black); |
94 | - XFillRectangle(w->dsp, w->win, w->gc, 0, 0, w->width, w->height); |
95 | + XFillRectangle(w->dsp, w->win, w->gc, 0, 0, width, height); |
96 | } |
97 | |
98 | static void output_touch(utouch_frame_handle fh, struct windata *w, |
99 | const struct utouch_contact *t) |
100 | { |
101 | const struct utouch_surface *s = utouch_frame_get_surface(fh); |
102 | - |
103 | - float x1 = s->min_x, y1 = s->min_y; |
104 | - float x2 = s->max_x, y2 = s->max_y; |
105 | - float dx = x2 - x1, dy = y2 - y1; |
106 | + float dx = s->mapped_max_x - s->mapped_min_x; |
107 | + float dy = s->mapped_max_y - s->mapped_min_y; |
108 | + float x = t->x - w->off_x, y = t->y - w->off_y; |
109 | float major = 0, minor = 0, angle = 0; |
110 | |
111 | if (s->use_pressure) { |
112 | - float p = DEF_FRAC / s->max_pressure; |
113 | - major = t->pressure * p * dx; |
114 | - minor = t->pressure * p * dx; |
115 | + major = DEF_FRAC * t->pressure * dy; |
116 | + minor = DEF_FRAC * t->pressure * dx; |
117 | angle = 0; |
118 | } |
119 | if (s->use_touch_major) { |
120 | @@ -68,15 +77,6 @@ |
121 | float as = fabs(sin(angle)); |
122 | float mx = max(minor * ac, major * as); |
123 | float my = max(major * ac, minor * as); |
124 | - float ux = t->x - 0.5 * mx; |
125 | - float uy = t->y - 0.5 * my; |
126 | - float vx = t->x + 0.5 * mx; |
127 | - float vy = t->y + 0.5 * my; |
128 | - |
129 | - float px = (ux - x1) / dx * w->width; |
130 | - float py = (uy - y1) / dy * w->height; |
131 | - float qx = (vx - x1) / dx * w->width; |
132 | - float qy = (vy - y1) / dy * w->height; |
133 | |
134 | if (w->id[t->slot] != t->id) { |
135 | w->id[t->slot] = t->id; |
136 | @@ -84,7 +84,9 @@ |
137 | } |
138 | |
139 | XSetForeground(w->dsp, w->gc, w->color[t->slot]); |
140 | - XFillArc(w->dsp, w->win, w->gc, px, py, qx - px, qy - py, 0, 360 * 64); |
141 | + |
142 | + XFillArc(w->dsp, w->win, w->gc, x - mx / 2, y - my / 2, |
143 | + mx, my, 0, 360 * 64); |
144 | XFlush(w->dsp); |
145 | } |
146 | |
147 | @@ -98,88 +100,105 @@ |
148 | output_touch(fh, w, frame->active[i]); |
149 | } |
150 | |
151 | -static void event_loop(utouch_frame_handle fh, |
152 | - struct mtdev *dev, int fd, |
153 | - struct windata *w) |
154 | +static int init_window(struct windata *w) |
155 | +{ |
156 | + int event, err; |
157 | + int i; |
158 | + |
159 | + memset(w, 0, sizeof(w)); |
160 | + for (i = 0; i < DIM_TOUCH; i++) |
161 | + w->id[i] = -1; |
162 | + |
163 | + w->dsp = XOpenDisplay(NULL); |
164 | + if (!w->dsp) |
165 | + return -1; |
166 | + if (!XQueryExtension(w->dsp, "XInputExtension", &opcode, &event, &err)) |
167 | + return -1; |
168 | + |
169 | + w->screen = DefaultScreen(w->dsp); |
170 | + w->white = WhitePixel(w->dsp, w->screen); |
171 | + w->black = BlackPixel(w->dsp, w->screen); |
172 | + |
173 | + w->win = XCreateSimpleWindow(w->dsp, XDefaultRootWindow(w->dsp), |
174 | + 0, 0, 200, 200, 0, w->black, w->white); |
175 | + w->gc = DefaultGC(w->dsp, w->screen); |
176 | + |
177 | + XMapWindow(w->dsp, w->win); |
178 | + XFlush(w->dsp); |
179 | + |
180 | + return 0; |
181 | +} |
182 | + |
183 | +static void term_window(struct windata *w) |
184 | +{ |
185 | + XDestroyWindow(w->dsp, w->win); |
186 | + XCloseDisplay(w->dsp); |
187 | +} |
188 | + |
189 | +static void set_screen_size_mtdev(utouch_frame_handle fh, |
190 | + struct windata *w, |
191 | + XEvent *xev) |
192 | +{ |
193 | + struct utouch_surface *s = utouch_frame_get_surface(fh); |
194 | + XConfigureEvent *cev = (XConfigureEvent *)xev; |
195 | + |
196 | + s->mapped_min_x = 0; |
197 | + s->mapped_min_y = 0; |
198 | + s->mapped_max_x = DisplayWidth(w->dsp, w->screen); |
199 | + s->mapped_max_y = DisplayHeight(w->dsp, w->screen); |
200 | + s->mapped_max_pressure = 1; |
201 | + |
202 | + if (cev) { |
203 | + w->off_x = cev->x; |
204 | + w->off_y = cev->y; |
205 | + } |
206 | + |
207 | + fprintf(stderr, "map: %f %f %f %f %f %f\n", |
208 | + w->off_x, w->off_y, |
209 | + s->mapped_min_x, s->mapped_min_y, |
210 | + s->mapped_max_x, s->mapped_max_y); |
211 | +} |
212 | + |
213 | +static void run_window_mtdev(utouch_frame_handle fh, struct mtdev *dev, int fd) |
214 | { |
215 | const struct utouch_frame *frame; |
216 | struct input_event iev; |
217 | + struct windata w; |
218 | XEvent xev; |
219 | |
220 | - XSelectInput(w->dsp, w->win, |
221 | - ButtonPressMask | ButtonReleaseMask | |
222 | - ExposureMask | StructureNotifyMask); |
223 | - |
224 | - clear_screen(w); |
225 | + if (init_window(&w)) |
226 | + return; |
227 | + |
228 | + clear_screen(fh, &w); |
229 | + |
230 | + set_screen_size_mtdev(fh, &w, 0); |
231 | + XSelectInput(w.dsp, w.win, StructureNotifyMask); |
232 | + |
233 | while (1) { |
234 | while (!mtdev_idle(dev, fd, 100)) { |
235 | while (mtdev_get(dev, fd, &iev, 1) > 0) { |
236 | frame = utouch_frame_pump_mtdev(fh, &iev); |
237 | if (frame) |
238 | - report_frame(fh, frame, w); |
239 | + report_frame(fh, frame, &w); |
240 | } |
241 | } |
242 | - while (XPending(w->dsp)) { |
243 | - XNextEvent(w->dsp, &xev); |
244 | + while (XPending(w.dsp)) { |
245 | + XNextEvent(w.dsp, &xev); |
246 | + set_screen_size_mtdev(fh, &w, &xev); |
247 | } |
248 | } |
249 | -} |
250 | - |
251 | -static void run_window(utouch_frame_handle fh, struct mtdev *dev, int fd) |
252 | -{ |
253 | - struct windata w; |
254 | - int i; |
255 | - memset(&w, 0, sizeof(w)); |
256 | - for (i = 0; i < DIM_TOUCH; i++) |
257 | - w.id[i] = -1; |
258 | - |
259 | - w.dsp = XOpenDisplay(NULL); |
260 | - if (!w.dsp) |
261 | - return; |
262 | - |
263 | - w.screen = DefaultScreen(w.dsp); |
264 | - w.white = WhitePixel(w.dsp, w.screen); |
265 | - w.black = BlackPixel(w.dsp, w.screen); |
266 | - w.width = DisplayWidth(w.dsp, w.screen) - XMARG; |
267 | - w.height = DisplayHeight(w.dsp, w.screen) - YMARG; |
268 | - |
269 | - w.root = DefaultRootWindow(w.dsp); |
270 | - w.win = XCreateSimpleWindow(w.dsp, w.root, |
271 | - 0, 0, w.width, w.height, |
272 | - 0, w.black, w.white); |
273 | - |
274 | - XMapWindow(w.dsp, w.win); |
275 | - |
276 | - long eventMask = StructureNotifyMask; |
277 | - XSelectInput(w.dsp, w.win, eventMask); |
278 | - |
279 | - XEvent ev; |
280 | - do { |
281 | - XNextEvent(w.dsp, &ev); |
282 | - } while (ev.type != MapNotify); |
283 | - |
284 | - |
285 | - w.gc = XCreateGC(w.dsp, w.win, 0, NULL); |
286 | - |
287 | - event_loop(fh, dev, fd, &w); |
288 | - |
289 | - XDestroyWindow(w.dsp, w.win); |
290 | - XCloseDisplay(w.dsp); |
291 | -} |
292 | - |
293 | -int main(int argc, char *argv[]) |
294 | + |
295 | + term_window(&w); |
296 | +} |
297 | + |
298 | +static int run_mtdev(const char *name) |
299 | { |
300 | struct evemu_device *evemu; |
301 | struct mtdev *mtdev; |
302 | utouch_frame_handle fh; |
303 | int fd; |
304 | |
305 | - if (argc < 2) { |
306 | - fprintf(stderr, "Usage: %s <device>\n", argv[0]); |
307 | - return -1; |
308 | - } |
309 | - |
310 | - fd = open(argv[1], O_RDONLY | O_NONBLOCK); |
311 | + fd = open(name, O_RDONLY | O_NONBLOCK); |
312 | if (fd < 0) { |
313 | fprintf(stderr, "error: could not open device\n"); |
314 | return -1; |
315 | @@ -209,7 +228,7 @@ |
316 | return -1; |
317 | } |
318 | |
319 | - run_window(fh, mtdev, fd); |
320 | + run_window_mtdev(fh, mtdev, fd); |
321 | |
322 | utouch_frame_delete_engine(fh); |
323 | mtdev_close_delete(mtdev); |
324 | @@ -220,3 +239,129 @@ |
325 | |
326 | return 0; |
327 | } |
328 | + |
329 | +#if HAVE_XI |
330 | +static void handle_event_xi2(struct windata *w, |
331 | + utouch_frame_handle fh, |
332 | + XEvent *ev) |
333 | +{ |
334 | + XConfigureEvent *cev = (XConfigureEvent *)ev; |
335 | + XGenericEventCookie *gev = &ev->xcookie; |
336 | + const struct utouch_frame *frame; |
337 | + |
338 | + switch(ev->type) { |
339 | + case ConfigureNotify: |
340 | + if (cev->window == XDefaultRootWindow(cev->display)) { |
341 | + utouch_frame_configure_xi2(fh, cev); |
342 | + } else { |
343 | + w->off_x = cev->x; |
344 | + w->off_y = cev->y; |
345 | + } |
346 | + break; |
347 | + case GenericEvent: |
348 | + if (!XGetEventData(w->dsp, gev)) |
349 | + break; |
350 | + if (gev->type == GenericEvent && gev->extension == opcode) { |
351 | + frame = utouch_frame_pump_xi2(fh, gev->data); |
352 | + if (frame) |
353 | + report_frame(fh, frame, w); |
354 | + } |
355 | + XFreeEventData(w->dsp, gev); |
356 | + break; |
357 | + } |
358 | +} |
359 | + |
360 | +static void run_window_xi2(struct windata *w, |
361 | + utouch_frame_handle fh, |
362 | + XIDeviceInfo *dev) |
363 | +{ |
364 | + const struct utouch_frame *frame; |
365 | + XIEventMask mask; |
366 | + |
367 | + fprintf(stderr, "xi2 running\n"); |
368 | + |
369 | + XSelectInput(w->dsp, w->win, StructureNotifyMask); |
370 | + XSelectInput(w->dsp, XDefaultRootWindow(w->dsp), StructureNotifyMask); |
371 | + |
372 | + mask.deviceid = dev->deviceid; |
373 | + mask.mask_len = XIMaskLen(XI_LASTEVENT); |
374 | + mask.mask = calloc(mask.mask_len, sizeof(char)); |
375 | + |
376 | + XISetMask(mask.mask, XI_PropertyEvent); |
377 | + XISetMask(mask.mask, XI_TouchBegin); |
378 | + XISetMask(mask.mask, XI_TouchUpdate); |
379 | + XISetMask(mask.mask, XI_TouchEnd); |
380 | + XISelectEvents(w->dsp, w->win, &mask, 1); |
381 | + |
382 | + while (1) { |
383 | + XEvent ev; |
384 | + XNextEvent(w->dsp, &ev); |
385 | + handle_event_xi2(w, fh, &ev); |
386 | + } |
387 | +} |
388 | + |
389 | +static int run_xi2(int id) |
390 | +{ |
391 | + struct windata w; |
392 | + XIDeviceInfo *info, *dev; |
393 | + utouch_frame_handle fh; |
394 | + int ndevice; |
395 | + int i; |
396 | + |
397 | + if (init_window(&w)) { |
398 | + fprintf(stderr, "error: could not init window\n"); |
399 | + return -1; |
400 | + } |
401 | + |
402 | + info = XIQueryDevice(w.dsp, XIAllDevices, &ndevice); |
403 | + dev = 0; |
404 | + for (i = 0; i < ndevice; i++) |
405 | + if (info[i].deviceid == id) |
406 | + dev = &info[i]; |
407 | + if (!dev) |
408 | + return -1; |
409 | + |
410 | + if (!utouch_frame_is_supported_xi2(w.dsp, dev)) { |
411 | + fprintf(stderr, "error: unsupported device\n"); |
412 | + return -1; |
413 | + } |
414 | + |
415 | + fh = utouch_frame_new_engine(100, 32, 100); |
416 | + if (!fh || utouch_frame_init_xi2(fh, w.dsp, dev)) { |
417 | + fprintf(stderr, "error: could not init frame\n"); |
418 | + return -1; |
419 | + } |
420 | + |
421 | + run_window_xi2(&w, fh, dev); |
422 | + |
423 | + utouch_frame_delete_engine(fh); |
424 | + XIFreeDeviceInfo(info); |
425 | + term_window(&w); |
426 | + |
427 | + return 0; |
428 | +} |
429 | +#else |
430 | +static int run_xi2(int id) |
431 | +{ |
432 | + fprintf(stderr, "XI2.1 not supported\n"); |
433 | + return 0; |
434 | +} |
435 | +#endif |
436 | + |
437 | +int main(int argc, char *argv[]) |
438 | +{ |
439 | + int id, ret; |
440 | + |
441 | + if (argc < 2) { |
442 | + fprintf(stderr, "Usage: %s <device>\n", argv[0]); |
443 | + return -1; |
444 | + } |
445 | + |
446 | + id = atoi(argv[1]); |
447 | + if (id) |
448 | + ret = run_xi2(id); |
449 | + else |
450 | + ret = run_mtdev(argv[1]); |
451 | + |
452 | + return ret; |
453 | +} |
Looks fine except that configure.ac needs to be fixed up the same way as utouch-frame was fixed.