clients: Add simple-touch client for testing touch events.
authorKristian Høgsberg <krh@bitplanet.net>
Thu, 22 Dec 2011 03:54:49 +0000 (22:54 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 22 Dec 2011 18:45:50 +0000 (13:45 -0500)
clients/Makefile.am
clients/simple-touch.c [new file with mode: 0644]
compositor/evdev.c

index 490e403..b54cc5c 100644 (file)
@@ -5,12 +5,15 @@ noinst_PROGRAMS = $(clients_programs)                 \
 libexec_PROGRAMS = $(desktop_shell) $(tablet_shell)
 
 if BUILD_SIMPLE_CLIENTS
-simple_clients_programs = simple-egl simple-shm
+simple_clients_programs = simple-egl simple-shm simple-touch
 simple_egl_SOURCES = simple-egl.c
 simple_egl_LDADD = $(SIMPLE_CLIENT_LIBS) -lm
 
 simple_shm_SOURCES = simple-shm.c
 simple_shm_LDADD = $(SIMPLE_CLIENT_LIBS)
+
+simple_touch_SOURCES = simple-touch.c
+simple_touch_LDADD = $(SIMPLE_CLIENT_LIBS)
 endif
 
 if BUILD_CLIENTS
diff --git a/clients/simple-touch.c b/clients/simple-touch.c
new file mode 100644 (file)
index 0000000..e80a00e
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright © 2011 Benjamin Franzke
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include <wayland-client.h>
+#include <wayland-egl.h>
+
+struct touch {
+       struct wl_display *display;
+       struct wl_compositor *compositor;
+       struct wl_shell *shell;
+       struct wl_shm *shm;
+       struct wl_input_device *input_device;
+       struct wl_surface *surface;
+       struct wl_shell_surface *shell_surface;
+       struct wl_buffer *buffer;
+       int has_argb;
+       uint32_t mask;
+       int width, height;
+       void *data;
+};
+
+static void
+create_shm_buffer(struct touch *touch)
+{
+       char filename[] = "/tmp/wayland-shm-XXXXXX";
+       int fd, size, stride;
+
+       fd = mkstemp(filename);
+       if (fd < 0) {
+               fprintf(stderr, "open %s failed: %m\n", filename);
+               exit(1);
+       }
+       stride = touch->width * 4;
+       size = stride * touch->height;
+       if (ftruncate(fd, size) < 0) {
+               fprintf(stderr, "ftruncate failed: %m\n");
+               close(fd);
+               exit(1);
+       }
+
+       touch->data =
+               mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+       unlink(filename);
+
+       if (touch->data == MAP_FAILED) {
+               fprintf(stderr, "mmap failed: %m\n");
+               close(fd);
+               exit(1);
+       }
+
+       touch->buffer =
+               wl_shm_create_buffer(touch->shm, fd,
+                                    touch->width, touch->height, stride,
+                                    WL_SHM_FORMAT_PREMULTIPLIED_ARGB32);
+
+       close(fd);
+}
+
+static void
+shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
+{
+       struct touch *touch = data;
+
+       if (format == WL_SHM_FORMAT_PREMULTIPLIED_ARGB32)
+               touch->has_argb = 1;
+}
+
+struct wl_shm_listener shm_listenter = {
+       shm_format
+};
+
+
+static void
+input_device_handle_motion(void *data, struct wl_input_device *input_device,
+                          uint32_t time,
+                          int32_t x, int32_t y, int32_t sx, int32_t sy)
+{
+}
+
+static void
+input_device_handle_button(void *data,
+                          struct wl_input_device *input_device,
+                          uint32_t time, uint32_t button, uint32_t state)
+{
+}
+
+static void
+input_device_handle_key(void *data, struct wl_input_device *input_device,
+                       uint32_t time, uint32_t key, uint32_t state)
+{
+}
+
+static void
+input_device_handle_pointer_focus(void *data,
+                                 struct wl_input_device *input_device,
+                                 uint32_t time, struct wl_surface *surface,
+                                 int32_t x, int32_t y, int32_t sx, int32_t sy)
+{
+}
+
+static void
+input_device_handle_keyboard_focus(void *data,
+                                  struct wl_input_device *input_device,
+                                  uint32_t time,
+                                  struct wl_surface *surface,
+                                  struct wl_array *keys)
+{
+}
+
+static void
+touch_paint(struct touch *touch, int32_t x, int32_t y, int32_t id)
+{
+       uint32_t *p, c;
+       static const uint32_t colors[] = {
+               0xffff0000,
+               0xffffff00,
+               0xff0000ff,
+               0xffff00ff,
+       };
+
+       if (id < ARRAY_LENGTH(colors))
+               c = colors[id];
+       else
+               c = 0xffffffff;
+
+       if (x < 1 || touch->width - 1 < x ||
+           y < 1 || touch->height - 1 < y)
+               return;
+
+       p = (uint32_t *) touch->data + (x - 1) + (y -1 ) * touch->width;
+       p[1] = c;
+       p += touch->width;
+       p[0] = c;
+       p[1] = c;
+       p[2] = c;
+       p += touch->width;
+       p[1] = c;
+
+       wl_buffer_damage(touch->buffer, 0, 0, touch->width, touch->height);
+       wl_surface_damage(touch->surface,
+                         0, 0, touch->width, touch->height);
+}
+
+static void
+input_device_handle_touch_down(void *data,
+                              struct wl_input_device *wl_input_device,
+                              uint32_t time, struct wl_surface *surface,
+                              int32_t id, int32_t x, int32_t y)
+{
+       struct touch *touch = data;
+
+       touch_paint(touch, x, y, id);
+}
+
+static void
+input_device_handle_touch_up(void *data,
+                            struct wl_input_device *wl_input_device,
+                            uint32_t time, int32_t id)
+{
+}
+
+static void
+input_device_handle_touch_motion(void *data,
+                                struct wl_input_device *wl_input_device,
+                                uint32_t time,
+                                int32_t id, int32_t x, int32_t y)
+{
+       struct touch *touch = data;
+
+       touch_paint(touch, x, y, id);
+}
+
+static void
+input_device_handle_touch_frame(void *data,
+                               struct wl_input_device *wl_input_device)
+{
+}
+
+static void
+input_device_handle_touch_cancel(void *data,
+                                struct wl_input_device *wl_input_device)
+{
+}
+
+static const struct wl_input_device_listener input_device_listener = {
+       input_device_handle_motion,
+       input_device_handle_button,
+       input_device_handle_key,
+       input_device_handle_pointer_focus,
+       input_device_handle_keyboard_focus,
+       input_device_handle_touch_down,
+       input_device_handle_touch_up,
+       input_device_handle_touch_motion,
+       input_device_handle_touch_frame,
+       input_device_handle_touch_cancel,
+};
+
+static void
+handle_global(struct wl_display *display, uint32_t id,
+             const char *interface, uint32_t version, void *data)
+{
+       struct touch *touch = data;
+
+       if (strcmp(interface, "wl_compositor") == 0) {
+               touch->compositor =
+                       wl_display_bind(display, id, &wl_compositor_interface);
+       } else if (strcmp(interface, "wl_shell") == 0) {
+               touch->shell =
+                       wl_display_bind(display, id, &wl_shell_interface);
+       } else if (strcmp(interface, "wl_shm") == 0) {
+               touch->shm = wl_display_bind(display, id, &wl_shm_interface);
+               wl_shm_add_listener(touch->shm, &shm_listenter, touch);
+       } else if (strcmp(interface, "wl_input_device") == 0) {
+               touch->input_device =
+                       wl_display_bind(display, id,
+                                       &wl_input_device_interface);
+               wl_input_device_add_listener(touch->input_device,
+                                            &input_device_listener, touch);
+       }
+}
+
+static int
+event_mask_update(uint32_t mask, void *data)
+{
+       struct touch *touch = data;
+
+       touch->mask = mask;
+
+       return 0;
+}
+
+static struct touch *
+touch_create(int width, int height)
+{
+       struct touch *touch;
+
+       touch = malloc(sizeof *touch);
+       touch->display = wl_display_connect(NULL);
+       assert(touch->display);
+
+       touch->has_argb = 0;
+       wl_display_add_global_listener(touch->display, handle_global, touch);
+       wl_display_iterate(touch->display, WL_DISPLAY_READABLE);
+       wl_display_roundtrip(touch->display);
+
+       if (!touch->has_argb) {
+               fprintf(stderr, "WL_SHM_FORMAT_ARGB32 not available\n");
+               exit(1);
+       }
+
+       wl_display_get_fd(touch->display, event_mask_update, touch);
+       
+       touch->width = width;
+       touch->height = height;
+       touch->surface = wl_compositor_create_surface(touch->compositor);
+       touch->shell_surface = wl_shell_get_shell_surface(touch->shell,
+                                                         touch->surface);
+       create_shm_buffer(touch);
+
+       wl_shell_surface_set_toplevel(touch->shell_surface);
+       wl_surface_set_user_data(touch->surface, touch);
+
+       memset(touch->data, 64, width * height * 4);
+       wl_buffer_damage(touch->buffer, 0, 0, width, height);
+       wl_surface_attach(touch->surface, touch->buffer, 0, 0);
+       wl_surface_damage(touch->surface, 0, 0, width, height);
+
+       return touch;
+}
+
+int
+main(int argc, char **argv)
+{
+       struct touch *touch;
+
+       touch = touch_create(600, 500);
+
+       while (true)
+               wl_display_iterate(touch->display, touch->mask);
+
+       return 0;
+}
index c065b33..08fef66 100644 (file)
@@ -37,7 +37,7 @@ struct evdev_input {
        char *seat_id;
 };
 
-#define MAX_SLOTS 10
+#define MAX_SLOTS 16
 
 struct evdev_input_device {
        struct evdev_input *master;
@@ -279,8 +279,7 @@ is_motion_event(struct input_event *e)
 static void
 evdev_flush_motion(struct evdev_input_device *device, uint32_t time)
 {
-       struct wl_input_device *master =
-               &device->master->base.input_device;
+       struct wl_input_device *master = &device->master->base.input_device;
 
        if (!device->type)
                return;