d93aaaaa366b30c6f5570ee34d19443f7b220afd
[profile/ivi/weston.git] / clients / simple-touch.c
1 /*
2  * Copyright © 2011 Benjamin Franzke
3  * Copyright © 2011 Intel Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting documentation, and
9  * that the name of the copyright holders not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no representations
12  * about the suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdbool.h>
28 #include <assert.h>
29 #include <unistd.h>
30 #include <sys/mman.h>
31
32 #include <wayland-client.h>
33 #include <wayland-egl.h>
34
35 struct touch {
36         struct wl_display *display;
37         struct wl_compositor *compositor;
38         struct wl_shell *shell;
39         struct wl_shm *shm;
40         struct wl_input_device *input_device;
41         struct wl_surface *surface;
42         struct wl_shell_surface *shell_surface;
43         struct wl_buffer *buffer;
44         int has_argb;
45         uint32_t mask;
46         int width, height;
47         void *data;
48 };
49
50 static void
51 create_shm_buffer(struct touch *touch)
52 {
53         char filename[] = "/tmp/wayland-shm-XXXXXX";
54         int fd, size, stride;
55
56         fd = mkstemp(filename);
57         if (fd < 0) {
58                 fprintf(stderr, "open %s failed: %m\n", filename);
59                 exit(1);
60         }
61         stride = touch->width * 4;
62         size = stride * touch->height;
63         if (ftruncate(fd, size) < 0) {
64                 fprintf(stderr, "ftruncate failed: %m\n");
65                 close(fd);
66                 exit(1);
67         }
68
69         touch->data =
70                 mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
71         unlink(filename);
72
73         if (touch->data == MAP_FAILED) {
74                 fprintf(stderr, "mmap failed: %m\n");
75                 close(fd);
76                 exit(1);
77         }
78
79         touch->buffer =
80                 wl_shm_create_buffer(touch->shm, fd,
81                                      touch->width, touch->height, stride,
82                                      WL_SHM_FORMAT_ARGB8888);
83
84         close(fd);
85 }
86
87 static void
88 shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
89 {
90         struct touch *touch = data;
91
92         if (format == WL_SHM_FORMAT_ARGB8888)
93                 touch->has_argb = 1;
94 }
95
96 struct wl_shm_listener shm_listenter = {
97         shm_format
98 };
99
100
101 static void
102 input_device_handle_motion(void *data, struct wl_input_device *input_device,
103                            uint32_t time, int32_t sx, int32_t sy)
104 {
105 }
106
107 static void
108 input_device_handle_button(void *data,
109                            struct wl_input_device *input_device,
110                            uint32_t time, uint32_t button, uint32_t state)
111 {
112 }
113
114 static void
115 input_device_handle_key(void *data, struct wl_input_device *input_device,
116                         uint32_t time, uint32_t key, uint32_t state)
117 {
118 }
119
120 static void
121 input_device_handle_pointer_enter(void *data,
122                                   struct wl_input_device *input_device,
123                                   uint32_t time, struct wl_surface *surface,
124                                   int32_t sx, int32_t sy)
125 {
126 }
127
128 static void
129 input_device_handle_pointer_leave(void *data,
130                                   struct wl_input_device *input_device,
131                                   uint32_t time, struct wl_surface *surface)
132 {
133 }
134
135 static void
136 input_device_handle_keyboard_enter(void *data,
137                                    struct wl_input_device *input_device,
138                                    uint32_t time,
139                                    struct wl_surface *surface,
140                                    struct wl_array *keys)
141 {
142 }
143
144 static void
145 input_device_handle_keyboard_leave(void *data,
146                                    struct wl_input_device *input_device,
147                                    uint32_t time,
148                                    struct wl_surface *surface)
149 {
150 }
151
152 static void
153 touch_paint(struct touch *touch, int32_t x, int32_t y, int32_t id)
154 {
155         uint32_t *p, c;
156         static const uint32_t colors[] = {
157                 0xffff0000,
158                 0xffffff00,
159                 0xff0000ff,
160                 0xffff00ff,
161         };
162
163         if (id < ARRAY_LENGTH(colors))
164                 c = colors[id];
165         else
166                 c = 0xffffffff;
167
168         if (x < 1 || touch->width - 1 < x ||
169             y < 1 || touch->height - 1 < y)
170                 return;
171
172         p = (uint32_t *) touch->data + (x - 1) + (y -1 ) * touch->width;
173         p[1] = c;
174         p += touch->width;
175         p[0] = c;
176         p[1] = c;
177         p[2] = c;
178         p += touch->width;
179         p[1] = c;
180
181         wl_buffer_damage(touch->buffer, 0, 0, touch->width, touch->height);
182         wl_surface_damage(touch->surface,
183                           0, 0, touch->width, touch->height);
184 }
185
186 static void
187 input_device_handle_touch_down(void *data,
188                                struct wl_input_device *wl_input_device,
189                                uint32_t time, struct wl_surface *surface,
190                                int32_t id, int32_t x, int32_t y)
191 {
192         struct touch *touch = data;
193
194         touch_paint(touch, x, y, id);
195 }
196
197 static void
198 input_device_handle_touch_up(void *data,
199                              struct wl_input_device *wl_input_device,
200                              uint32_t time, int32_t id)
201 {
202 }
203
204 static void
205 input_device_handle_touch_motion(void *data,
206                                  struct wl_input_device *wl_input_device,
207                                  uint32_t time,
208                                  int32_t id, int32_t x, int32_t y)
209 {
210         struct touch *touch = data;
211
212         touch_paint(touch, x, y, id);
213 }
214
215 static void
216 input_device_handle_touch_frame(void *data,
217                                 struct wl_input_device *wl_input_device)
218 {
219 }
220
221 static void
222 input_device_handle_touch_cancel(void *data,
223                                  struct wl_input_device *wl_input_device)
224 {
225 }
226
227 static const struct wl_input_device_listener input_device_listener = {
228         input_device_handle_motion,
229         input_device_handle_button,
230         input_device_handle_key,
231         input_device_handle_pointer_enter,
232         input_device_handle_pointer_leave,
233         input_device_handle_keyboard_enter,
234         input_device_handle_keyboard_leave,
235         input_device_handle_touch_down,
236         input_device_handle_touch_up,
237         input_device_handle_touch_motion,
238         input_device_handle_touch_frame,
239         input_device_handle_touch_cancel,
240 };
241
242 static void
243 handle_global(struct wl_display *display, uint32_t id,
244               const char *interface, uint32_t version, void *data)
245 {
246         struct touch *touch = data;
247
248         if (strcmp(interface, "wl_compositor") == 0) {
249                 touch->compositor =
250                         wl_display_bind(display, id, &wl_compositor_interface);
251         } else if (strcmp(interface, "wl_shell") == 0) {
252                 touch->shell =
253                         wl_display_bind(display, id, &wl_shell_interface);
254         } else if (strcmp(interface, "wl_shm") == 0) {
255                 touch->shm = wl_display_bind(display, id, &wl_shm_interface);
256                 wl_shm_add_listener(touch->shm, &shm_listenter, touch);
257         } else if (strcmp(interface, "wl_input_device") == 0) {
258                 touch->input_device =
259                         wl_display_bind(display, id,
260                                         &wl_input_device_interface);
261                 wl_input_device_add_listener(touch->input_device,
262                                              &input_device_listener, touch);
263         }
264 }
265
266 static int
267 event_mask_update(uint32_t mask, void *data)
268 {
269         struct touch *touch = data;
270
271         touch->mask = mask;
272
273         return 0;
274 }
275
276 static struct touch *
277 touch_create(int width, int height)
278 {
279         struct touch *touch;
280
281         touch = malloc(sizeof *touch);
282         touch->display = wl_display_connect(NULL);
283         assert(touch->display);
284
285         touch->has_argb = 0;
286         wl_display_add_global_listener(touch->display, handle_global, touch);
287         wl_display_iterate(touch->display, WL_DISPLAY_READABLE);
288         wl_display_roundtrip(touch->display);
289
290         if (!touch->has_argb) {
291                 fprintf(stderr, "WL_SHM_FORMAT_ARGB32 not available\n");
292                 exit(1);
293         }
294
295         wl_display_get_fd(touch->display, event_mask_update, touch);
296         
297         touch->width = width;
298         touch->height = height;
299         touch->surface = wl_compositor_create_surface(touch->compositor);
300         touch->shell_surface = wl_shell_get_shell_surface(touch->shell,
301                                                           touch->surface);
302         create_shm_buffer(touch);
303
304         wl_shell_surface_set_toplevel(touch->shell_surface);
305         wl_surface_set_user_data(touch->surface, touch);
306
307         memset(touch->data, 64, width * height * 4);
308         wl_buffer_damage(touch->buffer, 0, 0, width, height);
309         wl_surface_attach(touch->surface, touch->buffer, 0, 0);
310         wl_surface_damage(touch->surface, 0, 0, width, height);
311
312         return touch;
313 }
314
315 int
316 main(int argc, char **argv)
317 {
318         struct touch *touch;
319
320         touch = touch_create(600, 500);
321
322         while (true)
323                 wl_display_iterate(touch->display, touch->mask);
324
325         return 0;
326 }