blob: 3056bdcd61ea59438c6180fcf99ee4453d747019 [file] [log] [blame]
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001/*
2 * Copyright © 2012 Openismus GmbH
Jan Arne Petersen4c265182012-09-09 23:08:30 +02003 * Copyright © 2012 Intel Corporation
Jan Arne Petersencba9e472012-06-21 21:52:19 +02004 *
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
Philipp Brüschweiler591cfca2012-07-11 22:25:29 +020024#include <assert.h>
Jan Arne Petersencba9e472012-06-21 21:52:19 +020025#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
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +020035static const char *font_name = "sans-serif";
36static int font_size = 14;
37
38struct 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
Jan Arne Petersencba9e472012-06-21 21:52:19 +020047struct text_entry {
48 struct widget *widget;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020049 struct window *window;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020050 char *text;
51 int active;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +020052 uint32_t cursor;
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +020053 uint32_t anchor;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020054 struct text_model *model;
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +020055 struct text_layout *layout;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020056};
57
58struct editor {
Jan Arne Petersen51963742012-08-10 16:47:20 +020059 struct text_model_factory *text_model_factory;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020060 struct display *display;
61 struct window *window;
62 struct widget *widget;
63 struct text_entry *entry;
64 struct text_entry *editor;
65};
66
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +020067static struct text_layout *
68text_layout_create(void)
69{
70 struct text_layout *layout;
71 cairo_surface_t *surface;
72 cairo_t *cr;
73
74 layout = malloc(sizeof *layout);
75 if (!layout)
76 return NULL;
77
78 layout->glyphs = NULL;
79 layout->num_glyphs = 0;
80
81 layout->clusters = NULL;
82 layout->num_clusters = 0;
83
84 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
85 cr = cairo_create(surface);
86 cairo_set_font_size(cr, font_size);
87 cairo_select_font_face(cr, font_name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
88 layout->font = cairo_get_scaled_font(cr);
89 cairo_scaled_font_reference(layout->font);
90
91 cairo_destroy(cr);
92 cairo_surface_destroy(surface);
93
94 return layout;
95}
96
97static void
98text_layout_destroy(struct text_layout *layout)
99{
100 if (layout->glyphs)
101 cairo_glyph_free(layout->glyphs);
102
103 if (layout->clusters)
104 cairo_text_cluster_free(layout->clusters);
105
106 cairo_scaled_font_destroy(layout->font);
107
108 free(layout);
109}
110
111static void
112text_layout_set_text(struct text_layout *layout,
113 const char *text)
114{
115 if (layout->glyphs)
116 cairo_glyph_free(layout->glyphs);
117
118 if (layout->clusters)
119 cairo_text_cluster_free(layout->clusters);
120
121 layout->glyphs = NULL;
122 layout->num_glyphs = 0;
123 layout->clusters = NULL;
124 layout->num_clusters = 0;
125
126 cairo_scaled_font_text_to_glyphs(layout->font, 0, 0, text, -1,
127 &layout->glyphs, &layout->num_glyphs,
128 &layout->clusters, &layout->num_clusters,
129 &layout->cluster_flags);
130}
131
132static void
133text_layout_draw(struct text_layout *layout, cairo_t *cr)
134{
135 cairo_save(cr);
136 cairo_set_scaled_font(cr, layout->font);
137 cairo_show_glyphs(cr, layout->glyphs, layout->num_glyphs);
138 cairo_restore(cr);
139}
140
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200141static void
142text_layout_extents(struct text_layout *layout, cairo_text_extents_t *extents)
143{
144 cairo_scaled_font_glyph_extents(layout->font,
145 layout->glyphs, layout->num_glyphs,
146 extents);
147}
148
149static int
150text_layout_xy_to_index(struct text_layout *layout, double x, double y)
151{
152 cairo_text_extents_t extents;
153 int i;
154
155 cairo_scaled_font_glyph_extents(layout->font,
156 layout->glyphs, layout->num_glyphs,
157 &extents);
158
159 for (i = 1; i < layout->num_glyphs; i++) {
160 if (layout->glyphs[i].x >= x) {
161 return i - 1;
162 }
163 }
164
165 if (x >= layout->glyphs[layout->num_glyphs - 1].x && x < extents.width)
166 return layout->num_glyphs - 1;
167
168 return layout->num_glyphs;
169}
170
171static void
172text_layout_index_to_pos(struct text_layout *layout, uint32_t index, cairo_rectangle_t *pos)
173{
174 cairo_text_extents_t extents;
175
176 if (!pos)
177 return;
178
179 cairo_scaled_font_glyph_extents(layout->font,
180 layout->glyphs, layout->num_glyphs,
181 &extents);
182
183 if ((int)index >= layout->num_glyphs) {
184 pos->x = extents.x_advance;
185 pos->y = layout->num_glyphs ? layout->glyphs[layout->num_glyphs - 1].y : 0;
186 pos->width = 1;
187 pos->height = extents.height;
188 return;
189 }
190
191 pos->x = layout->glyphs[index].x;
192 pos->y = layout->glyphs[index].y;
193 pos->width = (int)index < layout->num_glyphs - 1 ? layout->glyphs[index + 1].x : extents.x_advance - pos->x;
194 pos->height = extents.height;
195}
196
197static void
198text_layout_get_cursor_pos(struct text_layout *layout, int index, cairo_rectangle_t *pos)
199{
200 text_layout_index_to_pos(layout, index, pos);
201 pos->width = 1;
202}
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200203
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200204static void text_entry_redraw_handler(struct widget *widget, void *data);
205static void text_entry_button_handler(struct widget *widget,
206 struct input *input, uint32_t time,
207 uint32_t button,
208 enum wl_pointer_button_state state, void *data);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200209static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200210
211static void
212text_model_commit_string(void *data,
213 struct text_model *text_model,
214 const char *text,
215 uint32_t index)
216{
217 struct text_entry *entry = data;
218
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200219 if (index > strlen(text)) {
220 fprintf(stderr, "Invalid cursor index %d\n", index);
221 index = strlen(text);
222 }
223
224 text_entry_insert_at_cursor(entry, text);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200225
226 widget_schedule_redraw(entry->widget);
227}
228
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200229static void
230text_model_preedit_string(void *data,
231 struct text_model *text_model,
232 const char *text,
233 uint32_t index)
234{
235}
236
237static void
238text_model_preedit_styling(void *data,
239 struct text_model *text_model)
240{
241}
242
243static void
244text_model_key(void *data,
245 struct text_model *text_model)
246{
247}
248
249static void
250text_model_selection_replacement(void *data,
251 struct text_model *text_model)
252{
253}
254
255static void
256text_model_direction(void *data,
257 struct text_model *text_model)
258{
259}
260
261static void
262text_model_locale(void *data,
263 struct text_model *text_model)
264{
265}
266
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200267static void
268text_model_activated(void *data,
269 struct text_model *text_model)
270{
271 struct text_entry *entry = data;
272
273 entry->active = 1;
274
275 widget_schedule_redraw(entry->widget);
276}
277
278static void
279text_model_deactivated(void *data,
280 struct text_model *text_model)
281{
282 struct text_entry *entry = data;
283
284 entry->active = 0;
285
286 widget_schedule_redraw(entry->widget);
287}
288
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200289static const struct text_model_listener text_model_listener = {
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200290 text_model_commit_string,
291 text_model_preedit_string,
292 text_model_preedit_styling,
293 text_model_key,
294 text_model_selection_replacement,
295 text_model_direction,
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200296 text_model_locale,
297 text_model_activated,
298 text_model_deactivated
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200299};
300
301static struct text_entry*
302text_entry_create(struct editor *editor, const char *text)
303{
304 struct text_entry *entry;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200305
306 entry = malloc(sizeof *entry);
307
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200308 entry->widget = widget_add_widget(editor->widget, entry);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200309 entry->window = editor->window;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200310 entry->text = strdup(text);
311 entry->active = 0;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200312 entry->cursor = strlen(text);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200313 entry->anchor = entry->cursor;
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200314 entry->model = text_model_factory_create_text_model(editor->text_model_factory);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200315 text_model_add_listener(entry->model, &text_model_listener, entry);
316
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200317 entry->layout = text_layout_create();
318 text_layout_set_text(entry->layout, entry->text);
319
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200320 widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
321 widget_set_button_handler(entry->widget, text_entry_button_handler);
322
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200323 return entry;
324}
325
326static void
327text_entry_destroy(struct text_entry *entry)
328{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200329 widget_destroy(entry->widget);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200330 text_model_destroy(entry->model);
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200331 text_layout_destroy(entry->layout);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200332 free(entry->text);
333 free(entry);
334}
335
336static void
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200337redraw_handler(struct widget *widget, void *data)
338{
339 struct editor *editor = data;
340 cairo_surface_t *surface;
341 struct rectangle allocation;
342 cairo_t *cr;
343
344 surface = window_get_surface(editor->window);
345 widget_get_allocation(editor->widget, &allocation);
346
347 cr = cairo_create(surface);
348 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
349 cairo_clip(cr);
350
351 cairo_translate(cr, allocation.x, allocation.y);
352
353 /* Draw background */
354 cairo_push_group(cr);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200355 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200356 cairo_set_source_rgba(cr, 1, 1, 1, 1);
357 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
358 cairo_fill(cr);
359
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200360 cairo_pop_group_to_source(cr);
361 cairo_paint(cr);
362
363 cairo_destroy(cr);
364 cairo_surface_destroy(surface);
365}
366
367static void
368text_entry_allocate(struct text_entry *entry, int32_t x, int32_t y,
369 int32_t width, int32_t height)
370{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200371 widget_set_allocation(entry->widget, x, y, width, height);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200372}
373
374static void
375resize_handler(struct widget *widget,
376 int32_t width, int32_t height, void *data)
377{
378 struct editor *editor = data;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200379 struct rectangle allocation;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200380
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200381 widget_get_allocation(editor->widget, &allocation);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200382
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200383 text_entry_allocate(editor->entry,
384 allocation.x + 20, allocation.y + 20,
385 width - 40, height / 2 - 40);
386 text_entry_allocate(editor->editor,
387 allocation.x + 20, allocation.y + height / 2 + 20,
388 width - 40, height / 2 - 40);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200389}
390
391static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200392text_entry_activate(struct text_entry *entry,
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200393 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200394{
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200395 struct wl_surface *surface = window_get_wl_surface(entry->window);
396
397 text_model_activate(entry->model,
398 seat,
399 surface);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200400}
401
402static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200403text_entry_deactivate(struct text_entry *entry,
404 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200405{
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200406 text_model_deactivate(entry->model,
407 seat);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200408}
409
410static void
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200411text_entry_insert_at_cursor(struct text_entry *entry, const char *text)
412{
413 char *new_text = malloc(strlen(entry->text) + strlen(text) + 1);
414
415 strncpy(new_text, entry->text, entry->cursor);
416 strcpy(new_text + entry->cursor, text);
417 strcpy(new_text + entry->cursor + strlen(text),
418 entry->text + entry->cursor);
419
420 free(entry->text);
421 entry->text = new_text;
422 entry->cursor += strlen(text);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200423 entry->anchor += strlen(text);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200424
425 text_layout_set_text(entry->layout, entry->text);
426}
427
428static void
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200429text_entry_set_cursor_position(struct text_entry *entry,
430 int32_t x, int32_t y)
431{
432 entry->cursor = text_layout_xy_to_index(entry->layout, x, y);
433
434 widget_schedule_redraw(entry->widget);
435}
436
437static void
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200438text_entry_set_anchor_position(struct text_entry *entry,
439 int32_t x, int32_t y)
440{
441 entry->anchor = text_layout_xy_to_index(entry->layout, x, y);
442
443 widget_schedule_redraw(entry->widget);
444}
445
446static void
447text_entry_draw_selection(struct text_entry *entry, cairo_t *cr)
448{
449 cairo_text_extents_t extents;
450 uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
451 uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
452 cairo_rectangle_t start;
453 cairo_rectangle_t end;
454
455 if (entry->anchor == entry->cursor)
456 return;
457
458 text_layout_extents(entry->layout, &extents);
459
460 text_layout_index_to_pos(entry->layout, start_index, &start);
461 text_layout_index_to_pos(entry->layout, end_index, &end);
462
463 cairo_save (cr);
464
465 cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
466 cairo_rectangle(cr,
467 start.x, extents.y_bearing + extents.height + 2,
468 end.x - start.x, -extents.height - 4);
469 cairo_fill(cr);
470
471 cairo_rectangle(cr,
472 start.x, extents.y_bearing + extents.height,
473 end.x - start.x, -extents.height);
474 cairo_clip(cr);
475 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
476 text_layout_draw(entry->layout, cr);
477
478 cairo_restore (cr);
479}
480
481static void
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200482text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
483{
484 cairo_text_extents_t extents;
485 cairo_rectangle_t cursor_pos;
486
487 text_layout_extents(entry->layout, &extents);
488 text_layout_get_cursor_pos(entry->layout, entry->cursor, &cursor_pos);
489
490 cairo_set_line_width(cr, 1.0);
491 cairo_move_to(cr, cursor_pos.x, extents.y_bearing + extents.height + 2);
492 cairo_line_to(cr, cursor_pos.x, extents.y_bearing - 2);
493 cairo_stroke(cr);
494}
495
496static void
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200497text_entry_redraw_handler(struct widget *widget, void *data)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200498{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200499 struct text_entry *entry = data;
500 cairo_surface_t *surface;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200501 struct rectangle allocation;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200502 cairo_t *cr;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200503
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200504 surface = window_get_surface(entry->window);
505 widget_get_allocation(entry->widget, &allocation);
506
507 cr = cairo_create(surface);
508 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
509 cairo_clip(cr);
510
511 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
512
513 cairo_push_group(cr);
514 cairo_translate(cr, allocation.x, allocation.y);
515
516 cairo_set_source_rgba(cr, 1, 1, 1, 1);
517 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
518 cairo_fill(cr);
519
520 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
521
522 if (entry->active) {
523 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
524 cairo_set_line_width (cr, 3);
525 cairo_set_source_rgba(cr, 0, 0, 1, 1.0);
526 cairo_stroke(cr);
527 }
528
529 cairo_set_source_rgba(cr, 0, 0, 0, 1);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200530
531 cairo_translate(cr, 10, allocation.height / 2);
Jan Arne Petersenb9eb02c2012-09-09 23:08:35 +0200532 text_layout_draw(entry->layout, cr);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200533
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200534 text_entry_draw_selection(entry, cr);
535
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200536 text_entry_draw_cursor(entry, cr);
537
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200538 cairo_pop_group_to_source(cr);
539 cairo_paint(cr);
540
541 cairo_destroy(cr);
542 cairo_surface_destroy(surface);
543}
544
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200545static int
546text_entry_motion_handler(struct widget *widget,
547 struct input *input, uint32_t time,
548 float x, float y, void *data)
549{
550 struct text_entry *entry = data;
551 struct rectangle allocation;
552
553 widget_get_allocation(entry->widget, &allocation);
554
555 text_entry_set_cursor_position(entry,
556 x - allocation.x,
557 y - allocation.y);
558
559 return CURSOR_IBEAM;
560}
561
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200562static void
563text_entry_button_handler(struct widget *widget,
564 struct input *input, uint32_t time,
565 uint32_t button,
566 enum wl_pointer_button_state state, void *data)
567{
568 struct text_entry *entry = data;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200569 struct rectangle allocation;
570 int32_t x, y;
571
572 widget_get_allocation(entry->widget, &allocation);
573 input_get_position(input, &x, &y);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200574
575 if (button != BTN_LEFT) {
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200576 return;
577 }
578
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200579 text_entry_set_cursor_position(entry,
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200580 x - allocation.x,
581 y - allocation.y);
582
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200583 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
584 struct wl_seat *seat = input_get_seat(input);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200585
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200586 text_entry_activate(entry, seat);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200587
588 text_entry_set_anchor_position(entry,
589 x - allocation.x,
590 y - allocation.y);
591
592 widget_set_motion_handler(entry->widget, text_entry_motion_handler);
593 } else {
594 widget_set_motion_handler(entry->widget, NULL);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200595 }
596}
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200597
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200598static void
599editor_button_handler(struct widget *widget,
600 struct input *input, uint32_t time,
601 uint32_t button,
602 enum wl_pointer_button_state state, void *data)
603{
604 struct editor *editor = data;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200605
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200606 if (button != BTN_LEFT) {
607 return;
608 }
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200609
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200610 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
611 struct wl_seat *seat = input_get_seat(input);
612
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200613 text_entry_deactivate(editor->entry, seat);
614 text_entry_deactivate(editor->editor, seat);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200615 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200616}
617
618static void
619global_handler(struct wl_display *display, uint32_t id,
620 const char *interface, uint32_t version, void *data)
621{
622 struct editor *editor = data;
623
Jan Arne Petersen51963742012-08-10 16:47:20 +0200624 if (!strcmp(interface, "text_model_factory")) {
625 editor->text_model_factory = wl_display_bind(display, id,
626 &text_model_factory_interface);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200627 }
628}
629
630int
631main(int argc, char *argv[])
632{
633 struct editor editor;
634
635 editor.display = display_create(argc, argv);
636 if (editor.display == NULL) {
637 fprintf(stderr, "failed to create display: %m\n");
638 return -1;
639 }
640 wl_display_add_global_listener(display_get_display(editor.display),
641 global_handler, &editor);
642
643
644 editor.window = window_create(editor.display);
645 editor.widget = frame_create(editor.window, &editor);
646
647 editor.entry = text_entry_create(&editor, "Entry");
648 editor.editor = text_entry_create(&editor, "Editor");
649
650 window_set_title(editor.window, "Text Editor");
651
652 widget_set_redraw_handler(editor.widget, redraw_handler);
653 widget_set_resize_handler(editor.widget, resize_handler);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200654 widget_set_button_handler(editor.widget, editor_button_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200655
656 window_schedule_resize(editor.window, 500, 400);
657
658 display_run(editor.display);
659
660 text_entry_destroy(editor.entry);
661 text_entry_destroy(editor.editor);
662
663 return 0;
664}