toytoolkit: Don't draw shadows for maximized windows.
[profile/ivi/weston.git] / clients / editor.c
1 /*
2  * Copyright © 2012 Openismus GmbH
3  * Copyright © 2012 Intel Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of the copyright holders not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission.  The copyright holders make
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <linux/input.h>
30 #include <cairo.h>
31
32 #include "window.h"
33 #include "text-client-protocol.h"
34
35 static const char *font_name = "sans-serif";
36 static int font_size = 14;
37
38 struct text_layout {
39         cairo_glyph_t *glyphs;
40         int num_glyphs;
41         cairo_text_cluster_t *clusters;
42         int num_clusters;
43         cairo_text_cluster_flags_t cluster_flags;
44         cairo_scaled_font_t *font;
45 };
46
47 struct text_entry {
48         struct widget *widget;
49         struct window *window;
50         char *text;
51         int active;
52         uint32_t cursor;
53         uint32_t anchor;
54         char *preedit_text;
55         uint32_t preedit_cursor;
56         struct text_model *model;
57         struct text_layout *layout;
58 };
59
60 struct editor {
61         struct text_model_factory *text_model_factory;
62         struct display *display;
63         struct window *window;
64         struct widget *widget;
65         struct text_entry *entry;
66         struct text_entry *editor;
67 };
68
69 static struct text_layout *
70 text_layout_create(void)
71 {
72         struct text_layout *layout;
73         cairo_surface_t *surface;
74         cairo_t *cr;
75
76         layout = malloc(sizeof *layout);
77         if (!layout)
78                 return NULL;
79
80         layout->glyphs = NULL;
81         layout->num_glyphs = 0;
82
83         layout->clusters = NULL;
84         layout->num_clusters = 0;
85
86         surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
87         cr = cairo_create(surface);
88         cairo_set_font_size(cr, font_size);
89         cairo_select_font_face(cr, font_name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
90         layout->font = cairo_get_scaled_font(cr);
91         cairo_scaled_font_reference(layout->font);
92
93         cairo_destroy(cr);
94         cairo_surface_destroy(surface);
95
96         return layout;
97 }
98
99 static void
100 text_layout_destroy(struct text_layout *layout)
101 {
102         if (layout->glyphs)
103                 cairo_glyph_free(layout->glyphs);
104
105         if (layout->clusters)
106                 cairo_text_cluster_free(layout->clusters);
107
108         cairo_scaled_font_destroy(layout->font);
109
110         free(layout);
111 }
112
113 static void
114 text_layout_set_text(struct text_layout *layout,
115                      const char *text)
116 {
117         if (layout->glyphs)
118                 cairo_glyph_free(layout->glyphs);
119
120         if (layout->clusters)
121                 cairo_text_cluster_free(layout->clusters);
122
123         layout->glyphs = NULL;
124         layout->num_glyphs = 0;
125         layout->clusters = NULL;
126         layout->num_clusters = 0;
127
128         cairo_scaled_font_text_to_glyphs(layout->font, 0, 0, text, -1,
129                                          &layout->glyphs, &layout->num_glyphs,
130                                          &layout->clusters, &layout->num_clusters,
131                                          &layout->cluster_flags);
132 }
133
134 static void
135 text_layout_draw(struct text_layout *layout, cairo_t *cr)
136 {
137         cairo_save(cr);
138         cairo_set_scaled_font(cr, layout->font);
139         cairo_show_glyphs(cr, layout->glyphs, layout->num_glyphs);
140         cairo_restore(cr);
141 }
142
143 static void
144 text_layout_extents(struct text_layout *layout, cairo_text_extents_t *extents)
145 {
146         cairo_scaled_font_glyph_extents(layout->font,
147                                         layout->glyphs, layout->num_glyphs,
148                                         extents);
149 }
150
151 static int
152 text_layout_xy_to_index(struct text_layout *layout, double x, double y)
153 {
154         cairo_text_extents_t extents;
155         int i;
156         double d;
157
158         if (layout->num_glyphs == 0)
159                 return 0;
160
161         cairo_scaled_font_glyph_extents(layout->font,
162                                         layout->glyphs, layout->num_glyphs,
163                                         &extents);
164
165         if (x < 0)
166                 return 0;
167
168         for (i = 0; i < layout->num_glyphs - 1; ++i) {
169                 d = layout->glyphs[i + 1].x - layout->glyphs[i].x;
170                 if (x < layout->glyphs[i].x + d/2)
171                         return i;
172         }
173
174         d = extents.width - layout->glyphs[layout->num_glyphs - 1].x;
175         if (x < layout->glyphs[layout->num_glyphs - 1].x + d/2)
176                 return layout->num_glyphs - 1;
177
178         return layout->num_glyphs;
179 }
180
181 static void
182 text_layout_index_to_pos(struct text_layout *layout, uint32_t index, cairo_rectangle_t *pos)
183 {
184         cairo_text_extents_t extents;
185
186         if (!pos)
187                 return;
188
189         cairo_scaled_font_glyph_extents(layout->font,
190                                         layout->glyphs, layout->num_glyphs,
191                                         &extents);
192
193         if ((int)index >= layout->num_glyphs) {
194                 pos->x = extents.x_advance;
195                 pos->y = layout->num_glyphs ? layout->glyphs[layout->num_glyphs - 1].y : 0;
196                 pos->width = 1;
197                 pos->height = extents.height;
198                 return;
199         }
200
201         pos->x = layout->glyphs[index].x;
202         pos->y = layout->glyphs[index].y;
203         pos->width = (int)index < layout->num_glyphs - 1 ? layout->glyphs[index + 1].x : extents.x_advance - pos->x;
204         pos->height = extents.height;
205 }
206
207 static void
208 text_layout_get_cursor_pos(struct text_layout *layout, int index, cairo_rectangle_t *pos)
209 {
210         text_layout_index_to_pos(layout, index, pos);
211         pos->width = 1;
212 }
213
214 static void text_entry_redraw_handler(struct widget *widget, void *data);
215 static void text_entry_button_handler(struct widget *widget,
216                                       struct input *input, uint32_t time,
217                                       uint32_t button,
218                                       enum wl_pointer_button_state state, void *data);
219 static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text);
220 static void text_entry_set_preedit(struct text_entry *entry,
221                                    const char *preedit_text,
222                                    int preedit_cursor);
223 static void text_entry_delete_text(struct text_entry *entry,
224                                    uint32_t index, uint32_t length);
225 static void text_entry_delete_selected_text(struct text_entry *entry);
226
227 static void
228 text_model_commit_string(void *data,
229                          struct text_model *text_model,
230                          const char *text,
231                          uint32_t index)
232 {
233         struct text_entry *entry = data;
234
235         if (index > strlen(text)) {
236                 fprintf(stderr, "Invalid cursor index %d\n", index);
237                 index = strlen(text);
238         }
239
240         text_entry_delete_selected_text(entry);
241         text_entry_insert_at_cursor(entry, text);
242
243         widget_schedule_redraw(entry->widget);
244 }
245
246 static void
247 text_model_preedit_string(void *data,
248                           struct text_model *text_model,
249                           const char *text,
250                           uint32_t index)
251 {
252         struct text_entry *entry = data;
253
254         if (index > strlen(text)) {
255                 fprintf(stderr, "Invalid cursor index %d\n", index);
256                 index = strlen(text);
257         }
258
259         text_entry_delete_selected_text(entry);
260         text_entry_set_preedit(entry, text, index);
261
262         widget_schedule_redraw(entry->widget);
263 }
264
265 static void
266 text_model_delete_surrounding_text(void *data,
267                                    struct text_model *text_model,
268                                    int32_t index,
269                                    uint32_t length)
270 {
271         struct text_entry *entry = data;
272         uint32_t cursor_index = index + entry->cursor;
273
274         if (cursor_index > strlen(entry->text)) {
275                 fprintf(stderr, "Invalid cursor index %d\n", index);
276                 return;
277         }
278
279         if (cursor_index + length > strlen(entry->text)) {
280                 fprintf(stderr, "Invalid length %d\n", length);
281                 return;
282         }
283
284         if (length == 0)
285                 return;
286
287         text_entry_delete_text(entry, cursor_index, length);
288 }
289
290 static void
291 text_model_preedit_styling(void *data,
292                            struct text_model *text_model)
293 {
294 }
295
296 static void
297 text_model_key(void *data,
298                struct text_model *text_model,
299                uint32_t key,
300                uint32_t state)
301 {
302         struct text_entry *entry = data;
303         const char *state_label;
304         const char *key_label = "released";
305
306         if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
307                 state_label = "pressed";
308         }
309
310         switch (key) {
311                 case XKB_KEY_Tab:
312                         key_label = "Tab";
313                         break;
314                 case XKB_KEY_KP_Enter:
315                         key_label = "Enter";
316                         break;
317                 case XKB_KEY_Left:
318                         if (entry->cursor > 0) {
319                                 entry->cursor--;
320                                 entry->anchor = entry->cursor;
321                                 widget_schedule_redraw(entry->widget);
322                         }
323                         break;
324                 case XKB_KEY_Right:
325                         if (entry->cursor < strlen(entry->text)) {
326                                 entry->cursor++;
327                                 entry->anchor = entry->cursor;
328                                 widget_schedule_redraw(entry->widget);
329                         }
330                         break;
331                 default:
332                         key_label = "Unknown";
333         }
334
335         fprintf(stderr, "%s key was %s.\n", key_label, state_label);
336 }
337
338 static void
339 text_model_selection_replacement(void *data,
340                                  struct text_model *text_model)
341 {
342 }
343
344 static void
345 text_model_direction(void *data,
346                      struct text_model *text_model)
347 {
348 }
349
350 static void
351 text_model_locale(void *data,
352                   struct text_model *text_model)
353 {
354 }
355
356 static void
357 text_model_enter(void *data,
358                  struct text_model *text_model,
359                  struct wl_surface *surface)
360 {
361         struct text_entry *entry = data;
362
363         if (surface != window_get_wl_surface(entry->window))
364                 return;
365
366         entry->active = 1;
367
368         widget_schedule_redraw(entry->widget);
369 }
370
371 static void
372 text_model_leave(void *data,
373                  struct text_model *text_model)
374 {
375         struct text_entry *entry = data;
376
377         entry->active = 0;
378
379         widget_schedule_redraw(entry->widget);
380 }
381
382 static const struct text_model_listener text_model_listener = {
383         text_model_commit_string,
384         text_model_preedit_string,
385         text_model_delete_surrounding_text,
386         text_model_preedit_styling,
387         text_model_key,
388         text_model_selection_replacement,
389         text_model_direction,
390         text_model_locale,
391         text_model_enter,
392         text_model_leave
393 };
394
395 static struct text_entry*
396 text_entry_create(struct editor *editor, const char *text)
397 {
398         struct text_entry *entry;
399
400         entry = malloc(sizeof *entry);
401
402         entry->widget = widget_add_widget(editor->widget, entry);
403         entry->window = editor->window;
404         entry->text = strdup(text);
405         entry->active = 0;
406         entry->cursor = strlen(text);
407         entry->anchor = entry->cursor;
408         entry->preedit_text = NULL;
409         entry->preedit_cursor = 0;
410         entry->model = text_model_factory_create_text_model(editor->text_model_factory);
411         text_model_add_listener(entry->model, &text_model_listener, entry);
412
413         entry->layout = text_layout_create();
414         text_layout_set_text(entry->layout, entry->text);
415
416         widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
417         widget_set_button_handler(entry->widget, text_entry_button_handler);
418
419         return entry;
420 }
421
422 static void
423 text_entry_destroy(struct text_entry *entry)
424 {
425         widget_destroy(entry->widget);
426         text_model_destroy(entry->model);
427         text_layout_destroy(entry->layout);
428         free(entry->text);
429         free(entry);
430 }
431
432 static void
433 redraw_handler(struct widget *widget, void *data)
434 {
435         struct editor *editor = data;
436         cairo_surface_t *surface;
437         struct rectangle allocation;
438         cairo_t *cr;
439
440         surface = window_get_surface(editor->window);
441         widget_get_allocation(editor->widget, &allocation);
442
443         cr = cairo_create(surface);
444         cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
445         cairo_clip(cr);
446
447         cairo_translate(cr, allocation.x, allocation.y);
448
449         /* Draw background */
450         cairo_push_group(cr);
451         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
452         cairo_set_source_rgba(cr, 1, 1, 1, 1);
453         cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
454         cairo_fill(cr);
455
456         cairo_pop_group_to_source(cr);
457         cairo_paint(cr);
458
459         cairo_destroy(cr);
460         cairo_surface_destroy(surface);
461 }
462
463 static void
464 text_entry_allocate(struct text_entry *entry, int32_t x, int32_t y,
465                     int32_t width, int32_t height)
466 {
467         widget_set_allocation(entry->widget, x, y, width, height);
468 }
469
470 static void
471 resize_handler(struct widget *widget,
472                int32_t width, int32_t height, void *data)
473 {
474         struct editor *editor = data;
475         struct rectangle allocation;
476
477         widget_get_allocation(editor->widget, &allocation);
478
479         text_entry_allocate(editor->entry,
480                             allocation.x + 20, allocation.y + 20,
481                             width - 40, height / 2 - 40);
482         text_entry_allocate(editor->editor,
483                             allocation.x + 20, allocation.y + height / 2 + 20,
484                             width - 40, height / 2 - 40);
485 }
486
487 static void
488 text_entry_activate(struct text_entry *entry,
489                     struct wl_seat *seat)
490 {
491         struct wl_surface *surface = window_get_wl_surface(entry->window);
492
493         text_model_activate(entry->model,
494                             seat,
495                             surface);
496 }
497
498 static void
499 text_entry_deactivate(struct text_entry *entry,
500                       struct wl_seat *seat)
501 {
502         text_model_deactivate(entry->model,
503                               seat);
504 }
505
506 static void
507 text_entry_update_layout(struct text_entry *entry)
508 {
509         char *text;
510
511         assert(((unsigned int)entry->cursor) <= strlen(entry->text) +
512                (entry->preedit_text ? strlen(entry->preedit_text) : 0));
513
514         if (!entry->preedit_text) {
515                 text_layout_set_text(entry->layout, entry->text);
516                 return;
517         }
518
519         text = malloc(strlen(entry->text) + strlen(entry->preedit_text) + 1);
520         strncpy(text, entry->text, entry->cursor);
521         strcpy(text + entry->cursor, entry->preedit_text);
522         strcpy(text + entry->cursor + strlen(entry->preedit_text),
523                entry->text + entry->cursor);
524
525         text_layout_set_text(entry->layout, text);
526         free(text);
527
528         widget_schedule_redraw(entry->widget);
529
530         text_model_set_surrounding_text(entry->model,
531                                         entry->text,
532                                         entry->cursor,
533                                         entry->anchor);
534 }
535
536 static void
537 text_entry_insert_at_cursor(struct text_entry *entry, const char *text)
538 {
539         char *new_text = malloc(strlen(entry->text) + strlen(text) + 1);
540
541         strncpy(new_text, entry->text, entry->cursor);
542         strcpy(new_text + entry->cursor, text);
543         strcpy(new_text + entry->cursor + strlen(text),
544                entry->text + entry->cursor);
545
546         free(entry->text);
547         entry->text = new_text;
548         entry->cursor += strlen(text);
549         entry->anchor += strlen(text);
550
551         text_entry_update_layout(entry);
552 }
553
554 static void
555 text_entry_set_preedit(struct text_entry *entry,
556                        const char *preedit_text,
557                        int preedit_cursor)
558 {
559         if (entry->preedit_text) {
560                 free(entry->preedit_text);
561                 entry->preedit_text = NULL;
562                 entry->preedit_cursor = 0;
563         }
564
565         if (!preedit_text)
566                 return;
567
568         entry->preedit_text = strdup(preedit_text);
569         entry->preedit_cursor = preedit_cursor;
570
571         text_entry_update_layout(entry);
572 }
573
574 static void
575 text_entry_set_cursor_position(struct text_entry *entry,
576                                int32_t x, int32_t y)
577 {
578         entry->cursor = text_layout_xy_to_index(entry->layout, x, y);
579
580         text_model_reset(entry->model);
581
582         if (entry->cursor >= entry->preedit_cursor) {
583                 entry->cursor -= entry->preedit_cursor;
584         }
585
586         text_entry_update_layout(entry);
587
588         widget_schedule_redraw(entry->widget);
589 }
590
591 static void
592 text_entry_set_anchor_position(struct text_entry *entry,
593                                int32_t x, int32_t y)
594 {
595         entry->anchor = text_layout_xy_to_index(entry->layout, x, y);
596
597         widget_schedule_redraw(entry->widget);
598 }
599
600 static void
601 text_entry_delete_text(struct text_entry *entry,
602                        uint32_t index, uint32_t length)
603 {
604         if (entry->cursor > index)
605                 entry->cursor -= length;
606
607         entry->anchor = entry->cursor;
608
609         entry->text[index] = '\0';
610         strcat(entry->text, entry->text + index + length);
611
612         text_entry_update_layout(entry);
613
614         widget_schedule_redraw(entry->widget);
615 }
616
617 static void
618 text_entry_delete_selected_text(struct text_entry *entry)
619 {
620         uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
621         uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
622
623         if (entry->anchor == entry->cursor)
624                 return;
625
626         text_entry_delete_text(entry, start_index, end_index - start_index);
627
628         entry->anchor = entry->cursor;
629 }
630
631 static void
632 text_entry_draw_selection(struct text_entry *entry, cairo_t *cr)
633 {
634         cairo_text_extents_t extents;
635         uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
636         uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
637         cairo_rectangle_t start;
638         cairo_rectangle_t end;
639
640         if (entry->anchor == entry->cursor)
641                 return;
642
643         text_layout_extents(entry->layout, &extents);
644
645         text_layout_index_to_pos(entry->layout, start_index, &start);
646         text_layout_index_to_pos(entry->layout, end_index, &end);
647
648         cairo_save (cr);
649
650         cairo_set_source_rgba(cr, 0.3, 0.3, 1.0, 0.5);
651         cairo_rectangle(cr,
652                         start.x, extents.y_bearing + extents.height + 2,
653                         end.x - start.x, -extents.height - 4);
654         cairo_fill(cr);
655
656         cairo_rectangle(cr,
657                         start.x, extents.y_bearing + extents.height,
658                         end.x - start.x, -extents.height);
659         cairo_clip(cr);
660         cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
661         text_layout_draw(entry->layout, cr);
662
663         cairo_restore (cr);
664 }
665
666 static void
667 text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
668 {
669         cairo_text_extents_t extents;
670         cairo_rectangle_t cursor_pos;
671
672         text_layout_extents(entry->layout, &extents);
673         text_layout_get_cursor_pos(entry->layout,
674                                    entry->cursor + entry->preedit_cursor,
675                                    &cursor_pos);
676
677         cairo_set_line_width(cr, 1.0);
678         cairo_move_to(cr, cursor_pos.x, extents.y_bearing + extents.height + 2);
679         cairo_line_to(cr, cursor_pos.x, extents.y_bearing - 2);
680         cairo_stroke(cr);
681 }
682
683 static void
684 text_entry_draw_preedit(struct text_entry *entry, cairo_t *cr)
685 {
686         cairo_text_extents_t extents;
687         cairo_rectangle_t start;
688         cairo_rectangle_t end;
689
690         if (!entry->preedit_text)
691                 return;
692
693         text_layout_extents(entry->layout, &extents);
694
695         text_layout_index_to_pos(entry->layout, entry->cursor, &start);
696         text_layout_index_to_pos(entry->layout,
697                                  entry->cursor + strlen(entry->preedit_text),
698                                  &end);
699
700         cairo_save (cr);
701
702         cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
703         cairo_rectangle(cr,
704                         start.x, 0,
705                         end.x - start.x, 1);
706         cairo_fill(cr);
707
708         cairo_restore (cr);
709 }
710
711 static const int text_offset_left = 10;
712
713 static void
714 text_entry_redraw_handler(struct widget *widget, void *data)
715 {
716         struct text_entry *entry = data;
717         cairo_surface_t *surface;
718         struct rectangle allocation;
719         cairo_t *cr;
720
721         surface = window_get_surface(entry->window);
722         widget_get_allocation(entry->widget, &allocation);
723
724         cr = cairo_create(surface);
725         cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
726         cairo_clip(cr);
727
728         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
729
730         cairo_push_group(cr);
731         cairo_translate(cr, allocation.x, allocation.y);
732
733         cairo_set_source_rgba(cr, 1, 1, 1, 1);
734         cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
735         cairo_fill(cr);
736
737         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
738
739         if (entry->active) {
740                 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
741                 cairo_set_line_width (cr, 3);
742                 cairo_set_source_rgba(cr, 0, 0, 1, 1.0);
743                 cairo_stroke(cr);
744         }
745
746         cairo_set_source_rgba(cr, 0, 0, 0, 1);
747
748         cairo_translate(cr, text_offset_left, allocation.height / 2);
749         text_layout_draw(entry->layout, cr);
750
751         text_entry_draw_selection(entry, cr);
752
753         text_entry_draw_cursor(entry, cr);
754
755         text_entry_draw_preedit(entry, cr);
756
757         cairo_pop_group_to_source(cr);
758         cairo_paint(cr);
759
760         cairo_destroy(cr);
761         cairo_surface_destroy(surface);
762 }
763
764 static int
765 text_entry_motion_handler(struct widget *widget,
766                           struct input *input, uint32_t time,
767                           float x, float y, void *data)
768 {
769         struct text_entry *entry = data;
770         struct rectangle allocation;
771
772         widget_get_allocation(entry->widget, &allocation);
773
774         text_entry_set_cursor_position(entry,
775                                        x - allocation.x - text_offset_left,
776                                        y - allocation.y - text_offset_left);
777
778         return CURSOR_IBEAM;
779 }
780
781 static void
782 text_entry_button_handler(struct widget *widget,
783                           struct input *input, uint32_t time,
784                           uint32_t button,
785                           enum wl_pointer_button_state state, void *data)
786 {
787         struct text_entry *entry = data;
788         struct rectangle allocation;
789         int32_t x, y;
790
791         widget_get_allocation(entry->widget, &allocation);
792         input_get_position(input, &x, &y);
793
794         if (button != BTN_LEFT) {
795                 return;
796         }
797
798         text_entry_set_cursor_position(entry,
799                                        x - allocation.x - text_offset_left,
800                                        y - allocation.y - text_offset_left);
801
802         if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
803                 struct wl_seat *seat = input_get_seat(input);
804
805                 text_entry_activate(entry, seat);
806
807                 text_entry_set_anchor_position(entry,
808                                                x - allocation.x - text_offset_left,
809                                                y - allocation.y - text_offset_left);
810
811                 widget_set_motion_handler(entry->widget, text_entry_motion_handler);
812         } else {
813                 widget_set_motion_handler(entry->widget, NULL);
814         }
815 }
816
817 static void
818 editor_button_handler(struct widget *widget,
819                       struct input *input, uint32_t time,
820                       uint32_t button,
821                       enum wl_pointer_button_state state, void *data)
822 {
823         struct editor *editor = data;
824
825         if (button != BTN_LEFT) {
826                 return;
827         }
828
829         if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
830                 struct wl_seat *seat = input_get_seat(input);
831
832                 text_entry_deactivate(editor->entry, seat);
833                 text_entry_deactivate(editor->editor, seat);
834         }
835 }
836
837 static void
838 global_handler(struct wl_display *display, uint32_t id,
839                const char *interface, uint32_t version, void *data)
840 {
841         struct editor *editor = data;
842
843         if (!strcmp(interface, "text_model_factory")) {
844                 editor->text_model_factory = wl_display_bind(display, id,
845                                                              &text_model_factory_interface);
846         }
847 }
848
849 int
850 main(int argc, char *argv[])
851 {
852         struct editor editor;
853
854         editor.display = display_create(argc, argv);
855         if (editor.display == NULL) {
856                 fprintf(stderr, "failed to create display: %m\n");
857                 return -1;
858         }
859         wl_display_add_global_listener(display_get_display(editor.display),
860                                        global_handler, &editor);
861
862
863         editor.window = window_create(editor.display);
864         editor.widget = frame_create(editor.window, &editor);
865
866         editor.entry = text_entry_create(&editor, "Entry");
867         editor.editor = text_entry_create(&editor, "Editor");
868         text_entry_set_preedit(editor.editor, "preedit", strlen("preedit"));
869
870         window_set_title(editor.window, "Text Editor");
871
872         widget_set_redraw_handler(editor.widget, redraw_handler);
873         widget_set_resize_handler(editor.widget, resize_handler);
874         widget_set_button_handler(editor.widget, editor_button_handler);
875
876         window_schedule_resize(editor.window, 500, 400);
877
878         display_run(editor.display);
879
880         text_entry_destroy(editor.entry);
881         text_entry_destroy(editor.editor);
882
883         return 0;
884 }