change wl_signal_emit_mutable into wl_signal_emit
[platform/core/uifw/libds-tizen.git] / 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 #include <text-client-protocol.h>
43 #include <xkbcommon/xkbcommon.h>
44
45 static uint64_t buffer_info_key;
46 #define BUFFER_INFO_KEY (unsigned long)(&buffer_info_key)
47 struct text_entry;
48
49 struct display {
50         struct wl_display *display;
51         struct wl_registry *registry;
52         struct wl_compositor *compositor;
53         struct xdg_wm_base *wm_base;
54         struct wl_shm *shm;
55         struct wl_seat *seat;
56     struct wayland_tbm_client *wl_tbm;
57         bool has_xrgb;
58
59         struct tizen_input_device_manager *devicemgr;
60         int notified;
61         bool blocked;
62         struct wl_surface *entered_surface;
63
64         struct wl_text_input_manager *text_input_mgr;
65         struct text_entry *entry;
66 };
67
68 struct window {
69         struct display *display;
70         int width, height;
71         struct wl_surface *surface;
72         struct xdg_surface *xdg_surface;
73         struct xdg_toplevel *xdg_toplevel;
74         struct wl_callback *callback;
75     tbm_surface_queue_h surface_queue;
76         bool wait_for_configure;
77 };
78
79 struct buffer_info {
80     struct window *window;
81     struct wl_buffer *wl_buffer;
82 };
83
84 struct text_entry {
85         char *text;
86         int active;
87         bool panel_visible;
88         uint32_t cursor;
89         uint32_t anchor;
90         struct {
91                 char *text;
92                 int32_t cursor;
93                 char *commit;
94         } preedit;
95         struct {
96                 int32_t cursor;
97         } preedit_info;
98         struct {
99                 int32_t cursor;
100                 int32_t anchor;
101                 uint32_t delete_index;
102                 uint32_t delete_length;
103                 bool invalid_delete;
104         } pending_commit;
105         struct wl_text_input *text_input;
106         struct {
107                 xkb_mod_mask_t shift_mask;
108         } keysym;
109         uint32_t serial;
110         uint32_t reset_serial;
111         uint32_t content_purpose;
112         bool click_to_show;
113         char *preferred_language;
114         bool button_pressed;
115 };
116
117 struct rectangle {
118         int32_t x;
119         int32_t y;
120         int32_t width;
121         int32_t height;
122 };
123
124 static int running = 1;
125
126 static void
127 redraw(void *data, struct wl_callback *callback, uint32_t time);
128 static void
129 text_entry_activate(struct display *d);
130 static void
131 text_entry_deactivate(struct display *d);
132
133 static void
134 handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
135                              uint32_t serial)
136 {
137         struct window *window = data;
138
139         xdg_surface_ack_configure(surface, serial);
140
141         if (window->wait_for_configure) {
142                 redraw(window, NULL, 0);
143                 window->wait_for_configure = false;
144         }
145 }
146
147 static const struct xdg_surface_listener xdg_surface_listener = {
148         handle_xdg_surface_configure,
149 };
150
151 static void
152 handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
153                               int32_t width, int32_t height,
154                               struct wl_array *state)
155 {
156 }
157
158 static void
159 handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
160 {
161         running = 0;
162 }
163
164 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
165         handle_xdg_toplevel_configure,
166         handle_xdg_toplevel_close,
167 };
168
169 static struct window *
170 create_window(struct display *display, int width, int height)
171 {
172         struct window *window;
173
174         window = calloc(1, sizeof *window);
175         if (!window)
176                 return NULL;
177
178         window->callback = NULL;
179         window->display = display;
180         window->width = width;
181         window->height = height;
182         window->surface = wl_compositor_create_surface(display->compositor);
183
184         if (display->wm_base) {
185                 window->xdg_surface =
186                         xdg_wm_base_get_xdg_surface(display->wm_base,
187                                                     window->surface);
188                 assert(window->xdg_surface);
189                 xdg_surface_add_listener(window->xdg_surface,
190                                          &xdg_surface_listener, window);
191
192                 window->xdg_toplevel =
193                         xdg_surface_get_toplevel(window->xdg_surface);
194                 assert(window->xdg_toplevel);
195                 xdg_toplevel_add_listener(window->xdg_toplevel,
196                                           &xdg_toplevel_listener, window);
197
198                 xdg_toplevel_set_title(window->xdg_toplevel, "simple-tbm");
199                 wl_surface_commit(window->surface);
200                 window->wait_for_configure = true;
201         } else {
202                 assert(0);
203         }
204
205     window->surface_queue =
206         wayland_tbm_client_create_surface_queue(display->wl_tbm,
207                 window->surface,
208                 3,
209                 width,
210                 height,
211                 TBM_FORMAT_XRGB8888);
212     assert(window->surface_queue);
213
214         return window;
215 }
216
217 static void
218 destroy_window(struct window *window)
219 {
220     tbm_surface_queue_destroy(window->surface_queue);
221
222         if (window->callback)
223                 wl_callback_destroy(window->callback);
224
225         if (window->xdg_toplevel)
226                 xdg_toplevel_destroy(window->xdg_toplevel);
227         if (window->xdg_surface)
228                 xdg_surface_destroy(window->xdg_surface);
229         wl_surface_destroy(window->surface);
230         free(window);
231 }
232
233 static void
234 paint_pixels(void *image, int padding, int width, int height, uint32_t time)
235 {
236         const int halfh = padding + (height - padding * 2) / 2;
237         const int halfw = padding + (width  - padding * 2) / 2;
238         int ir, or;
239         uint32_t *pixel = image;
240         int y;
241
242         /* squared radii thresholds */
243         or = (halfw < halfh ? halfw : halfh) - 8;
244         ir = or - 32;
245         or *= or;
246         ir *= ir;
247
248         pixel += padding * width;
249         for (y = padding; y < height - padding; y++) {
250                 int x;
251                 int y2 = (y - halfh) * (y - halfh);
252
253                 pixel += padding;
254                 for (x = padding; x < width - padding; x++) {
255                         uint32_t v;
256
257                         /* squared distance from center */
258                         int r2 = (x - halfw) * (x - halfw) + y2;
259
260                         if (r2 < ir)
261                                 v = (r2 / 32 + time / 64) * 0x0080401;
262                         else if (r2 < or)
263                                 v = (y + time / 32) * 0x0080401;
264                         else
265                                 v = (x + time / 16) * 0x0080401;
266                         v &= 0x00ffffff;
267
268                         /* cross if compositor uses X from XRGB as alpha */
269                         if (abs(x - y) > 6 && abs(x + y - height) > 6)
270                                 v |= 0xff000000;
271
272                         *pixel++ = v;
273                 }
274
275                 pixel += padding;
276         }
277 }
278
279 static void
280 buffer_info_free_cb(void *data)
281 {
282     struct buffer_info *buffer_info = data;
283
284     if (!buffer_info)
285         return;
286
287     wayland_tbm_client_destroy_buffer(buffer_info->window->display->wl_tbm,
288             buffer_info->wl_buffer);
289     free(buffer_info);
290 }
291
292 static void
293 buffer_handle_release(void *data, struct wl_buffer *wl_buffer)
294 {
295     tbm_surface_h surface = data;
296     struct buffer_info *buffer_info;
297
298     tbm_surface_internal_get_user_data(surface, BUFFER_INFO_KEY,
299             (void **)&buffer_info);
300     if (buffer_info)
301         tbm_surface_queue_release(buffer_info->window->surface_queue, surface);
302 }
303
304 static const struct wl_buffer_listener buffer_listener = {
305     .release = buffer_handle_release,
306 };
307
308 static const struct wl_callback_listener frame_listener;
309
310 static void
311 redraw(void *data, struct wl_callback *callback, uint32_t time)
312 {
313         struct window *window = data;
314     struct buffer_info *buffer_info = NULL;
315     tbm_surface_h surface = NULL;
316     tbm_surface_info_s surface_info;
317
318     if (!tbm_surface_queue_can_dequeue(window->surface_queue, 0))
319         return;
320
321     tbm_surface_queue_dequeue(window->surface_queue, &surface);
322     assert(surface);
323
324     tbm_surface_internal_get_user_data(surface, BUFFER_INFO_KEY,
325             (void **)&buffer_info);
326     if (!buffer_info) {
327         buffer_info = calloc(1, sizeof *buffer_info);
328         assert(buffer_info);
329
330         tbm_surface_internal_add_user_data(surface, BUFFER_INFO_KEY, buffer_info_free_cb);
331         tbm_surface_internal_set_user_data(surface, BUFFER_INFO_KEY, buffer_info);
332
333         buffer_info->wl_buffer =
334             wayland_tbm_client_create_buffer(window->display->wl_tbm, surface);
335         assert(buffer_info->wl_buffer);
336
337         wl_buffer_add_listener(buffer_info->wl_buffer, &buffer_listener,
338                 surface);
339
340         buffer_info->window = window;
341     }
342
343     tbm_surface_map(surface, TBM_SURF_OPTION_WRITE, &surface_info);
344
345         paint_pixels(surface_info.planes[0].ptr, 20,
346             (surface_info.planes[0].stride/4), surface_info.height, time);
347
348     tbm_surface_unmap(surface);
349
350         wl_surface_attach(window->surface, buffer_info->wl_buffer, 0, 0);
351         wl_surface_damage(window->surface,
352                           20, 20, window->width - 40, window->height - 40);
353
354         if (callback)
355                 wl_callback_destroy(callback);
356
357         window->callback = wl_surface_frame(window->surface);
358         wl_callback_add_listener(window->callback, &frame_listener, window);
359         wl_surface_commit(window->surface);
360 }
361
362 static const struct wl_callback_listener frame_listener = {
363         redraw
364 };
365
366 static void
367 shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
368 {
369         struct display *d = data;
370
371         if (format == WL_SHM_FORMAT_XRGB8888)
372                 d->has_xrgb = true;
373 }
374
375 struct wl_shm_listener shm_listener = {
376         shm_format
377 };
378
379 static void
380 xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
381 {
382         xdg_wm_base_pong(shell, serial);
383 }
384
385 static const struct xdg_wm_base_listener xdg_wm_base_listener = {
386         xdg_wm_base_ping,
387 };
388
389 static void pointer_handle_button(void *data, struct wl_pointer *pointer,
390         uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
391 {
392     struct display *d = data;
393     static int warp_x = 0, warp_y = 0;
394
395     if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
396         fprintf(stderr, "pointer_handle_button: button(%d) PRESSED\n", button);
397         if (button == 1) { //left button
398             text_entry_activate(d);
399         }
400         else if (button == 3) {//right button
401             warp_x += 10;
402             warp_y += 10;
403             tizen_input_device_manager_pointer_warp(d->devicemgr,
404                     d->entered_surface,
405                     wl_fixed_from_int(warp_x),
406                     wl_fixed_from_int(warp_y));
407             fprintf(stderr, "requesting pointer_warp: surface:%p sx: %d sy: %d\n",
408                     d->entered_surface,
409                     warp_x, warp_y);
410         }
411     }
412     else {
413         fprintf(stderr, "pointer_handle_button: button(%d) RELEASED\n", button);
414         if (button == 1) {
415             text_entry_deactivate(d);
416         }
417     }
418 }
419
420 static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
421         uint32_t serial, struct wl_surface *surface,
422         wl_fixed_t surface_x, wl_fixed_t surface_y)
423 {
424     struct display *d = data;
425
426     fprintf(stderr, "pointer_handle_enter surface_x:%d, surface_y:%d\n",
427             wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y));
428     d->entered_surface = surface;
429 }
430
431 static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
432         uint32_t serial, struct wl_surface *surface)
433 {
434     fprintf(stderr, "pointer_handle_leave\n");
435 }
436
437 static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
438         uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
439 {
440     fprintf(stderr, "pointer_handle_motion surface_x:%d, surface_y:%d\n",
441             wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y));
442 }
443
444 static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer)
445 {
446     fprintf(stderr, "pointer_handle_frame\n");
447 }
448
449 static struct wl_pointer_listener pointer_listener = {
450     .enter = pointer_handle_enter,
451     .leave = pointer_handle_leave,
452     .motion = pointer_handle_motion,
453     .button = pointer_handle_button,
454     .axis = NULL,
455     .frame = pointer_handle_frame,
456     .axis_source = NULL,
457     .axis_stop = NULL,
458     .axis_discrete = NULL,
459 };
460
461 static void touch_handle_down(void *data, struct wl_touch *wl_touch,
462         uint32_t serial, uint32_t time, struct wl_surface *surface,
463         int32_t id, wl_fixed_t x, wl_fixed_t y)
464 {
465     fprintf(stderr, "touch_handle_down id:%d, x:%d, y:%d\n",
466             id, wl_fixed_to_int(x), wl_fixed_to_int(y));
467
468     struct display *d = data;
469
470     tizen_input_device_manager_block_events(d->devicemgr, 0, TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD, 50000);
471
472     while (d->notified == -1)
473         wl_display_roundtrip(d->display);
474
475     if (d->notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
476         printf("Success to block keyboard events\n");
477     } else {
478         printf("Failed to block keyboard events: %d\n", d->notified);
479     }
480     d->notified = -1;
481     d->blocked = true;
482 }
483
484 static void touch_handle_up(void *data, struct wl_touch *wl_touch,
485         uint32_t serial, uint32_t time, int32_t id)
486 {
487     fprintf(stderr, "touch_handle_up id:%d\n", id);
488
489     struct display *d = data;
490
491     if (!d->blocked) return;
492     tizen_input_device_manager_unblock_events(d->devicemgr, 0);
493
494     while (d->notified == -1)
495         wl_display_roundtrip(d->display);
496
497     if (d->notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
498         printf("Success to unblock keyboard events\n");
499     } else {
500         printf("Failed to unblock keyboard events: %d\n", d->notified);
501     }
502     d->notified = -1;
503     d->blocked = false;
504 }
505
506 static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
507         uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
508 {
509     fprintf(stderr, "touch_handle_motion id:%d, x:%d, y:%d\n",
510             id, wl_fixed_to_int(x), wl_fixed_to_int(y));
511 }
512
513 static void touch_handle_frame(void *data, struct wl_touch *wl_touch)
514 {
515     fprintf(stderr, "touch_handle_frame\n");
516 }
517
518 static struct wl_touch_listener touch_listener = {
519     .down = touch_handle_down,
520     .up = touch_handle_up,
521     .motion = touch_handle_motion,
522     .frame = touch_handle_frame,
523     .cancel = NULL,
524     .shape = NULL,
525     .orientation = NULL,
526 };
527
528 static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
529         uint32_t format, int32_t fd, uint32_t size)
530 {
531     fprintf(stderr, "keyboard_handle_keymap\n");
532 }
533 static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
534         uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
535 {
536     fprintf(stderr, "keyboard_handle_enter\n");
537 }
538 static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
539         uint32_t serial, struct wl_surface *surface)
540 {
541     fprintf(stderr, "keyboard_handle_leave\n");
542 }
543 static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
544         uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
545         uint32_t mods_locked, uint32_t group)
546 {
547     fprintf(stderr, "keyboard_handle_modifiers\n");
548 }
549 static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
550         int32_t rate, int32_t delay)
551 {
552     fprintf(stderr, "keyboard_handle_repeat_info\n");
553 }
554
555 static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
556         uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
557 {
558     if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
559         fprintf(stderr, "keyboard_handle_key: key:%d, PRESSED\n", key);
560     } else {
561         fprintf(stderr, "keyboard_handle_key: key:%d, RELEASED\n", key);
562     }
563 }
564
565 static struct wl_keyboard_listener keyboard_listener = {
566     .keymap = keyboard_handle_keymap,
567     .enter = keyboard_handle_enter,
568     .leave = keyboard_handle_leave,
569     .key = keyboard_handle_key,
570     .modifiers = keyboard_handle_modifiers,
571     .repeat_info = keyboard_handle_repeat_info,
572 };
573
574 static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
575         enum wl_seat_capability caps)
576 {
577         struct display *d = data;
578     if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) {
579         struct wl_keyboard *keyboard = wl_seat_get_keyboard(wl_seat);
580         wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL);
581         fprintf(stderr, "seat_handle_capabilities: keyboard\n");
582     }
583     if ((caps & WL_SEAT_CAPABILITY_POINTER)) {
584         struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat);
585         wl_pointer_add_listener(pointer, &pointer_listener, d);
586         fprintf(stderr, "seat_handle_capabilities: pointer\n");
587     }
588     if ((caps & WL_SEAT_CAPABILITY_TOUCH)) {
589         struct wl_touch *touch = wl_seat_get_touch(wl_seat);
590         wl_touch_add_listener(touch, &touch_listener, d);
591         fprintf(stderr, "seat_handle_capabilities: touch\n");
592     }
593 }
594
595 static void seat_handle_name(void *data, struct wl_seat *wl_seat,
596         const char *name)
597 {
598     fprintf(stderr, "seat_handle_name name:%s\n", name);
599 }
600
601 const struct wl_seat_listener seat_listener = {
602     .capabilities = seat_handle_capabilities,
603     .name = seat_handle_name,
604 };
605
606 static void
607 input_device_manager_handle_error(void *data,
608         struct tizen_input_device_manager *tizen_input_device_manager,
609         uint32_t errorcode)
610 {
611     struct display *d = data;
612     fprintf(stderr, "errorcode: %d\n", errorcode);
613     d->notified = errorcode;
614 }
615
616 static void
617 input_device_manager_handle_block_expired(void *data,
618         struct tizen_input_device_manager *tizen_input_device_manager)
619 {
620     fprintf(stderr, "block expired\n");
621 }
622
623 static const struct tizen_input_device_manager_listener _input_device_manager_listener =
624 {
625     .device_add = NULL,
626     .device_remove = NULL,
627     .error = input_device_manager_handle_error,
628     .block_expired = input_device_manager_handle_block_expired,
629 };
630
631
632 static void
633 text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rectangle)
634 {
635         if (entry->preedit.text && entry->preedit.cursor < 0) {
636                 rectangle->x = 0;
637                 rectangle->y = 0;
638                 rectangle->width = 0;
639                 rectangle->height = 0;
640                 return;
641         }
642
643         rectangle->x = 10;
644         rectangle->y = 20;
645         rectangle->width = 50;
646         rectangle->height = 50;
647 }
648
649 static void
650 text_entry_update(struct text_entry *entry)
651 {
652         struct rectangle cursor_rectangle;
653
654         fprintf(stderr, "text_entry_update()\n");
655
656         wl_text_input_set_content_type(entry->text_input,
657                                        WL_TEXT_INPUT_CONTENT_HINT_NONE,
658                                        entry->content_purpose);
659
660         if (entry->preferred_language)
661                 wl_text_input_set_preferred_language(entry->text_input,
662                                                      entry->preferred_language);
663
664         text_entry_get_cursor_rectangle(entry, &cursor_rectangle);
665         wl_text_input_set_cursor_rectangle(entry->text_input,
666                                            cursor_rectangle.x,
667                                            cursor_rectangle.y,
668                                            cursor_rectangle.width,
669                                            cursor_rectangle.height);
670
671         wl_text_input_commit_state(entry->text_input, ++entry->serial);
672 }
673
674 static void
675 text_entry_reset_preedit(struct text_entry *entry)
676 {
677         fprintf(stderr, "text_entry_reset_preedit()\n");
678         entry->preedit.cursor = 0;
679
680         free(entry->preedit.text);
681         entry->preedit.text = NULL;
682
683         free(entry->preedit.commit);
684         entry->preedit.commit = NULL;
685 }
686
687 static void
688 text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
689                             int32_t cursor, int32_t anchor)
690 {
691         fprintf(stderr, "text_entry_insert_at_cursor()\n");
692         char *new_text;
693         int len_entry_text, len_text;
694
695         len_entry_text = strlen(entry->text);
696         len_text = strlen(text);
697         new_text = malloc(len_entry_text + len_text + 1);
698         if (new_text == NULL) {
699                 fprintf(stderr, "alloc fail");
700                 return;
701         }
702
703         memcpy(new_text, entry->text, entry->cursor);
704         memcpy(new_text + entry->cursor, text, len_text);
705         memcpy(new_text + entry->cursor + len_text,
706                entry->text + entry->cursor, len_entry_text - entry->cursor);
707         new_text[len_entry_text + len_text] = '\0';
708
709         free(entry->text);
710         entry->text = new_text;
711         if (anchor >= 0)
712                 entry->anchor = entry->cursor + strlen(text) + anchor;
713         else
714                 entry->anchor = entry->cursor + 1 + anchor;
715
716         if (cursor >= 0)
717                 entry->cursor += strlen(text) + cursor;
718         else
719                 entry->cursor += 1 + cursor;
720
721         text_entry_update(entry);
722 }
723
724 static void
725 text_entry_commit_and_reset(struct text_entry *entry)
726 {
727         char *commit = NULL;
728
729         fprintf(stderr, "text_entry_commit_and_reset()\n");
730
731         if (entry->preedit.commit)
732                 commit = strdup(entry->preedit.commit);
733
734         text_entry_reset_preedit(entry);
735         if (commit) {
736                 text_entry_insert_at_cursor(entry, commit, 0, 0);
737                 free(commit);
738         }
739
740         wl_text_input_reset(entry->text_input);
741         text_entry_update(entry);
742         entry->reset_serial = entry->serial;
743 }
744
745 static void
746 text_input_enter(void *data, struct wl_text_input *text_input,
747         struct wl_surface *surface)
748 {
749         fprintf(stderr, "text_input_enter()\n");
750
751         struct display *d = data;
752         struct text_entry *entry = d->entry;
753
754         entry->active++;
755
756         text_entry_update(entry);
757         entry->reset_serial = entry->serial;
758 }
759
760 static void
761 text_input_leave(void *data, struct wl_text_input *text_input)
762 {
763         fprintf(stderr, "text_input_leave()\n");
764
765         struct display *d = data;
766         struct text_entry *entry = d->entry;
767
768         text_entry_commit_and_reset(entry);
769         d->entry->active--;
770
771         if (!entry->active) {
772                 wl_text_input_hide_input_panel(text_input);
773                 entry->panel_visible = false;
774         }
775 }
776
777 static void
778 text_input_modifiers_map(void *data, struct wl_text_input *text_input,
779         struct wl_array *map)
780 {
781         fprintf(stderr, "text_input_modifiers_map()\n");
782 }
783
784 static void
785 text_input_input_panel_state(void *data, struct wl_text_input *text_input,
786         uint32_t state)
787 {
788         fprintf(stderr, "text_input_input_panel_state() state:%u\n", state);
789 }
790
791 static void
792 clear_pending_preedit(struct text_entry *entry)
793 {
794         fprintf(stderr, "clear_pending_preedit()\n");
795
796         memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
797
798         entry->preedit_info.cursor = 0;
799
800         memset(&entry->preedit_info, 0, sizeof entry->preedit_info);
801 }
802
803 static void
804 text_entry_delete_text(struct text_entry *entry,
805                            uint32_t index, uint32_t length)
806 {
807         uint32_t l;
808
809         fprintf(stderr, "text_entry_delete_text()\n");
810
811         assert(index <= strlen(entry->text));
812         assert(index + length <= strlen(entry->text));
813         assert(index + length >= length);
814
815         l = strlen(entry->text + index + length);
816         memmove(entry->text + index,
817                 entry->text + index + length,
818                 l + 1);
819
820         if (entry->cursor > (index + length))
821                 entry->cursor -= length;
822         else if (entry->cursor > index)
823                 entry->cursor = index;
824
825         entry->anchor = entry->cursor;
826
827         text_entry_update(entry);
828 }
829
830 static void
831 text_entry_delete_selected_text(struct text_entry *entry)
832 {
833         uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
834         uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
835
836         fprintf(stderr, "text_entry_delete_selected_text()\n");
837
838         if (entry->anchor == entry->cursor)
839                 return;
840
841         text_entry_delete_text(entry, start_index, end_index - start_index);
842
843         entry->anchor = entry->cursor;
844 }
845
846 static void
847 text_entry_set_preedit(struct text_entry *entry,
848                            const char *preedit_text,
849                            int preedit_cursor)
850 {
851         fprintf(stderr, "text_entry_set_preedit()\n");
852
853         text_entry_reset_preedit(entry);
854
855         if (!preedit_text)
856                 return;
857
858         entry->preedit.text = strdup(preedit_text);
859         entry->preedit.cursor = preedit_cursor;
860 }
861
862 static void
863 text_input_preedit_string(void *data, struct wl_text_input *text_input,
864         uint32_t serial, const char *text, const char *commit)
865 {
866         struct display *d = data;
867         struct text_entry *entry = d->entry;
868
869         fprintf(stderr, "text_input_preedit_string() serial(%u), text(%s), commit(%s)\n", serial, text, commit);
870
871         if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) {
872                 fprintf(stderr, "Ignore preedit_string. Serial: %u, Current: %u, Reset: %u\n",
873                         serial, entry->serial, entry->reset_serial);
874                 clear_pending_preedit(entry);
875                 return;
876         }
877
878         if (entry->pending_commit.invalid_delete) {
879                 fprintf(stderr, "Ignore preedit_string. Invalid previous delete_surrounding event.\n");
880                 clear_pending_preedit(entry);
881                 return;
882         }
883
884         if (entry->pending_commit.delete_length) {
885                 text_entry_delete_text(entry,
886                                        entry->pending_commit.delete_index,
887                                        entry->pending_commit.delete_length);
888         } else {
889                 text_entry_delete_selected_text(entry);
890         }
891
892         text_entry_set_preedit(entry, text, entry->preedit_info.cursor);
893         entry->preedit.commit = strdup(commit);
894
895         clear_pending_preedit(entry);
896
897         text_entry_update(entry);
898 }
899
900 static void
901 text_input_preedit_styling(void *data, struct wl_text_input *text_input,
902         uint32_t index, uint32_t length, uint32_t style)
903 {
904         fprintf(stderr, "text_input_preedit_styling() index(%u), length(%u), style(%u)\n", index, length, style);
905
906         switch (style) {
907                 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
908                         fprintf(stderr, "text_input_preedit_styling() style:DEFAULT");
909                         break;
910                 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
911                         fprintf(stderr, "text_input_preedit_styling() style:UNDERLINE");
912                         break;
913                 case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT:
914                         fprintf(stderr, "text_input_preedit_styling() style:INCORRECT");
915                         break;
916                 case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION:
917                         fprintf(stderr, "text_input_preedit_styling() style:SELECTION");
918                         break;
919                 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
920                         fprintf(stderr, "text_input_preedit_styling() style:HIGHLIGHT");
921                         break;
922                 case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE:
923                         fprintf(stderr, "text_input_preedit_styling() style:ACTIVE");
924                         break;
925                 case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE:
926                         fprintf(stderr, "text_input_preedit_styling() style:INACTIVE");
927                         break;
928                 default:
929                         fprintf(stderr, "text_input_preedit_styling() no style enum found");
930                         break;
931         }
932 }
933
934 static void
935 text_input_preedit_cursor(void *data, struct wl_text_input *text_input,
936         int32_t index)
937 {
938         struct display *d = data;
939         struct text_entry *entry = d->entry;
940
941         fprintf(stderr, "text_input_preedit_cursor() index(%u)\n", index);
942
943         entry->preedit_info.cursor = index;
944 }
945
946 static void
947 text_input_commit_string(void *data, struct wl_text_input *text_input,
948         uint32_t serial, const char *text)
949 {
950         struct display *d = data;
951         struct text_entry *entry = d->entry;
952
953         fprintf(stderr, "text_input_commit_string() serial(%u), text(%s)\n", serial, text);
954
955         if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) {
956                 fprintf(stderr, "Ignore commit. Serial: %u, Current: %u, Reset: %u\n",
957                         serial, entry->serial, entry->reset_serial);
958                 return;
959         }
960
961         if (entry->pending_commit.invalid_delete) {
962                 fprintf(stderr, "Ignore commit. Invalid previous delete_surrounding event.\n");
963                 memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
964                 return;
965         }
966
967         text_entry_reset_preedit(entry);
968
969         if (entry->pending_commit.delete_length) {
970                 text_entry_delete_text(entry,
971                                        entry->pending_commit.delete_index,
972                                        entry->pending_commit.delete_length);
973         } else {
974                 text_entry_delete_selected_text(entry);
975         }
976
977         text_entry_insert_at_cursor(entry, text,
978                                     entry->pending_commit.cursor,
979                                     entry->pending_commit.anchor);
980
981         memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
982 }
983
984 static void
985 text_input_cursor_position(void *data, struct wl_text_input *text_input,
986         int32_t index, int32_t anchor)
987 {
988         fprintf(stderr, "text_input_cursor_position() index(%d), anchor(%d)\n", index, anchor);
989 }
990
991 static void
992 text_input_delete_surrounding_text(void *data,
993         struct wl_text_input *text_input, int32_t index, uint32_t length)
994 {
995         struct text_entry *entry = data;
996         uint32_t text_length;
997
998         fprintf(stderr, "text_input_delete_surrounding_text() index(%d), length(%u)\n", index, length);
999
1000         entry->pending_commit.delete_index = entry->cursor + index;
1001         entry->pending_commit.delete_length = length;
1002         entry->pending_commit.invalid_delete = false;
1003
1004         text_length = strlen(entry->text);
1005
1006         if (entry->pending_commit.delete_index > text_length ||
1007             length > text_length ||
1008             entry->pending_commit.delete_index + length > text_length) {
1009                 fprintf(stderr, "delete_surrounding_text: Invalid index: %d," \
1010                         "length %u'; cursor: %u text length: %u\n", index, length, entry->cursor, text_length);
1011                 entry->pending_commit.invalid_delete = true;
1012                 return;
1013         }
1014 }
1015
1016 static void
1017 text_input_keysym(void *data, struct wl_text_input *text_input,
1018         uint32_t serial, uint32_t time, uint32_t sym, uint32_t state,
1019         uint32_t modifiers)
1020 {
1021         fprintf(stderr, "text_input_keysym() serial(%u), time(%u), sym(%u), state(%u), modifiers(%u)\n",
1022                 serial, time, sym, state, modifiers);
1023 }
1024
1025 static void
1026 text_input_language(void *data, struct wl_text_input *text_input,
1027         uint32_t serial, const char *language)
1028 {
1029         fprintf(stderr, "text_input_language() serial(%u), language(%s)\n", serial, language);
1030 }
1031
1032 static void
1033 text_input_text_direction(void *data, struct wl_text_input *text_input,
1034         uint32_t serial, uint32_t direction)
1035 {
1036         fprintf(stderr, "text_input_text_direction() serial(%d), direction(%d)\n", serial, direction);
1037 }
1038
1039 static const struct wl_text_input_listener text_input_listener = {
1040     .enter = text_input_enter,
1041     .leave = text_input_leave,
1042     .modifiers_map = text_input_modifiers_map,
1043     .input_panel_state = text_input_input_panel_state,
1044     .preedit_string = text_input_preedit_string,
1045     .preedit_styling = text_input_preedit_styling,
1046     .preedit_cursor = text_input_preedit_cursor,
1047     .commit_string = text_input_commit_string,
1048     .cursor_position = text_input_cursor_position,
1049     .delete_surrounding_text = text_input_delete_surrounding_text,
1050     .keysym = text_input_keysym,
1051     .language = text_input_language,
1052     .text_direction = text_input_text_direction,
1053     // TIZEN_ONLY
1054     .selection_region = NULL,
1055     .private_command = NULL,
1056     .input_panel_geometry = NULL,
1057     .input_panel_data = NULL,
1058     .get_selection_text = NULL,
1059     .get_surrounding_text = NULL,
1060     .filter_key_event_done = NULL,
1061     .hide_permission = NULL,
1062     .recapture_string = NULL,
1063     .input_panel_event = NULL,
1064     .commit_content = NULL,
1065     //
1066 };
1067
1068 static void
1069 text_entry_activate(struct display *d)
1070 {
1071         struct wl_surface *surface = d->entered_surface;
1072         struct text_entry *entry = d->entry;
1073
1074         fprintf(stderr, "text_entry_activate\n");
1075         if (entry->click_to_show && entry->active) {
1076                 entry->panel_visible = !entry->panel_visible;
1077
1078                 if (entry->panel_visible)
1079                         wl_text_input_show_input_panel(entry->text_input);
1080                 else
1081                         wl_text_input_hide_input_panel(entry->text_input);
1082
1083                 return;
1084         }
1085
1086         if (!entry->click_to_show)
1087                 wl_text_input_show_input_panel(entry->text_input);
1088
1089         wl_text_input_activate(entry->text_input,
1090                                d->seat,
1091                                surface);
1092 }
1093
1094 static void
1095 text_entry_deactivate(struct display *d)
1096 {
1097         struct text_entry *entry = d->entry;
1098
1099         fprintf(stderr, "text_entry_deactivate\n");
1100         wl_text_input_deactivate(entry->text_input,
1101                                  d->seat);
1102 }
1103
1104 static void
1105 text_entry_destroy(struct display *d)
1106 {
1107         struct text_entry *entry;
1108
1109         entry = d->entry;
1110         d->entry = NULL;
1111
1112         wl_text_input_destroy(entry->text_input);
1113         free(entry->text);
1114         free(entry->preferred_language);
1115         free(entry);
1116 }
1117
1118 static struct text_entry*
1119 text_entry_create(struct display *d, const char *text)
1120 {
1121         struct text_entry *entry;
1122
1123         entry = calloc(1, sizeof *entry);
1124         if (!entry)
1125                 return NULL;
1126
1127         entry->text = strdup(text);
1128         entry->active = 0;
1129         entry->panel_visible = false;
1130         entry->cursor = strlen(text);
1131         entry->anchor = entry->cursor;
1132         entry->click_to_show = true;
1133         entry->text_input =
1134                 wl_text_input_manager_create_text_input(d->text_input_mgr);
1135         wl_text_input_add_listener(entry->text_input,
1136                                         &text_input_listener, d);
1137
1138         d->entry = entry;
1139         fprintf(stderr, "text_entry_create() entry(%p) created.\n", entry);
1140
1141         return entry;
1142 }
1143
1144 static void
1145 registry_handle_global(void *data, struct wl_registry *registry,
1146                        uint32_t id, const char *interface, uint32_t version)
1147 {
1148         struct display *d = data;
1149
1150         if (strcmp(interface, "wl_compositor") == 0) {
1151                 d->compositor =
1152                         wl_registry_bind(registry,
1153                                          id, &wl_compositor_interface, 1);
1154         } else if (strcmp(interface, "xdg_wm_base") == 0) {
1155                 d->wm_base = wl_registry_bind(registry,
1156                                               id, &xdg_wm_base_interface, 1);
1157                 xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
1158         } else if (strcmp(interface, "wl_shm") == 0) {
1159                 d->shm = wl_registry_bind(registry,
1160                                           id, &wl_shm_interface, 1);
1161                 wl_shm_add_listener(d->shm, &shm_listener, d);
1162         } else if (strcmp(interface, "wl_seat") == 0) {
1163                 d->seat = wl_registry_bind(registry,
1164                                           id, &wl_seat_interface, 7);
1165                 wl_seat_add_listener(d->seat, &seat_listener, d);
1166                 fprintf(stderr, "wl_seat bound!\n");
1167         } else if (strcmp(interface, "tizen_input_device_manager") == 0) {
1168                 d->devicemgr = wl_registry_bind(registry,
1169                                           id, &tizen_input_device_manager_interface, version);
1170                 tizen_input_device_manager_add_listener(d->devicemgr,
1171                                  &_input_device_manager_listener, d);
1172                 fprintf(stderr, "tizen input device manager bound!\n");
1173     } else if (strcmp(interface, "wl_text_input_manager") == 0) {
1174                 d->text_input_mgr = wl_registry_bind(registry,
1175                                           id, &wl_text_input_manager_interface, version);
1176                 fprintf(stderr, "wl_text_input_manager bound!\n");
1177
1178                 text_entry_create(d, "Entry");
1179     }
1180 }
1181
1182 static void
1183 registry_handle_global_remove(void *data, struct wl_registry *registry,
1184                               uint32_t name)
1185 {
1186 }
1187
1188 static const struct wl_registry_listener registry_listener = {
1189         registry_handle_global,
1190         registry_handle_global_remove
1191 };
1192
1193 static struct display *
1194 create_display(void)
1195 {
1196         struct display *display;
1197
1198         display = calloc(1, sizeof *display);
1199         if (display == NULL) {
1200                 fprintf(stderr, "out of memory\n");
1201                 exit(1);
1202         }
1203         display->display = wl_display_connect(NULL);
1204         assert(display->display);
1205
1206         display->has_xrgb = false;
1207         display->registry = wl_display_get_registry(display->display);
1208         wl_registry_add_listener(display->registry,
1209                                  &registry_listener, display);
1210         wl_display_roundtrip(display->display);
1211         if (display->shm == NULL) {
1212                 fprintf(stderr, "No wl_shm global\n");
1213                 exit(1);
1214         }
1215
1216         wl_display_roundtrip(display->display);
1217
1218         /*
1219          * Why do we need two roundtrips here?
1220          *
1221          * wl_display_get_registry() sends a request to the server, to which
1222          * the server replies by emitting the wl_registry.global events.
1223          * The first wl_display_roundtrip() sends wl_display.sync. The server
1224          * first processes the wl_display.get_registry which includes sending
1225          * the global events, and then processes the sync. Therefore when the
1226          * sync (roundtrip) returns, we are guaranteed to have received and
1227          * processed all the global events.
1228          *
1229          * While we are inside the first wl_display_roundtrip(), incoming
1230          * events are dispatched, which causes registry_handle_global() to
1231          * be called for each global. One of these globals is wl_shm.
1232          * registry_handle_global() sends wl_registry.bind request for the
1233          * wl_shm global. However, wl_registry.bind request is sent after
1234          * the first wl_display.sync, so the reply to the sync comes before
1235          * the initial events of the wl_shm object.
1236          *
1237          * The initial events that get sent as a reply to binding to wl_shm
1238          * include wl_shm.format. These tell us which pixel formats are
1239          * supported, and we need them before we can create buffers. They
1240          * don't change at runtime, so we receive them as part of init.
1241          *
1242          * When the reply to the first sync comes, the server may or may not
1243          * have sent the initial wl_shm events. Therefore we need the second
1244          * wl_display_roundtrip() call here.
1245          *
1246          * The server processes the wl_registry.bind for wl_shm first, and
1247          * the second wl_display.sync next. During our second call to
1248          * wl_display_roundtrip() the initial wl_shm events are received and
1249          * processed. Finally, when the reply to the second wl_display.sync
1250          * arrives, it guarantees we have processed all wl_shm initial events.
1251          *
1252          * This sequence contains two examples on how wl_display_roundtrip()
1253          * can be used to guarantee, that all reply events to a request
1254          * have been received and processed. This is a general Wayland
1255          * technique.
1256          */
1257
1258         if (!display->has_xrgb) {
1259                 fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
1260                 exit(1);
1261         }
1262
1263     display->wl_tbm = wayland_tbm_client_init(display->display);
1264     if (!display->wl_tbm) {
1265         fprintf(stderr, "failed wayland_tbm_client_init()\n");
1266         exit(1);
1267     }
1268
1269         display->notified = -1;
1270
1271         return display;
1272 }
1273
1274 static void
1275 destroy_display(struct display *display)
1276 {
1277         text_entry_destroy(display);
1278
1279         if (display->text_input_mgr)
1280                 wl_text_input_manager_destroy(display->text_input_mgr);
1281
1282         if (display->seat)
1283             wl_seat_destroy(display->seat);
1284
1285         if (display->devicemgr)
1286             tizen_input_device_manager_destroy(display->devicemgr);
1287
1288         if (display->shm)
1289                 wl_shm_destroy(display->shm);
1290
1291         if (display->wm_base)
1292                 xdg_wm_base_destroy(display->wm_base);
1293
1294         if (display->compositor)
1295                 wl_compositor_destroy(display->compositor);
1296
1297     wayland_tbm_client_deinit(display->wl_tbm);
1298         wl_registry_destroy(display->registry);
1299         wl_display_flush(display->display);
1300         wl_display_disconnect(display->display);
1301         free(display);
1302 }
1303
1304 static void
1305 signal_int(int signum)
1306 {
1307         running = 0;
1308 }
1309
1310 int
1311 main(int argc, char **argv)
1312 {
1313         struct sigaction sigint;
1314         struct display *display;
1315         struct window *window;
1316         int ret = 0;
1317
1318         display = create_display();
1319         window = create_window(display, 250, 250);
1320         if (!window)
1321                 return 1;
1322
1323         sigint.sa_handler = signal_int;
1324         sigemptyset(&sigint.sa_mask);
1325         sigint.sa_flags = SA_RESETHAND;
1326         sigaction(SIGINT, &sigint, NULL);
1327
1328         /* Initialise damage to full surface, so the padding gets painted */
1329         wl_surface_damage(window->surface, 0, 0,
1330                           window->width, window->height);
1331
1332         if (!window->wait_for_configure)
1333                 redraw(window, NULL, 0);
1334
1335         while (running && ret != -1)
1336                 ret = wl_display_dispatch(display->display);
1337
1338         fprintf(stderr, "simple-shm exiting\n");
1339
1340         destroy_window(window);
1341         destroy_display(display);
1342
1343         return 0;
1344 }