2 * Copyright (C) 2009 Red Hat, Inc.
3 * Copyright (C) 2012 Collabora Ltd.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * Boston, MA 02111-1307, USA.
23 #include <clutter/clutter.h>
25 #if defined CLUTTER_WINDOWING_X11 && OS_LINUX && HAVE_XINPUT_2_2
33 #include <linux/input.h>
34 #include <linux/uinput.h>
37 #include <clutter/x11/clutter-x11.h>
39 #include "test-conform-common.h"
41 #define ABS_MAX_X 32768
42 #define ABS_MAX_Y 32768
44 #define TOUCH_POINTS 10
46 static ClutterPoint gesture_points[] = {
59 typedef struct _State State;
64 ClutterPoint gesture_points_to_check[TOUCH_POINTS];
70 static void send_event(int fd, int type, int code, int value, int sec, int usec)
72 static int sec_offset = -1;
73 static long last_time = -1;
75 struct input_event event;
85 newtime = sec * 1000000 + usec;
88 usleep(newtime - last_time);
90 gettimeofday(&event.time, NULL);
92 if (write(fd, &event, sizeof(event)) < sizeof(event))
93 perror("Send event failed.");
99 event_cb (ClutterActor *actor, ClutterEvent *event, State *state)
103 if (event->type != CLUTTER_TOUCH_BEGIN &&
104 event->type != CLUTTER_TOUCH_UPDATE)
107 state->gesture_points_to_check[state->gesture_points].x = ceil (event->touch.x);
108 state->gesture_points_to_check[state->gesture_points].y = ceil (event->touch.y);
109 state->gesture_points++;
111 if (state->gesture_points == TOUCH_POINTS)
113 for (i = 0; i < TOUCH_POINTS; i++)
115 if (state->gesture_points_to_check[i].x != gesture_points[i].x ||
116 state->gesture_points_to_check[i].y != gesture_points[i].y)
118 if (g_test_verbose ())
119 g_print ("error: expected (%d, %d) but found (%d, %d) at position %d\n",
120 (int) gesture_points[i].x, (int) gesture_points[i].y,
121 (int) state->gesture_points_to_check[i].x,
122 (int) state->gesture_points_to_check[i].y,
129 clutter_main_quit ();
136 screen_coords_to_device (int screen_x, int screen_y,
137 int *device_x, int *device_y)
139 int display_width = DisplayWidth (clutter_x11_get_default_display (),
140 clutter_x11_get_default_screen ());
141 int display_height = DisplayHeight (clutter_x11_get_default_display (),
142 clutter_x11_get_default_screen ());
144 *device_x = (screen_x * ABS_MAX_X) / display_width;
145 *device_y = (screen_y * ABS_MAX_Y) / display_height;
149 perform_gesture (gpointer data)
154 for (i = 0; i < TOUCH_POINTS; i++)
156 int x = gesture_points[i].x;
157 int y = gesture_points[i].y;
159 screen_coords_to_device (x, y, &x, &y);
161 send_event(fd, EV_ABS, ABS_MT_SLOT, 0, 1, i * 100);
162 send_event(fd, EV_ABS, ABS_MT_TRACKING_ID, 1, 1, i * 100 + 10);
164 send_event(fd, EV_ABS, ABS_MT_POSITION_X, x, 1, i * 100 + 20);
165 send_event(fd, EV_ABS, ABS_MT_POSITION_Y, y, 1, i * 100 + 30);
166 send_event(fd, EV_SYN, SYN_MT_REPORT, 0, 1, i * 100 + 40);
167 send_event(fd, EV_SYN, SYN_REPORT, 0, 1, i * 100 + 50);
170 send_event(fd, EV_ABS, ABS_MT_TRACKING_ID, -1, 1, TOUCH_POINTS * 100 + 10);
171 send_event(fd, EV_SYN, SYN_MT_REPORT, 0, 1, TOUCH_POINTS * 100 + 20);
172 send_event(fd, EV_SYN, SYN_REPORT, 0, 1, TOUCH_POINTS * 100 + 30);
174 return G_SOURCE_REMOVE;
178 setup (struct uinput_user_dev *dev, int fd)
180 strcpy (dev->name, "eGalax Touch Screen");
181 dev->id.bustype = 0x18;
182 dev->id.vendor = 0xeef;
183 dev->id.product = 0x20;
184 dev->id.version = 0x1;
186 if (ioctl (fd, UI_SET_EVBIT, EV_SYN) == -1)
189 if (ioctl (fd, UI_SET_EVBIT, EV_KEY) == -1)
192 if (ioctl (fd, UI_SET_KEYBIT, BTN_TOUCH) == -1)
195 if (ioctl (fd, UI_SET_EVBIT, EV_ABS) == -1)
198 if (ioctl (fd, UI_SET_ABSBIT, ABS_X) == -1)
203 dev->absmin[idx] = 0;
204 dev->absmax[idx] = ABS_MAX_X;
205 dev->absfuzz[idx] = 1;
206 dev->absflat[idx] = 0;
208 if (dev->absmin[idx] == dev->absmax[idx])
212 if (ioctl (fd, UI_SET_ABSBIT, ABS_Y) == -1)
217 dev->absmin[idx] = 0;
218 dev->absmax[idx] = ABS_MAX_Y;
219 dev->absfuzz[idx] = 1;
220 dev->absflat[idx] = 0;
222 if (dev->absmin[idx] == dev->absmax[idx])
226 if (ioctl (fd, UI_SET_ABSBIT, ABS_PRESSURE) == -1)
230 int idx = ABS_PRESSURE;
231 dev->absmin[idx] = 0;
232 dev->absmax[idx] = 0;
233 dev->absfuzz[idx] = 0;
234 dev->absflat[idx] = 0;
236 if (dev->absmin[idx] == dev->absmax[idx])
240 if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR) == -1)
244 int idx = ABS_MT_TOUCH_MAJOR;
245 dev->absmin[idx] = 0;
246 dev->absmax[idx] = 255;
247 dev->absfuzz[idx] = 1;
248 dev->absflat[idx] = 0;
250 if (dev->absmin[idx] == dev->absmax[idx])
254 if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_WIDTH_MAJOR) == -1)
258 int idx = ABS_MT_WIDTH_MAJOR;
259 dev->absmin[idx] = 0;
260 dev->absmax[idx] = 255;
261 dev->absfuzz[idx] = 1;
262 dev->absflat[idx] = 0;
264 if (dev->absmin[idx] == dev->absmax[idx])
268 if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_POSITION_X) == -1)
272 int idx = ABS_MT_POSITION_X;
273 dev->absmin[idx] = 0;
274 dev->absmax[idx] = ABS_MAX_X;
275 dev->absfuzz[idx] = 1;
276 dev->absflat[idx] = 0;
278 if (dev->absmin[idx] == dev->absmax[idx])
282 if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y) == -1)
286 int idx = ABS_MT_POSITION_Y;
287 dev->absmin[idx] = 0;
288 dev->absmax[idx] = ABS_MAX_Y;
289 dev->absfuzz[idx] = 1;
290 dev->absflat[idx] = 0;
292 if (dev->absmin[idx] == dev->absmax[idx])
296 if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID) == -1)
300 int idx = ABS_MT_TRACKING_ID;
301 dev->absmin[idx] = 0;
302 dev->absmax[idx] = 5;
303 dev->absfuzz[idx] = 0;
304 dev->absflat[idx] = 0;
306 if (dev->absmin[idx] == dev->absmax[idx])
314 perror ("ioctl failed.");
321 struct uinput_user_dev dev;
323 fd = open ("/dev/uinput", O_RDWR);
324 if (fd < 0 && errno == ENODEV)
325 fd = open ("/dev/input/uinput", O_RDWR);
329 memset (&dev, 0, sizeof (dev));
332 if (write (fd, &dev, sizeof (dev)) < sizeof (dev))
334 if (ioctl (fd, UI_DEV_CREATE, NULL) == -1)
340 if (g_test_verbose ())
341 g_print ("error: %s\n", strerror (errno));
349 #endif /* defined CLUTTER_WINDOWING_X11 && OS_LINUX && HAVE_XINPUT_2_2 */
354 #if defined CLUTTER_WINDOWING_X11 && OS_LINUX && HAVE_XINPUT_2_2
359 state.gesture_points = 0;
361 stage = clutter_stage_new ();
362 g_signal_connect (stage, "event", G_CALLBACK (event_cb), &state);
363 clutter_stage_set_fullscreen (CLUTTER_STAGE (stage), TRUE);
364 clutter_actor_show (stage);
366 g_assert (init_uinput () == 0);
368 clutter_threads_add_timeout (500, perform_gesture, &state);
372 if (g_test_verbose ())
373 g_print ("end result: %s\n", state.pass ? "pass" : "FAIL");
375 g_assert (state.pass);
377 clutter_actor_destroy (stage);
378 #endif /* defined CLUTTER_WINDOWING_X11 && OS_LINUX && HAVE_XINPUT_2_2 */