c82349f63013dd5b6617a9709a1a04d19851ca5f
[platform/core/uifw/libds-tizen.git] / src / clients / simple-tbm.c
1 /*
2  * Copyright © 2011 Benjamin Franzke
3  * Copyright © 2010 Intel Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdbool.h>
30 #include <assert.h>
31 #include <unistd.h>
32 #include <sys/mman.h>
33 #include <signal.h>
34 #include <errno.h>
35
36 #include <wayland-client.h>
37 #include <wayland-tbm-client.h>
38 #include <tbm_surface.h>
39 #include <tbm_surface_internal.h>
40 #include "xdg-shell-client-protocol.h"
41 #include <tizen-extension-client-protocol.h>
42
43 static uint64_t buffer_info_key;
44 #define BUFFER_INFO_KEY (unsigned long)(&buffer_info_key)
45
46 struct display {
47         struct wl_display *display;
48         struct wl_registry *registry;
49         struct wl_compositor *compositor;
50         struct xdg_wm_base *wm_base;
51         struct wl_shm *shm;
52         struct wl_seat *seat;
53     struct wayland_tbm_client *wl_tbm;
54         bool has_xrgb;
55
56         struct tizen_input_device_manager *devicemgr;
57         int notified;
58         bool blocked;
59 };
60
61 struct window {
62         struct display *display;
63         int width, height;
64         struct wl_surface *surface;
65         struct xdg_surface *xdg_surface;
66         struct xdg_toplevel *xdg_toplevel;
67         struct wl_callback *callback;
68     tbm_surface_queue_h surface_queue;
69         bool wait_for_configure;
70 };
71
72 struct buffer_info {
73     struct window *window;
74     struct wl_buffer *wl_buffer;
75 };
76
77 static int running = 1;
78
79 static void
80 redraw(void *data, struct wl_callback *callback, uint32_t time);
81
82 static void
83 handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
84                              uint32_t serial)
85 {
86         struct window *window = data;
87
88         xdg_surface_ack_configure(surface, serial);
89
90         if (window->wait_for_configure) {
91                 redraw(window, NULL, 0);
92                 window->wait_for_configure = false;
93         }
94 }
95
96 static const struct xdg_surface_listener xdg_surface_listener = {
97         handle_xdg_surface_configure,
98 };
99
100 static void
101 handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
102                               int32_t width, int32_t height,
103                               struct wl_array *state)
104 {
105 }
106
107 static void
108 handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
109 {
110         running = 0;
111 }
112
113 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
114         handle_xdg_toplevel_configure,
115         handle_xdg_toplevel_close,
116 };
117
118 static struct window *
119 create_window(struct display *display, int width, int height)
120 {
121         struct window *window;
122
123         window = calloc(1, sizeof *window);
124         if (!window)
125                 return NULL;
126
127         window->callback = NULL;
128         window->display = display;
129         window->width = width;
130         window->height = height;
131         window->surface = wl_compositor_create_surface(display->compositor);
132
133         if (display->wm_base) {
134                 window->xdg_surface =
135                         xdg_wm_base_get_xdg_surface(display->wm_base,
136                                                     window->surface);
137                 assert(window->xdg_surface);
138                 xdg_surface_add_listener(window->xdg_surface,
139                                          &xdg_surface_listener, window);
140
141                 window->xdg_toplevel =
142                         xdg_surface_get_toplevel(window->xdg_surface);
143                 assert(window->xdg_toplevel);
144                 xdg_toplevel_add_listener(window->xdg_toplevel,
145                                           &xdg_toplevel_listener, window);
146
147                 xdg_toplevel_set_title(window->xdg_toplevel, "simple-tbm");
148                 wl_surface_commit(window->surface);
149                 window->wait_for_configure = true;
150         } else {
151                 assert(0);
152         }
153
154     window->surface_queue =
155         wayland_tbm_client_create_surface_queue(display->wl_tbm,
156                 window->surface,
157                 3,
158                 width,
159                 height,
160                 TBM_FORMAT_XRGB8888);
161     assert(window->surface_queue);
162
163         return window;
164 }
165
166 static void
167 destroy_window(struct window *window)
168 {
169     tbm_surface_queue_destroy(window->surface_queue);
170
171         if (window->callback)
172                 wl_callback_destroy(window->callback);
173
174         if (window->xdg_toplevel)
175                 xdg_toplevel_destroy(window->xdg_toplevel);
176         if (window->xdg_surface)
177                 xdg_surface_destroy(window->xdg_surface);
178         wl_surface_destroy(window->surface);
179         free(window);
180 }
181
182 static void
183 paint_pixels(void *image, int padding, int width, int height, uint32_t time)
184 {
185         const int halfh = padding + (height - padding * 2) / 2;
186         const int halfw = padding + (width  - padding * 2) / 2;
187         int ir, or;
188         uint32_t *pixel = image;
189         int y;
190
191         /* squared radii thresholds */
192         or = (halfw < halfh ? halfw : halfh) - 8;
193         ir = or - 32;
194         or *= or;
195         ir *= ir;
196
197         pixel += padding * width;
198         for (y = padding; y < height - padding; y++) {
199                 int x;
200                 int y2 = (y - halfh) * (y - halfh);
201
202                 pixel += padding;
203                 for (x = padding; x < width - padding; x++) {
204                         uint32_t v;
205
206                         /* squared distance from center */
207                         int r2 = (x - halfw) * (x - halfw) + y2;
208
209                         if (r2 < ir)
210                                 v = (r2 / 32 + time / 64) * 0x0080401;
211                         else if (r2 < or)
212                                 v = (y + time / 32) * 0x0080401;
213                         else
214                                 v = (x + time / 16) * 0x0080401;
215                         v &= 0x00ffffff;
216
217                         /* cross if compositor uses X from XRGB as alpha */
218                         if (abs(x - y) > 6 && abs(x + y - height) > 6)
219                                 v |= 0xff000000;
220
221                         *pixel++ = v;
222                 }
223
224                 pixel += padding;
225         }
226 }
227
228 static void
229 buffer_info_free_cb(void *data)
230 {
231     struct buffer_info *buffer_info = data;
232
233     if (!buffer_info)
234         return;
235
236     wayland_tbm_client_destroy_buffer(buffer_info->window->display->wl_tbm,
237             buffer_info->wl_buffer);
238     free(buffer_info);
239 }
240
241 static void
242 buffer_handle_release(void *data, struct wl_buffer *wl_buffer)
243 {
244     tbm_surface_h surface = data;
245     struct buffer_info *buffer_info;
246
247     tbm_surface_internal_get_user_data(surface, BUFFER_INFO_KEY,
248             (void **)&buffer_info);
249     if (buffer_info)
250         tbm_surface_queue_release(buffer_info->window->surface_queue, surface);
251 }
252
253 static const struct wl_buffer_listener buffer_listener = {
254     .release = buffer_handle_release,
255 };
256
257 static const struct wl_callback_listener frame_listener;
258
259 static void
260 redraw(void *data, struct wl_callback *callback, uint32_t time)
261 {
262         struct window *window = data;
263     struct buffer_info *buffer_info = NULL;
264     tbm_surface_h surface = NULL;
265     tbm_surface_info_s surface_info;
266
267     if (!tbm_surface_queue_can_dequeue(window->surface_queue, 0))
268         return;
269
270     tbm_surface_queue_dequeue(window->surface_queue, &surface);
271     assert(surface);
272
273     tbm_surface_internal_get_user_data(surface, BUFFER_INFO_KEY,
274             (void **)&buffer_info);
275     if (!buffer_info) {
276         buffer_info = calloc(1, sizeof *buffer_info);
277         assert(buffer_info);
278
279         tbm_surface_internal_add_user_data(surface, BUFFER_INFO_KEY, buffer_info_free_cb);
280         tbm_surface_internal_set_user_data(surface, BUFFER_INFO_KEY, buffer_info);
281
282         buffer_info->wl_buffer =
283             wayland_tbm_client_create_buffer(window->display->wl_tbm, surface);
284         assert(buffer_info->wl_buffer);
285
286         wl_buffer_add_listener(buffer_info->wl_buffer, &buffer_listener,
287                 surface);
288
289         buffer_info->window = window;
290     }
291
292     tbm_surface_map(surface, TBM_SURF_OPTION_WRITE, &surface_info);
293
294         paint_pixels(surface_info.planes[0].ptr, 20,
295             (surface_info.planes[0].stride/4), surface_info.height, time);
296
297     tbm_surface_unmap(surface);
298
299         wl_surface_attach(window->surface, buffer_info->wl_buffer, 0, 0);
300         wl_surface_damage(window->surface,
301                           20, 20, window->width - 40, window->height - 40);
302
303         if (callback)
304                 wl_callback_destroy(callback);
305
306         window->callback = wl_surface_frame(window->surface);
307         wl_callback_add_listener(window->callback, &frame_listener, window);
308         wl_surface_commit(window->surface);
309 }
310
311 static const struct wl_callback_listener frame_listener = {
312         redraw
313 };
314
315 static void
316 shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
317 {
318         struct display *d = data;
319
320         if (format == WL_SHM_FORMAT_XRGB8888)
321                 d->has_xrgb = true;
322 }
323
324 struct wl_shm_listener shm_listener = {
325         shm_format
326 };
327
328 static void
329 xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
330 {
331         xdg_wm_base_pong(shell, serial);
332 }
333
334 static const struct xdg_wm_base_listener xdg_wm_base_listener = {
335         xdg_wm_base_ping,
336 };
337
338 static void pointer_handle_button(void *data, struct wl_pointer *pointer,
339         uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
340 {
341     if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
342         fprintf(stderr, "pointer_handle_button: PRESSED\n");
343     }
344     else {
345         fprintf(stderr, "pointer_handle_button: RELEASED\n");
346     }
347 }
348
349 static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
350         uint32_t serial, struct wl_surface *surface,
351         wl_fixed_t surface_x, wl_fixed_t surface_y)
352 {
353     fprintf(stderr, "pointer_handle_enter surface_x:%d, surface_y:%d\n",
354             wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y));
355 }
356
357 static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
358         uint32_t serial, struct wl_surface *surface)
359 {
360     fprintf(stderr, "pointer_handle_leave\n");
361 }
362
363 static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
364         uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
365 {
366     fprintf(stderr, "pointer_handle_motion surface_x:%d, surface_y:%d\n",
367             wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y));
368 }
369
370 static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer)
371 {
372     fprintf(stderr, "pointer_handle_frame\n");
373 }
374
375 static struct wl_pointer_listener pointer_listener = {
376     .enter = pointer_handle_enter,
377     .leave = pointer_handle_leave,
378     .motion = pointer_handle_motion,
379     .button = pointer_handle_button,
380     .axis = NULL,
381     .frame = pointer_handle_frame,
382     .axis_source = NULL,
383     .axis_stop = NULL,
384     .axis_discrete = NULL,
385 };
386
387 static void touch_handle_down(void *data, struct wl_touch *wl_touch,
388         uint32_t serial, uint32_t time, struct wl_surface *surface,
389         int32_t id, wl_fixed_t x, wl_fixed_t y)
390 {
391     fprintf(stderr, "touch_handle_down id:%d, x:%d, y:%d\n",
392             id, wl_fixed_to_int(x), wl_fixed_to_int(y));
393
394     struct display *d = data;
395
396     tizen_input_device_manager_block_events(d->devicemgr, 0, TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD, 50000);
397
398     while (d->notified == -1)
399         wl_display_roundtrip(d->display);
400
401     if (d->notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
402         printf("Success to block keyboard events\n");
403     } else {
404         printf("Failed to block keyboard events: %d\n", d->notified);
405     }
406     d->notified = -1;
407     d->blocked = true;
408 }
409
410 static void touch_handle_up(void *data, struct wl_touch *wl_touch,
411         uint32_t serial, uint32_t time, int32_t id)
412 {
413     fprintf(stderr, "touch_handle_up id:%d\n", id);
414
415     struct display *d = data;
416
417     if (!d->blocked) return;
418     tizen_input_device_manager_unblock_events(d->devicemgr, 0);
419
420     while (d->notified == -1)
421         wl_display_roundtrip(d->display);
422
423     if (d->notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
424         printf("Success to unblock keyboard events\n");
425     } else {
426         printf("Failed to unblock keyboard events: %d\n", d->notified);
427     }
428     d->notified = -1;
429     d->blocked = false;
430 }
431
432 static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
433         uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
434 {
435     fprintf(stderr, "touch_handle_motion id:%d, x:%d, y:%d\n",
436             id, wl_fixed_to_int(x), wl_fixed_to_int(y));
437 }
438
439 static void touch_handle_frame(void *data, struct wl_touch *wl_touch)
440 {
441     fprintf(stderr, "touch_handle_frame\n");
442 }
443
444 static struct wl_touch_listener touch_listener = {
445     .down = touch_handle_down,
446     .up = touch_handle_up,
447     .motion = touch_handle_motion,
448     .frame = touch_handle_frame,
449     .cancel = NULL,
450     .shape = NULL,
451     .orientation = NULL,
452 };
453
454 static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
455         uint32_t format, int32_t fd, uint32_t size)
456 {
457     fprintf(stderr, "keyboard_handle_keymap\n");
458 }
459 static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
460         uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
461 {
462     fprintf(stderr, "keyboard_handle_enter\n");
463 }
464 static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
465         uint32_t serial, struct wl_surface *surface)
466 {
467     fprintf(stderr, "keyboard_handle_leave\n");
468 }
469 static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
470         uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
471         uint32_t mods_locked, uint32_t group)
472 {
473     fprintf(stderr, "keyboard_handle_modifiers\n");
474 }
475 static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
476         int32_t rate, int32_t delay)
477 {
478     fprintf(stderr, "keyboard_handle_repeat_info\n");
479 }
480
481 static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
482         uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
483 {
484     if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
485         fprintf(stderr, "keyboard_handle_key: key:%d, PRESSED\n", key);
486     } else {
487         fprintf(stderr, "keyboard_handle_key: key:%d, RELEASED\n", key);
488     }
489 }
490
491 static struct wl_keyboard_listener keyboard_listener = {
492     .keymap = keyboard_handle_keymap,
493     .enter = keyboard_handle_enter,
494     .leave = keyboard_handle_leave,
495     .key = keyboard_handle_key,
496     .modifiers = keyboard_handle_modifiers,
497     .repeat_info = keyboard_handle_repeat_info,
498 };
499
500 static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
501         enum wl_seat_capability caps)
502 {
503         struct display *d = data;
504     if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) {
505         struct wl_keyboard *keyboard = wl_seat_get_keyboard(wl_seat);
506         wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL);
507         fprintf(stderr, "seat_handle_capabilities: keyboard\n");
508     }
509     if ((caps & WL_SEAT_CAPABILITY_POINTER)) {
510         struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat);
511         wl_pointer_add_listener(pointer, &pointer_listener, NULL);
512         fprintf(stderr, "seat_handle_capabilities: pointer\n");
513     }
514     if ((caps & WL_SEAT_CAPABILITY_TOUCH)) {
515         struct wl_touch *touch = wl_seat_get_touch(wl_seat);
516         wl_touch_add_listener(touch, &touch_listener, d);
517         fprintf(stderr, "seat_handle_capabilities: touch\n");
518     }
519 }
520
521 static void seat_handle_name(void *data, struct wl_seat *wl_seat,
522         const char *name)
523 {
524     fprintf(stderr, "seat_handle_name name:%s\n", name);
525 }
526
527 const struct wl_seat_listener seat_listener = {
528     .capabilities = seat_handle_capabilities,
529     .name = seat_handle_name,
530 };
531
532 static void
533 input_device_manager_handle_error(void *data,
534         struct tizen_input_device_manager *tizen_input_device_manager,
535         uint32_t errorcode)
536 {
537     struct display *d = data;
538     fprintf(stderr, "errorcode: %d\n", errorcode);
539     d->notified = errorcode;
540 }
541
542 static void
543 input_device_manager_handle_block_expired(void *data,
544         struct tizen_input_device_manager *tizen_input_device_manager)
545 {
546     fprintf(stderr, "block expired\n");
547 }
548
549 static const struct tizen_input_device_manager_listener _input_device_manager_listener =
550 {
551     .device_add = NULL,
552     .device_remove = NULL,
553     .error = input_device_manager_handle_error,
554     .block_expired = input_device_manager_handle_block_expired,
555 };
556
557 static void
558 registry_handle_global(void *data, struct wl_registry *registry,
559                        uint32_t id, const char *interface, uint32_t version)
560 {
561         struct display *d = data;
562
563         if (strcmp(interface, "wl_compositor") == 0) {
564                 d->compositor =
565                         wl_registry_bind(registry,
566                                          id, &wl_compositor_interface, 1);
567         } else if (strcmp(interface, "xdg_wm_base") == 0) {
568                 d->wm_base = wl_registry_bind(registry,
569                                               id, &xdg_wm_base_interface, 1);
570                 xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
571         } else if (strcmp(interface, "wl_shm") == 0) {
572                 d->shm = wl_registry_bind(registry,
573                                           id, &wl_shm_interface, 1);
574                 wl_shm_add_listener(d->shm, &shm_listener, d);
575         } else if (strcmp(interface, "wl_seat") == 0) {
576                 d->seat = wl_registry_bind(registry,
577                                           id, &wl_seat_interface, 7);
578                 wl_seat_add_listener(d->seat, &seat_listener, d);
579                 fprintf(stderr, "wl_seat bound!\n");
580         } else if (strcmp(interface, "tizen_input_device_manager") == 0) {
581                 d->devicemgr = wl_registry_bind(registry,
582                                           id, &tizen_input_device_manager_interface, version);
583                 tizen_input_device_manager_add_listener(d->devicemgr,
584                                  &_input_device_manager_listener, d);
585                 fprintf(stderr, "tizen input device manager bound!\n");
586     }
587 }
588
589 static void
590 registry_handle_global_remove(void *data, struct wl_registry *registry,
591                               uint32_t name)
592 {
593 }
594
595 static const struct wl_registry_listener registry_listener = {
596         registry_handle_global,
597         registry_handle_global_remove
598 };
599
600 static struct display *
601 create_display(void)
602 {
603         struct display *display;
604
605         display = calloc(1, sizeof *display);
606         if (display == NULL) {
607                 fprintf(stderr, "out of memory\n");
608                 exit(1);
609         }
610         display->display = wl_display_connect(NULL);
611         assert(display->display);
612
613         display->has_xrgb = false;
614         display->registry = wl_display_get_registry(display->display);
615         wl_registry_add_listener(display->registry,
616                                  &registry_listener, display);
617         wl_display_roundtrip(display->display);
618         if (display->shm == NULL) {
619                 fprintf(stderr, "No wl_shm global\n");
620                 exit(1);
621         }
622
623         wl_display_roundtrip(display->display);
624
625         /*
626          * Why do we need two roundtrips here?
627          *
628          * wl_display_get_registry() sends a request to the server, to which
629          * the server replies by emitting the wl_registry.global events.
630          * The first wl_display_roundtrip() sends wl_display.sync. The server
631          * first processes the wl_display.get_registry which includes sending
632          * the global events, and then processes the sync. Therefore when the
633          * sync (roundtrip) returns, we are guaranteed to have received and
634          * processed all the global events.
635          *
636          * While we are inside the first wl_display_roundtrip(), incoming
637          * events are dispatched, which causes registry_handle_global() to
638          * be called for each global. One of these globals is wl_shm.
639          * registry_handle_global() sends wl_registry.bind request for the
640          * wl_shm global. However, wl_registry.bind request is sent after
641          * the first wl_display.sync, so the reply to the sync comes before
642          * the initial events of the wl_shm object.
643          *
644          * The initial events that get sent as a reply to binding to wl_shm
645          * include wl_shm.format. These tell us which pixel formats are
646          * supported, and we need them before we can create buffers. They
647          * don't change at runtime, so we receive them as part of init.
648          *
649          * When the reply to the first sync comes, the server may or may not
650          * have sent the initial wl_shm events. Therefore we need the second
651          * wl_display_roundtrip() call here.
652          *
653          * The server processes the wl_registry.bind for wl_shm first, and
654          * the second wl_display.sync next. During our second call to
655          * wl_display_roundtrip() the initial wl_shm events are received and
656          * processed. Finally, when the reply to the second wl_display.sync
657          * arrives, it guarantees we have processed all wl_shm initial events.
658          *
659          * This sequence contains two examples on how wl_display_roundtrip()
660          * can be used to guarantee, that all reply events to a request
661          * have been received and processed. This is a general Wayland
662          * technique.
663          */
664
665         if (!display->has_xrgb) {
666                 fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
667                 exit(1);
668         }
669
670     display->wl_tbm = wayland_tbm_client_init(display->display);
671     if (!display->wl_tbm) {
672         fprintf(stderr, "failed wayland_tbm_client_init()\n");
673         exit(1);
674     }
675
676         display->notified = -1;
677
678         return display;
679 }
680
681 static void
682 destroy_display(struct display *display)
683 {
684         if (display->seat)
685             wl_seat_destroy(display->seat);
686
687         if (display->devicemgr)
688             tizen_input_device_manager_destroy(display->devicemgr);
689
690         if (display->shm)
691                 wl_shm_destroy(display->shm);
692
693         if (display->wm_base)
694                 xdg_wm_base_destroy(display->wm_base);
695
696         if (display->compositor)
697                 wl_compositor_destroy(display->compositor);
698
699     wayland_tbm_client_deinit(display->wl_tbm);
700         wl_registry_destroy(display->registry);
701         wl_display_flush(display->display);
702         wl_display_disconnect(display->display);
703         free(display);
704 }
705
706 static void
707 signal_int(int signum)
708 {
709         running = 0;
710 }
711
712 int
713 main(int argc, char **argv)
714 {
715         struct sigaction sigint;
716         struct display *display;
717         struct window *window;
718         int ret = 0;
719
720         display = create_display();
721         window = create_window(display, 250, 250);
722         if (!window)
723                 return 1;
724
725         sigint.sa_handler = signal_int;
726         sigemptyset(&sigint.sa_mask);
727         sigint.sa_flags = SA_RESETHAND;
728         sigaction(SIGINT, &sigint, NULL);
729
730         /* Initialise damage to full surface, so the padding gets painted */
731         wl_surface_damage(window->surface, 0, 0,
732                           window->width, window->height);
733
734         if (!window->wait_for_configure)
735                 redraw(window, NULL, 0);
736
737         while (running && ret != -1)
738                 ret = wl_display_dispatch(display->display);
739
740         fprintf(stderr, "simple-shm exiting\n");
741
742         destroy_window(window);
743         destroy_display(display);
744
745         return 0;
746 }